diff options
author | VirtualTam <virtualtam@flibidi.net> | 2017-08-23 01:08:41 +0200 |
---|---|---|
committer | VirtualTam <virtualtam@flibidi.net> | 2017-08-23 01:08:41 +0200 |
commit | 9d7a02afcee3c740712a7c95182d332db0504b7e (patch) | |
tree | 3266e3d3bfec6a3ac075084cbec07ba4090c4cd2 /application | |
parent | c318096c7a6fb3f6b00bd8c694ab7acb8fbb7cd0 (diff) | |
parent | 7c2460c856c1d561b8347316f3045208f9f3d24e (diff) | |
download | Shaarli-9d7a02afcee3c740712a7c95182d332db0504b7e.tar.gz Shaarli-9d7a02afcee3c740712a7c95182d332db0504b7e.tar.zst Shaarli-9d7a02afcee3c740712a7c95182d332db0504b7e.zip |
Merge branch 'master' into v0.9
Diffstat (limited to 'application')
-rw-r--r-- | application/FeedBuilder.php | 5 | ||||
-rw-r--r-- | application/HttpUtils.php | 14 | ||||
-rw-r--r-- | application/LinkDB.php | 76 | ||||
-rw-r--r-- | application/LinkFilter.php | 65 | ||||
-rw-r--r-- | application/PageBuilder.php | 3 | ||||
-rw-r--r-- | application/Router.php | 12 | ||||
-rw-r--r-- | application/Updater.php | 15 | ||||
-rw-r--r-- | application/Url.php | 24 | ||||
-rw-r--r-- | application/Utils.php | 35 | ||||
-rw-r--r-- | application/config/ConfigManager.php | 1 |
10 files changed, 192 insertions, 58 deletions
diff --git a/application/FeedBuilder.php b/application/FeedBuilder.php index a1f4da48..7377bcec 100644 --- a/application/FeedBuilder.php +++ b/application/FeedBuilder.php | |||
@@ -97,6 +97,11 @@ class FeedBuilder | |||
97 | */ | 97 | */ |
98 | public function buildData() | 98 | public function buildData() |
99 | { | 99 | { |
100 | // Search for untagged links | ||
101 | if (isset($this->userInput['searchtags']) && empty($this->userInput['searchtags'])) { | ||
102 | $this->userInput['searchtags'] = false; | ||
103 | } | ||
104 | |||
100 | // Optionally filter the results: | 105 | // Optionally filter the results: |
101 | $linksToDisplay = $this->linkDB->filterSearch($this->userInput); | 106 | $linksToDisplay = $this->linkDB->filterSearch($this->userInput); |
102 | 107 | ||
diff --git a/application/HttpUtils.php b/application/HttpUtils.php index a81f9056..88a1efdb 100644 --- a/application/HttpUtils.php +++ b/application/HttpUtils.php | |||
@@ -311,7 +311,19 @@ function server_url($server) | |||
311 | } | 311 | } |
312 | } | 312 | } |
313 | 313 | ||
314 | return $scheme.'://'.$server['SERVER_NAME'].$port; | 314 | if (isset($server['HTTP_X_FORWARDED_HOST'])) { |
315 | // Keep forwarded host | ||
316 | if (strpos($server['HTTP_X_FORWARDED_HOST'], ',') !== false) { | ||
317 | $hosts = explode(',', $server['HTTP_X_FORWARDED_HOST']); | ||
318 | $host = trim($hosts[0]); | ||
319 | } else { | ||
320 | $host = $server['HTTP_X_FORWARDED_HOST']; | ||
321 | } | ||
322 | } else { | ||
323 | $host = $server['SERVER_NAME']; | ||
324 | } | ||
325 | |||
326 | return $scheme.'://'.$host.$port; | ||
315 | } | 327 | } |
316 | 328 | ||
317 | // SSL detection | 329 | // SSL detection |
diff --git a/application/LinkDB.php b/application/LinkDB.php index 0d3c85bd..9308164a 100644 --- a/application/LinkDB.php +++ b/application/LinkDB.php | |||
@@ -417,49 +417,36 @@ You use the community supported version of the original Shaarli project, by Seba | |||
417 | * - searchterm: term search | 417 | * - searchterm: term search |
418 | * @param bool $casesensitive Optional: Perform case sensitive filter | 418 | * @param bool $casesensitive Optional: Perform case sensitive filter |
419 | * @param string $visibility return only all/private/public links | 419 | * @param string $visibility return only all/private/public links |
420 | * @param string $untaggedonly return only untagged links | ||
420 | * | 421 | * |
421 | * @return array filtered links, all links if no suitable filter was provided. | 422 | * @return array filtered links, all links if no suitable filter was provided. |
422 | */ | 423 | */ |
423 | public function filterSearch($filterRequest = array(), $casesensitive = false, $visibility = 'all') | 424 | public function filterSearch($filterRequest = array(), $casesensitive = false, $visibility = 'all', $untaggedonly = false) |
424 | { | 425 | { |
425 | // Filter link database according to parameters. | 426 | // Filter link database according to parameters. |
426 | $searchtags = !empty($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : ''; | 427 | $searchtags = isset($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : ''; |
427 | $searchterm = !empty($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : ''; | 428 | $searchterm = isset($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : ''; |
428 | 429 | ||
429 | // Search tags + fullsearch. | 430 | // Search tags + fullsearch - blank string parameter will return all links. |
430 | if (! empty($searchtags) && ! empty($searchterm)) { | 431 | $type = LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT; // == "vuotext" |
431 | $type = LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT; | 432 | $request = [$searchtags, $searchterm]; |
432 | $request = array($searchtags, $searchterm); | ||
433 | } | ||
434 | // Search by tags. | ||
435 | elseif (! empty($searchtags)) { | ||
436 | $type = LinkFilter::$FILTER_TAG; | ||
437 | $request = $searchtags; | ||
438 | } | ||
439 | // Fulltext search. | ||
440 | elseif (! empty($searchterm)) { | ||
441 | $type = LinkFilter::$FILTER_TEXT; | ||
442 | $request = $searchterm; | ||
443 | } | ||
444 | // Otherwise, display without filtering. | ||
445 | else { | ||
446 | $type = ''; | ||
447 | $request = ''; | ||
448 | } | ||
449 | 433 | ||
450 | $linkFilter = new LinkFilter($this); | 434 | $linkFilter = new LinkFilter($this); |
451 | return $linkFilter->filter($type, $request, $casesensitive, $visibility); | 435 | return $linkFilter->filter($type, $request, $casesensitive, $visibility, $untaggedonly); |
452 | } | 436 | } |
453 | 437 | ||
454 | /** | 438 | /** |
455 | * Returns the list of all tags | 439 | * Returns the list tags appearing in the links with the given tags |
456 | * Output: associative array key=tags, value=0 | 440 | * @param $filteringTags: tags selecting the links to consider |
441 | * @param $visibility: process only all/private/public links | ||
442 | * @return: a tag=>linksCount array | ||
457 | */ | 443 | */ |
458 | public function allTags() | 444 | public function linksCountPerTag($filteringTags = [], $visibility = 'all') |
459 | { | 445 | { |
446 | $links = empty($filteringTags) ? $this->links : $this->filterSearch(['searchtags' => $filteringTags], false, $visibility); | ||
460 | $tags = array(); | 447 | $tags = array(); |
461 | $caseMapping = array(); | 448 | $caseMapping = array(); |
462 | foreach ($this->links as $link) { | 449 | foreach ($links as $link) { |
463 | foreach (preg_split('/\s+/', $link['tags'], 0, PREG_SPLIT_NO_EMPTY) as $tag) { | 450 | foreach (preg_split('/\s+/', $link['tags'], 0, PREG_SPLIT_NO_EMPTY) as $tag) { |
464 | if (empty($tag)) { | 451 | if (empty($tag)) { |
465 | continue; | 452 | continue; |
@@ -478,6 +465,39 @@ You use the community supported version of the original Shaarli project, by Seba | |||
478 | } | 465 | } |
479 | 466 | ||
480 | /** | 467 | /** |
468 | * Rename or delete a tag across all links. | ||
469 | * | ||
470 | * @param string $from Tag to rename | ||
471 | * @param string $to New tag. If none is provided, the from tag will be deleted | ||
472 | * | ||
473 | * @return array|bool List of altered links or false on error | ||
474 | */ | ||
475 | public function renameTag($from, $to) | ||
476 | { | ||
477 | if (empty($from)) { | ||
478 | return false; | ||
479 | } | ||
480 | $delete = empty($to); | ||
481 | // True for case-sensitive tag search. | ||
482 | $linksToAlter = $this->filterSearch(['searchtags' => $from], true); | ||
483 | foreach($linksToAlter as $key => &$value) | ||
484 | { | ||
485 | $tags = preg_split('/\s+/', trim($value['tags'])); | ||
486 | if (($pos = array_search($from, $tags)) !== false) { | ||
487 | if ($delete) { | ||
488 | unset($tags[$pos]); // Remove tag. | ||
489 | } else { | ||
490 | $tags[$pos] = trim($to); | ||
491 | } | ||
492 | $value['tags'] = trim(implode(' ', array_unique($tags))); | ||
493 | $this[$value['id']] = $value; | ||
494 | } | ||
495 | } | ||
496 | |||
497 | return $linksToAlter; | ||
498 | } | ||
499 | |||
500 | /** | ||
481 | * Returns the list of days containing articles (oldest first) | 501 | * Returns the list of days containing articles (oldest first) |
482 | * Output: An array containing days (in format YYYYMMDD). | 502 | * Output: An array containing days (in format YYYYMMDD). |
483 | */ | 503 | */ |
diff --git a/application/LinkFilter.php b/application/LinkFilter.php index 81832a4b..95519528 100644 --- a/application/LinkFilter.php +++ b/application/LinkFilter.php | |||
@@ -52,10 +52,11 @@ class LinkFilter | |||
52 | * @param mixed $request Filter content. | 52 | * @param mixed $request Filter content. |
53 | * @param bool $casesensitive Optional: Perform case sensitive filter if true. | 53 | * @param bool $casesensitive Optional: Perform case sensitive filter if true. |
54 | * @param string $visibility Optional: return only all/private/public links | 54 | * @param string $visibility Optional: return only all/private/public links |
55 | * @param string $untaggedonly Optional: return only untagged links. Applies only if $type includes FILTER_TAG | ||
55 | * | 56 | * |
56 | * @return array filtered link list. | 57 | * @return array filtered link list. |
57 | */ | 58 | */ |
58 | public function filter($type, $request, $casesensitive = false, $visibility = 'all') | 59 | public function filter($type, $request, $casesensitive = false, $visibility = 'all', $untaggedonly = false) |
59 | { | 60 | { |
60 | if (! in_array($visibility, ['all', 'public', 'private'])) { | 61 | if (! in_array($visibility, ['all', 'public', 'private'])) { |
61 | $visibility = 'all'; | 62 | $visibility = 'all'; |
@@ -64,23 +65,34 @@ class LinkFilter | |||
64 | switch($type) { | 65 | switch($type) { |
65 | case self::$FILTER_HASH: | 66 | case self::$FILTER_HASH: |
66 | return $this->filterSmallHash($request); | 67 | return $this->filterSmallHash($request); |
67 | case self::$FILTER_TAG | self::$FILTER_TEXT: | 68 | case self::$FILTER_TAG | self::$FILTER_TEXT: // == "vuotext" |
68 | if (!empty($request)) { | 69 | $noRequest = empty($request) || (empty($request[0]) && empty($request[1])); |
69 | $filtered = $this->links; | 70 | if ($noRequest) { |
70 | if (isset($request[0])) { | 71 | if ($untaggedonly) { |
71 | $filtered = $this->filterTags($request[0], $casesensitive, $visibility); | 72 | return $this->filterUntagged($visibility); |
72 | } | ||
73 | if (isset($request[1])) { | ||
74 | $lf = new LinkFilter($filtered); | ||
75 | $filtered = $lf->filterFulltext($request[1], $visibility); | ||
76 | } | 73 | } |
77 | return $filtered; | 74 | return $this->noFilter($visibility); |
78 | } | 75 | } |
79 | return $this->noFilter($visibility); | 76 | if ($untaggedonly) { |
77 | $filtered = $this->filterUntagged($visibility); | ||
78 | } else { | ||
79 | $filtered = $this->links; | ||
80 | } | ||
81 | if (!empty($request[0])) { | ||
82 | $filtered = (new LinkFilter($filtered))->filterTags($request[0], $casesensitive, $visibility); | ||
83 | } | ||
84 | if (!empty($request[1])) { | ||
85 | $filtered = (new LinkFilter($filtered))->filterFulltext($request[1], $visibility); | ||
86 | } | ||
87 | return $filtered; | ||
80 | case self::$FILTER_TEXT: | 88 | case self::$FILTER_TEXT: |
81 | return $this->filterFulltext($request, $visibility); | 89 | return $this->filterFulltext($request, $visibility); |
82 | case self::$FILTER_TAG: | 90 | case self::$FILTER_TAG: |
83 | return $this->filterTags($request, $casesensitive, $visibility); | 91 | if ($untaggedonly) { |
92 | return $this->filterUntagged($visibility); | ||
93 | } else { | ||
94 | return $this->filterTags($request, $casesensitive, $visibility); | ||
95 | } | ||
84 | case self::$FILTER_DAY: | 96 | case self::$FILTER_DAY: |
85 | return $this->filterDay($request); | 97 | return $this->filterDay($request); |
86 | default: | 98 | default: |
@@ -296,6 +308,33 @@ class LinkFilter | |||
296 | } | 308 | } |
297 | 309 | ||
298 | /** | 310 | /** |
311 | * Return only links without any tag. | ||
312 | * | ||
313 | * @param string $visibility return only all/private/public links. | ||
314 | * | ||
315 | * @return array filtered links. | ||
316 | */ | ||
317 | public function filterUntagged($visibility) | ||
318 | { | ||
319 | $filtered = []; | ||
320 | foreach ($this->links as $key => $link) { | ||
321 | if ($visibility !== 'all') { | ||
322 | if (! $link['private'] && $visibility === 'private') { | ||
323 | continue; | ||
324 | } else if ($link['private'] && $visibility === 'public') { | ||
325 | continue; | ||
326 | } | ||
327 | } | ||
328 | |||
329 | if (empty(trim($link['tags']))) { | ||
330 | $filtered[$key] = $link; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | return $filtered; | ||
335 | } | ||
336 | |||
337 | /** | ||
299 | * Returns the list of articles for a given day, chronologically sorted | 338 | * Returns the list of articles for a given day, chronologically sorted |
300 | * | 339 | * |
301 | * Day must be in the form 'YYYYMMDD' (e.g. '20120125'), e.g. | 340 | * Day must be in the form 'YYYYMMDD' (e.g. '20120125'), e.g. |
diff --git a/application/PageBuilder.php b/application/PageBuilder.php index 50e3f124..7a42400d 100644 --- a/application/PageBuilder.php +++ b/application/PageBuilder.php | |||
@@ -78,6 +78,7 @@ class PageBuilder | |||
78 | $this->tpl->assign('version', shaarli_version); | 78 | $this->tpl->assign('version', shaarli_version); |
79 | $this->tpl->assign('scripturl', index_url($_SERVER)); | 79 | $this->tpl->assign('scripturl', index_url($_SERVER)); |
80 | $this->tpl->assign('privateonly', !empty($_SESSION['privateonly'])); // Show only private links? | 80 | $this->tpl->assign('privateonly', !empty($_SESSION['privateonly'])); // Show only private links? |
81 | $this->tpl->assign('untaggedonly', !empty($_SESSION['untaggedonly'])); | ||
81 | $this->tpl->assign('pagetitle', $this->conf->get('general.title', 'Shaarli')); | 82 | $this->tpl->assign('pagetitle', $this->conf->get('general.title', 'Shaarli')); |
82 | if ($this->conf->exists('general.header_link')) { | 83 | if ($this->conf->exists('general.header_link')) { |
83 | $this->tpl->assign('titleLink', $this->conf->get('general.header_link')); | 84 | $this->tpl->assign('titleLink', $this->conf->get('general.header_link')); |
@@ -89,7 +90,7 @@ class PageBuilder | |||
89 | $this->tpl->assign('hide_timestamps', $this->conf->get('privacy.hide_timestamps', false)); | 90 | $this->tpl->assign('hide_timestamps', $this->conf->get('privacy.hide_timestamps', false)); |
90 | $this->tpl->assign('token', getToken($this->conf)); | 91 | $this->tpl->assign('token', getToken($this->conf)); |
91 | if ($this->linkDB !== null) { | 92 | if ($this->linkDB !== null) { |
92 | $this->tpl->assign('tags', $this->linkDB->allTags()); | 93 | $this->tpl->assign('tags', $this->linkDB->linksCountPerTag()); |
93 | } | 94 | } |
94 | // To be removed with a proper theme configuration. | 95 | // To be removed with a proper theme configuration. |
95 | $this->tpl->assign('conf', $this->conf); | 96 | $this->tpl->assign('conf', $this->conf); |
diff --git a/application/Router.php b/application/Router.php index c9a51912..4df0387c 100644 --- a/application/Router.php +++ b/application/Router.php | |||
@@ -13,6 +13,8 @@ class Router | |||
13 | 13 | ||
14 | public static $PAGE_TAGCLOUD = 'tagcloud'; | 14 | public static $PAGE_TAGCLOUD = 'tagcloud'; |
15 | 15 | ||
16 | public static $PAGE_TAGLIST = 'taglist'; | ||
17 | |||
16 | public static $PAGE_DAILY = 'daily'; | 18 | public static $PAGE_DAILY = 'daily'; |
17 | 19 | ||
18 | public static $PAGE_FEED_ATOM = 'atom'; | 20 | public static $PAGE_FEED_ATOM = 'atom'; |
@@ -45,6 +47,8 @@ class Router | |||
45 | 47 | ||
46 | public static $PAGE_SAVE_PLUGINSADMIN = 'save_pluginadmin'; | 48 | public static $PAGE_SAVE_PLUGINSADMIN = 'save_pluginadmin'; |
47 | 49 | ||
50 | public static $GET_TOKEN = 'token'; | ||
51 | |||
48 | /** | 52 | /** |
49 | * Reproducing renderPage() if hell, to avoid regression. | 53 | * Reproducing renderPage() if hell, to avoid regression. |
50 | * | 54 | * |
@@ -77,6 +81,10 @@ class Router | |||
77 | return self::$PAGE_TAGCLOUD; | 81 | return self::$PAGE_TAGCLOUD; |
78 | } | 82 | } |
79 | 83 | ||
84 | if (startsWith($query, 'do='. self::$PAGE_TAGLIST)) { | ||
85 | return self::$PAGE_TAGLIST; | ||
86 | } | ||
87 | |||
80 | if (startsWith($query, 'do='. self::$PAGE_OPENSEARCH)) { | 88 | if (startsWith($query, 'do='. self::$PAGE_OPENSEARCH)) { |
81 | return self::$PAGE_OPENSEARCH; | 89 | return self::$PAGE_OPENSEARCH; |
82 | } | 90 | } |
@@ -142,6 +150,10 @@ class Router | |||
142 | return self::$PAGE_SAVE_PLUGINSADMIN; | 150 | return self::$PAGE_SAVE_PLUGINSADMIN; |
143 | } | 151 | } |
144 | 152 | ||
153 | if (startsWith($query, 'do='. self::$GET_TOKEN)) { | ||
154 | return self::$GET_TOKEN; | ||
155 | } | ||
156 | |||
145 | return self::$PAGE_LINKLIST; | 157 | return self::$PAGE_LINKLIST; |
146 | } | 158 | } |
147 | } | 159 | } |
diff --git a/application/Updater.php b/application/Updater.php index 03d93a6f..40a15906 100644 --- a/application/Updater.php +++ b/application/Updater.php | |||
@@ -329,21 +329,6 @@ class Updater | |||
329 | } | 329 | } |
330 | 330 | ||
331 | /** | 331 | /** |
332 | * While the new default theme is in an unstable state | ||
333 | * continue to use the vintage theme | ||
334 | */ | ||
335 | public function updateMethodDefaultThemeVintage() | ||
336 | { | ||
337 | if ($this->conf->get('resource.theme') !== 'default') { | ||
338 | return true; | ||
339 | } | ||
340 | $this->conf->set('resource.theme', 'vintage'); | ||
341 | $this->conf->write($this->isLoggedIn); | ||
342 | |||
343 | return true; | ||
344 | } | ||
345 | |||
346 | /** | ||
347 | * * `markdown_escape` is a new setting, set to true as default. | 332 | * * `markdown_escape` is a new setting, set to true as default. |
348 | * | 333 | * |
349 | * If the markdown plugin was already enabled, escaping is disabled to avoid | 334 | * If the markdown plugin was already enabled, escaping is disabled to avoid |
diff --git a/application/Url.php b/application/Url.php index 25a62a8a..b3759377 100644 --- a/application/Url.php +++ b/application/Url.php | |||
@@ -64,6 +64,30 @@ function add_trailing_slash($url) | |||
64 | } | 64 | } |
65 | 65 | ||
66 | /** | 66 | /** |
67 | * Replace not whitelisted protocols by 'http://' from given URL. | ||
68 | * | ||
69 | * @param string $url URL to clean | ||
70 | * @param array $protocols List of allowed protocols (aside from http(s)). | ||
71 | * | ||
72 | * @return string URL with allowed protocol | ||
73 | */ | ||
74 | function whitelist_protocols($url, $protocols) | ||
75 | { | ||
76 | if (startsWith($url, '?') || startsWith($url, '/')) { | ||
77 | return $url; | ||
78 | } | ||
79 | $protocols = array_merge(['http', 'https'], $protocols); | ||
80 | $protocol = preg_match('#^(\w+):/?/?#', $url, $match); | ||
81 | // Protocol not allowed: we remove it and replace it with http | ||
82 | if ($protocol === 1 && ! in_array($match[1], $protocols)) { | ||
83 | $url = str_replace($match[0], 'http://', $url); | ||
84 | } else if ($protocol !== 1) { | ||
85 | $url = 'http://' . $url; | ||
86 | } | ||
87 | return $url; | ||
88 | } | ||
89 | |||
90 | /** | ||
67 | * URL representation and cleanup utilities | 91 | * URL representation and cleanup utilities |
68 | * | 92 | * |
69 | * Form | 93 | * Form |
diff --git a/application/Utils.php b/application/Utils.php index ab463af9..4a2f5561 100644 --- a/application/Utils.php +++ b/application/Utils.php | |||
@@ -91,6 +91,10 @@ function endsWith($haystack, $needle, $case = true) | |||
91 | */ | 91 | */ |
92 | function escape($input) | 92 | function escape($input) |
93 | { | 93 | { |
94 | if (is_bool($input)) { | ||
95 | return $input; | ||
96 | } | ||
97 | |||
94 | if (is_array($input)) { | 98 | if (is_array($input)) { |
95 | $out = array(); | 99 | $out = array(); |
96 | foreach($input as $key => $value) { | 100 | foreach($input as $key => $value) { |
@@ -435,3 +439,34 @@ function get_max_upload_size($limitPost, $limitUpload, $format = true) | |||
435 | $maxsize = min($size1, $size2); | 439 | $maxsize = min($size1, $size2); |
436 | return $format ? human_bytes($maxsize) : $maxsize; | 440 | return $format ? human_bytes($maxsize) : $maxsize; |
437 | } | 441 | } |
442 | |||
443 | /** | ||
444 | * Sort the given array alphabetically using php-intl if available. | ||
445 | * Case sensitive. | ||
446 | * | ||
447 | * Note: doesn't support multidimensional arrays | ||
448 | * | ||
449 | * @param array $data Input array, passed by reference | ||
450 | * @param bool $reverse Reverse sort if set to true | ||
451 | * @param bool $byKeys Sort the array by keys if set to true, by value otherwise. | ||
452 | */ | ||
453 | function alphabetical_sort(&$data, $reverse = false, $byKeys = false) | ||
454 | { | ||
455 | $callback = function($a, $b) use ($reverse) { | ||
456 | // Collator is part of PHP intl. | ||
457 | if (class_exists('Collator')) { | ||
458 | $collator = new Collator(setlocale(LC_COLLATE, 0)); | ||
459 | if (!intl_is_failure(intl_get_error_code())) { | ||
460 | return $collator->compare($a, $b) * ($reverse ? -1 : 1); | ||
461 | } | ||
462 | } | ||
463 | |||
464 | return strcasecmp($a, $b) * ($reverse ? -1 : 1); | ||
465 | }; | ||
466 | |||
467 | if ($byKeys) { | ||
468 | uksort($data, $callback); | ||
469 | } else { | ||
470 | usort($data, $callback); | ||
471 | } | ||
472 | } | ||
diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php index 86a917fb..8eab26f1 100644 --- a/application/config/ConfigManager.php +++ b/application/config/ConfigManager.php | |||
@@ -312,6 +312,7 @@ class ConfigManager | |||
312 | $this->setEmpty('security.ban_duration', 1800); | 312 | $this->setEmpty('security.ban_duration', 1800); |
313 | $this->setEmpty('security.session_protection_disabled', false); | 313 | $this->setEmpty('security.session_protection_disabled', false); |
314 | $this->setEmpty('security.open_shaarli', false); | 314 | $this->setEmpty('security.open_shaarli', false); |
315 | $this->setEmpty('security.allowed_protocols', ['ftp', 'ftps', 'magnet']); | ||
315 | 316 | ||
316 | $this->setEmpty('general.header_link', '?'); | 317 | $this->setEmpty('general.header_link', '?'); |
317 | $this->setEmpty('general.links_per_page', 20); | 318 | $this->setEmpty('general.links_per_page', 20); |