aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile68
-rw-r--r--application/ApplicationUtils.php17
-rw-r--r--application/Base64Url.php7
-rw-r--r--application/FeedBuilder.php4
-rw-r--r--application/HttpUtils.php29
-rw-r--r--application/Languages.php15
-rw-r--r--application/LinkDB.php29
-rw-r--r--application/LinkFilter.php25
-rw-r--r--application/LinkUtils.php5
-rw-r--r--application/NetscapeBookmarkUtils.php16
-rw-r--r--application/PageBuilder.php3
-rw-r--r--application/PluginManager.php3
-rw-r--r--application/Thumbnailer.php5
-rw-r--r--application/Updater.php2
-rw-r--r--application/Url.php19
-rw-r--r--application/Utils.php16
-rw-r--r--application/api/ApiMiddleware.php5
-rw-r--r--application/api/controllers/ApiController.php2
-rw-r--r--application/api/controllers/History.php3
-rw-r--r--application/api/controllers/Info.php4
-rw-r--r--application/api/exceptions/ApiException.php8
-rw-r--r--application/api/exceptions/ApiLinkNotFoundException.php1
-rw-r--r--application/api/exceptions/ApiTagNotFoundException.php1
-rw-r--r--application/config/ConfigPhp.php12
-rw-r--r--application/config/ConfigPlugin.php3
-rw-r--r--application/security/LoginManager.php1
-rw-r--r--composer.json6
-rw-r--r--composer.lock357
-rw-r--r--index.php278
-rw-r--r--phpcs.xml17
-rw-r--r--plugins/archiveorg/archiveorg.php2
-rw-r--r--plugins/demo_plugin/demo_plugin.php12
-rw-r--r--plugins/markdown/markdown.php16
-rw-r--r--plugins/pubsubhubbub/pubsubhubbub.php5
-rw-r--r--plugins/qrcode/qrcode.php3
-rw-r--r--plugins/wallabag/wallabag.php1
-rw-r--r--tests/ApplicationUtilsTest.php6
-rw-r--r--tests/CacheTest.php2
-rw-r--r--tests/HttpUtils/GetIpAdressFromProxyTest.php3
-rw-r--r--tests/LinkDBTest.php6
-rw-r--r--tests/LinkFilterTest.php18
-rw-r--r--tests/LinkUtilsTest.php24
-rw-r--r--tests/RouterTest.php1
-rw-r--r--tests/ThumbnailerTest.php8
-rw-r--r--tests/Updater/DummyUpdater.php8
-rw-r--r--tests/Updater/UpdaterTest.php20
-rw-r--r--tests/Url/CleanupUrlTest.php1
-rw-r--r--tests/Url/GetUrlSchemeTest.php1
-rw-r--r--tests/Url/UnparseUrlTest.php1
-rw-r--r--tests/Url/UrlTest.php6
-rw-r--r--tests/UtilsTest.php9
-rw-r--r--tests/api/ApiUtilsTest.php3
-rw-r--r--tests/api/controllers/history/HistoryTest.php1
-rw-r--r--tests/api/controllers/info/InfoTest.php4
-rw-r--r--tests/api/controllers/links/PostLinkTest.php9
-rw-r--r--tests/api/controllers/links/PutLinkTest.php9
-rw-r--r--tests/api/controllers/tags/PutTagTest.php1
-rw-r--r--tests/languages/de/UtilsDeTest.php2
-rw-r--r--tests/languages/fr/LanguagesFrTest.php1
-rw-r--r--tests/plugins/PluginQrcodeTest.php3
-rw-r--r--tests/security/SessionManagerTest.php1
-rw-r--r--tests/utils/ReferenceLinkDB.php6
-rw-r--r--tests/utils/config/configPhp.php2
63 files changed, 432 insertions, 724 deletions
diff --git a/Makefile b/Makefile
index 56cf09b2..b758d1fd 100644
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,6 @@
2# Makefile for PHP code analysis & testing, documentation and release generation 2# Makefile for PHP code analysis & testing, documentation and release generation
3 3
4BIN = vendor/bin 4BIN = vendor/bin
5PHP_SOURCE = index.php application tests plugins
6PHP_COMMA_SOURCE = index.php,application,tests,plugins
7 5
8all: static_analysis_summary check_permissions test 6all: static_analysis_summary check_permissions test
9 7
@@ -18,84 +16,32 @@ docker_%:
18 cd ~/shaarli && make $* 16 cd ~/shaarli && make $*
19 17
20## 18##
21# Concise status of the project
22# These targets are non-blocking: || exit 0
23##
24
25static_analysis_summary: code_sniffer_source copy_paste mess_detector_summary
26 @echo
27
28##
29# PHP_CodeSniffer 19# PHP_CodeSniffer
30# Detects PHP syntax errors 20# Detects PHP syntax errors
31# Documentation (usage, output formatting): 21# Documentation (usage, output formatting):
32# - http://pear.php.net/manual/en/package.php.php-codesniffer.usage.php 22# - http://pear.php.net/manual/en/package.php.php-codesniffer.usage.php
33# - http://pear.php.net/manual/en/package.php.php-codesniffer.reporting.php 23# - http://pear.php.net/manual/en/package.php.php-codesniffer.reporting.php
34## 24##
25PHPCS := $(BIN)/phpcs
35 26
36code_sniffer: code_sniffer_full 27code_sniffer:
28 @$(PHPCS)
37 29
38### - errors filtered by coding standard: PEAR, PSR1, PSR2, Zend... 30### - errors filtered by coding standard: PEAR, PSR1, PSR2, Zend...
39PHPCS_%: 31PHPCS_%:
40 @$(BIN)/phpcs $(PHP_SOURCE) --report-full --report-width=200 --standard=$* 32 @$(PHPCS) --report-full --report-width=200 --standard=$*
41 33
42### - errors by Git author 34### - errors by Git author
43code_sniffer_blame: 35code_sniffer_blame:
44 @$(BIN)/phpcs $(PHP_SOURCE) --report-gitblame 36 @$(PHPCS) --report-gitblame
45 37
46### - all errors/warnings 38### - all errors/warnings
47code_sniffer_full: 39code_sniffer_full:
48 @$(BIN)/phpcs $(PHP_SOURCE) --report-full --report-width=200 40 @$(PHPCS) --report-full --report-width=200
49 41
50### - errors grouped by kind 42### - errors grouped by kind
51code_sniffer_source: 43code_sniffer_source:
52 @$(BIN)/phpcs $(PHP_SOURCE) --report-source || exit 0 44 @$(PHPCS) --report-source || exit 0
53
54##
55# PHP Copy/Paste Detector
56# Detects code redundancy
57# Documentation: https://github.com/sebastianbergmann/phpcpd
58##
59
60copy_paste:
61 @echo "-----------------------"
62 @echo "PHP COPY/PASTE DETECTOR"
63 @echo "-----------------------"
64 @$(BIN)/phpcpd $(PHP_SOURCE) || exit 0
65 @echo
66
67##
68# PHP Mess Detector
69# Detects PHP syntax errors, sorted by category
70# Rules documentation: http://phpmd.org/rules/index.html
71##
72MESS_DETECTOR_RULES = cleancode,codesize,controversial,design,naming,unusedcode
73
74mess_title:
75 @echo "-----------------"
76 @echo "PHP MESS DETECTOR"
77 @echo "-----------------"
78
79### - all warnings
80mess_detector: mess_title
81 @$(BIN)/phpmd $(PHP_COMMA_SOURCE) text $(MESS_DETECTOR_RULES) | sed 's_.*\/__'
82
83### - all warnings + HTML output contains links to PHPMD's documentation
84mess_detector_html:
85 @$(BIN)/phpmd $(PHP_COMMA_SOURCE) html $(MESS_DETECTOR_RULES) \
86 --reportfile phpmd.html || exit 0
87
88### - warnings grouped by message, sorted by descending frequency order
89mess_detector_grouped: mess_title
90 @$(BIN)/phpmd $(PHP_SOURCE) text $(MESS_DETECTOR_RULES) \
91 | cut -f 2 | sort | uniq -c | sort -nr
92
93### - summary: number of warnings by rule set
94mess_detector_summary: mess_title
95 @for rule in $$(echo $(MESS_DETECTOR_RULES) | tr ',' ' '); do \
96 warnings=$$($(BIN)/phpmd $(PHP_COMMA_SOURCE) text $$rule | wc -l); \
97 printf "$$warnings\t$$rule\n"; \
98 done;
99 45
100## 46##
101# Checks source file & script permissions 47# Checks source file & script permissions
diff --git a/application/ApplicationUtils.php b/application/ApplicationUtils.php
index 911873a0..a3b2dcb1 100644
--- a/application/ApplicationUtils.php
+++ b/application/ApplicationUtils.php
@@ -24,7 +24,7 @@ class ApplicationUtils
24 * 24 *
25 * @return mixed the version code from the repository if available, else 'false' 25 * @return mixed the version code from the repository if available, else 'false'
26 */ 26 */
27 public static function getLatestGitVersionCode($url, $timeout=2) 27 public static function getLatestGitVersionCode($url, $timeout = 2)
28 { 28 {
29 list($headers, $data) = get_http_response($url, $timeout); 29 list($headers, $data) = get_http_response($url, $timeout);
30 30
@@ -86,13 +86,14 @@ class ApplicationUtils
86 * 86 *
87 * @return mixed the new version code if available and greater, else 'false' 87 * @return mixed the new version code if available and greater, else 'false'
88 */ 88 */
89 public static function checkUpdate($currentVersion, 89 public static function checkUpdate(
90 $updateFile, 90 $currentVersion,
91 $checkInterval, 91 $updateFile,
92 $enableCheck, 92 $checkInterval,
93 $isLoggedIn, 93 $enableCheck,
94 $branch='stable') 94 $isLoggedIn,
95 { 95 $branch = 'stable'
96 ) {
96 // Do not check versions for visitors 97 // Do not check versions for visitors
97 // Do not check if the user doesn't want to 98 // Do not check if the user doesn't want to
98 // Do not check with dev version 99 // Do not check with dev version
diff --git a/application/Base64Url.php b/application/Base64Url.php
index 61590e43..54d0fcd5 100644
--- a/application/Base64Url.php
+++ b/application/Base64Url.php
@@ -2,7 +2,6 @@
2 2
3namespace Shaarli; 3namespace Shaarli;
4 4
5
6/** 5/**
7 * URL-safe Base64 operations 6 * URL-safe Base64 operations
8 * 7 *
@@ -17,7 +16,8 @@ class Base64Url
17 * 16 *
18 * @return string Base64Url-encoded data 17 * @return string Base64Url-encoded data
19 */ 18 */
20 public static function encode($data) { 19 public static function encode($data)
20 {
21 return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); 21 return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
22 } 22 }
23 23
@@ -28,7 +28,8 @@ class Base64Url
28 * 28 *
29 * @return string Decoded data 29 * @return string Decoded data
30 */ 30 */
31 public static function decode($data) { 31 public static function decode($data)
32 {
32 return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT)); 33 return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
33 } 34 }
34} 35}
diff --git a/application/FeedBuilder.php b/application/FeedBuilder.php
index ebae18b4..73fafcbe 100644
--- a/application/FeedBuilder.php
+++ b/application/FeedBuilder.php
@@ -163,7 +163,8 @@ class FeedBuilder
163 $upDate = $link['updated']; 163 $upDate = $link['updated'];
164 $link['up_iso_date'] = $this->getIsoDate($upDate, DateTime::ATOM); 164 $link['up_iso_date'] = $this->getIsoDate($upDate, DateTime::ATOM);
165 } else { 165 } else {
166 $link['up_iso_date'] = $this->getIsoDate($pubDate, DateTime::ATOM);; 166 $link['up_iso_date'] = $this->getIsoDate($pubDate, DateTime::ATOM);
167 ;
167 } 168 }
168 169
169 // Save the more recent item. 170 // Save the more recent item.
@@ -261,7 +262,6 @@ class FeedBuilder
261 } 262 }
262 if ($this->feedType == self::$FEED_RSS) { 263 if ($this->feedType == self::$FEED_RSS) {
263 return $date->format(DateTime::RSS); 264 return $date->format(DateTime::RSS);
264
265 } 265 }
266 return $date->format(DateTime::ATOM); 266 return $date->format(DateTime::ATOM);
267 } 267 }
diff --git a/application/HttpUtils.php b/application/HttpUtils.php
index e9282506..9c438160 100644
--- a/application/HttpUtils.php
+++ b/application/HttpUtils.php
@@ -7,7 +7,8 @@
7 * @param int $timeout network timeout (in seconds) 7 * @param int $timeout network timeout (in seconds)
8 * @param int $maxBytes maximum downloaded bytes (default: 4 MiB) 8 * @param int $maxBytes maximum downloaded bytes (default: 4 MiB)
9 * @param callable|string $curlWriteFunction Optional callback called during the download (cURL CURLOPT_WRITEFUNCTION). 9 * @param callable|string $curlWriteFunction Optional callback called during the download (cURL CURLOPT_WRITEFUNCTION).
10 * Can be used to add download conditions on the headers (response code, content type, etc.). 10 * Can be used to add download conditions on the
11 * headers (response code, content type, etc.).
11 * 12 *
12 * @return array HTTP response headers, downloaded content 13 * @return array HTTP response headers, downloaded content
13 * 14 *
@@ -64,29 +65,30 @@ function get_http_response($url, $timeout = 30, $maxBytes = 4194304, $curlWriteF
64 } 65 }
65 66
66 // General cURL settings 67 // General cURL settings
67 curl_setopt($ch, CURLOPT_AUTOREFERER, true); 68 curl_setopt($ch, CURLOPT_AUTOREFERER, true);
68 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 69 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
69 curl_setopt($ch, CURLOPT_HEADER, true); 70 curl_setopt($ch, CURLOPT_HEADER, true);
70 curl_setopt( 71 curl_setopt(
71 $ch, 72 $ch,
72 CURLOPT_HTTPHEADER, 73 CURLOPT_HTTPHEADER,
73 array('Accept-Language: ' . $acceptLanguage) 74 array('Accept-Language: ' . $acceptLanguage)
74 ); 75 );
75 curl_setopt($ch, CURLOPT_MAXREDIRS, $maxRedirs); 76 curl_setopt($ch, CURLOPT_MAXREDIRS, $maxRedirs);
76 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 77 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
77 curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); 78 curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
78 curl_setopt($ch, CURLOPT_USERAGENT, $userAgent); 79 curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
79 80
80 if (is_callable($curlWriteFunction)) { 81 if (is_callable($curlWriteFunction)) {
81 curl_setopt($ch, CURLOPT_WRITEFUNCTION, $curlWriteFunction); 82 curl_setopt($ch, CURLOPT_WRITEFUNCTION, $curlWriteFunction);
82 } 83 }
83 84
84 // Max download size management 85 // Max download size management
85 curl_setopt($ch, CURLOPT_BUFFERSIZE, 1024*16); 86 curl_setopt($ch, CURLOPT_BUFFERSIZE, 1024*16);
86 curl_setopt($ch, CURLOPT_NOPROGRESS, false); 87 curl_setopt($ch, CURLOPT_NOPROGRESS, false);
87 curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 88 curl_setopt(
88 function($arg0, $arg1, $arg2, $arg3, $arg4 = 0) use ($maxBytes) 89 $ch,
89 { 90 CURLOPT_PROGRESSFUNCTION,
91 function ($arg0, $arg1, $arg2, $arg3, $arg4 = 0) use ($maxBytes) {
90 if (version_compare(phpversion(), '5.5', '<')) { 92 if (version_compare(phpversion(), '5.5', '<')) {
91 // PHP version lower than 5.5 93 // PHP version lower than 5.5
92 // Callback has 4 arguments 94 // Callback has 4 arguments
@@ -232,7 +234,6 @@ function get_redirected_headers($url, $redirectionLimit = 3)
232 && !empty($headers) 234 && !empty($headers)
233 && (strpos($headers[0], '301') !== false || strpos($headers[0], '302') !== false) 235 && (strpos($headers[0], '301') !== false || strpos($headers[0], '302') !== false)
234 && !empty($headers['Location'])) { 236 && !empty($headers['Location'])) {
235
236 $redirection = is_array($headers['Location']) ? end($headers['Location']) : $headers['Location']; 237 $redirection = is_array($headers['Location']) ? end($headers['Location']) : $headers['Location'];
237 if ($redirection != $url) { 238 if ($redirection != $url) {
238 $redirection = getAbsoluteUrl($url, $redirection); 239 $redirection = getAbsoluteUrl($url, $redirection);
diff --git a/application/Languages.php b/application/Languages.php
index 4fa32426..b9c5d0e8 100644
--- a/application/Languages.php
+++ b/application/Languages.php
@@ -92,7 +92,7 @@ class Languages
92 /** 92 /**
93 * Initialize the translator using php gettext extension (gettext dependency act as a wrapper). 93 * Initialize the translator using php gettext extension (gettext dependency act as a wrapper).
94 */ 94 */
95 protected function initGettextTranslator () 95 protected function initGettextTranslator()
96 { 96 {
97 $this->translator = new GettextTranslator(); 97 $this->translator = new GettextTranslator();
98 $this->translator->setLanguage($this->language); 98 $this->translator->setLanguage($this->language);
@@ -125,7 +125,8 @@ class Languages
125 $translations = $translations->addFromPoFile('inc/languages/'. $this->language .'/LC_MESSAGES/shaarli.po'); 125 $translations = $translations->addFromPoFile('inc/languages/'. $this->language .'/LC_MESSAGES/shaarli.po');
126 $translations->setDomain('shaarli'); 126 $translations->setDomain('shaarli');
127 $this->translator->loadTranslations($translations); 127 $this->translator->loadTranslations($translations);
128 } catch (\InvalidArgumentException $e) {} 128 } catch (\InvalidArgumentException $e) {
129 }
129 130
130 // Default extension translation from the current theme 131 // Default extension translation from the current theme
131 $theme = $this->conf->get('theme'); 132 $theme = $this->conf->get('theme');
@@ -137,7 +138,8 @@ class Languages
137 ); 138 );
138 $translations->setDomain($theme); 139 $translations->setDomain($theme);
139 $this->translator->loadTranslations($translations); 140 $this->translator->loadTranslations($translations);
140 } catch (\InvalidArgumentException $e) {} 141 } catch (\InvalidArgumentException $e) {
142 }
141 } 143 }
142 144
143 // Extension translations (plugins, themes, etc.). 145 // Extension translations (plugins, themes, etc.).
@@ -147,10 +149,13 @@ class Languages
147 } 149 }
148 150
149 try { 151 try {
150 $extension = Translations::fromPoFile($translationPath . $this->language .'/LC_MESSAGES/'. $domain .'.po'); 152 $extension = Translations::fromPoFile(
153 $translationPath . $this->language .'/LC_MESSAGES/'. $domain .'.po'
154 );
151 $extension->setDomain($domain); 155 $extension->setDomain($domain);
152 $this->translator->loadTranslations($extension); 156 $this->translator->loadTranslations($extension);
153 } catch (\InvalidArgumentException $e) {} 157 } catch (\InvalidArgumentException $e) {
158 }
154 } 159 }
155 } 160 }
156 161
diff --git a/application/LinkDB.php b/application/LinkDB.php
index cdd68cfb..4bbc2950 100644
--- a/application/LinkDB.php
+++ b/application/LinkDB.php
@@ -107,8 +107,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess
107 $hidePublicLinks, 107 $hidePublicLinks,
108 $redirector = '', 108 $redirector = '',
109 $redirectorEncode = true 109 $redirectorEncode = true
110 ) 110 ) {
111 {
112 $this->datastore = $datastore; 111 $this->datastore = $datastore;
113 $this->loggedIn = $isLoggedIn; 112 $this->loggedIn = $isLoggedIn;
114 $this->hidePublicLinks = $hidePublicLinks; 113 $this->hidePublicLinks = $hidePublicLinks;
@@ -250,11 +249,14 @@ class LinkDB implements Iterator, Countable, ArrayAccess
250 'id' => 1, 249 'id' => 1,
251 'title'=> t('The personal, minimalist, super-fast, database free, bookmarking service'), 250 'title'=> t('The personal, minimalist, super-fast, database free, bookmarking service'),
252 'url'=>'https://shaarli.readthedocs.io', 251 'url'=>'https://shaarli.readthedocs.io',
253 'description'=>t('Welcome to Shaarli! This is your first public bookmark. To edit or delete me, you must first login. 252 'description'=>t(
253 'Welcome to Shaarli! This is your first public bookmark. '
254 .'To edit or delete me, you must first login.
254 255
255To learn how to use Shaarli, consult the link "Documentation" at the bottom of this page. 256To learn how to use Shaarli, consult the link "Documentation" at the bottom of this page.
256 257
257You use the community supported version of the original Shaarli project, by Sebastien Sauvage.'), 258You use the community supported version of the original Shaarli project, by Sebastien Sauvage.'
259 ),
258 'private'=>0, 260 'private'=>0,
259 'created'=> new DateTime(), 261 'created'=> new DateTime(),
260 'tags'=>'opensource software' 262 'tags'=>'opensource software'
@@ -317,8 +319,7 @@ You use the community supported version of the original Shaarli project, by Seba
317 } else { 319 } else {
318 $link['real_url'] .= $link['url']; 320 $link['real_url'] .= $link['url'];
319 } 321 }
320 } 322 } else {
321 else {
322 $link['real_url'] = $link['url']; 323 $link['real_url'] = $link['url'];
323 } 324 }
324 325
@@ -403,7 +404,8 @@ You use the community supported version of the original Shaarli project, by Seba
403 * 404 *
404 * @return array list of shaare found. 405 * @return array list of shaare found.
405 */ 406 */
406 public function filterDay($request) { 407 public function filterDay($request)
408 {
407 $linkFilter = new LinkFilter($this->links); 409 $linkFilter = new LinkFilter($this->links);
408 return $linkFilter->filter(LinkFilter::$FILTER_DAY, $request); 410 return $linkFilter->filter(LinkFilter::$FILTER_DAY, $request);
409 } 411 }
@@ -420,8 +422,12 @@ You use the community supported version of the original Shaarli project, by Seba
420 * 422 *
421 * @return array filtered links, all links if no suitable filter was provided. 423 * @return array filtered links, all links if no suitable filter was provided.
422 */ 424 */
423 public function filterSearch($filterRequest = array(), $casesensitive = false, $visibility = 'all', $untaggedonly = false) 425 public function filterSearch(
424 { 426 $filterRequest = array(),
427 $casesensitive = false,
428 $visibility = 'all',
429 $untaggedonly = false
430 ) {
425 // Filter link database according to parameters. 431 // Filter link database according to parameters.
426 $searchtags = isset($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : ''; 432 $searchtags = isset($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : '';
427 $searchterm = isset($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : ''; 433 $searchterm = isset($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : '';
@@ -492,8 +498,7 @@ You use the community supported version of the original Shaarli project, by Seba
492 $delete = empty($to); 498 $delete = empty($to);
493 // True for case-sensitive tag search. 499 // True for case-sensitive tag search.
494 $linksToAlter = $this->filterSearch(['searchtags' => $from], true); 500 $linksToAlter = $this->filterSearch(['searchtags' => $from], true);
495 foreach($linksToAlter as $key => &$value) 501 foreach ($linksToAlter as $key => &$value) {
496 {
497 $tags = preg_split('/\s+/', trim($value['tags'])); 502 $tags = preg_split('/\s+/', trim($value['tags']));
498 if (($pos = array_search($from, $tags)) !== false) { 503 if (($pos = array_search($from, $tags)) !== false) {
499 if ($delete) { 504 if ($delete) {
@@ -536,7 +541,7 @@ You use the community supported version of the original Shaarli project, by Seba
536 { 541 {
537 $order = $order === 'ASC' ? -1 : 1; 542 $order = $order === 'ASC' ? -1 : 1;
538 // Reorder array by dates. 543 // Reorder array by dates.
539 usort($this->links, function($a, $b) use ($order) { 544 usort($this->links, function ($a, $b) use ($order) {
540 if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) { 545 if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) {
541 return $a['sticky'] ? -1 : 1; 546 return $a['sticky'] ? -1 : 1;
542 } 547 }
diff --git a/application/LinkFilter.php b/application/LinkFilter.php
index e52239b8..8f147974 100644
--- a/application/LinkFilter.php
+++ b/application/LinkFilter.php
@@ -62,7 +62,7 @@ class LinkFilter
62 $visibility = 'all'; 62 $visibility = 'all';
63 } 63 }
64 64
65 switch($type) { 65 switch ($type) {
66 case self::$FILTER_HASH: 66 case self::$FILTER_HASH:
67 return $this->filterSmallHash($request); 67 return $this->filterSmallHash($request);
68 case self::$FILTER_TAG | self::$FILTER_TEXT: // == "vuotext" 68 case self::$FILTER_TAG | self::$FILTER_TEXT: // == "vuotext"
@@ -205,7 +205,6 @@ class LinkFilter
205 205
206 // Iterate over every stored link. 206 // Iterate over every stored link.
207 foreach ($this->links as $id => $link) { 207 foreach ($this->links as $id => $link) {
208
209 // ignore non private links when 'privatonly' is on. 208 // ignore non private links when 'privatonly' is on.
210 if ($visibility !== 'all') { 209 if ($visibility !== 'all') {
211 if (! $link['private'] && $visibility === 'private') { 210 if (! $link['private'] && $visibility === 'private') {
@@ -257,11 +256,11 @@ class LinkFilter
257 private static function tag2regex($tag) 256 private static function tag2regex($tag)
258 { 257 {
259 $len = strlen($tag); 258 $len = strlen($tag);
260 if(!$len || $tag === "-" || $tag === "*"){ 259 if (!$len || $tag === "-" || $tag === "*") {
261 // nothing to search, return empty regex 260 // nothing to search, return empty regex
262 return ''; 261 return '';
263 } 262 }
264 if($tag[0] === "-") { 263 if ($tag[0] === "-") {
265 // query is negated 264 // query is negated
266 $i = 1; // use offset to start after '-' character 265 $i = 1; // use offset to start after '-' character
267 $regex = '(?!'; // create negative lookahead 266 $regex = '(?!'; // create negative lookahead
@@ -271,14 +270,14 @@ class LinkFilter
271 } 270 }
272 $regex .= '.*(?:^| )'; // before tag may only be a space or the beginning 271 $regex .= '.*(?:^| )'; // before tag may only be a space or the beginning
273 // iterate over string, separating it into placeholder and content 272 // iterate over string, separating it into placeholder and content
274 for(; $i < $len; $i++){ 273 for (; $i < $len; $i++) {
275 if($tag[$i] === '*'){ 274 if ($tag[$i] === '*') {
276 // placeholder found 275 // placeholder found
277 $regex .= '[^ ]*?'; 276 $regex .= '[^ ]*?';
278 } else { 277 } else {
279 // regular characters 278 // regular characters
280 $offset = strpos($tag, '*', $i); 279 $offset = strpos($tag, '*', $i);
281 if($offset === false){ 280 if ($offset === false) {
282 // no placeholder found, set offset to end of string 281 // no placeholder found, set offset to end of string
283 $offset = $len; 282 $offset = $len;
284 } 283 }
@@ -310,19 +309,19 @@ class LinkFilter
310 { 309 {
311 // get single tags (we may get passed an array, even though the docs say different) 310 // get single tags (we may get passed an array, even though the docs say different)
312 $inputTags = $tags; 311 $inputTags = $tags;
313 if(!is_array($tags)) { 312 if (!is_array($tags)) {
314 // we got an input string, split tags 313 // we got an input string, split tags
315 $inputTags = preg_split('/(?:\s+)|,/', $inputTags, -1, PREG_SPLIT_NO_EMPTY); 314 $inputTags = preg_split('/(?:\s+)|,/', $inputTags, -1, PREG_SPLIT_NO_EMPTY);
316 } 315 }
317 316
318 if(!count($inputTags)){ 317 if (!count($inputTags)) {
319 // no input tags 318 // no input tags
320 return $this->noFilter($visibility); 319 return $this->noFilter($visibility);
321 } 320 }
322 321
323 // build regex from all tags 322 // build regex from all tags
324 $re = '/^' . implode(array_map("self::tag2regex", $inputTags)) . '.*$/'; 323 $re = '/^' . implode(array_map("self::tag2regex", $inputTags)) . '.*$/';
325 if(!$casesensitive) { 324 if (!$casesensitive) {
326 // make regex case insensitive 325 // make regex case insensitive
327 $re .= 'i'; 326 $re .= 'i';
328 } 327 }
@@ -342,7 +341,7 @@ class LinkFilter
342 } 341 }
343 } 342 }
344 $search = $link['tags']; // build search string, start with tags of current link 343 $search = $link['tags']; // build search string, start with tags of current link
345 if(strlen(trim($link['description'])) && strpos($link['description'], '#') !== false){ 344 if (strlen(trim($link['description'])) && strpos($link['description'], '#') !== false) {
346 // description given and at least one possible tag found 345 // description given and at least one possible tag found
347 $descTags = array(); 346 $descTags = array();
348 // find all tags in the form of #tag in the description 347 // find all tags in the form of #tag in the description
@@ -351,13 +350,13 @@ class LinkFilter
351 $link['description'], 350 $link['description'],
352 $descTags 351 $descTags
353 ); 352 );
354 if(count($descTags[1])){ 353 if (count($descTags[1])) {
355 // there were some tags in the description, add them to the search string 354 // there were some tags in the description, add them to the search string
356 $search .= ' ' . implode(' ', $descTags[1]); 355 $search .= ' ' . implode(' ', $descTags[1]);
357 } 356 }
358 }; 357 };
359 // match regular expression with search string 358 // match regular expression with search string
360 if(!preg_match($re, $search)){ 359 if (!preg_match($re, $search)) {
361 // this entry does _not_ match our regex 360 // this entry does _not_ match our regex
362 continue; 361 continue;
363 } 362 }
diff --git a/application/LinkUtils.php b/application/LinkUtils.php
index 4df5c0ca..d56e019f 100644
--- a/application/LinkUtils.php
+++ b/application/LinkUtils.php
@@ -23,7 +23,7 @@ function get_curl_download_callback(&$charset, &$title, $curlGetInfo = 'curl_get
23 * 23 *
24 * @return int|bool length of $data or false if we need to stop the download 24 * @return int|bool length of $data or false if we need to stop the download
25 */ 25 */
26 return function(&$ch, $data) use ($curlGetInfo, &$charset, &$title, &$isRedirected) { 26 return function (&$ch, $data) use ($curlGetInfo, &$charset, &$title, &$isRedirected) {
27 $responseCode = $curlGetInfo($ch, CURLINFO_RESPONSE_CODE); 27 $responseCode = $curlGetInfo($ch, CURLINFO_RESPONSE_CODE);
28 if (!empty($responseCode) && in_array($responseCode, [301, 302])) { 28 if (!empty($responseCode) && in_array($responseCode, [301, 302])) {
29 $isRedirected = true; 29 $isRedirected = true;
@@ -201,7 +201,8 @@ function space2nbsp($text)
201 201
202 * @return string formatted description. 202 * @return string formatted description.
203 */ 203 */
204function format_description($description, $redirector = '', $urlEncode = true, $indexUrl = '') { 204function format_description($description, $redirector = '', $urlEncode = true, $indexUrl = '')
205{
205 return nl2br(space2nbsp(hashtag_autolink(text2clickable($description, $redirector, $urlEncode), $indexUrl))); 206 return nl2br(space2nbsp(hashtag_autolink(text2clickable($description, $redirector, $urlEncode), $indexUrl)));
206} 207}
207 208
diff --git a/application/NetscapeBookmarkUtils.php b/application/NetscapeBookmarkUtils.php
index b4d16d00..84dd2b20 100644
--- a/application/NetscapeBookmarkUtils.php
+++ b/application/NetscapeBookmarkUtils.php
@@ -72,18 +72,20 @@ class NetscapeBookmarkUtils
72 private static function importStatus( 72 private static function importStatus(
73 $filename, 73 $filename,
74 $filesize, 74 $filesize,
75 $importCount=0, 75 $importCount = 0,
76 $overwriteCount=0, 76 $overwriteCount = 0,
77 $skipCount=0, 77 $skipCount = 0,
78 $duration=0 78 $duration = 0
79 ) 79 ) {
80 {
81 $status = sprintf(t('File %s (%d bytes) '), $filename, $filesize); 80 $status = sprintf(t('File %s (%d bytes) '), $filename, $filesize);
82 if ($importCount == 0 && $overwriteCount == 0 && $skipCount == 0) { 81 if ($importCount == 0 && $overwriteCount == 0 && $skipCount == 0) {
83 $status .= t('has an unknown file format. Nothing was imported.'); 82 $status .= t('has an unknown file format. Nothing was imported.');
84 } else { 83 } else {
85 $status .= vsprintf( 84 $status .= vsprintf(
86 t('was successfully processed in %d seconds: %d links imported, %d links overwritten, %d links skipped.'), 85 t(
86 'was successfully processed in %d seconds: '
87 .'%d links imported, %d links overwritten, %d links skipped.'
88 ),
87 [$duration, $importCount, $overwriteCount, $skipCount] 89 [$duration, $importCount, $overwriteCount, $skipCount]
88 ); 90 );
89 } 91 }
diff --git a/application/PageBuilder.php b/application/PageBuilder.php
index 0efd24c3..2ca95832 100644
--- a/application/PageBuilder.php
+++ b/application/PageBuilder.php
@@ -78,7 +78,6 @@ class PageBuilder
78 ); 78 );
79 $this->tpl->assign('newVersion', escape($version)); 79 $this->tpl->assign('newVersion', escape($version));
80 $this->tpl->assign('versionError', ''); 80 $this->tpl->assign('versionError', '');
81
82 } catch (Exception $exc) { 81 } catch (Exception $exc) {
83 logm($this->conf->get('resource.log'), $_SERVER['REMOTE_ADDR'], $exc->getMessage()); 82 logm($this->conf->get('resource.log'), $_SERVER['REMOTE_ADDR'], $exc->getMessage());
84 $this->tpl->assign('newVersion', ''); 83 $this->tpl->assign('newVersion', '');
@@ -163,7 +162,7 @@ class PageBuilder
163 $this->initialize(); 162 $this->initialize();
164 } 163 }
165 164
166 if (empty($data) || !is_array($data)){ 165 if (empty($data) || !is_array($data)) {
167 return false; 166 return false;
168 } 167 }
169 168
diff --git a/application/PluginManager.php b/application/PluginManager.php
index cf603845..1ed4db4b 100644
--- a/application/PluginManager.php
+++ b/application/PluginManager.php
@@ -75,8 +75,7 @@ class PluginManager
75 75
76 try { 76 try {
77 $this->loadPlugin($dirs[$index], $plugin); 77 $this->loadPlugin($dirs[$index], $plugin);
78 } 78 } catch (PluginFileNotFoundException $e) {
79 catch (PluginFileNotFoundException $e) {
80 error_log($e->getMessage()); 79 error_log($e->getMessage());
81 } 80 }
82 } 81 }
diff --git a/application/Thumbnailer.php b/application/Thumbnailer.php
index 7d0d9c33..37ed97a1 100644
--- a/application/Thumbnailer.php
+++ b/application/Thumbnailer.php
@@ -58,7 +58,10 @@ class Thumbnailer
58 $this->conf->set('thumbnails.enabled', false); 58 $this->conf->set('thumbnails.enabled', false);
59 $this->conf->write(true); 59 $this->conf->write(true);
60 // TODO: create a proper error handling system able to catch exceptions... 60 // TODO: create a proper error handling system able to catch exceptions...
61 die(t('php-gd extension must be loaded to use thumbnails. Thumbnails are now disabled. Please reload the page.')); 61 die(t(
62 'php-gd extension must be loaded to use thumbnails. '
63 .'Thumbnails are now disabled. Please reload the page.'
64 ));
62 } 65 }
63 66
64 $this->wt = new WebThumbnailer(); 67 $this->wt = new WebThumbnailer();
diff --git a/application/Updater.php b/application/Updater.php
index 5dde47cb..6b94c5e3 100644
--- a/application/Updater.php
+++ b/application/Updater.php
@@ -183,7 +183,7 @@ class Updater
183 } 183 }
184 } 184 }
185 185
186 try{ 186 try {
187 $this->conf->write($this->isLoggedIn); 187 $this->conf->write($this->isLoggedIn);
188 return true; 188 return true;
189 } catch (IOException $e) { 189 } catch (IOException $e) {
diff --git a/application/Url.php b/application/Url.php
index 6b9870f0..3b7f19c2 100644
--- a/application/Url.php
+++ b/application/Url.php
@@ -34,8 +34,8 @@ function unparse_url($parsedUrl)
34 */ 34 */
35function cleanup_url($url) 35function cleanup_url($url)
36{ 36{
37 $obj_url = new Url($url); 37 $obj_url = new Url($url);
38 return $obj_url->cleanup(); 38 return $obj_url->cleanup();
39} 39}
40 40
41/** 41/**
@@ -47,8 +47,8 @@ function cleanup_url($url)
47 */ 47 */
48function get_url_scheme($url) 48function get_url_scheme($url)
49{ 49{
50 $obj_url = new Url($url); 50 $obj_url = new Url($url);
51 return $obj_url->getScheme(); 51 return $obj_url->getScheme();
52} 52}
53 53
54/** 54/**
@@ -217,7 +217,7 @@ class Url
217 } 217 }
218 218
219 $this->parts['query'] = implode('&', $queryParams); 219 $this->parts['query'] = implode('&', $queryParams);
220 } 220 }
221 221
222 /** 222 /**
223 * Removes undesired fragments 223 * Removes undesired fragments
@@ -269,7 +269,8 @@ class Url
269 * 269 *
270 * @return string the URL scheme or false if none is provided. 270 * @return string the URL scheme or false if none is provided.
271 */ 271 */
272 public function getScheme() { 272 public function getScheme()
273 {
273 if (!isset($this->parts['scheme'])) { 274 if (!isset($this->parts['scheme'])) {
274 return false; 275 return false;
275 } 276 }
@@ -281,7 +282,8 @@ class Url
281 * 282 *
282 * @return string the URL host or false if none is provided. 283 * @return string the URL host or false if none is provided.
283 */ 284 */
284 public function getHost() { 285 public function getHost()
286 {
285 if (empty($this->parts['host'])) { 287 if (empty($this->parts['host'])) {
286 return false; 288 return false;
287 } 289 }
@@ -293,7 +295,8 @@ class Url
293 * 295 *
294 * @return true is HTTP, false otherwise. 296 * @return true is HTTP, false otherwise.
295 */ 297 */
296 public function isHttp() { 298 public function isHttp()
299 {
297 return strpos(strtolower($this->parts['scheme']), 'http') !== false; 300 return strpos(strtolower($this->parts['scheme']), 'http') !== false;
298 } 301 }
299} 302}
diff --git a/application/Utils.php b/application/Utils.php
index 97b12fcf..925e1a22 100644
--- a/application/Utils.php
+++ b/application/Utils.php
@@ -97,7 +97,7 @@ function escape($input)
97 97
98 if (is_array($input)) { 98 if (is_array($input)) {
99 $out = array(); 99 $out = array();
100 foreach($input as $key => $value) { 100 foreach ($input as $key => $value) {
101 $out[$key] = escape($value); 101 $out[$key] = escape($value);
102 } 102 }
103 return $out; 103 return $out;
@@ -355,10 +355,13 @@ function return_bytes($val)
355 $val = trim($val); 355 $val = trim($val);
356 $last = strtolower($val[strlen($val)-1]); 356 $last = strtolower($val[strlen($val)-1]);
357 $val = intval(substr($val, 0, -1)); 357 $val = intval(substr($val, 0, -1));
358 switch($last) { 358 switch ($last) {
359 case 'g': $val *= 1024; 359 case 'g':
360 case 'm': $val *= 1024; 360 $val *= 1024;
361 case 'k': $val *= 1024; 361 case 'm':
362 $val *= 1024;
363 case 'k':
364 $val *= 1024;
362 } 365 }
363 return $val; 366 return $val;
364} 367}
@@ -452,6 +455,7 @@ function alphabetical_sort(&$data, $reverse = false, $byKeys = false)
452 * 455 *
453 * @return string Text translated. 456 * @return string Text translated.
454 */ 457 */
455function t($text, $nText = '', $nb = 1, $domain = 'shaarli') { 458function t($text, $nText = '', $nb = 1, $domain = 'shaarli')
459{
456 return dn__($domain, $text, $nText, $nb); 460 return dn__($domain, $text, $nText, $nb);
457} 461}
diff --git a/application/api/ApiMiddleware.php b/application/api/ApiMiddleware.php
index ff209393..66eac133 100644
--- a/application/api/ApiMiddleware.php
+++ b/application/api/ApiMiddleware.php
@@ -65,7 +65,7 @@ class ApiMiddleware
65 try { 65 try {
66 $this->checkRequest($request); 66 $this->checkRequest($request);
67 $response = $next($request, $response); 67 $response = $next($request, $response);
68 } catch(ApiException $e) { 68 } catch (ApiException $e) {
69 $e->setResponse($response); 69 $e->setResponse($response);
70 $e->setDebug($this->conf->get('dev.debug', false)); 70 $e->setDebug($this->conf->get('dev.debug', false));
71 $response = $e->getApiResponse(); 71 $response = $e->getApiResponse();
@@ -98,7 +98,8 @@ class ApiMiddleware
98 * 98 *
99 * @throws ApiAuthorizationException The token couldn't be validated. 99 * @throws ApiAuthorizationException The token couldn't be validated.
100 */ 100 */
101 protected function checkToken($request) { 101 protected function checkToken($request)
102 {
102 if (! $request->hasHeader('Authorization')) { 103 if (! $request->hasHeader('Authorization')) {
103 throw new ApiAuthorizationException('JWT token not provided'); 104 throw new ApiAuthorizationException('JWT token not provided');
104 } 105 }
diff --git a/application/api/controllers/ApiController.php b/application/api/controllers/ApiController.php
index 3be85b98..9edefcf6 100644
--- a/application/api/controllers/ApiController.php
+++ b/application/api/controllers/ApiController.php
@@ -41,7 +41,7 @@ abstract class ApiController
41 41
42 /** 42 /**
43 * ApiController constructor. 43 * ApiController constructor.
44 * 44 *
45 * Note: enabling debug mode displays JSON with readable formatting. 45 * Note: enabling debug mode displays JSON with readable formatting.
46 * 46 *
47 * @param Container $ci Slim container. 47 * @param Container $ci Slim container.
diff --git a/application/api/controllers/History.php b/application/api/controllers/History.php
index 5cc453bf..4582e8b2 100644
--- a/application/api/controllers/History.php
+++ b/application/api/controllers/History.php
@@ -35,8 +35,7 @@ class History extends ApiController
35 $offset = $request->getParam('offset'); 35 $offset = $request->getParam('offset');
36 if (empty($offset)) { 36 if (empty($offset)) {
37 $offset = 0; 37 $offset = 0;
38 } 38 } elseif (ctype_digit($offset)) {
39 elseif (ctype_digit($offset)) {
40 $offset = (int) $offset; 39 $offset = (int) $offset;
41 } else { 40 } else {
42 throw new ApiBadParametersException('Invalid offset'); 41 throw new ApiBadParametersException('Invalid offset');
diff --git a/application/api/controllers/Info.php b/application/api/controllers/Info.php
index 25433f72..f37dcae5 100644
--- a/application/api/controllers/Info.php
+++ b/application/api/controllers/Info.php
@@ -7,7 +7,7 @@ use Slim\Http\Response;
7 7
8/** 8/**
9 * Class Info 9 * Class Info
10 * 10 *
11 * REST API Controller: /info 11 * REST API Controller: /info
12 * 12 *
13 * @package Api\Controllers 13 * @package Api\Controllers
@@ -17,7 +17,7 @@ class Info extends ApiController
17{ 17{
18 /** 18 /**
19 * Service providing various information about Shaarli instance. 19 * Service providing various information about Shaarli instance.
20 * 20 *
21 * @param Request $request Slim request. 21 * @param Request $request Slim request.
22 * @param Response $response Slim response. 22 * @param Response $response Slim response.
23 * 23 *
diff --git a/application/api/exceptions/ApiException.php b/application/api/exceptions/ApiException.php
index c8490e0c..d6b66323 100644
--- a/application/api/exceptions/ApiException.php
+++ b/application/api/exceptions/ApiException.php
@@ -10,7 +10,8 @@ use Slim\Http\Response;
10 * Parent Exception related to the API, able to generate a valid Response (ResponseInterface). 10 * Parent Exception related to the API, able to generate a valid Response (ResponseInterface).
11 * Also can include various information in debug mode. 11 * Also can include various information in debug mode.
12 */ 12 */
13abstract class ApiException extends \Exception { 13abstract class ApiException extends \Exception
14{
14 15
15 /** 16 /**
16 * @var Response instance from Slim. 17 * @var Response instance from Slim.
@@ -27,7 +28,7 @@ abstract class ApiException extends \Exception {
27 * 28 *
28 * @return Response Final response to give. 29 * @return Response Final response to give.
29 */ 30 */
30 public abstract function getApiResponse(); 31 abstract public function getApiResponse();
31 32
32 /** 33 /**
33 * Creates ApiResponse body. 34 * Creates ApiResponse body.
@@ -36,7 +37,8 @@ abstract class ApiException extends \Exception {
36 * 37 *
37 * @return array|string response body 38 * @return array|string response body
38 */ 39 */
39 protected function getApiResponseBody() { 40 protected function getApiResponseBody()
41 {
40 if ($this->debug !== true) { 42 if ($this->debug !== true) {
41 return $this->getMessage(); 43 return $this->getMessage();
42 } 44 }
diff --git a/application/api/exceptions/ApiLinkNotFoundException.php b/application/api/exceptions/ApiLinkNotFoundException.php
index de7e14f5..c727f4f0 100644
--- a/application/api/exceptions/ApiLinkNotFoundException.php
+++ b/application/api/exceptions/ApiLinkNotFoundException.php
@@ -2,7 +2,6 @@
2 2
3namespace Shaarli\Api\Exceptions; 3namespace Shaarli\Api\Exceptions;
4 4
5
6use Slim\Http\Response; 5use Slim\Http\Response;
7 6
8/** 7/**
diff --git a/application/api/exceptions/ApiTagNotFoundException.php b/application/api/exceptions/ApiTagNotFoundException.php
index eed5afa5..eee152fe 100644
--- a/application/api/exceptions/ApiTagNotFoundException.php
+++ b/application/api/exceptions/ApiTagNotFoundException.php
@@ -2,7 +2,6 @@
2 2
3namespace Shaarli\Api\Exceptions; 3namespace Shaarli\Api\Exceptions;
4 4
5
6use Slim\Http\Response; 5use Slim\Http\Response;
7 6
8/** 7/**
diff --git a/application/config/ConfigPhp.php b/application/config/ConfigPhp.php
index 8add8bcd..9625fe1a 100644
--- a/application/config/ConfigPhp.php
+++ b/application/config/ConfigPhp.php
@@ -104,12 +104,20 @@ class ConfigPhp implements ConfigIO
104 104
105 // Store all $conf['config'] 105 // Store all $conf['config']
106 foreach ($conf['config'] as $key => $value) { 106 foreach ($conf['config'] as $key => $value) {
107 $configStr .= '$GLOBALS[\'config\'][\''. $key .'\'] = '.var_export($conf['config'][$key], true).';'. PHP_EOL; 107 $configStr .= '$GLOBALS[\'config\'][\''
108 . $key
109 .'\'] = '
110 .var_export($conf['config'][$key], true).';'
111 . PHP_EOL;
108 } 112 }
109 113
110 if (isset($conf['plugins'])) { 114 if (isset($conf['plugins'])) {
111 foreach ($conf['plugins'] as $key => $value) { 115 foreach ($conf['plugins'] as $key => $value) {
112 $configStr .= '$GLOBALS[\'plugins\'][\''. $key .'\'] = '.var_export($conf['plugins'][$key], true).';'. PHP_EOL; 116 $configStr .= '$GLOBALS[\'plugins\'][\''
117 . $key
118 .'\'] = '
119 .var_export($conf['plugins'][$key], true).';'
120 . PHP_EOL;
113 } 121 }
114 } 122 }
115 123
diff --git a/application/config/ConfigPlugin.php b/application/config/ConfigPlugin.php
index b3d9752b..dbb24937 100644
--- a/application/config/ConfigPlugin.php
+++ b/application/config/ConfigPlugin.php
@@ -34,8 +34,7 @@ function save_plugin_config($formData)
34 // If there is no order, it means a disabled plugin has been enabled. 34 // If there is no order, it means a disabled plugin has been enabled.
35 if (isset($formData['order_' . $key])) { 35 if (isset($formData['order_' . $key])) {
36 $plugins[(int) $formData['order_' . $key]] = $key; 36 $plugins[(int) $formData['order_' . $key]] = $key;
37 } 37 } else {
38 else {
39 $newEnabledPlugins[] = $key; 38 $newEnabledPlugins[] = $key;
40 } 39 }
41 } 40 }
diff --git a/application/security/LoginManager.php b/application/security/LoginManager.php
index d6784d6d..0f315483 100644
--- a/application/security/LoginManager.php
+++ b/application/security/LoginManager.php
@@ -95,7 +95,6 @@ class LoginManager
95 // The user client has a valid stay-signed-in cookie 95 // The user client has a valid stay-signed-in cookie
96 // Session information is updated with the current client information 96 // Session information is updated with the current client information
97 $this->sessionManager->storeLoginInfo($clientIpId); 97 $this->sessionManager->storeLoginInfo($clientIpId);
98
99 } elseif ($this->sessionManager->hasSessionExpired() 98 } elseif ($this->sessionManager->hasSessionExpired()
100 || $this->sessionManager->hasClientIpChanged($clientIpId) 99 || $this->sessionManager->hasClientIpChanged($clientIpId)
101 ) { 100 ) {
diff --git a/composer.json b/composer.json
index f5e7a9cd..dccf83b6 100644
--- a/composer.json
+++ b/composer.json
@@ -24,11 +24,9 @@
24 "gettext/gettext": "^4.4" 24 "gettext/gettext": "^4.4"
25 }, 25 },
26 "require-dev": { 26 "require-dev": {
27 "phpmd/phpmd" : "@stable", 27 "phpunit/phpcov": "*",
28 "phpunit/phpunit": "^5.0", 28 "phpunit/phpunit": "^5.0",
29 "sebastian/phpcpd": "*", 29 "squizlabs/php_codesniffer": "2.*"
30 "squizlabs/php_codesniffer": "2.*",
31 "phpunit/phpcov": "*"
32 }, 30 },
33 "autoload": { 31 "autoload": {
34 "psr-4": { 32 "psr-4": {
diff --git a/composer.lock b/composer.lock
index bdf1861c..c43dad6f 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
4 "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 4 "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 "This file is @generated automatically" 5 "This file is @generated automatically"
6 ], 6 ],
7 "content-hash": "0dc33ee0b7d9f47868d4fa961f0d13b4", 7 "content-hash": "3876b34296fedb365517b785af8384de",
8 "packages": [ 8 "packages": [
9 { 9 {
10 "name": "arthurhoaro/web-thumbnailer", 10 "name": "arthurhoaro/web-thumbnailer",
@@ -593,12 +593,12 @@
593 "source": { 593 "source": {
594 "type": "git", 594 "type": "git",
595 "url": "https://github.com/pubsubhubbub/php-publisher.git", 595 "url": "https://github.com/pubsubhubbub/php-publisher.git",
596 "reference": "e8a7cf52a2c86b0c364da56f7192ec020c83b8f7" 596 "reference": "047b0faf6219071527a45942d6fef4dbc6d1d884"
597 }, 597 },
598 "dist": { 598 "dist": {
599 "type": "zip", 599 "type": "zip",
600 "url": "https://api.github.com/repos/pubsubhubbub/php-publisher/zipball/e8a7cf52a2c86b0c364da56f7192ec020c83b8f7", 600 "url": "https://api.github.com/repos/pubsubhubbub/php-publisher/zipball/047b0faf6219071527a45942d6fef4dbc6d1d884",
601 "reference": "e8a7cf52a2c86b0c364da56f7192ec020c83b8f7", 601 "reference": "047b0faf6219071527a45942d6fef4dbc6d1d884",
602 "shasum": "" 602 "shasum": ""
603 }, 603 },
604 "require": { 604 "require": {
@@ -627,9 +627,10 @@
627 "data", 627 "data",
628 "feeds", 628 "feeds",
629 "publishers", 629 "publishers",
630 "pubsubhubbub" 630 "pubsubhubbub",
631 "websub"
631 ], 632 ],
632 "time": "2018-10-05T12:31:04+00:00" 633 "time": "2018-10-09T05:20:28+00:00"
633 }, 634 },
634 { 635 {
635 "name": "shaarli/netscape-bookmark-parser", 636 "name": "shaarli/netscape-bookmark-parser",
@@ -859,46 +860,6 @@
859 "time": "2017-10-19T19:58:43+00:00" 860 "time": "2017-10-19T19:58:43+00:00"
860 }, 861 },
861 { 862 {
862 "name": "pdepend/pdepend",
863 "version": "2.5.2",
864 "source": {
865 "type": "git",
866 "url": "https://github.com/pdepend/pdepend.git",
867 "reference": "9daf26d0368d4a12bed1cacae1a9f3a6f0adf239"
868 },
869 "dist": {
870 "type": "zip",
871 "url": "https://api.github.com/repos/pdepend/pdepend/zipball/9daf26d0368d4a12bed1cacae1a9f3a6f0adf239",
872 "reference": "9daf26d0368d4a12bed1cacae1a9f3a6f0adf239",
873 "shasum": ""
874 },
875 "require": {
876 "php": ">=5.3.7",
877 "symfony/config": "^2.3.0|^3|^4",
878 "symfony/dependency-injection": "^2.3.0|^3|^4",
879 "symfony/filesystem": "^2.3.0|^3|^4"
880 },
881 "require-dev": {
882 "phpunit/phpunit": "^4.8|^5.7",
883 "squizlabs/php_codesniffer": "^2.0.0"
884 },
885 "bin": [
886 "src/bin/pdepend"
887 ],
888 "type": "library",
889 "autoload": {
890 "psr-4": {
891 "PDepend\\": "src/main/php/PDepend"
892 }
893 },
894 "notification-url": "https://packagist.org/downloads/",
895 "license": [
896 "BSD-3-Clause"
897 ],
898 "description": "Official version of pdepend to be handled with Composer",
899 "time": "2017-12-13T13:21:38+00:00"
900 },
901 {
902 "name": "phpdocumentor/reflection-common", 863 "name": "phpdocumentor/reflection-common",
903 "version": "1.0.1", 864 "version": "1.0.1",
904 "source": { 865 "source": {
@@ -1045,72 +1006,6 @@
1045 "time": "2017-07-14T14:27:02+00:00" 1006 "time": "2017-07-14T14:27:02+00:00"
1046 }, 1007 },
1047 { 1008 {
1048 "name": "phpmd/phpmd",
1049 "version": "2.6.0",
1050 "source": {
1051 "type": "git",
1052 "url": "https://github.com/phpmd/phpmd.git",
1053 "reference": "4e9924b2c157a3eb64395460fcf56b31badc8374"
1054 },
1055 "dist": {
1056 "type": "zip",
1057 "url": "https://api.github.com/repos/phpmd/phpmd/zipball/4e9924b2c157a3eb64395460fcf56b31badc8374",
1058 "reference": "4e9924b2c157a3eb64395460fcf56b31badc8374",
1059 "shasum": ""
1060 },
1061 "require": {
1062 "ext-xml": "*",
1063 "pdepend/pdepend": "^2.5",
1064 "php": ">=5.3.9"
1065 },
1066 "require-dev": {
1067 "phpunit/phpunit": "^4.0",
1068 "squizlabs/php_codesniffer": "^2.0"
1069 },
1070 "bin": [
1071 "src/bin/phpmd"
1072 ],
1073 "type": "project",
1074 "autoload": {
1075 "psr-0": {
1076 "PHPMD\\": "src/main/php"
1077 }
1078 },
1079 "notification-url": "https://packagist.org/downloads/",
1080 "license": [
1081 "BSD-3-Clause"
1082 ],
1083 "authors": [
1084 {
1085 "name": "Manuel Pichler",
1086 "email": "github@manuel-pichler.de",
1087 "homepage": "https://github.com/manuelpichler",
1088 "role": "Project Founder"
1089 },
1090 {
1091 "name": "Other contributors",
1092 "homepage": "https://github.com/phpmd/phpmd/graphs/contributors",
1093 "role": "Contributors"
1094 },
1095 {
1096 "name": "Marc Würth",
1097 "email": "ravage@bluewin.ch",
1098 "homepage": "https://github.com/ravage84",
1099 "role": "Project Maintainer"
1100 }
1101 ],
1102 "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.",
1103 "homepage": "http://phpmd.org/",
1104 "keywords": [
1105 "mess detection",
1106 "mess detector",
1107 "pdepend",
1108 "phpmd",
1109 "pmd"
1110 ],
1111 "time": "2017-01-20T14:41:10+00:00"
1112 },
1113 {
1114 "name": "phpspec/prophecy", 1009 "name": "phpspec/prophecy",
1115 "version": "1.8.0", 1010 "version": "1.8.0",
1116 "source": { 1011 "source": {
@@ -1989,56 +1884,6 @@
1989 "time": "2017-02-18T15:18:39+00:00" 1884 "time": "2017-02-18T15:18:39+00:00"
1990 }, 1885 },
1991 { 1886 {
1992 "name": "sebastian/phpcpd",
1993 "version": "3.0.1",
1994 "source": {
1995 "type": "git",
1996 "url": "https://github.com/sebastianbergmann/phpcpd.git",
1997 "reference": "dfed51c1288790fc957c9433e2f49ab152e8a564"
1998 },
1999 "dist": {
2000 "type": "zip",
2001 "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/dfed51c1288790fc957c9433e2f49ab152e8a564",
2002 "reference": "dfed51c1288790fc957c9433e2f49ab152e8a564",
2003 "shasum": ""
2004 },
2005 "require": {
2006 "php": "^5.6|^7.0",
2007 "phpunit/php-timer": "^1.0.6",
2008 "sebastian/finder-facade": "^1.1",
2009 "sebastian/version": "^1.0|^2.0",
2010 "symfony/console": "^2.7|^3.0|^4.0"
2011 },
2012 "bin": [
2013 "phpcpd"
2014 ],
2015 "type": "library",
2016 "extra": {
2017 "branch-alias": {
2018 "dev-master": "3.0-dev"
2019 }
2020 },
2021 "autoload": {
2022 "classmap": [
2023 "src/"
2024 ]
2025 },
2026 "notification-url": "https://packagist.org/downloads/",
2027 "license": [
2028 "BSD-3-Clause"
2029 ],
2030 "authors": [
2031 {
2032 "name": "Sebastian Bergmann",
2033 "email": "sebastian@phpunit.de",
2034 "role": "lead"
2035 }
2036 ],
2037 "description": "Copy/Paste Detector (CPD) for PHP code.",
2038 "homepage": "https://github.com/sebastianbergmann/phpcpd",
2039 "time": "2017-11-16T08:49:28+00:00"
2040 },
2041 {
2042 "name": "sebastian/recursion-context", 1887 "name": "sebastian/recursion-context",
2043 "version": "2.0.0", 1888 "version": "2.0.0",
2044 "source": { 1889 "source": {
@@ -2255,70 +2100,6 @@
2255 "time": "2017-05-22T02:43:20+00:00" 2100 "time": "2017-05-22T02:43:20+00:00"
2256 }, 2101 },
2257 { 2102 {
2258 "name": "symfony/config",
2259 "version": "v3.4.17",
2260 "source": {
2261 "type": "git",
2262 "url": "https://github.com/symfony/config.git",
2263 "reference": "e5389132dc6320682de3643091121c048ff796b3"
2264 },
2265 "dist": {
2266 "type": "zip",
2267 "url": "https://api.github.com/repos/symfony/config/zipball/e5389132dc6320682de3643091121c048ff796b3",
2268 "reference": "e5389132dc6320682de3643091121c048ff796b3",
2269 "shasum": ""
2270 },
2271 "require": {
2272 "php": "^5.5.9|>=7.0.8",
2273 "symfony/filesystem": "~2.8|~3.0|~4.0",
2274 "symfony/polyfill-ctype": "~1.8"
2275 },
2276 "conflict": {
2277 "symfony/dependency-injection": "<3.3",
2278 "symfony/finder": "<3.3"
2279 },
2280 "require-dev": {
2281 "symfony/dependency-injection": "~3.3|~4.0",
2282 "symfony/event-dispatcher": "~3.3|~4.0",
2283 "symfony/finder": "~3.3|~4.0",
2284 "symfony/yaml": "~3.0|~4.0"
2285 },
2286 "suggest": {
2287 "symfony/yaml": "To use the yaml reference dumper"
2288 },
2289 "type": "library",
2290 "extra": {
2291 "branch-alias": {
2292 "dev-master": "3.4-dev"
2293 }
2294 },
2295 "autoload": {
2296 "psr-4": {
2297 "Symfony\\Component\\Config\\": ""
2298 },
2299 "exclude-from-classmap": [
2300 "/Tests/"
2301 ]
2302 },
2303 "notification-url": "https://packagist.org/downloads/",
2304 "license": [
2305 "MIT"
2306 ],
2307 "authors": [
2308 {
2309 "name": "Fabien Potencier",
2310 "email": "fabien@symfony.com"
2311 },
2312 {
2313 "name": "Symfony Community",
2314 "homepage": "https://symfony.com/contributors"
2315 }
2316 ],
2317 "description": "Symfony Config Component",
2318 "homepage": "https://symfony.com",
2319 "time": "2018-09-08T13:15:14+00:00"
2320 },
2321 {
2322 "name": "symfony/console", 2103 "name": "symfony/console",
2323 "version": "v3.4.17", 2104 "version": "v3.4.17",
2324 "source": { 2105 "source": {
@@ -2444,127 +2225,6 @@
2444 "time": "2018-10-02T16:33:53+00:00" 2225 "time": "2018-10-02T16:33:53+00:00"
2445 }, 2226 },
2446 { 2227 {
2447 "name": "symfony/dependency-injection",
2448 "version": "v3.4.17",
2449 "source": {
2450 "type": "git",
2451 "url": "https://github.com/symfony/dependency-injection.git",
2452 "reference": "aea20fef4e92396928b5db175788b90234c0270d"
2453 },
2454 "dist": {
2455 "type": "zip",
2456 "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/aea20fef4e92396928b5db175788b90234c0270d",
2457 "reference": "aea20fef4e92396928b5db175788b90234c0270d",
2458 "shasum": ""
2459 },
2460 "require": {
2461 "php": "^5.5.9|>=7.0.8",
2462 "psr/container": "^1.0"
2463 },
2464 "conflict": {
2465 "symfony/config": "<3.3.7",
2466 "symfony/finder": "<3.3",
2467 "symfony/proxy-manager-bridge": "<3.4",
2468 "symfony/yaml": "<3.4"
2469 },
2470 "provide": {
2471 "psr/container-implementation": "1.0"
2472 },
2473 "require-dev": {
2474 "symfony/config": "~3.3|~4.0",
2475 "symfony/expression-language": "~2.8|~3.0|~4.0",
2476 "symfony/yaml": "~3.4|~4.0"
2477 },
2478 "suggest": {
2479 "symfony/config": "",
2480 "symfony/expression-language": "For using expressions in service container configuration",
2481 "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required",
2482 "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
2483 "symfony/yaml": ""
2484 },
2485 "type": "library",
2486 "extra": {
2487 "branch-alias": {
2488 "dev-master": "3.4-dev"
2489 }
2490 },
2491 "autoload": {
2492 "psr-4": {
2493 "Symfony\\Component\\DependencyInjection\\": ""
2494 },
2495 "exclude-from-classmap": [
2496 "/Tests/"
2497 ]
2498 },
2499 "notification-url": "https://packagist.org/downloads/",
2500 "license": [
2501 "MIT"
2502 ],
2503 "authors": [
2504 {
2505 "name": "Fabien Potencier",
2506 "email": "fabien@symfony.com"
2507 },
2508 {
2509 "name": "Symfony Community",
2510 "homepage": "https://symfony.com/contributors"
2511 }
2512 ],
2513 "description": "Symfony DependencyInjection Component",
2514 "homepage": "https://symfony.com",
2515 "time": "2018-10-02T12:28:39+00:00"
2516 },
2517 {
2518 "name": "symfony/filesystem",
2519 "version": "v3.4.17",
2520 "source": {
2521 "type": "git",
2522 "url": "https://github.com/symfony/filesystem.git",
2523 "reference": "d69930fc337d767607267d57c20a7403d0a822a4"
2524 },
2525 "dist": {
2526 "type": "zip",
2527 "url": "https://api.github.com/repos/symfony/filesystem/zipball/d69930fc337d767607267d57c20a7403d0a822a4",
2528 "reference": "d69930fc337d767607267d57c20a7403d0a822a4",
2529 "shasum": ""
2530 },
2531 "require": {
2532 "php": "^5.5.9|>=7.0.8",
2533 "symfony/polyfill-ctype": "~1.8"
2534 },
2535 "type": "library",
2536 "extra": {
2537 "branch-alias": {
2538 "dev-master": "3.4-dev"
2539 }
2540 },
2541 "autoload": {
2542 "psr-4": {
2543 "Symfony\\Component\\Filesystem\\": ""
2544 },
2545 "exclude-from-classmap": [
2546 "/Tests/"
2547 ]
2548 },
2549 "notification-url": "https://packagist.org/downloads/",
2550 "license": [
2551 "MIT"
2552 ],
2553 "authors": [
2554 {
2555 "name": "Fabien Potencier",
2556 "email": "fabien@symfony.com"
2557 },
2558 {
2559 "name": "Symfony Community",
2560 "homepage": "https://symfony.com/contributors"
2561 }
2562 ],
2563 "description": "Symfony Filesystem Component",
2564 "homepage": "https://symfony.com",
2565 "time": "2018-10-02T12:28:39+00:00"
2566 },
2567 {
2568 "name": "symfony/finder", 2228 "name": "symfony/finder",
2569 "version": "v3.4.17", 2229 "version": "v3.4.17",
2570 "source": { 2230 "source": {
@@ -2883,8 +2543,7 @@
2883 "aliases": [], 2543 "aliases": [],
2884 "minimum-stability": "stable", 2544 "minimum-stability": "stable",
2885 "stability-flags": { 2545 "stability-flags": {
2886 "pubsubhubbub/publisher": 20, 2546 "pubsubhubbub/publisher": 20
2887 "phpmd/phpmd": 0
2888 }, 2547 },
2889 "prefer-stable": false, 2548 "prefer-stable": false,
2890 "prefer-lowest": false, 2549 "prefer-lowest": false,
diff --git a/index.php b/index.php
index 82285dd9..acfcc660 100644
--- a/index.php
+++ b/index.php
@@ -28,7 +28,7 @@ if (date_default_timezone_get() == '') {
28define('WEB_PATH', substr($_SERVER['REQUEST_URI'], 0, 1+strrpos($_SERVER['REQUEST_URI'], '/', 0))); 28define('WEB_PATH', substr($_SERVER['REQUEST_URI'], 0, 1+strrpos($_SERVER['REQUEST_URI'], '/', 0)));
29 29
30// High execution time in case of problematic imports/exports. 30// High execution time in case of problematic imports/exports.
31ini_set('max_input_time','60'); 31ini_set('max_input_time', '60');
32 32
33// Try to set max upload file size and read 33// Try to set max upload file size and read
34ini_set('memory_limit', '128M'); 34ini_set('memory_limit', '128M');
@@ -85,7 +85,7 @@ use \Shaarli\Thumbnailer;
85// Ensure the PHP version is supported 85// Ensure the PHP version is supported
86try { 86try {
87 ApplicationUtils::checkPHPVersion('5.5', PHP_VERSION); 87 ApplicationUtils::checkPHPVersion('5.5', PHP_VERSION);
88} catch(Exception $exc) { 88} catch (Exception $exc) {
89 header('Content-Type: text/plain; charset=utf-8'); 89 header('Content-Type: text/plain; charset=utf-8');
90 echo $exc->getMessage(); 90 echo $exc->getMessage();
91 exit; 91 exit;
@@ -223,7 +223,6 @@ if (isset($_POST['login'])) {
223 $expirationTime, 223 $expirationTime,
224 WEB_PATH 224 WEB_PATH
225 ); 225 );
226
227 } else { 226 } else {
228 // Standard session expiration (=when browser closes) 227 // Standard session expiration (=when browser closes)
229 $expirationTime = 0; 228 $expirationTime = 0;
@@ -257,7 +256,8 @@ if (isset($_POST['login'])) {
257 exit; 256 exit;
258 } 257 }
259 } 258 }
260 header('Location: ?'); exit; 259 header('Location: ?');
260 exit;
261 } else { 261 } else {
262 $loginManager->handleFailedLogin($_SERVER); 262 $loginManager->handleFailedLogin($_SERVER);
263 $redir = '&username='. urlencode($_POST['login']); 263 $redir = '&username='. urlencode($_POST['login']);
@@ -278,7 +278,9 @@ if (isset($_POST['login'])) {
278// ------------------------------------------------------------------------------------------ 278// ------------------------------------------------------------------------------------------
279// Token management for XSRF protection 279// Token management for XSRF protection
280// Token should be used in any form which acts on data (create,update,delete,import...). 280// Token should be used in any form which acts on data (create,update,delete,import...).
281if (!isset($_SESSION['tokens'])) $_SESSION['tokens']=array(); // Token are attached to the session. 281if (!isset($_SESSION['tokens'])) {
282 $_SESSION['tokens']=array(); // Token are attached to the session.
283}
282 284
283/** 285/**
284 * Daily RSS feed: 1 RSS entry per day giving all the links on that day. 286 * Daily RSS feed: 1 RSS entry per day giving all the links on that day.
@@ -288,13 +290,14 @@ if (!isset($_SESSION['tokens'])) $_SESSION['tokens']=array(); // Token are atta
288 * @param ConfigManager $conf Configuration Manager instance 290 * @param ConfigManager $conf Configuration Manager instance
289 * @param LoginManager $loginManager LoginManager instance 291 * @param LoginManager $loginManager LoginManager instance
290 */ 292 */
291function showDailyRSS($conf, $loginManager) { 293function showDailyRSS($conf, $loginManager)
294{
292 // Cache system 295 // Cache system
293 $query = $_SERVER['QUERY_STRING']; 296 $query = $_SERVER['QUERY_STRING'];
294 $cache = new CachedPage( 297 $cache = new CachedPage(
295 $conf->get('config.PAGE_CACHE'), 298 $conf->get('config.PAGE_CACHE'),
296 page_url($_SERVER), 299 page_url($_SERVER),
297 startsWith($query,'do=dailyrss') && !$loginManager->isLoggedIn() 300 startsWith($query, 'do=dailyrss') && !$loginManager->isLoggedIn()
298 ); 301 );
299 $cached = $cache->cachedVersion(); 302 $cached = $cache->cachedVersion();
300 if (!empty($cached)) { 303 if (!empty($cached)) {
@@ -395,7 +398,7 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
395{ 398{
396 $day = date('Ymd', strtotime('-1 day')); // Yesterday, in format YYYYMMDD. 399 $day = date('Ymd', strtotime('-1 day')); // Yesterday, in format YYYYMMDD.
397 if (isset($_GET['day'])) { 400 if (isset($_GET['day'])) {
398 $day = $_GET['day']; 401 $day = $_GET['day'];
399 } 402 }
400 403
401 $days = $LINKSDB->days(); 404 $days = $LINKSDB->days();
@@ -413,7 +416,7 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
413 $previousday=$days[$i - 1]; 416 $previousday=$days[$i - 1];
414 } 417 }
415 if ($i < count($days) - 1) { 418 if ($i < count($days) - 1) {
416 $nextday = $days[$i + 1]; 419 $nextday = $days[$i + 1];
417 } 420 }
418 } 421 }
419 try { 422 try {
@@ -424,8 +427,8 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
424 } 427 }
425 428
426 // We pre-format some fields for proper output. 429 // We pre-format some fields for proper output.
427 foreach($linksToDisplay as $key => $link) { 430 foreach ($linksToDisplay as $key => $link) {
428 $taglist = explode(' ',$link['tags']); 431 $taglist = explode(' ', $link['tags']);
429 uasort($taglist, 'strcasecmp'); 432 uasort($taglist, 'strcasecmp');
430 $linksToDisplay[$key]['taglist']=$taglist; 433 $linksToDisplay[$key]['taglist']=$taglist;
431 $linksToDisplay[$key]['formatedDescription'] = format_description( 434 $linksToDisplay[$key]['formatedDescription'] = format_description(
@@ -457,14 +460,14 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
457 */ 460 */
458 $columns = array(array(), array(), array()); // Entries to display, for each column. 461 $columns = array(array(), array(), array()); // Entries to display, for each column.
459 $fill = array(0, 0, 0); // Rough estimate of columns fill. 462 $fill = array(0, 0, 0); // Rough estimate of columns fill.
460 foreach($data['linksToDisplay'] as $key => $link) { 463 foreach ($data['linksToDisplay'] as $key => $link) {
461 // Roughly estimate length of entry (by counting characters) 464 // Roughly estimate length of entry (by counting characters)
462 // Title: 30 chars = 1 line. 1 line is 30 pixels height. 465 // Title: 30 chars = 1 line. 1 line is 30 pixels height.
463 // Description: 836 characters gives roughly 342 pixel height. 466 // Description: 836 characters gives roughly 342 pixel height.
464 // This is not perfect, but it's usually OK. 467 // This is not perfect, but it's usually OK.
465 $length = strlen($link['title']) + (342 * strlen($link['description'])) / 836; 468 $length = strlen($link['title']) + (342 * strlen($link['description'])) / 836;
466 if ($link['thumbnail']) { 469 if ($link['thumbnail']) {
467 $length += 100; // 1 thumbnails roughly takes 100 pixels height. 470 $length += 100; // 1 thumbnails roughly takes 100 pixels height.
468 } 471 }
469 // Then put in column which is the less filled: 472 // Then put in column which is the less filled:
470 $smallest = min($fill); // find smallest value in array. 473 $smallest = min($fill); // find smallest value in array.
@@ -492,8 +495,9 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
492 * @param ConfigManager $conf Configuration Manager instance. 495 * @param ConfigManager $conf Configuration Manager instance.
493 * @param PluginManager $pluginManager Plugin Manager instance. 496 * @param PluginManager $pluginManager Plugin Manager instance.
494 */ 497 */
495function showLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager) { 498function showLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager)
496 buildLinkList($PAGE,$LINKSDB, $conf, $pluginManager, $loginManager); 499{
500 buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager);
497 $PAGE->renderPage('linklist'); 501 $PAGE->renderPage('linklist');
498} 502}
499 503
@@ -524,8 +528,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
524 $updater->getDoneUpdates() 528 $updater->getDoneUpdates()
525 ); 529 );
526 } 530 }
527 } 531 } catch (Exception $e) {
528 catch(Exception $e) {
529 die($e->getMessage()); 532 die($e->getMessage());
530 } 533 }
531 534
@@ -538,8 +541,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
538 $query = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : ''; 541 $query = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : '';
539 $targetPage = Router::findPage($query, $_GET, $loginManager->isLoggedIn()); 542 $targetPage = Router::findPage($query, $_GET, $loginManager->isLoggedIn());
540 543
541 if ( 544 if (// if the user isn't logged in
542 // if the user isn't logged in
543 !$loginManager->isLoggedIn() && 545 !$loginManager->isLoggedIn() &&
544 // and Shaarli doesn't have public content... 546 // and Shaarli doesn't have public content...
545 $conf->get('privacy.hide_public_links') && 547 $conf->get('privacy.hide_public_links') &&
@@ -563,9 +565,11 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
563 'footer', 565 'footer',
564 ); 566 );
565 567
566 foreach($common_hooks as $name) { 568 foreach ($common_hooks as $name) {
567 $plugin_data = array(); 569 $plugin_data = array();
568 $pluginManager->executeHooks('render_' . $name, $plugin_data, 570 $pluginManager->executeHooks(
571 'render_' . $name,
572 $plugin_data,
569 array( 573 array(
570 'target' => $targetPage, 574 'target' => $targetPage,
571 'loggedin' => $loginManager->isLoggedIn() 575 'loggedin' => $loginManager->isLoggedIn()
@@ -575,13 +579,15 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
575 } 579 }
576 580
577 // -------- Display login form. 581 // -------- Display login form.
578 if ($targetPage == Router::$PAGE_LOGIN) 582 if ($targetPage == Router::$PAGE_LOGIN) {
579 { 583 if ($conf->get('security.open_shaarli')) {
580 if ($conf->get('security.open_shaarli')) { header('Location: ?'); exit; } // No need to login for open Shaarli 584 header('Location: ?');
585 exit;
586 } // No need to login for open Shaarli
581 if (isset($_GET['username'])) { 587 if (isset($_GET['username'])) {
582 $PAGE->assign('username', escape($_GET['username'])); 588 $PAGE->assign('username', escape($_GET['username']));
583 } 589 }
584 $PAGE->assign('returnurl',(isset($_SERVER['HTTP_REFERER']) ? escape($_SERVER['HTTP_REFERER']):'')); 590 $PAGE->assign('returnurl', (isset($_SERVER['HTTP_REFERER']) ? escape($_SERVER['HTTP_REFERER']):''));
585 // add default state of the 'remember me' checkbox 591 // add default state of the 'remember me' checkbox
586 $PAGE->assign('remember_user_default', $conf->get('privacy.remember_user_default')); 592 $PAGE->assign('remember_user_default', $conf->get('privacy.remember_user_default'));
587 $PAGE->assign('user_can_login', $loginManager->canLogin($_SERVER)); 593 $PAGE->assign('user_can_login', $loginManager->canLogin($_SERVER));
@@ -590,8 +596,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
590 exit; 596 exit;
591 } 597 }
592 // -------- User wants to logout. 598 // -------- User wants to logout.
593 if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=logout')) 599 if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=logout')) {
594 {
595 invalidateCaches($conf->get('resource.page_cache')); 600 invalidateCaches($conf->get('resource.page_cache'));
596 $sessionManager->logout(); 601 $sessionManager->logout();
597 setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, 'false', 0, WEB_PATH); 602 setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, 'false', 0, WEB_PATH);
@@ -600,8 +605,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
600 } 605 }
601 606
602 // -------- Picture wall 607 // -------- Picture wall
603 if ($targetPage == Router::$PAGE_PICWALL) 608 if ($targetPage == Router::$PAGE_PICWALL) {
604 {
605 $PAGE->assign('pagetitle', t('Picture wall') .' - '. $conf->get('general.title', 'Shaarli')); 609 $PAGE->assign('pagetitle', t('Picture wall') .' - '. $conf->get('general.title', 'Shaarli'));
606 if (! $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) === Thumbnailer::MODE_NONE) { 610 if (! $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) === Thumbnailer::MODE_NONE) {
607 $PAGE->assign('linksToDisplay', []); 611 $PAGE->assign('linksToDisplay', []);
@@ -615,8 +619,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
615 619
616 // Get only links which have a thumbnail. 620 // Get only links which have a thumbnail.
617 // Note: we do not retrieve thumbnails here, the request is too heavy. 621 // Note: we do not retrieve thumbnails here, the request is too heavy.
618 foreach($links as $key => $link) 622 foreach ($links as $key => $link) {
619 {
620 if (isset($link['thumbnail']) && $link['thumbnail'] !== false) { 623 if (isset($link['thumbnail']) && $link['thumbnail'] !== false) {
621 $linksToDisplay[] = $link; // Add to array. 624 $linksToDisplay[] = $link; // Add to array.
622 } 625 }
@@ -637,8 +640,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
637 } 640 }
638 641
639 // -------- Tag cloud 642 // -------- Tag cloud
640 if ($targetPage == Router::$PAGE_TAGCLOUD) 643 if ($targetPage == Router::$PAGE_TAGCLOUD) {
641 {
642 $visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : ''; 644 $visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : '';
643 $filteringTags = isset($_GET['searchtags']) ? explode(' ', $_GET['searchtags']) : []; 645 $filteringTags = isset($_GET['searchtags']) ? explode(' ', $_GET['searchtags']) : [];
644 $tags = $LINKSDB->linksCountPerTag($filteringTags, $visibility); 646 $tags = $LINKSDB->linksCountPerTag($filteringTags, $visibility);
@@ -653,7 +655,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
653 alphabetical_sort($tags, false, true); 655 alphabetical_sort($tags, false, true);
654 656
655 $tagList = array(); 657 $tagList = array();
656 foreach($tags as $key => $value) { 658 foreach ($tags as $key => $value) {
657 if (in_array($key, $filteringTags)) { 659 if (in_array($key, $filteringTags)) {
658 continue; 660 continue;
659 } 661 }
@@ -685,8 +687,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
685 } 687 }
686 688
687 // -------- Tag list 689 // -------- Tag list
688 if ($targetPage == Router::$PAGE_TAGLIST) 690 if ($targetPage == Router::$PAGE_TAGLIST) {
689 {
690 $visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : ''; 691 $visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : '';
691 $filteringTags = isset($_GET['searchtags']) ? explode(' ', $_GET['searchtags']) : []; 692 $filteringTags = isset($_GET['searchtags']) ? explode(' ', $_GET['searchtags']) : [];
692 $tags = $LINKSDB->linksCountPerTag($filteringTags, $visibility); 693 $tags = $LINKSDB->linksCountPerTag($filteringTags, $visibility);
@@ -732,7 +733,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
732 $cache = new CachedPage( 733 $cache = new CachedPage(
733 $conf->get('resource.page_cache'), 734 $conf->get('resource.page_cache'),
734 page_url($_SERVER), 735 page_url($_SERVER),
735 startsWith($query,'do='. $targetPage) && !$loginManager->isLoggedIn() 736 startsWith($query, 'do='. $targetPage) && !$loginManager->isLoggedIn()
736 ); 737 );
737 $cached = $cache->cachedVersion(); 738 $cached = $cache->cachedVersion();
738 if (!empty($cached)) { 739 if (!empty($cached)) {
@@ -770,11 +771,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
770 } 771 }
771 772
772 // -------- User clicks on a tag in a link: The tag is added to the list of searched tags (searchtags=...) 773 // -------- User clicks on a tag in a link: The tag is added to the list of searched tags (searchtags=...)
773 if (isset($_GET['addtag'])) 774 if (isset($_GET['addtag'])) {
774 {
775 // Get previous URL (http_referer) and add the tag to the searchtags parameters in query. 775 // Get previous URL (http_referer) and add the tag to the searchtags parameters in query.
776 if (empty($_SERVER['HTTP_REFERER'])) { header('Location: ?searchtags='.urlencode($_GET['addtag'])); exit; } // In case browser does not send HTTP_REFERER 776 if (empty($_SERVER['HTTP_REFERER'])) {
777 parse_str(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_QUERY), $params); 777 // In case browser does not send HTTP_REFERER
778 header('Location: ?searchtags='.urlencode($_GET['addtag']));
779 exit;
780 }
781 parse_str(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY), $params);
778 782
779 // Prevent redirection loop 783 // Prevent redirection loop
780 if (isset($params['addtag'])) { 784 if (isset($params['addtag'])) {
@@ -798,12 +802,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
798 // Append the tag if necessary 802 // Append the tag if necessary
799 if (empty($params['searchtags'])) { 803 if (empty($params['searchtags'])) {
800 $params['searchtags'] = trim($_GET['addtag']); 804 $params['searchtags'] = trim($_GET['addtag']);
801 } 805 } elseif ($addtag) {
802 elseif ($addtag) {
803 $params['searchtags'] = trim($params['searchtags']).' '.trim($_GET['addtag']); 806 $params['searchtags'] = trim($params['searchtags']).' '.trim($_GET['addtag']);
804 } 807 }
805 808
806 unset($params['page']); // We also remove page (keeping the same page has no sense, since the results are different) 809 // We also remove page (keeping the same page has no sense, since the
810 // results are different)
811 unset($params['page']);
812
807 header('Location: ?'.http_build_query($params)); 813 header('Location: ?'.http_build_query($params));
808 exit; 814 exit;
809 } 815 }
@@ -828,13 +834,15 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
828 $tags = explode(' ', $params['searchtags']); 834 $tags = explode(' ', $params['searchtags']);
829 // Remove value from array $tags. 835 // Remove value from array $tags.
830 $tags = array_diff($tags, array($_GET['removetag'])); 836 $tags = array_diff($tags, array($_GET['removetag']));
831 $params['searchtags'] = implode(' ',$tags); 837 $params['searchtags'] = implode(' ', $tags);
832 838
833 if (empty($params['searchtags'])) { 839 if (empty($params['searchtags'])) {
834 unset($params['searchtags']); 840 unset($params['searchtags']);
835 } 841 }
836 842
837 unset($params['page']); // We also remove page (keeping the same page has no sense, since the results are different) 843 // We also remove page (keeping the same page has no sense, since
844 // the results are different)
845 unset($params['page']);
838 } 846 }
839 header('Location: ?'.http_build_query($params)); 847 header('Location: ?'.http_build_query($params));
840 exit; 848 exit;
@@ -897,12 +905,10 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
897 } 905 }
898 906
899 // -------- Handle other actions allowed for non-logged in users: 907 // -------- Handle other actions allowed for non-logged in users:
900 if (!$loginManager->isLoggedIn()) 908 if (!$loginManager->isLoggedIn()) {
901 {
902 // User tries to post new link but is not logged in: 909 // User tries to post new link but is not logged in:
903 // Show login screen, then redirect to ?post=... 910 // Show login screen, then redirect to ?post=...
904 if (isset($_GET['post'])) 911 if (isset($_GET['post'])) {
905 {
906 header( // Redirect to login page, then back to post link. 912 header( // Redirect to login page, then back to post link.
907 'Location: ?do=login&post='.urlencode($_GET['post']). 913 'Location: ?do=login&post='.urlencode($_GET['post']).
908 (!empty($_GET['title'])?'&title='.urlencode($_GET['title']):''). 914 (!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').
@@ -925,8 +931,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
925 // -------- All other functions are reserved for the registered user: 931 // -------- All other functions are reserved for the registered user:
926 932
927 // -------- Display the Tools menu if requested (import/export/bookmarklet...) 933 // -------- Display the Tools menu if requested (import/export/bookmarklet...)
928 if ($targetPage == Router::$PAGE_TOOLS) 934 if ($targetPage == Router::$PAGE_TOOLS) {
929 {
930 $data = [ 935 $data = [
931 'pageabsaddr' => index_url($_SERVER), 936 'pageabsaddr' => index_url($_SERVER),
932 'sslenabled' => is_https($_SERVER), 937 'sslenabled' => is_https($_SERVER),
@@ -943,30 +948,40 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
943 } 948 }
944 949
945 // -------- User wants to change his/her password. 950 // -------- User wants to change his/her password.
946 if ($targetPage == Router::$PAGE_CHANGEPASSWORD) 951 if ($targetPage == Router::$PAGE_CHANGEPASSWORD) {
947 {
948 if ($conf->get('security.open_shaarli')) { 952 if ($conf->get('security.open_shaarli')) {
949 die(t('You are not supposed to change a password on an Open Shaarli.')); 953 die(t('You are not supposed to change a password on an Open Shaarli.'));
950 } 954 }
951 955
952 if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword'])) 956 if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword'])) {
953 { 957 if (!$sessionManager->checkToken($_POST['token'])) {
954 if (!$sessionManager->checkToken($_POST['token'])) die(t('Wrong token.')); // Go away! 958 die(t('Wrong token.')); // Go away!
959 }
955 960
956 // Make sure old password is correct. 961 // Make sure old password is correct.
957 $oldhash = sha1($_POST['oldpassword'].$conf->get('credentials.login').$conf->get('credentials.salt')); 962 $oldhash = sha1(
958 if ($oldhash!= $conf->get('credentials.hash')) { 963 $_POST['oldpassword'].$conf->get('credentials.login').$conf->get('credentials.salt')
959 echo '<script>alert("'. t('The old password is not correct.') .'");document.location=\'?do=changepasswd\';</script>'; 964 );
965 if ($oldhash != $conf->get('credentials.hash')) {
966 echo '<script>alert("'
967 . t('The old password is not correct.')
968 .'");document.location=\'?do=changepasswd\';</script>';
960 exit; 969 exit;
961 } 970 }
962 // Save new password 971 // Save new password
963 // Salt renders rainbow-tables attacks useless. 972 // Salt renders rainbow-tables attacks useless.
964 $conf->set('credentials.salt', sha1(uniqid('', true) .'_'. mt_rand())); 973 $conf->set('credentials.salt', sha1(uniqid('', true) .'_'. mt_rand()));
965 $conf->set('credentials.hash', sha1($_POST['setpassword'] . $conf->get('credentials.login') . $conf->get('credentials.salt'))); 974 $conf->set(
975 'credentials.hash',
976 sha1(
977 $_POST['setpassword']
978 . $conf->get('credentials.login')
979 . $conf->get('credentials.salt')
980 )
981 );
966 try { 982 try {
967 $conf->write($loginManager->isLoggedIn()); 983 $conf->write($loginManager->isLoggedIn());
968 } 984 } catch (Exception $e) {
969 catch(Exception $e) {
970 error_log( 985 error_log(
971 'ERROR while writing config file after changing password.' . PHP_EOL . 986 'ERROR while writing config file after changing password.' . PHP_EOL .
972 $e->getMessage() 987 $e->getMessage()
@@ -978,9 +993,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
978 } 993 }
979 echo '<script>alert("'. t('Your password has been changed') .'");document.location=\'?do=tools\';</script>'; 994 echo '<script>alert("'. t('Your password has been changed') .'");document.location=\'?do=tools\';</script>';
980 exit; 995 exit;
981 } 996 } else {
982 else // show the change password form. 997 // show the change password form.
983 {
984 $PAGE->assign('pagetitle', t('Change password') .' - '. $conf->get('general.title', 'Shaarli')); 998 $PAGE->assign('pagetitle', t('Change password') .' - '. $conf->get('general.title', 'Shaarli'));
985 $PAGE->renderPage('changepassword'); 999 $PAGE->renderPage('changepassword');
986 exit; 1000 exit;
@@ -988,10 +1002,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
988 } 1002 }
989 1003
990 // -------- User wants to change configuration 1004 // -------- User wants to change configuration
991 if ($targetPage == Router::$PAGE_CONFIGURE) 1005 if ($targetPage == Router::$PAGE_CONFIGURE) {
992 { 1006 if (!empty($_POST['title'])) {
993 if (!empty($_POST['title']) )
994 {
995 if (!$sessionManager->checkToken($_POST['token'])) { 1007 if (!$sessionManager->checkToken($_POST['token'])) {
996 die(t('Wrong token.')); // Go away! 1008 die(t('Wrong token.')); // Go away!
997 } 1009 }
@@ -1019,7 +1031,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1019 && $thumbnailsMode !== $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) 1031 && $thumbnailsMode !== $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)
1020 ) { 1032 ) {
1021 $_SESSION['warnings'][] = t( 1033 $_SESSION['warnings'][] = t(
1022 'You have enabled or changed thumbnails mode. <a href="?do=thumbs_update">Please synchronize them</a>.' 1034 'You have enabled or changed thumbnails mode. '
1035 .'<a href="?do=thumbs_update">Please synchronize them</a>.'
1023 ); 1036 );
1024 } 1037 }
1025 $conf->set('thumbnails.mode', $thumbnailsMode); 1038 $conf->set('thumbnails.mode', $thumbnailsMode);
@@ -1028,8 +1041,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1028 $conf->write($loginManager->isLoggedIn()); 1041 $conf->write($loginManager->isLoggedIn());
1029 $history->updateSettings(); 1042 $history->updateSettings();
1030 invalidateCaches($conf->get('resource.page_cache')); 1043 invalidateCaches($conf->get('resource.page_cache'));
1031 } 1044 } catch (Exception $e) {
1032 catch(Exception $e) {
1033 error_log( 1045 error_log(
1034 'ERROR while writing config file after configuration update.' . PHP_EOL . 1046 'ERROR while writing config file after configuration update.' . PHP_EOL .
1035 $e->getMessage() 1047 $e->getMessage()
@@ -1041,9 +1053,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1041 } 1053 }
1042 echo '<script>alert("'. t('Configuration was saved.') .'");document.location=\'?do=configure\';</script>'; 1054 echo '<script>alert("'. t('Configuration was saved.') .'");document.location=\'?do=configure\';</script>';
1043 exit; 1055 exit;
1044 } 1056 } else {
1045 else // Show the configuration form. 1057 // Show the configuration form.
1046 {
1047 $PAGE->assign('title', $conf->get('general.title')); 1058 $PAGE->assign('title', $conf->get('general.title'));
1048 $PAGE->assign('theme', $conf->get('resource.theme')); 1059 $PAGE->assign('theme', $conf->get('resource.theme'));
1049 $PAGE->assign('theme_available', ThemeUtils::getThemes($conf->get('resource.raintpl_tpl'))); 1060 $PAGE->assign('theme_available', ThemeUtils::getThemes($conf->get('resource.raintpl_tpl')));
@@ -1071,8 +1082,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1071 } 1082 }
1072 1083
1073 // -------- User wants to rename a tag or delete it 1084 // -------- User wants to rename a tag or delete it
1074 if ($targetPage == Router::$PAGE_CHANGETAG) 1085 if ($targetPage == Router::$PAGE_CHANGETAG) {
1075 {
1076 if (empty($_POST['fromtag']) || (empty($_POST['totag']) && isset($_POST['renametag']))) { 1086 if (empty($_POST['fromtag']) || (empty($_POST['totag']) && isset($_POST['renametag']))) {
1077 $PAGE->assign('fromtag', ! empty($_GET['fromtag']) ? escape($_GET['fromtag']) : ''); 1087 $PAGE->assign('fromtag', ! empty($_GET['fromtag']) ? escape($_GET['fromtag']) : '');
1078 $PAGE->assign('pagetitle', t('Manage tags') .' - '. $conf->get('general.title', 'Shaarli')); 1088 $PAGE->assign('pagetitle', t('Manage tags') .' - '. $conf->get('general.title', 'Shaarli'));
@@ -1101,16 +1111,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1101 } 1111 }
1102 1112
1103 // -------- User wants to add a link without using the bookmarklet: Show form. 1113 // -------- User wants to add a link without using the bookmarklet: Show form.
1104 if ($targetPage == Router::$PAGE_ADDLINK) 1114 if ($targetPage == Router::$PAGE_ADDLINK) {
1105 {
1106 $PAGE->assign('pagetitle', t('Shaare a new link') .' - '. $conf->get('general.title', 'Shaarli')); 1115 $PAGE->assign('pagetitle', t('Shaare a new link') .' - '. $conf->get('general.title', 'Shaarli'));
1107 $PAGE->renderPage('addlink'); 1116 $PAGE->renderPage('addlink');
1108 exit; 1117 exit;
1109 } 1118 }
1110 1119
1111 // -------- User clicked the "Save" button when editing a link: Save link to database. 1120 // -------- User clicked the "Save" button when editing a link: Save link to database.
1112 if (isset($_POST['save_edit'])) 1121 if (isset($_POST['save_edit'])) {
1113 {
1114 // Go away! 1122 // Go away!
1115 if (! $sessionManager->checkToken($_POST['token'])) { 1123 if (! $sessionManager->checkToken($_POST['token'])) {
1116 die(t('Wrong token.')); 1124 die(t('Wrong token.'));
@@ -1197,14 +1205,16 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1197 } 1205 }
1198 1206
1199 // -------- User clicked the "Cancel" button when editing a link. 1207 // -------- User clicked the "Cancel" button when editing a link.
1200 if (isset($_POST['cancel_edit'])) 1208 if (isset($_POST['cancel_edit'])) {
1201 {
1202 $id = isset($_POST['lf_id']) ? (int) escape($_POST['lf_id']) : false; 1209 $id = isset($_POST['lf_id']) ? (int) escape($_POST['lf_id']) : false;
1203 if (! isset($LINKSDB[$id])) { 1210 if (! isset($LINKSDB[$id])) {
1204 header('Location: ?'); 1211 header('Location: ?');
1205 } 1212 }
1206 // If we are called from the bookmarklet, we must close the popup: 1213 // If we are called from the bookmarklet, we must close the popup:
1207 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; } 1214 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) {
1215 echo '<script>self.close();</script>';
1216 exit;
1217 }
1208 $link = $LINKSDB[$id]; 1218 $link = $LINKSDB[$id];
1209 $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); 1219 $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' );
1210 // Scroll to the link which has been edited. 1220 // Scroll to the link which has been edited.
@@ -1215,8 +1225,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1215 } 1225 }
1216 1226
1217 // -------- User clicked the "Delete" button when editing a link: Delete link from database. 1227 // -------- User clicked the "Delete" button when editing a link: Delete link from database.
1218 if ($targetPage == Router::$PAGE_DELETELINK) 1228 if ($targetPage == Router::$PAGE_DELETELINK) {
1219 {
1220 if (! $sessionManager->checkToken($_GET['token'])) { 1229 if (! $sessionManager->checkToken($_GET['token'])) {
1221 die(t('Wrong token.')); 1230 die(t('Wrong token.'));
1222 } 1231 }
@@ -1230,7 +1239,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1230 $ids = [$ids]; 1239 $ids = [$ids];
1231 } 1240 }
1232 // assert at least one id is given 1241 // assert at least one id is given
1233 if(!count($ids)){ 1242 if (!count($ids)) {
1234 die('no id provided'); 1243 die('no id provided');
1235 } 1244 }
1236 foreach ($ids as $id) { 1245 foreach ($ids as $id) {
@@ -1243,15 +1252,18 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1243 $LINKSDB->save($conf->get('resource.page_cache')); // save to disk 1252 $LINKSDB->save($conf->get('resource.page_cache')); // save to disk
1244 1253
1245 // If we are called from the bookmarklet, we must close the popup: 1254 // If we are called from the bookmarklet, we must close the popup:
1246 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; } 1255 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) {
1256 echo '<script>self.close();</script>';
1257 exit;
1258 }
1247 1259
1248 $location = '?'; 1260 $location = '?';
1249 if (isset($_SERVER['HTTP_REFERER'])) { 1261 if (isset($_SERVER['HTTP_REFERER'])) {
1250 // Don't redirect to where we were previously if it was a permalink or an edit_link, because it would 404. 1262 // Don't redirect to where we were previously if it was a permalink or an edit_link, because it would 404.
1251 $location = generateLocation( 1263 $location = generateLocation(
1252 $_SERVER['HTTP_REFERER'], 1264 $_SERVER['HTTP_REFERER'],
1253 $_SERVER['HTTP_HOST'], 1265 $_SERVER['HTTP_HOST'],
1254 ['delete_link', 'edit_link', $link['shorturl']] 1266 ['delete_link', 'edit_link', $link['shorturl']]
1255 ); 1267 );
1256 } 1268 }
1257 1269
@@ -1260,11 +1272,13 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1260 } 1272 }
1261 1273
1262 // -------- User clicked the "EDIT" button on a link: Display link edit form. 1274 // -------- User clicked the "EDIT" button on a link: Display link edit form.
1263 if (isset($_GET['edit_link'])) 1275 if (isset($_GET['edit_link'])) {
1264 {
1265 $id = (int) escape($_GET['edit_link']); 1276 $id = (int) escape($_GET['edit_link']);
1266 $link = $LINKSDB[$id]; // Read database 1277 $link = $LINKSDB[$id]; // Read database
1267 if (!$link) { header('Location: ?'); exit; } // Link not found in database. 1278 if (!$link) {
1279 header('Location: ?');
1280 exit;
1281 } // Link not found in database.
1268 $link['linkdate'] = $link['created']->format(LinkDB::LINK_DATE_FORMAT); 1282 $link['linkdate'] = $link['created']->format(LinkDB::LINK_DATE_FORMAT);
1269 $data = array( 1283 $data = array(
1270 'link' => $link, 1284 'link' => $link,
@@ -1290,8 +1304,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1290 $link_is_new = false; 1304 $link_is_new = false;
1291 // Check if URL is not already in database (in this case, we will edit the existing link) 1305 // Check if URL is not already in database (in this case, we will edit the existing link)
1292 $link = $LINKSDB->getLinkFromUrl($url); 1306 $link = $LINKSDB->getLinkFromUrl($url);
1293 if (! $link) 1307 if (! $link) {
1294 {
1295 $link_is_new = true; 1308 $link_is_new = true;
1296 $linkdate = strval(date(LinkDB::LINK_DATE_FORMAT)); 1309 $linkdate = strval(date(LinkDB::LINK_DATE_FORMAT));
1297 // Get title if it was provided in URL (by the bookmarklet). 1310 // Get title if it was provided in URL (by the bookmarklet).
@@ -1300,7 +1313,9 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1300 $description = empty($_GET['description']) ? '' : escape($_GET['description']); 1313 $description = empty($_GET['description']) ? '' : escape($_GET['description']);
1301 $tags = empty($_GET['tags']) ? '' : escape($_GET['tags']); 1314 $tags = empty($_GET['tags']) ? '' : escape($_GET['tags']);
1302 $private = !empty($_GET['private']) && $_GET['private'] === "1" ? 1 : 0; 1315 $private = !empty($_GET['private']) && $_GET['private'] === "1" ? 1 : 0;
1303 // If this is an HTTP(S) link, we try go get the page to extract the title (otherwise we will to straight to the edit form.) 1316
1317 // If this is an HTTP(S) link, we try go get the page to extract
1318 // the title (otherwise we will to straight to the edit form.)
1304 if (empty($title) && strpos(get_url_scheme($url), 'http') !== false) { 1319 if (empty($title) && strpos(get_url_scheme($url), 'http') !== false) {
1305 // Short timeout to keep the application responsive 1320 // Short timeout to keep the application responsive
1306 // The callback will fill $charset and $title with data from the downloaded page. 1321 // The callback will fill $charset and $title with data from the downloaded page.
@@ -1408,7 +1423,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1408 header('Content-Type: text/html; charset=utf-8'); 1423 header('Content-Type: text/html; charset=utf-8');
1409 header( 1424 header(
1410 'Content-disposition: attachment; filename=bookmarks_' 1425 'Content-disposition: attachment; filename=bookmarks_'
1411 .$selection.'_'.$now->format(LinkDB::LINK_DATE_FORMAT).'.html' 1426 .$selection.'_'.$now->format(LinkDB::LINK_DATE_FORMAT).'.html'
1412 ); 1427 );
1413 $PAGE->assign('date', $now->format(DateTime::RFC822)); 1428 $PAGE->assign('date', $now->format(DateTime::RFC822));
1414 $PAGE->assign('eol', PHP_EOL); 1429 $PAGE->assign('eol', PHP_EOL);
@@ -1476,14 +1491,20 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1476 $pluginMeta = $pluginManager->getPluginsMeta(); 1491 $pluginMeta = $pluginManager->getPluginsMeta();
1477 1492
1478 // Split plugins into 2 arrays: ordered enabled plugins and disabled. 1493 // Split plugins into 2 arrays: ordered enabled plugins and disabled.
1479 $enabledPlugins = array_filter($pluginMeta, function($v) { return $v['order'] !== false; }); 1494 $enabledPlugins = array_filter($pluginMeta, function ($v) {
1495 return $v['order'] !== false;
1496 });
1480 // Load parameters. 1497 // Load parameters.
1481 $enabledPlugins = load_plugin_parameter_values($enabledPlugins, $conf->get('plugins', array())); 1498 $enabledPlugins = load_plugin_parameter_values($enabledPlugins, $conf->get('plugins', array()));
1482 uasort( 1499 uasort(
1483 $enabledPlugins, 1500 $enabledPlugins,
1484 function($a, $b) { return $a['order'] - $b['order']; } 1501 function ($a, $b) {
1502 return $a['order'] - $b['order'];
1503 }
1485 ); 1504 );
1486 $disabledPlugins = array_filter($pluginMeta, function($v) { return $v['order'] === false; }); 1505 $disabledPlugins = array_filter($pluginMeta, function ($v) {
1506 return $v['order'] === false;
1507 });
1487 1508
1488 $PAGE->assign('enabledPlugins', $enabledPlugins); 1509 $PAGE->assign('enabledPlugins', $enabledPlugins);
1489 $PAGE->assign('disabledPlugins', $disabledPlugins); 1510 $PAGE->assign('disabledPlugins', $disabledPlugins);
@@ -1500,21 +1521,23 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1500 foreach ($_POST as $param => $value) { 1521 foreach ($_POST as $param => $value) {
1501 $conf->set('plugins.'. $param, escape($value)); 1522 $conf->set('plugins.'. $param, escape($value));
1502 } 1523 }
1503 } 1524 } else {
1504 else {
1505 $conf->set('general.enabled_plugins', save_plugin_config($_POST)); 1525 $conf->set('general.enabled_plugins', save_plugin_config($_POST));
1506 } 1526 }
1507 $conf->write($loginManager->isLoggedIn()); 1527 $conf->write($loginManager->isLoggedIn());
1508 $history->updateSettings(); 1528 $history->updateSettings();
1509 } 1529 } catch (Exception $e) {
1510 catch (Exception $e) {
1511 error_log( 1530 error_log(
1512 'ERROR while saving plugin configuration:.' . PHP_EOL . 1531 'ERROR while saving plugin configuration:.' . PHP_EOL .
1513 $e->getMessage() 1532 $e->getMessage()
1514 ); 1533 );
1515 1534
1516 // TODO: do not handle exceptions/errors in JS. 1535 // TODO: do not handle exceptions/errors in JS.
1517 echo '<script>alert("'. $e->getMessage() .'");document.location=\'?do='. Router::$PAGE_PLUGINSADMIN .'\';</script>'; 1536 echo '<script>alert("'
1537 . $e->getMessage()
1538 .'");document.location=\'?do='
1539 . Router::$PAGE_PLUGINSADMIN
1540 .'\';</script>';
1518 exit; 1541 exit;
1519 } 1542 }
1520 header('Location: ?do='. Router::$PAGE_PLUGINSADMIN); 1543 header('Location: ?do='. Router::$PAGE_PLUGINSADMIN);
@@ -1635,8 +1658,7 @@ function buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager)
1635 } 1658 }
1636 1659
1637 $linkDisp = array(); 1660 $linkDisp = array();
1638 while ($i<$end && $i<count($keys)) 1661 while ($i<$end && $i<count($keys)) {
1639 {
1640 $link = $linksToDisplay[$keys[$i]]; 1662 $link = $linksToDisplay[$keys[$i]];
1641 $link['description'] = format_description( 1663 $link['description'] = format_description(
1642 $link['description'], 1664 $link['description'],
@@ -1739,16 +1761,19 @@ function buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager)
1739 * @param SessionManager $sessionManager SessionManager instance 1761 * @param SessionManager $sessionManager SessionManager instance
1740 * @param LoginManager $loginManager LoginManager instance 1762 * @param LoginManager $loginManager LoginManager instance
1741 */ 1763 */
1742function install($conf, $sessionManager, $loginManager) { 1764function install($conf, $sessionManager, $loginManager)
1765{
1743 // On free.fr host, make sure the /sessions directory exists, otherwise login will not work. 1766 // On free.fr host, make sure the /sessions directory exists, otherwise login will not work.
1744 if (endsWith($_SERVER['HTTP_HOST'],'.free.fr') && !is_dir($_SERVER['DOCUMENT_ROOT'].'/sessions')) mkdir($_SERVER['DOCUMENT_ROOT'].'/sessions',0705); 1767 if (endsWith($_SERVER['HTTP_HOST'], '.free.fr') && !is_dir($_SERVER['DOCUMENT_ROOT'].'/sessions')) {
1768 mkdir($_SERVER['DOCUMENT_ROOT'].'/sessions', 0705);
1769 }
1745 1770
1746 1771
1747 // This part makes sure sessions works correctly. 1772 // This part makes sure sessions works correctly.
1748 // (Because on some hosts, session.save_path may not be set correctly, 1773 // (Because on some hosts, session.save_path may not be set correctly,
1749 // or we may not have write access to it.) 1774 // or we may not have write access to it.)
1750 if (isset($_GET['test_session']) && ( !isset($_SESSION) || !isset($_SESSION['session_tested']) || $_SESSION['session_tested']!='Working')) 1775 if (isset($_GET['test_session'])
1751 { 1776 && ( !isset($_SESSION) || !isset($_SESSION['session_tested']) || $_SESSION['session_tested']!='Working')) {
1752 // Step 2: Check if data in session is correct. 1777 // Step 2: Check if data in session is correct.
1753 $msg = t( 1778 $msg = t(
1754 '<pre>Sessions do not seem to work correctly on your server.<br>'. 1779 '<pre>Sessions do not seem to work correctly on your server.<br>'.
@@ -1764,19 +1789,18 @@ function install($conf, $sessionManager, $loginManager) {
1764 echo '<br><a href="?">'. t('Click to try again.') .'</a></pre>'; 1789 echo '<br><a href="?">'. t('Click to try again.') .'</a></pre>';
1765 die; 1790 die;
1766 } 1791 }
1767 if (!isset($_SESSION['session_tested'])) 1792 if (!isset($_SESSION['session_tested'])) {
1768 { // Step 1 : Try to store data in session and reload page. 1793 // Step 1 : Try to store data in session and reload page.
1769 $_SESSION['session_tested'] = 'Working'; // Try to set a variable in session. 1794 $_SESSION['session_tested'] = 'Working'; // Try to set a variable in session.
1770 header('Location: '.index_url($_SERVER).'?test_session'); // Redirect to check stored data. 1795 header('Location: '.index_url($_SERVER).'?test_session'); // Redirect to check stored data.
1771 } 1796 }
1772 if (isset($_GET['test_session'])) 1797 if (isset($_GET['test_session'])) {
1773 { // Step 3: Sessions are OK. Remove test parameter from URL. 1798 // Step 3: Sessions are OK. Remove test parameter from URL.
1774 header('Location: '.index_url($_SERVER)); 1799 header('Location: '.index_url($_SERVER));
1775 } 1800 }
1776 1801
1777 1802
1778 if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) 1803 if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) {
1779 {
1780 $tz = 'UTC'; 1804 $tz = 'UTC';
1781 if (!empty($_POST['continent']) && !empty($_POST['city']) 1805 if (!empty($_POST['continent']) && !empty($_POST['city'])
1782 && isTimeZoneValid($_POST['continent'], $_POST['city']) 1806 && isTimeZoneValid($_POST['continent'], $_POST['city'])
@@ -1807,18 +1831,20 @@ function install($conf, $sessionManager, $loginManager) {
1807 try { 1831 try {
1808 // Everything is ok, let's create config file. 1832 // Everything is ok, let's create config file.
1809 $conf->write($loginManager->isLoggedIn()); 1833 $conf->write($loginManager->isLoggedIn());
1810 } 1834 } catch (Exception $e) {
1811 catch(Exception $e) {
1812 error_log( 1835 error_log(
1813 'ERROR while writing config file after installation.' . PHP_EOL . 1836 'ERROR while writing config file after installation.' . PHP_EOL .
1814 $e->getMessage() 1837 $e->getMessage()
1815 ); 1838 );
1816 1839
1817 // TODO: do not handle exceptions/errors in JS. 1840 // TODO: do not handle exceptions/errors in JS.
1818 echo '<script>alert("'. $e->getMessage() .'");document.location=\'?\';</script>'; 1841 echo '<script>alert("'. $e->getMessage() .'");document.location=\'?\';</script>';
1819 exit; 1842 exit;
1820 } 1843 }
1821 echo '<script>alert("Shaarli is now configured. Please enter your login/password and start shaaring your links!");document.location=\'?do=login\';</script>'; 1844 echo '<script>alert('
1845 .'"Shaarli is now configured. '
1846 .'Please enter your login/password and start shaaring your links!"'
1847 .');document.location=\'?do=login\';</script>';
1822 exit; 1848 exit;
1823 } 1849 }
1824 1850
@@ -1842,7 +1868,7 @@ if (!isset($_SESSION['LINKS_PER_PAGE'])) {
1842 1868
1843try { 1869try {
1844 $history = new History($conf->get('resource.history')); 1870 $history = new History($conf->get('resource.history'));
1845} catch(Exception $e) { 1871} catch (Exception $e) {
1846 die($e->getMessage()); 1872 die($e->getMessage());
1847} 1873}
1848 1874
@@ -1861,7 +1887,7 @@ $container['history'] = $history;
1861$app = new \Slim\App($container); 1887$app = new \Slim\App($container);
1862 1888
1863// REST API routes 1889// REST API routes
1864$app->group('/api/v1', function() { 1890$app->group('/api/v1', function () {
1865 $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo')->setName('getInfo'); 1891 $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo')->setName('getInfo');
1866 $this->get('/links', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks'); 1892 $this->get('/links', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks');
1867 $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink'); 1893 $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink');
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 00000000..29b95d56
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,17 @@
1<?xml version="1.0"?>
2<ruleset name="Shaarli">
3 <description>The Shaarli coding standards</description>
4
5 <file>index.php</file>
6 <file>application</file>
7 <file>plugins</file>
8 <file>tests</file>
9
10 <exclude-pattern>*/*.css</exclude-pattern>
11 <exclude-pattern>*/*.js</exclude-pattern>
12
13 <arg name="colors"/>
14
15 <rule ref="PSR1"/>
16 <rule ref="PSR2"/>
17</ruleset>
diff --git a/plugins/archiveorg/archiveorg.php b/plugins/archiveorg/archiveorg.php
index cda35751..5dcea5a6 100644
--- a/plugins/archiveorg/archiveorg.php
+++ b/plugins/archiveorg/archiveorg.php
@@ -17,7 +17,7 @@ function hook_archiveorg_render_linklist($data)
17 $archive_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/archiveorg/archiveorg.html'); 17 $archive_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/archiveorg/archiveorg.html');
18 18
19 foreach ($data['links'] as &$value) { 19 foreach ($data['links'] as &$value) {
20 if($value['private'] && preg_match('/^\?[a-zA-Z0-9-_@]{6}($|&|#)/', $value['real_url'])) { 20 if ($value['private'] && preg_match('/^\?[a-zA-Z0-9-_@]{6}($|&|#)/', $value['real_url'])) {
21 continue; 21 continue;
22 } 22 }
23 $archive = sprintf($archive_html, $value['url'], t('View on archive.org')); 23 $archive = sprintf($archive_html, $value['url'], t('View on archive.org'));
diff --git a/plugins/demo_plugin/demo_plugin.php b/plugins/demo_plugin/demo_plugin.php
index f3a63b6a..ca520d15 100644
--- a/plugins/demo_plugin/demo_plugin.php
+++ b/plugins/demo_plugin/demo_plugin.php
@@ -73,7 +73,6 @@ function hook_demo_plugin_render_header($data)
73{ 73{
74 // Only execute when linklist is rendered. 74 // Only execute when linklist is rendered.
75 if ($data['_PAGE_'] == Router::$PAGE_LINKLIST) { 75 if ($data['_PAGE_'] == Router::$PAGE_LINKLIST) {
76
77 // If loggedin 76 // If loggedin
78 if ($data['_LOGGEDIN_'] === true) { 77 if ($data['_LOGGEDIN_'] === true) {
79 /* 78 /*
@@ -109,10 +108,10 @@ function hook_demo_plugin_render_header($data)
109 * ], 108 * ],
110 * ] 109 * ]
111 * This example renders as: 110 * This example renders as:
112 * <form form-attribute-1="form attribute 1 value" form-attribute-2="form attribute 2 value"> 111 * <form form-attribute-1="form attribute 1 value" form-attribute-2="form attribute 2 value">
113 * <input input-1-attribute-1="input 1 attribute 1 value" input-1-attribute-2="input 1 attribute 2 value"> 112 * <input input-1-attribute-1="input 1 attribute 1 value" input-1-attribute-2="input 1 attribute 2 value">
114 * <input input-2-attribute-1="input 2 attribute 1 value"> 113 * <input input-2-attribute-1="input 2 attribute 1 value">
115 * </form> 114 * </form>
116 */ 115 */
117 $form = array( 116 $form = array(
118 'attr' => array( 117 'attr' => array(
@@ -448,8 +447,7 @@ function hook_demo_plugin_render_feed($data)
448 foreach ($data['links'] as &$link) { 447 foreach ($data['links'] as &$link) {
449 if ($data['_PAGE_'] == Router::$PAGE_FEED_ATOM) { 448 if ($data['_PAGE_'] == Router::$PAGE_FEED_ATOM) {
450 $link['description'] .= ' - ATOM Feed' ; 449 $link['description'] .= ' - ATOM Feed' ;
451 } 450 } elseif ($data['_PAGE_'] == Router::$PAGE_FEED_RSS) {
452 elseif ($data['_PAGE_'] == Router::$PAGE_FEED_RSS) {
453 $link['description'] .= ' - RSS Feed'; 451 $link['description'] .= ' - RSS Feed';
454 } 452 }
455 } 453 }
diff --git a/plugins/markdown/markdown.php b/plugins/markdown/markdown.php
index 08e64dae..8823af91 100644
--- a/plugins/markdown/markdown.php
+++ b/plugins/markdown/markdown.php
@@ -139,7 +139,6 @@ function hook_markdown_render_includes($data)
139 || $data['_PAGE_'] == Router::$PAGE_DAILY 139 || $data['_PAGE_'] == Router::$PAGE_DAILY
140 || $data['_PAGE_'] == Router::$PAGE_EDITLINK 140 || $data['_PAGE_'] == Router::$PAGE_EDITLINK
141 ) { 141 ) {
142
143 $data['css_files'][] = PluginManager::$PLUGINS_PATH . '/markdown/markdown.css'; 142 $data['css_files'][] = PluginManager::$PLUGINS_PATH . '/markdown/markdown.css';
144 } 143 }
145 144
@@ -195,8 +194,7 @@ function reverse_text2clickable($description)
195 // Detect and toggle block of code 194 // Detect and toggle block of code
196 if (!$codeBlockOn) { 195 if (!$codeBlockOn) {
197 $codeBlockOn = preg_match('/^```/', $descriptionLine) > 0; 196 $codeBlockOn = preg_match('/^```/', $descriptionLine) > 0;
198 } 197 } elseif (preg_match('/^```/', $descriptionLine) > 0) {
199 elseif (preg_match('/^```/', $descriptionLine) > 0) {
200 $codeBlockOn = false; 198 $codeBlockOn = false;
201 } 199 }
202 200
@@ -302,13 +300,17 @@ function sanitize_html($description)
302 foreach ($escapeTags as $tag) { 300 foreach ($escapeTags as $tag) {
303 $description = preg_replace_callback( 301 $description = preg_replace_callback(
304 '#<\s*'. $tag .'[^>]*>(.*</\s*'. $tag .'[^>]*>)?#is', 302 '#<\s*'. $tag .'[^>]*>(.*</\s*'. $tag .'[^>]*>)?#is',
305 function ($match) { return escape($match[0]); }, 303 function ($match) {
306 $description); 304 return escape($match[0]);
305 },
306 $description
307 );
307 } 308 }
308 $description = preg_replace( 309 $description = preg_replace(
309 '#(<[^>]+\s)on[a-z]*="?[^ "]*"?#is', 310 '#(<[^>]+\s)on[a-z]*="?[^ "]*"?#is',
310 '$1', 311 '$1',
311 $description); 312 $description
313 );
312 return $description; 314 return $description;
313} 315}
314 316
@@ -341,7 +343,7 @@ function process_markdown($description, $escape = true, $allowedProtocols = [])
341 ->text($processedDescription); 343 ->text($processedDescription);
342 $processedDescription = sanitize_html($processedDescription); 344 $processedDescription = sanitize_html($processedDescription);
343 345
344 if(!empty($processedDescription)){ 346 if (!empty($processedDescription)) {
345 $processedDescription = '<div class="markdown">'. $processedDescription . '</div>'; 347 $processedDescription = '<div class="markdown">'. $processedDescription . '</div>';
346 } 348 }
347 349
diff --git a/plugins/pubsubhubbub/pubsubhubbub.php b/plugins/pubsubhubbub/pubsubhubbub.php
index 184b588b..9f0342a3 100644
--- a/plugins/pubsubhubbub/pubsubhubbub.php
+++ b/plugins/pubsubhubbub/pubsubhubbub.php
@@ -6,7 +6,7 @@
6 * PubSub is a protocol which fasten up RSS fetching: 6 * PubSub is a protocol which fasten up RSS fetching:
7 * - Every time a new link is posted, Shaarli notify the hub. 7 * - Every time a new link is posted, Shaarli notify the hub.
8 * - The hub notify all feed subscribers that a new link has been posted. 8 * - The hub notify all feed subscribers that a new link has been posted.
9 * - Subscribers retrieve the new link. 9 * - Subscribers retrieve the new link.
10 */ 10 */
11 11
12use pubsubhubbub\publisher\Publisher; 12use pubsubhubbub\publisher\Publisher;
@@ -82,7 +82,8 @@ function hook_pubsubhubbub_save_link($data, $conf)
82 * 82 *
83 * @throws Exception An error occurred. 83 * @throws Exception An error occurred.
84 */ 84 */
85function nocurl_http_post($url, $postString) { 85function nocurl_http_post($url, $postString)
86{
86 $params = array('http' => array( 87 $params = array('http' => array(
87 'method' => 'POST', 88 'method' => 'POST',
88 'content' => $postString, 89 'content' => $postString,
diff --git a/plugins/qrcode/qrcode.php b/plugins/qrcode/qrcode.php
index 0f96a106..4b59caa0 100644
--- a/plugins/qrcode/qrcode.php
+++ b/plugins/qrcode/qrcode.php
@@ -17,7 +17,8 @@ function hook_qrcode_render_linklist($data)
17 $qrcode_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/qrcode/qrcode.html'); 17 $qrcode_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/qrcode/qrcode.html');
18 18
19 foreach ($data['links'] as &$value) { 19 foreach ($data['links'] as &$value) {
20 $qrcode = sprintf($qrcode_html, 20 $qrcode = sprintf(
21 $qrcode_html,
21 urlencode($value['url']), 22 urlencode($value['url']),
22 $value['url'], 23 $value['url'],
23 PluginManager::$PLUGINS_PATH 24 PluginManager::$PLUGINS_PATH
diff --git a/plugins/wallabag/wallabag.php b/plugins/wallabag/wallabag.php
index 9dfd079e..a6476c71 100644
--- a/plugins/wallabag/wallabag.php
+++ b/plugins/wallabag/wallabag.php
@@ -69,4 +69,3 @@ function wallabag_dummy_translation()
69 t('Wallabag API URL'); 69 t('Wallabag API URL');
70 t('Wallabag API version (1 or 2)'); 70 t('Wallabag API version (1 or 2)');
71} 71}
72
diff --git a/tests/ApplicationUtilsTest.php b/tests/ApplicationUtilsTest.php
index ff4c9e17..fe5f84ce 100644
--- a/tests/ApplicationUtilsTest.php
+++ b/tests/ApplicationUtilsTest.php
@@ -17,7 +17,7 @@ class FakeApplicationUtils extends ApplicationUtils
17 /** 17 /**
18 * Toggle HTTP requests, allow overriding the version code 18 * Toggle HTTP requests, allow overriding the version code
19 */ 19 */
20 public static function getVersion($url, $timeout=0) 20 public static function getVersion($url, $timeout = 0)
21 { 21 {
22 return self::$VERSION_CODE; 22 return self::$VERSION_CODE;
23 } 23 }
@@ -67,7 +67,7 @@ class ApplicationUtilsTest extends PHPUnit_Framework_TestCase
67 '0.5.4', 67 '0.5.4',
68 ApplicationUtils::getVersion( 68 ApplicationUtils::getVersion(
69 'https://raw.githubusercontent.com/shaarli/Shaarli/' 69 'https://raw.githubusercontent.com/shaarli/Shaarli/'
70 .'v0.5.4/shaarli_version.php', 70 .'v0.5.4/shaarli_version.php',
71 $testTimeout 71 $testTimeout
72 ) 72 )
73 ); 73 );
@@ -75,7 +75,7 @@ class ApplicationUtilsTest extends PHPUnit_Framework_TestCase
75 self::$versionPattern, 75 self::$versionPattern,
76 ApplicationUtils::getVersion( 76 ApplicationUtils::getVersion(
77 'https://raw.githubusercontent.com/shaarli/Shaarli/' 77 'https://raw.githubusercontent.com/shaarli/Shaarli/'
78 .'latest/shaarli_version.php', 78 .'latest/shaarli_version.php',
79 $testTimeout 79 $testTimeout
80 ) 80 )
81 ); 81 );
diff --git a/tests/CacheTest.php b/tests/CacheTest.php
index 992e26a5..f60fad91 100644
--- a/tests/CacheTest.php
+++ b/tests/CacheTest.php
@@ -84,7 +84,7 @@ class CacheTest extends PHPUnit_Framework_TestCase
84 invalidateCaches(self::$testCacheDir); 84 invalidateCaches(self::$testCacheDir);
85 foreach (self::$pages as $page) { 85 foreach (self::$pages as $page) {
86 $this->assertFileNotExists(self::$testCacheDir.'/'.$page.'.cache'); 86 $this->assertFileNotExists(self::$testCacheDir.'/'.$page.'.cache');
87 } 87 }
88 88
89 $this->assertArrayNotHasKey('tags', $_SESSION); 89 $this->assertArrayNotHasKey('tags', $_SESSION);
90 } 90 }
diff --git a/tests/HttpUtils/GetIpAdressFromProxyTest.php b/tests/HttpUtils/GetIpAdressFromProxyTest.php
index 6a74a45a..7af5bd9d 100644
--- a/tests/HttpUtils/GetIpAdressFromProxyTest.php
+++ b/tests/HttpUtils/GetIpAdressFromProxyTest.php
@@ -5,7 +5,8 @@ require_once 'application/HttpUtils.php';
5/** 5/**
6 * Unitary tests for getIpAddressFromProxy() 6 * Unitary tests for getIpAddressFromProxy()
7 */ 7 */
8class GetIpAdressFromProxyTest extends PHPUnit_Framework_TestCase { 8class GetIpAdressFromProxyTest extends PHPUnit_Framework_TestCase
9{
9 10
10 /** 11 /**
11 * Test without proxy 12 * Test without proxy
diff --git a/tests/LinkDBTest.php b/tests/LinkDBTest.php
index fcab76f6..c763c0cb 100644
--- a/tests/LinkDBTest.php
+++ b/tests/LinkDBTest.php
@@ -362,7 +362,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
362 public function testLinkRealUrlWithoutRedirector() 362 public function testLinkRealUrlWithoutRedirector()
363 { 363 {
364 $db = new LinkDB(self::$testDatastore, false, false); 364 $db = new LinkDB(self::$testDatastore, false, false);
365 foreach($db as $link) { 365 foreach ($db as $link) {
366 $this->assertEquals($link['url'], $link['real_url']); 366 $this->assertEquals($link['url'], $link['real_url']);
367 } 367 }
368 } 368 }
@@ -374,13 +374,13 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
374 { 374 {
375 $redirector = 'http://redirector.to?'; 375 $redirector = 'http://redirector.to?';
376 $db = new LinkDB(self::$testDatastore, false, false, $redirector); 376 $db = new LinkDB(self::$testDatastore, false, false, $redirector);
377 foreach($db as $link) { 377 foreach ($db as $link) {
378 $this->assertStringStartsWith($redirector, $link['real_url']); 378 $this->assertStringStartsWith($redirector, $link['real_url']);
379 $this->assertNotFalse(strpos($link['real_url'], urlencode('://'))); 379 $this->assertNotFalse(strpos($link['real_url'], urlencode('://')));
380 } 380 }
381 381
382 $db = new LinkDB(self::$testDatastore, false, false, $redirector, false); 382 $db = new LinkDB(self::$testDatastore, false, false, $redirector, false);
383 foreach($db as $link) { 383 foreach ($db as $link) {
384 $this->assertStringStartsWith($redirector, $link['real_url']); 384 $this->assertStringStartsWith($redirector, $link['real_url']);
385 $this->assertFalse(strpos($link['real_url'], urlencode('://'))); 385 $this->assertFalse(strpos($link['real_url'], urlencode('://')));
386 } 386 }
diff --git a/tests/LinkFilterTest.php b/tests/LinkFilterTest.php
index 9cd6dbd4..eb54c359 100644
--- a/tests/LinkFilterTest.php
+++ b/tests/LinkFilterTest.php
@@ -76,7 +76,15 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
76 76
77 $this->assertEquals( 77 $this->assertEquals(
78 self::$refDB->countUntaggedLinks(), 78 self::$refDB->countUntaggedLinks(),
79 count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, /*$request=*/'', /*$casesensitive=*/false, /*$visibility=*/'all', /*$untaggedonly=*/true)) 79 count(
80 self::$linkFilter->filter(
81 LinkFilter::$FILTER_TAG,
82 /*$request=*/'',
83 /*$casesensitive=*/false,
84 /*$visibility=*/'all',
85 /*$untaggedonly=*/true
86 )
87 )
80 ); 88 );
81 89
82 $this->assertEquals( 90 $this->assertEquals(
@@ -246,7 +254,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
246 2, 254 2,
247 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'ars.userfriendly.org')) 255 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'ars.userfriendly.org'))
248 ); 256 );
249 257
250 $this->assertEquals( 258 $this->assertEquals(
251 2, 259 2,
252 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'ars org')) 260 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'ars org'))
@@ -288,16 +296,16 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
288 1, 296 1,
289 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'publishing media')) 297 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'publishing media'))
290 ); 298 );
291 299
292 $this->assertEquals( 300 $this->assertEquals(
293 1, 301 1,
294 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'mercurial w3c')) 302 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'mercurial w3c'))
295 ); 303 );
296 304
297 $this->assertEquals( 305 $this->assertEquals(
298 3, 306 3,
299 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '"free software"')) 307 count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '"free software"'))
300 ); 308 );
301 } 309 }
302 310
303 /** 311 /**
diff --git a/tests/LinkUtilsTest.php b/tests/LinkUtilsTest.php
index 7fbd59b0..5407159a 100644
--- a/tests/LinkUtilsTest.php
+++ b/tests/LinkUtilsTest.php
@@ -83,7 +83,9 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase
83 'Date: Sat, 28 Oct 2017 12:01:33 GMT', 83 'Date: Sat, 28 Oct 2017 12:01:33 GMT',
84 'Content-Type: text/html; charset=utf-8', 84 'Content-Type: text/html; charset=utf-8',
85 'Status: 200 OK', 85 'Status: 200 OK',
86 'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea', 86 'end' => 'th=device-width">'
87 .'<title>Refactoring · GitHub</title>'
88 .'<link rel="search" type="application/opensea',
87 '<title>ignored</title>', 89 '<title>ignored</title>',
88 ]; 90 ];
89 foreach ($data as $key => $line) { 91 foreach ($data as $key => $line) {
@@ -106,7 +108,9 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase
106 $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_no_charset'); 108 $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_no_charset');
107 $data = [ 109 $data = [
108 'HTTP/1.1 200 OK', 110 'HTTP/1.1 200 OK',
109 'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea', 111 'end' => 'th=device-width">'
112 .'<title>Refactoring · GitHub</title>'
113 .'<link rel="search" type="application/opensea',
110 '<title>ignored</title>', 114 '<title>ignored</title>',
111 ]; 115 ];
112 foreach ($data as $key => $line) { 116 foreach ($data as $key => $line) {
@@ -126,7 +130,9 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase
126 $data = [ 130 $data = [
127 'HTTP/1.1 200 OK', 131 'HTTP/1.1 200 OK',
128 '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />', 132 '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
129 'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea', 133 'end' => 'th=device-width">'
134 .'<title>Refactoring · GitHub</title>'
135 .'<link rel="search" type="application/opensea',
130 '<title>ignored</title>', 136 '<title>ignored</title>',
131 ]; 137 ];
132 foreach ($data as $key => $line) { 138 foreach ($data as $key => $line) {
@@ -211,23 +217,26 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase
211 public function testText2clickableWithoutRedirector() 217 public function testText2clickableWithoutRedirector()
212 { 218 {
213 $text = 'stuff http://hello.there/is=someone#here otherstuff'; 219 $text = 'stuff http://hello.there/is=someone#here otherstuff';
214 $expectedText = 'stuff <a href="http://hello.there/is=someone#here">http://hello.there/is=someone#here</a> otherstuff'; 220 $expectedText = 'stuff <a href="http://hello.there/is=someone#here">'
221 .'http://hello.there/is=someone#here</a> otherstuff';
215 $processedText = text2clickable($text, ''); 222 $processedText = text2clickable($text, '');
216 $this->assertEquals($expectedText, $processedText); 223 $this->assertEquals($expectedText, $processedText);
217 224
218 $text = 'stuff http://hello.there/is=someone#here(please) otherstuff'; 225 $text = 'stuff http://hello.there/is=someone#here(please) otherstuff';
219 $expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)">http://hello.there/is=someone#here(please)</a> otherstuff'; 226 $expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)">'
227 .'http://hello.there/is=someone#here(please)</a> otherstuff';
220 $processedText = text2clickable($text, ''); 228 $processedText = text2clickable($text, '');
221 $this->assertEquals($expectedText, $processedText); 229 $this->assertEquals($expectedText, $processedText);
222 230
223 $text = 'stuff http://hello.there/is=someone#here(please)&no otherstuff'; 231 $text = 'stuff http://hello.there/is=someone#here(please)&no otherstuff';
224 $expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)&no">http://hello.there/is=someone#here(please)&no</a> otherstuff'; 232 $expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)&no">'
233 .'http://hello.there/is=someone#here(please)&no</a> otherstuff';
225 $processedText = text2clickable($text, ''); 234 $processedText = text2clickable($text, '');
226 $this->assertEquals($expectedText, $processedText); 235 $this->assertEquals($expectedText, $processedText);
227 } 236 }
228 237
229 /** 238 /**
230 * Test text2clickable a redirector set. 239 * Test text2clickable with a redirector set.
231 */ 240 */
232 public function testText2clickableWithRedirector() 241 public function testText2clickableWithRedirector()
233 { 242 {
@@ -410,4 +419,3 @@ function ut_curl_getinfo_rs_ct_ko($ch, $type)
410 return 'text/plain'; 419 return 'text/plain';
411 } 420 }
412} 421}
413
diff --git a/tests/RouterTest.php b/tests/RouterTest.php
index 544bcf9c..abf1bd5f 100644
--- a/tests/RouterTest.php
+++ b/tests/RouterTest.php
@@ -218,7 +218,6 @@ class RouterTest extends PHPUnit_Framework_TestCase
218 Router::$PAGE_CHANGEPASSWORD, 218 Router::$PAGE_CHANGEPASSWORD,
219 Router::findPage('do=changepasswd&stuff', array(), true) 219 Router::findPage('do=changepasswd&stuff', array(), true)
220 ); 220 );
221
222 } 221 }
223 222
224 /** 223 /**
diff --git a/tests/ThumbnailerTest.php b/tests/ThumbnailerTest.php
index 08311545..c01849f7 100644
--- a/tests/ThumbnailerTest.php
+++ b/tests/ThumbnailerTest.php
@@ -98,15 +98,17 @@ class ThumbnailerTest extends TestCase
98 ini_set('error_log', $oldlog); 98 ini_set('error_log', $oldlog);
99 } 99 }
100 100
101 protected function rrmdirContent($dir) { 101 protected function rrmdirContent($dir)
102 {
102 if (is_dir($dir)) { 103 if (is_dir($dir)) {
103 $objects = scandir($dir); 104 $objects = scandir($dir);
104 foreach ($objects as $object) { 105 foreach ($objects as $object) {
105 if ($object != "." && $object != "..") { 106 if ($object != "." && $object != "..") {
106 if (is_dir($dir."/".$object)) 107 if (is_dir($dir."/".$object)) {
107 $this->rrmdirContent($dir."/".$object); 108 $this->rrmdirContent($dir."/".$object);
108 else 109 } else {
109 unlink($dir."/".$object); 110 unlink($dir."/".$object);
111 }
110 } 112 }
111 } 113 }
112 } 114 }
diff --git a/tests/Updater/DummyUpdater.php b/tests/Updater/DummyUpdater.php
index a0be4413..a805ab5e 100644
--- a/tests/Updater/DummyUpdater.php
+++ b/tests/Updater/DummyUpdater.php
@@ -31,7 +31,7 @@ class DummyUpdater extends Updater
31 * 31 *
32 * @return bool true. 32 * @return bool true.
33 */ 33 */
34 private final function updateMethodDummy1() 34 final private function updateMethodDummy1()
35 { 35 {
36 return true; 36 return true;
37 } 37 }
@@ -41,7 +41,7 @@ class DummyUpdater extends Updater
41 * 41 *
42 * @return bool true. 42 * @return bool true.
43 */ 43 */
44 private final function updateMethodDummy2() 44 final private function updateMethodDummy2()
45 { 45 {
46 return true; 46 return true;
47 } 47 }
@@ -51,7 +51,7 @@ class DummyUpdater extends Updater
51 * 51 *
52 * @return bool true. 52 * @return bool true.
53 */ 53 */
54 private final function updateMethodDummy3() 54 final private function updateMethodDummy3()
55 { 55 {
56 return true; 56 return true;
57 } 57 }
@@ -61,7 +61,7 @@ class DummyUpdater extends Updater
61 * 61 *
62 * @throws Exception error. 62 * @throws Exception error.
63 */ 63 */
64 private final function updateMethodException() 64 final private function updateMethodException()
65 { 65 {
66 throw new Exception('whatever'); 66 throw new Exception('whatever');
67 } 67 }
diff --git a/tests/Updater/UpdaterTest.php b/tests/Updater/UpdaterTest.php
index 870f169a..c4a6e7ef 100644
--- a/tests/Updater/UpdaterTest.php
+++ b/tests/Updater/UpdaterTest.php
@@ -393,20 +393,32 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
393 $this->assertEquals('Naming conventions... #private', $linkDB[0]['description']); 393 $this->assertEquals('Naming conventions... #private', $linkDB[0]['description']);
394 $this->assertEquals('samba cartoon web', $linkDB[0]['tags']); 394 $this->assertEquals('samba cartoon web', $linkDB[0]['tags']);
395 $this->assertTrue($linkDB[0]['private']); 395 $this->assertTrue($linkDB[0]['private']);
396 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_142300'), $linkDB[0]['created']); 396 $this->assertEquals(
397 DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_142300'),
398 $linkDB[0]['created']
399 );
397 400
398 $this->assertTrue(isset($linkDB[1])); 401 $this->assertTrue(isset($linkDB[1]));
399 $this->assertFalse(isset($linkDB[1]['linkdate'])); 402 $this->assertFalse(isset($linkDB[1]['linkdate']));
400 $this->assertEquals(1, $linkDB[1]['id']); 403 $this->assertEquals(1, $linkDB[1]['id']);
401 $this->assertEquals('UserFriendly - Samba', $linkDB[1]['title']); 404 $this->assertEquals('UserFriendly - Samba', $linkDB[1]['title']);
402 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_172539'), $linkDB[1]['created']); 405 $this->assertEquals(
406 DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_172539'),
407 $linkDB[1]['created']
408 );
403 409
404 $this->assertTrue(isset($linkDB[2])); 410 $this->assertTrue(isset($linkDB[2]));
405 $this->assertFalse(isset($linkDB[2]['linkdate'])); 411 $this->assertFalse(isset($linkDB[2]['linkdate']));
406 $this->assertEquals(2, $linkDB[2]['id']); 412 $this->assertEquals(2, $linkDB[2]['id']);
407 $this->assertEquals('Geek and Poke', $linkDB[2]['title']); 413 $this->assertEquals('Geek and Poke', $linkDB[2]['title']);
408 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_182539'), $linkDB[2]['created']); 414 $this->assertEquals(
409 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_190301'), $linkDB[2]['updated']); 415 DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_182539'),
416 $linkDB[2]['created']
417 );
418 $this->assertEquals(
419 DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_190301'),
420 $linkDB[2]['updated']
421 );
410 } 422 }
411 423
412 /** 424 /**
diff --git a/tests/Url/CleanupUrlTest.php b/tests/Url/CleanupUrlTest.php
index 1407d7d2..24791948 100644
--- a/tests/Url/CleanupUrlTest.php
+++ b/tests/Url/CleanupUrlTest.php
@@ -107,4 +107,3 @@ class CleanupUrlTest extends PHPUnit_Framework_TestCase
107 ); 107 );
108 } 108 }
109} 109}
110
diff --git a/tests/Url/GetUrlSchemeTest.php b/tests/Url/GetUrlSchemeTest.php
index 72d80b30..18b932d6 100644
--- a/tests/Url/GetUrlSchemeTest.php
+++ b/tests/Url/GetUrlSchemeTest.php
@@ -28,4 +28,3 @@ class GetUrlSchemeTest extends PHPUnit_Framework_TestCase
28 $this->assertEquals('git', get_url_scheme('git://domain.tld/push?pull=clone#checkout')); 28 $this->assertEquals('git', get_url_scheme('git://domain.tld/push?pull=clone#checkout'));
29 } 29 }
30} 30}
31
diff --git a/tests/Url/UnparseUrlTest.php b/tests/Url/UnparseUrlTest.php
index edde73e4..e314b484 100644
--- a/tests/Url/UnparseUrlTest.php
+++ b/tests/Url/UnparseUrlTest.php
@@ -28,4 +28,3 @@ class UnparseUrlTest extends PHPUnit_Framework_TestCase
28 $this->assertEquals($ref, unparse_url(parse_url($ref))); 28 $this->assertEquals($ref, unparse_url(parse_url($ref)));
29 } 29 }
30} 30}
31
diff --git a/tests/Url/UrlTest.php b/tests/Url/UrlTest.php
index aa2f2234..db229ce0 100644
--- a/tests/Url/UrlTest.php
+++ b/tests/Url/UrlTest.php
@@ -16,7 +16,7 @@ class UrlTest extends PHPUnit_Framework_TestCase
16 /** 16 /**
17 * Helper method 17 * Helper method
18 */ 18 */
19 private function assertUrlIsCleaned($query='', $fragment='') 19 private function assertUrlIsCleaned($query = '', $fragment = '')
20 { 20 {
21 $url = new Url(self::$baseUrl.$query.$fragment); 21 $url = new Url(self::$baseUrl.$query.$fragment);
22 $url->cleanup(); 22 $url->cleanup();
@@ -135,13 +135,13 @@ class UrlTest extends PHPUnit_Framework_TestCase
135 'about://reader?url=' . urlencode(self::$baseUrl .'?my=stuff&is=kept') 135 'about://reader?url=' . urlencode(self::$baseUrl .'?my=stuff&is=kept')
136 ); 136 );
137 $this->assertEquals(self::$baseUrl.'?my=stuff&is=kept', $url->cleanup()); 137 $this->assertEquals(self::$baseUrl.'?my=stuff&is=kept', $url->cleanup());
138
139 } 138 }
140 139
141 /** 140 /**
142 * Test default http scheme. 141 * Test default http scheme.
143 */ 142 */
144 public function testDefaultScheme() { 143 public function testDefaultScheme()
144 {
145 $url = new Url(self::$baseUrl); 145 $url = new Url(self::$baseUrl);
146 $this->assertEquals('http', $url->getScheme()); 146 $this->assertEquals('http', $url->getScheme());
147 $url = new Url('domain.tld'); 147 $url = new Url('domain.tld');
diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php
index 6cd37a7a..d0abd996 100644
--- a/tests/UtilsTest.php
+++ b/tests/UtilsTest.php
@@ -187,7 +187,8 @@ class UtilsTest extends PHPUnit_Framework_TestCase
187 /** 187 /**
188 * Test generate location with valid data. 188 * Test generate location with valid data.
189 */ 189 */
190 public function testGenerateLocation() { 190 public function testGenerateLocation()
191 {
191 $ref = 'http://localhost/?test'; 192 $ref = 'http://localhost/?test';
192 $this->assertEquals($ref, generateLocation($ref, 'localhost')); 193 $this->assertEquals($ref, generateLocation($ref, 'localhost'));
193 $ref = 'http://localhost:8080/?test'; 194 $ref = 'http://localhost:8080/?test';
@@ -199,7 +200,8 @@ class UtilsTest extends PHPUnit_Framework_TestCase
199 /** 200 /**
200 * Test generate location - anti loop. 201 * Test generate location - anti loop.
201 */ 202 */
202 public function testGenerateLocationLoop() { 203 public function testGenerateLocationLoop()
204 {
203 $ref = 'http://localhost/?test'; 205 $ref = 'http://localhost/?test';
204 $this->assertEquals('?', generateLocation($ref, 'localhost', array('test'))); 206 $this->assertEquals('?', generateLocation($ref, 'localhost', array('test')));
205 } 207 }
@@ -207,7 +209,8 @@ class UtilsTest extends PHPUnit_Framework_TestCase
207 /** 209 /**
208 * Test generate location - from other domain. 210 * Test generate location - from other domain.
209 */ 211 */
210 public function testGenerateLocationOut() { 212 public function testGenerateLocationOut()
213 {
211 $ref = 'http://somewebsite.com/?test'; 214 $ref = 'http://somewebsite.com/?test';
212 $this->assertEquals('?', generateLocation($ref, 'localhost')); 215 $this->assertEquals('?', generateLocation($ref, 'localhost'));
213 } 216 }
diff --git a/tests/api/ApiUtilsTest.php b/tests/api/ApiUtilsTest.php
index 62baf4c5..df4e189a 100644
--- a/tests/api/ApiUtilsTest.php
+++ b/tests/api/ApiUtilsTest.php
@@ -4,7 +4,6 @@ namespace Shaarli\Api;
4 4
5use Shaarli\Base64Url; 5use Shaarli\Base64Url;
6 6
7
8/** 7/**
9 * Class ApiUtilsTest 8 * Class ApiUtilsTest
10 */ 9 */
@@ -34,7 +33,7 @@ class ApiUtilsTest extends \PHPUnit_Framework_TestCase
34 $payload = Base64Url::encode('{ 33 $payload = Base64Url::encode('{
35 "iat": '. time() .' 34 "iat": '. time() .'
36 }'); 35 }');
37 $signature = Base64Url::encode(hash_hmac('sha512', $header .'.'. $payload , $secret, true)); 36 $signature = Base64Url::encode(hash_hmac('sha512', $header .'.'. $payload, $secret, true));
38 return $header .'.'. $payload .'.'. $signature; 37 return $header .'.'. $payload .'.'. $signature;
39 } 38 }
40 39
diff --git a/tests/api/controllers/history/HistoryTest.php b/tests/api/controllers/history/HistoryTest.php
index 61046d97..ff34e16d 100644
--- a/tests/api/controllers/history/HistoryTest.php
+++ b/tests/api/controllers/history/HistoryTest.php
@@ -3,7 +3,6 @@
3 3
4namespace Shaarli\Api\Controllers; 4namespace Shaarli\Api\Controllers;
5 5
6
7use Shaarli\Config\ConfigManager; 6use Shaarli\Config\ConfigManager;
8use Slim\Container; 7use Slim\Container;
9use Slim\Http\Environment; 8use Slim\Http\Environment;
diff --git a/tests/api/controllers/info/InfoTest.php b/tests/api/controllers/info/InfoTest.php
index f7e63bfa..e437082a 100644
--- a/tests/api/controllers/info/InfoTest.php
+++ b/tests/api/controllers/info/InfoTest.php
@@ -10,9 +10,9 @@ use Slim\Http\Response;
10 10
11/** 11/**
12 * Class InfoTest 12 * Class InfoTest
13 * 13 *
14 * Test REST API controller Info. 14 * Test REST API controller Info.
15 * 15 *
16 * @package Api\Controllers 16 * @package Api\Controllers
17 */ 17 */
18class InfoTest extends \PHPUnit_Framework_TestCase 18class InfoTest extends \PHPUnit_Framework_TestCase
diff --git a/tests/api/controllers/links/PostLinkTest.php b/tests/api/controllers/links/PostLinkTest.php
index 100a9170..5c2b5623 100644
--- a/tests/api/controllers/links/PostLinkTest.php
+++ b/tests/api/controllers/links/PostLinkTest.php
@@ -2,7 +2,6 @@
2 2
3namespace Shaarli\Api\Controllers; 3namespace Shaarli\Api\Controllers;
4 4
5
6use PHPUnit\Framework\TestCase; 5use PHPUnit\Framework\TestCase;
7use Shaarli\Config\ConfigManager; 6use Shaarli\Config\ConfigManager;
8use Slim\Container; 7use Slim\Container;
@@ -128,7 +127,9 @@ class PostLinkTest extends TestCase
128 $this->assertEquals('', $data['description']); 127 $this->assertEquals('', $data['description']);
129 $this->assertEquals([], $data['tags']); 128 $this->assertEquals([], $data['tags']);
130 $this->assertEquals(false, $data['private']); 129 $this->assertEquals(false, $data['private']);
131 $this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])); 130 $this->assertTrue(
131 new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
132 );
132 $this->assertEquals('', $data['updated']); 133 $this->assertEquals('', $data['updated']);
133 134
134 $historyEntry = $this->history->getHistory()[0]; 135 $historyEntry = $this->history->getHistory()[0];
@@ -171,7 +172,9 @@ class PostLinkTest extends TestCase
171 $this->assertEquals($link['description'], $data['description']); 172 $this->assertEquals($link['description'], $data['description']);
172 $this->assertEquals($link['tags'], $data['tags']); 173 $this->assertEquals($link['tags'], $data['tags']);
173 $this->assertEquals(true, $data['private']); 174 $this->assertEquals(true, $data['private']);
174 $this->assertTrue(new \DateTime('2 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])); 175 $this->assertTrue(
176 new \DateTime('2 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
177 );
175 $this->assertEquals('', $data['updated']); 178 $this->assertEquals('', $data['updated']);
176 } 179 }
177 180
diff --git a/tests/api/controllers/links/PutLinkTest.php b/tests/api/controllers/links/PutLinkTest.php
index 8a562571..f276b4c1 100644
--- a/tests/api/controllers/links/PutLinkTest.php
+++ b/tests/api/controllers/links/PutLinkTest.php
@@ -3,7 +3,6 @@
3 3
4namespace Shaarli\Api\Controllers; 4namespace Shaarli\Api\Controllers;
5 5
6
7use Shaarli\Config\ConfigManager; 6use Shaarli\Config\ConfigManager;
8use Slim\Container; 7use Slim\Container;
9use Slim\Http\Environment; 8use Slim\Http\Environment;
@@ -115,7 +114,9 @@ class PutLinkTest extends \PHPUnit_Framework_TestCase
115 \DateTime::createFromFormat('Ymd_His', '20150310_114651'), 114 \DateTime::createFromFormat('Ymd_His', '20150310_114651'),
116 \DateTime::createFromFormat(\DateTime::ATOM, $data['created']) 115 \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
117 ); 116 );
118 $this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])); 117 $this->assertTrue(
118 new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
119 );
119 120
120 $historyEntry = $this->history->getHistory()[0]; 121 $historyEntry = $this->history->getHistory()[0];
121 $this->assertEquals(\History::UPDATED, $historyEntry['event']); 122 $this->assertEquals(\History::UPDATED, $historyEntry['event']);
@@ -160,7 +161,9 @@ class PutLinkTest extends \PHPUnit_Framework_TestCase
160 \DateTime::createFromFormat('Ymd_His', '20150310_114651'), 161 \DateTime::createFromFormat('Ymd_His', '20150310_114651'),
161 \DateTime::createFromFormat(\DateTime::ATOM, $data['created']) 162 \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
162 ); 163 );
163 $this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])); 164 $this->assertTrue(
165 new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
166 );
164 } 167 }
165 168
166 /** 169 /**
diff --git a/tests/api/controllers/tags/PutTagTest.php b/tests/api/controllers/tags/PutTagTest.php
index 6f7dec22..38017243 100644
--- a/tests/api/controllers/tags/PutTagTest.php
+++ b/tests/api/controllers/tags/PutTagTest.php
@@ -3,7 +3,6 @@
3 3
4namespace Shaarli\Api\Controllers; 4namespace Shaarli\Api\Controllers;
5 5
6
7use Shaarli\Api\Exceptions\ApiBadParametersException; 6use Shaarli\Api\Exceptions\ApiBadParametersException;
8use Shaarli\Config\ConfigManager; 7use Shaarli\Config\ConfigManager;
9use Slim\Container; 8use Slim\Container;
diff --git a/tests/languages/de/UtilsDeTest.php b/tests/languages/de/UtilsDeTest.php
index 4569c923..588c9fd6 100644
--- a/tests/languages/de/UtilsDeTest.php
+++ b/tests/languages/de/UtilsDeTest.php
@@ -20,7 +20,7 @@ class UtilsDeTest extends UtilsTest
20 public function testDateFormatNoTime() 20 public function testDateFormatNoTime()
21 { 21 {
22 $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); 22 $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
23 $this->assertRegExp('/1\. Januar 2017/', format_date($date, false,true)); 23 $this->assertRegExp('/1\. Januar 2017/', format_date($date, false, true));
24 } 24 }
25 25
26 /** 26 /**
diff --git a/tests/languages/fr/LanguagesFrTest.php b/tests/languages/fr/LanguagesFrTest.php
index 0cf74891..38347de1 100644
--- a/tests/languages/fr/LanguagesFrTest.php
+++ b/tests/languages/fr/LanguagesFrTest.php
@@ -3,7 +3,6 @@
3 3
4namespace Shaarli; 4namespace Shaarli;
5 5
6
7use Shaarli\Config\ConfigManager; 6use Shaarli\Config\ConfigManager;
8 7
9/** 8/**
diff --git a/tests/plugins/PluginQrcodeTest.php b/tests/plugins/PluginQrcodeTest.php
index ebfadddf..dd632eee 100644
--- a/tests/plugins/PluginQrcodeTest.php
+++ b/tests/plugins/PluginQrcodeTest.php
@@ -15,7 +15,8 @@ class PluginQrcodeTest extends PHPUnit_Framework_TestCase
15 /** 15 /**
16 * Reset plugin path 16 * Reset plugin path
17 */ 17 */
18 public function setUp() { 18 public function setUp()
19 {
19 PluginManager::$PLUGINS_PATH = 'plugins'; 20 PluginManager::$PLUGINS_PATH = 'plugins';
20 } 21 }
21 22
diff --git a/tests/security/SessionManagerTest.php b/tests/security/SessionManagerTest.php
index 9bd868f8..7961e771 100644
--- a/tests/security/SessionManagerTest.php
+++ b/tests/security/SessionManagerTest.php
@@ -8,7 +8,6 @@ ReferenceSessionIdHashes::genAllHashes();
8use \Shaarli\Security\SessionManager; 8use \Shaarli\Security\SessionManager;
9use \PHPUnit\Framework\TestCase; 9use \PHPUnit\Framework\TestCase;
10 10
11
12/** 11/**
13 * Test coverage for SessionManager 12 * Test coverage for SessionManager
14 */ 13 */
diff --git a/tests/utils/ReferenceLinkDB.php b/tests/utils/ReferenceLinkDB.php
index 7426ad07..59679e38 100644
--- a/tests/utils/ReferenceLinkDB.php
+++ b/tests/utils/ReferenceLinkDB.php
@@ -150,8 +150,8 @@ class ReferenceLinkDB
150 $tags, 150 $tags,
151 $updated = '', 151 $updated = '',
152 $shorturl = '', 152 $shorturl = '',
153 $pinned = false) 153 $pinned = false
154 { 154 ) {
155 $link = array( 155 $link = array(
156 'id' => $id, 156 'id' => $id,
157 'title' => $title, 157 'title' => $title,
@@ -201,7 +201,7 @@ class ReferenceLinkDB
201 201
202 $order = $order === 'ASC' ? -1 : 1; 202 $order = $order === 'ASC' ? -1 : 1;
203 // Reorder array by dates. 203 // Reorder array by dates.
204 usort($this->_links, function($a, $b) use ($order) { 204 usort($this->_links, function ($a, $b) use ($order) {
205 if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) { 205 if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) {
206 return $a['sticky'] ? -1 : 1; 206 return $a['sticky'] ? -1 : 1;
207 } 207 }
diff --git a/tests/utils/config/configPhp.php b/tests/utils/config/configPhp.php
index 0e034175..34b11fcd 100644
--- a/tests/utils/config/configPhp.php
+++ b/tests/utils/config/configPhp.php
@@ -1,4 +1,4 @@
1<?php 1<?php
2$GLOBALS['login'] = 'root'; 2$GLOBALS['login'] = 'root';
3$GLOBALS['hash'] = 'hash'; 3$GLOBALS['hash'] = 'hash';
4$GLOBALS['salt'] = 'salt'; 4$GLOBALS['salt'] = 'salt';