diff options
101 files changed, 1207 insertions, 1194 deletions
@@ -1,6 +1,6 @@ | |||
1 | 687 ArthurHoaro <arthur@hoa.ro> | 1 | 715 ArthurHoaro <arthur@hoa.ro> |
2 | 355 VirtualTam <virtualtam@flibidi.net> | 2 | 370 VirtualTam <virtualtam@flibidi.net> |
3 | 195 nodiscc <nodiscc@gmail.com> | 3 | 208 nodiscc <nodiscc@gmail.com> |
4 | 56 Sébastien Sauvage <sebsauvage@sebsauvage.net> | 4 | 56 Sébastien Sauvage <sebsauvage@sebsauvage.net> |
5 | 15 Florian Eula <eula.florian@gmail.com> | 5 | 15 Florian Eula <eula.florian@gmail.com> |
6 | 13 Emilien Klein <emilien@klein.st> | 6 | 13 Emilien Klein <emilien@klein.st> |
@@ -8,6 +8,7 @@ | |||
8 | 9 Willi Eggeling <thewilli@gmail.com> | 8 | 9 Willi Eggeling <thewilli@gmail.com> |
9 | 8 Christophe HENRY <christophe.henry@sbgodin.fr> | 9 | 8 Christophe HENRY <christophe.henry@sbgodin.fr> |
10 | 6 B. van Berkum <dev@dotmpe.com> | 10 | 6 B. van Berkum <dev@dotmpe.com> |
11 | 6 llune <llune@users.noreply.github.com> | ||
11 | 5 Lucas Cimon <lucas.cimon@gmail.com> | 12 | 5 Lucas Cimon <lucas.cimon@gmail.com> |
12 | 5 Mark Schmitz <kramred@gmail.com> | 13 | 5 Mark Schmitz <kramred@gmail.com> |
13 | 5 kalvn <kalvnthereal@gmail.com> | 14 | 5 kalvn <kalvnthereal@gmail.com> |
@@ -15,10 +16,11 @@ | |||
15 | 4 David Sferruzza <david.sferruzza@gmail.com> | 16 | 4 David Sferruzza <david.sferruzza@gmail.com> |
16 | 4 Immánuel Fodor <immanuelfactor+github@gmail.com> | 17 | 4 Immánuel Fodor <immanuelfactor+github@gmail.com> |
17 | 3 Teromene <teromene@teromene.fr> | 18 | 3 Teromene <teromene@teromene.fr> |
18 | 3 llune <llune@users.noreply.github.com> | 19 | 2 Alexandre G.-Raymond <alex@ndre.gr> |
19 | 2 Chris Kuethe <chris.kuethe@gmail.com> | 20 | 2 Chris Kuethe <chris.kuethe@gmail.com> |
20 | 2 Felix Bartels <felix@host-consultants.de> | 21 | 2 Felix Bartels <felix@host-consultants.de> |
21 | 2 Knah Tsaeb <Knah-Tsaeb@knah-tsaeb.org> | 22 | 2 Knah Tsaeb <Knah-Tsaeb@knah-tsaeb.org> |
23 | 2 Luce Carević <lcarevic@access42.net> | ||
22 | 2 Mathieu Chabanon <git@matchab.fr> | 24 | 2 Mathieu Chabanon <git@matchab.fr> |
23 | 2 Miloš Jovanović <mjovanovic@gmail.com> | 25 | 2 Miloš Jovanović <mjovanovic@gmail.com> |
24 | 2 Qwerty <champlywood@free.fr> | 26 | 2 Qwerty <champlywood@free.fr> |
@@ -29,9 +31,9 @@ | |||
29 | 2 pips <pips@e5150.fr> | 31 | 2 pips <pips@e5150.fr> |
30 | 1 Adrien Oliva <adrien.oliva@yapbreak.fr> | 32 | 1 Adrien Oliva <adrien.oliva@yapbreak.fr> |
31 | 1 Adrien le Maire <adrien@alemaire.be> | 33 | 1 Adrien le Maire <adrien@alemaire.be> |
32 | 1 Alexandre G.-Raymond <alex@ndre.gr> | ||
33 | 1 Alexis J <alexis@effingo.be> | 34 | 1 Alexis J <alexis@effingo.be> |
34 | 1 Angristan <angristan@users.noreply.github.com> | 35 | 1 Angristan <angristan@users.noreply.github.com> |
36 | 1 Bish Erbas <42714627+bisherbas@users.noreply.github.com> | ||
35 | 1 BoboTiG <bobotig@gmail.com> | 37 | 1 BoboTiG <bobotig@gmail.com> |
36 | 1 Bronco <bronco@warriordudimanche.net> | 38 | 1 Bronco <bronco@warriordudimanche.net> |
37 | 1 Buster One <37770318+buster-one@users.noreply.github.com> | 39 | 1 Buster One <37770318+buster-one@users.noreply.github.com> |
diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e2464a3..c4f77fa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md | |||
@@ -4,6 +4,36 @@ All notable changes to this project will be documented in this file. | |||
4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) |
5 | and this project adheres to [Semantic Versioning](http://semver.org/). | 5 | and this project adheres to [Semantic Versioning](http://semver.org/). |
6 | 6 | ||
7 | |||
8 | ## [v0.10.3](https://github.com/shaarli/Shaarli/releases/tag/v0.10.3) - 2019-02-23 | ||
9 | ### Added | ||
10 | - Add OpenGraph metadata tags on permalink page | ||
11 | - Add CORS headers to REST API reponses | ||
12 | - Add a button to toggle checkboxes of displayed links | ||
13 | - Add an icon to the link list when the Isso plugin is enabled | ||
14 | - Add noindex, nofollow to documentation pages | ||
15 | - Document usage of robots.txt | ||
16 | - Add a button to set links as sticky | ||
17 | |||
18 | ### Changed | ||
19 | - Update French translation | ||
20 | - Refactor the documentation homepage | ||
21 | - Bump netscape-bookmark-parser | ||
22 | - Update session_start condition | ||
23 | - Improve accessibility | ||
24 | - Cleanup and refactor lint tooling | ||
25 | |||
26 | ### Fixed | ||
27 | - Fix input size for dropdown search form | ||
28 | - Fix history for bulk link deletion | ||
29 | - Fix thumbnail requests | ||
30 | - Fix hashtag rendering when markdown escaping is enabled | ||
31 | - Fix AJAX tag deletion | ||
32 | - Fix lint errors and improve PSR-1 and PSR-2 compliance | ||
33 | |||
34 | ### Removed | ||
35 | - Remove Firefox Share documentation | ||
36 | |||
7 | ## [v0.10.2](https://github.com/shaarli/Shaarli/releases/tag/v0.10.2) - 2018-08-11 | 37 | ## [v0.10.2](https://github.com/shaarli/Shaarli/releases/tag/v0.10.2) - 2018-08-11 |
8 | 38 | ||
9 | ### Fixed | 39 | ### Fixed |
@@ -12,7 +42,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). | |||
12 | 42 | ||
13 | ## [v0.10.1](https://github.com/shaarli/Shaarli/releases/tag/v0.10.1) - 2018-08-11 | 43 | ## [v0.10.1](https://github.com/shaarli/Shaarli/releases/tag/v0.10.1) - 2018-08-11 |
14 | 44 | ||
15 | ### Changed | 45 | ### Changed |
16 | 46 | ||
17 | - Accessibility: | 47 | - Accessibility: |
18 | - Remove alt text on the logo | 48 | - Remove alt text on the logo |
@@ -46,7 +76,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). | |||
46 | - Use Travis matrix and stages to run Javascript tests in a dedicated environment | 76 | - Use Travis matrix and stages to run Javascript tests in a dedicated environment |
47 | - Add tag endpoint in the REST API | 77 | - Add tag endpoint in the REST API |
48 | - Build the documentation in Travis builds | 78 | - Build the documentation in Travis builds |
49 | - Provide a Docker Compose example | 79 | - Provide a Docker Compose example |
50 | 80 | ||
51 | ### Changed | 81 | ### Changed |
52 | - Use web-thumbnailer to retrieve thumbnails (see #687) | 82 | - Use web-thumbnailer to retrieve thumbnails (see #687) |
@@ -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 | ||
4 | BIN = vendor/bin | 4 | BIN = vendor/bin |
5 | PHP_SOURCE = index.php application tests plugins | ||
6 | PHP_COMMA_SOURCE = index.php,application,tests,plugins | ||
7 | 5 | ||
8 | all: static_analysis_summary check_permissions test | 6 | all: 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 | |||
25 | static_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 | ## |
25 | PHPCS := $(BIN)/phpcs | ||
35 | 26 | ||
36 | code_sniffer: code_sniffer_full | 27 | code_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... |
39 | PHPCS_%: | 31 | PHPCS_%: |
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 |
43 | code_sniffer_blame: | 35 | code_sniffer_blame: |
44 | @$(BIN)/phpcs $(PHP_SOURCE) --report-gitblame | 36 | @$(PHPCS) --report-gitblame |
45 | 37 | ||
46 | ### - all errors/warnings | 38 | ### - all errors/warnings |
47 | code_sniffer_full: | 39 | code_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 |
51 | code_sniffer_source: | 43 | code_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 | |||
60 | copy_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 | ## | ||
72 | MESS_DETECTOR_RULES = cleancode,codesize,controversial,design,naming,unusedcode | ||
73 | |||
74 | mess_title: | ||
75 | @echo "-----------------" | ||
76 | @echo "PHP MESS DETECTOR" | ||
77 | @echo "-----------------" | ||
78 | |||
79 | ### - all warnings | ||
80 | mess_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 | ||
84 | mess_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 | ||
89 | mess_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 | ||
94 | mess_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 |
@@ -9,7 +9,7 @@ _It is designed to be personal (single-user), fast and handy._ | |||
9 | [![](https://img.shields.io/badge/stable-v0.9.7-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.9.7) | 9 | [![](https://img.shields.io/badge/stable-v0.9.7-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.9.7) |
10 | [![](https://img.shields.io/travis/shaarli/Shaarli/stable.svg?label=stable)](https://travis-ci.org/shaarli/Shaarli) | 10 | [![](https://img.shields.io/travis/shaarli/Shaarli/stable.svg?label=stable)](https://travis-ci.org/shaarli/Shaarli) |
11 | • | 11 | • |
12 | [![](https://img.shields.io/badge/latest-v0.10.1-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.10.1) | 12 | [![](https://img.shields.io/badge/latest-v0.10.2-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.10.2) |
13 | [![](https://img.shields.io/travis/shaarli/Shaarli/latest.svg?label=latest)](https://travis-ci.org/shaarli/Shaarli) | 13 | [![](https://img.shields.io/travis/shaarli/Shaarli/latest.svg?label=latest)](https://travis-ci.org/shaarli/Shaarli) |
14 | • | 14 | • |
15 | [![](https://img.shields.io/badge/master-v0.10.x-blue.svg)](https://github.com/shaarli/Shaarli) | 15 | [![](https://img.shields.io/badge/master-v0.10.x-blue.svg)](https://github.com/shaarli/Shaarli) |
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 | ||
3 | namespace Shaarli; | 3 | namespace 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 cd0f2967..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 | ||
255 | To learn how to use Shaarli, consult the link "Documentation" at the bottom of this page. | 256 | To learn how to use Shaarli, consult the link "Documentation" at the bottom of this page. |
256 | 257 | ||
257 | You use the community supported version of the original Shaarli project, by Sebastien Sauvage.'), | 258 | You 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,10 @@ 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) { |
545 | if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) { | ||
546 | return $a['sticky'] ? -1 : 1; | ||
547 | } | ||
540 | return $a['created'] < $b['created'] ? 1 * $order : -1 * $order; | 548 | return $a['created'] < $b['created'] ? 1 * $order : -1 * $order; |
541 | }); | 549 | }); |
542 | 550 | ||
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 | */ |
204 | function format_description($description, $redirector = '', $urlEncode = true, $indexUrl = '') { | 204 | function 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 b1abe0d0..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', ''); |
@@ -101,7 +100,7 @@ class PageBuilder | |||
101 | 'version_hash', | 100 | 'version_hash', |
102 | ApplicationUtils::getVersionHash(SHAARLI_VERSION, $this->conf->get('credentials.salt')) | 101 | ApplicationUtils::getVersionHash(SHAARLI_VERSION, $this->conf->get('credentials.salt')) |
103 | ); | 102 | ); |
104 | $this->tpl->assign('scripturl', index_url($_SERVER)); | 103 | $this->tpl->assign('index_url', index_url($_SERVER)); |
105 | $visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : ''; | 104 | $visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : ''; |
106 | $this->tpl->assign('visibility', $visibility); | 105 | $this->tpl->assign('visibility', $visibility); |
107 | $this->tpl->assign('untaggedonly', !empty($_SESSION['untaggedonly'])); | 106 | $this->tpl->assign('untaggedonly', !empty($_SESSION['untaggedonly'])); |
@@ -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/Router.php b/application/Router.php index bf86b884..beb3165b 100644 --- a/application/Router.php +++ b/application/Router.php | |||
@@ -37,6 +37,8 @@ class Router | |||
37 | 37 | ||
38 | public static $PAGE_DELETELINK = 'delete_link'; | 38 | public static $PAGE_DELETELINK = 'delete_link'; |
39 | 39 | ||
40 | public static $PAGE_PINLINK = 'pin'; | ||
41 | |||
40 | public static $PAGE_EXPORT = 'export'; | 42 | public static $PAGE_EXPORT = 'export'; |
41 | 43 | ||
42 | public static $PAGE_IMPORT = 'import'; | 44 | public static $PAGE_IMPORT = 'import'; |
@@ -146,6 +148,10 @@ class Router | |||
146 | return self::$PAGE_DELETELINK; | 148 | return self::$PAGE_DELETELINK; |
147 | } | 149 | } |
148 | 150 | ||
151 | if (startsWith($query, 'do='. self::$PAGE_PINLINK)) { | ||
152 | return self::$PAGE_PINLINK; | ||
153 | } | ||
154 | |||
149 | if (startsWith($query, 'do='. self::$PAGE_EXPORT)) { | 155 | if (startsWith($query, 'do='. self::$PAGE_EXPORT)) { |
150 | return self::$PAGE_EXPORT; | 156 | return self::$PAGE_EXPORT; |
151 | } | 157 | } |
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 480bff82..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) { |
@@ -517,6 +517,26 @@ class Updater | |||
517 | 517 | ||
518 | return true; | 518 | return true; |
519 | } | 519 | } |
520 | |||
521 | /** | ||
522 | * Set sticky = false on all links | ||
523 | * | ||
524 | * @return bool true if the update is successful, false otherwise. | ||
525 | */ | ||
526 | public function updateMethodSetSticky() | ||
527 | { | ||
528 | foreach ($this->linkDB as $key => $link) { | ||
529 | if (isset($link['sticky'])) { | ||
530 | return true; | ||
531 | } | ||
532 | $link['sticky'] = false; | ||
533 | $this->linkDB[$key] = $link; | ||
534 | } | ||
535 | |||
536 | $this->linkDB->save($this->conf->get('resource.page_cache')); | ||
537 | |||
538 | return true; | ||
539 | } | ||
520 | } | 540 | } |
521 | 541 | ||
522 | /** | 542 | /** |
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 | */ |
35 | function cleanup_url($url) | 35 | function 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 | */ |
48 | function get_url_scheme($url) | 48 | function 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 | */ |
455 | function t($text, $nText = '', $nb = 1, $domain = 'shaarli') { | 458 | function 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 | */ |
13 | abstract class ApiException extends \Exception { | 13 | abstract 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 | ||
3 | namespace Shaarli\Api\Exceptions; | 3 | namespace Shaarli\Api\Exceptions; |
4 | 4 | ||
5 | |||
6 | use Slim\Http\Response; | 5 | use 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 | ||
3 | namespace Shaarli\Api\Exceptions; | 3 | namespace Shaarli\Api\Exceptions; |
4 | 4 | ||
5 | |||
6 | use Slim\Http\Response; | 5 | use 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/assets/default/js/base.js b/assets/default/js/base.js index 8bf79d3e..99e03370 100644 --- a/assets/default/js/base.js +++ b/assets/default/js/base.js | |||
@@ -422,12 +422,12 @@ function init(description) { | |||
422 | /** | 422 | /** |
423 | * Bulk actions | 423 | * Bulk actions |
424 | */ | 424 | */ |
425 | const linkCheckboxes = document.querySelectorAll('.delete-checkbox'); | 425 | const linkCheckboxes = document.querySelectorAll('.link-checkbox'); |
426 | const bar = document.getElementById('actions'); | 426 | const bar = document.getElementById('actions'); |
427 | [...linkCheckboxes].forEach((checkbox) => { | 427 | [...linkCheckboxes].forEach((checkbox) => { |
428 | checkbox.style.display = 'inline-block'; | 428 | checkbox.style.display = 'inline-block'; |
429 | checkbox.addEventListener('click', () => { | 429 | checkbox.addEventListener('change', () => { |
430 | const linkCheckedCheckboxes = document.querySelectorAll('.delete-checkbox:checked'); | 430 | const linkCheckedCheckboxes = document.querySelectorAll('.link-checkbox:checked'); |
431 | const count = [...linkCheckedCheckboxes].length; | 431 | const count = [...linkCheckedCheckboxes].length; |
432 | if (count === 0 && bar.classList.contains('open')) { | 432 | if (count === 0 && bar.classList.contains('open')) { |
433 | bar.classList.toggle('open'); | 433 | bar.classList.toggle('open'); |
@@ -444,7 +444,7 @@ function init(description) { | |||
444 | event.preventDefault(); | 444 | event.preventDefault(); |
445 | 445 | ||
446 | const links = []; | 446 | const links = []; |
447 | const linkCheckedCheckboxes = document.querySelectorAll('.delete-checkbox:checked'); | 447 | const linkCheckedCheckboxes = document.querySelectorAll('.link-checkbox:checked'); |
448 | [...linkCheckedCheckboxes].forEach((checkbox) => { | 448 | [...linkCheckedCheckboxes].forEach((checkbox) => { |
449 | links.push({ | 449 | links.push({ |
450 | id: checkbox.value, | 450 | id: checkbox.value, |
@@ -467,6 +467,25 @@ function init(description) { | |||
467 | } | 467 | } |
468 | 468 | ||
469 | /** | 469 | /** |
470 | * Select all button | ||
471 | */ | ||
472 | const selectAllButtons = document.querySelectorAll('.select-all-button'); | ||
473 | [...selectAllButtons].forEach((selectAllButton) => { | ||
474 | selectAllButton.addEventListener('click', (e) => { | ||
475 | e.preventDefault(); | ||
476 | const checked = selectAllButton.classList.contains('filter-off'); | ||
477 | [...selectAllButtons].forEach((selectAllButton2) => { | ||
478 | selectAllButton2.classList.toggle('filter-off'); | ||
479 | selectAllButton2.classList.toggle('filter-on'); | ||
480 | }); | ||
481 | [...linkCheckboxes].forEach((linkCheckbox) => { | ||
482 | linkCheckbox.checked = checked; | ||
483 | linkCheckbox.dispatchEvent(new Event('change')); | ||
484 | }); | ||
485 | }); | ||
486 | }); | ||
487 | |||
488 | /** | ||
470 | * Tag list operations | 489 | * Tag list operations |
471 | * | 490 | * |
472 | * TODO: support error code in the backend for AJAX requests | 491 | * TODO: support error code in the backend for AJAX requests |
@@ -548,7 +567,7 @@ function init(description) { | |||
548 | event.preventDefault(); | 567 | event.preventDefault(); |
549 | const block = findParent(event.target, 'div', { class: 'tag-list-item' }); | 568 | const block = findParent(event.target, 'div', { class: 'tag-list-item' }); |
550 | const tag = block.getAttribute('data-tag'); | 569 | const tag = block.getAttribute('data-tag'); |
551 | const refreshedToken = document.getElementById('token'); | 570 | const refreshedToken = document.getElementById('token').value; |
552 | 571 | ||
553 | if (confirm(`Are you sure you want to delete the tag "${tag}"?`)) { | 572 | if (confirm(`Are you sure you want to delete the tag "${tag}"?`)) { |
554 | const xhr = new XMLHttpRequest(); | 573 | const xhr = new XMLHttpRequest(); |
diff --git a/assets/default/scss/shaarli.scss b/assets/default/scss/shaarli.scss index 6b286f1e..760d8d6a 100644 --- a/assets/default/scss/shaarli.scss +++ b/assets/default/scss/shaarli.scss | |||
@@ -381,8 +381,6 @@ body, | |||
381 | box-shadow: 0 1px 0 $light-shadow, 0 1px 4px $dark-shadow inset; | 381 | box-shadow: 0 1px 0 $light-shadow, 0 1px 4px $dark-shadow inset; |
382 | background: $almost-white; | 382 | background: $almost-white; |
383 | padding: 5px 5px 3px 15px; | 383 | padding: 5px 5px 3px 15px; |
384 | width: 20%; | ||
385 | height: 20px; | ||
386 | color: $dark-grey; | 384 | color: $dark-grey; |
387 | } | 385 | } |
388 | 386 | ||
@@ -742,7 +740,7 @@ body, | |||
742 | font-size: 1em; | 740 | font-size: 1em; |
743 | } | 741 | } |
744 | 742 | ||
745 | .delete-checkbox { | 743 | .link-checkbox { |
746 | display: none; | 744 | display: none; |
747 | } | 745 | } |
748 | } | 746 | } |
@@ -757,6 +755,14 @@ body, | |||
757 | font-size: 1.3em; | 755 | font-size: 1.3em; |
758 | } | 756 | } |
759 | 757 | ||
758 | .pin-link { | ||
759 | font-size: 1.3em; | ||
760 | } | ||
761 | |||
762 | .pinned-link { | ||
763 | color: $blue !important; | ||
764 | } | ||
765 | |||
760 | .linklist-item-description { | 766 | .linklist-item-description { |
761 | position: relative; | 767 | position: relative; |
762 | padding: 0 10px; | 768 | padding: 0 10px; |
@@ -850,6 +856,10 @@ body, | |||
850 | margin: 0 7px; | 856 | margin: 0 7px; |
851 | } | 857 | } |
852 | 858 | ||
859 | .ctrl-delete { | ||
860 | margin: 0 7px 0 0; | ||
861 | } | ||
862 | |||
853 | // 64em -> lg | 863 | // 64em -> lg |
854 | @media screen and (max-width: 64em) { | 864 | @media screen and (max-width: 64em) { |
855 | .linklist-item-infos-url { | 865 | .linklist-item-infos-url { |
diff --git a/composer.json b/composer.json index 99ef0b5e..dccf83b6 100644 --- a/composer.json +++ b/composer.json | |||
@@ -16,7 +16,7 @@ | |||
16 | }, | 16 | }, |
17 | "require": { | 17 | "require": { |
18 | "php": ">=5.6", | 18 | "php": ">=5.6", |
19 | "shaarli/netscape-bookmark-parser": "^2.0", | 19 | "shaarli/netscape-bookmark-parser": "^2.1", |
20 | "erusev/parsedown": "^1.6", | 20 | "erusev/parsedown": "^1.6", |
21 | "slim/slim": "^3.0", | 21 | "slim/slim": "^3.0", |
22 | "arthurhoaro/web-thumbnailer": "^1.1", | 22 | "arthurhoaro/web-thumbnailer": "^1.1", |
@@ -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 22c97fa9..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": "da7a0c081b61d949154c5d2e5370cbab", | 7 | "content-hash": "3876b34296fedb365517b785af8384de", |
8 | "packages": [ | 8 | "packages": [ |
9 | { | 9 | { |
10 | "name": "arthurhoaro/web-thumbnailer", | 10 | "name": "arthurhoaro/web-thumbnailer", |
@@ -133,16 +133,16 @@ | |||
133 | }, | 133 | }, |
134 | { | 134 | { |
135 | "name": "gettext/gettext", | 135 | "name": "gettext/gettext", |
136 | "version": "v4.6.0", | 136 | "version": "v4.6.1", |
137 | "source": { | 137 | "source": { |
138 | "type": "git", | 138 | "type": "git", |
139 | "url": "https://github.com/oscarotero/Gettext.git", | 139 | "url": "https://github.com/oscarotero/Gettext.git", |
140 | "reference": "cae84aff39a87e07bd6e5cddb5adb720a0ffa357" | 140 | "reference": "854ff5f5aaf92d2af7080ba8fc15718b27b5c89a" |
141 | }, | 141 | }, |
142 | "dist": { | 142 | "dist": { |
143 | "type": "zip", | 143 | "type": "zip", |
144 | "url": "https://api.github.com/repos/oscarotero/Gettext/zipball/cae84aff39a87e07bd6e5cddb5adb720a0ffa357", | 144 | "url": "https://api.github.com/repos/oscarotero/Gettext/zipball/854ff5f5aaf92d2af7080ba8fc15718b27b5c89a", |
145 | "reference": "cae84aff39a87e07bd6e5cddb5adb720a0ffa357", | 145 | "reference": "854ff5f5aaf92d2af7080ba8fc15718b27b5c89a", |
146 | "shasum": "" | 146 | "shasum": "" |
147 | }, | 147 | }, |
148 | "require": { | 148 | "require": { |
@@ -191,7 +191,7 @@ | |||
191 | "po", | 191 | "po", |
192 | "translation" | 192 | "translation" |
193 | ], | 193 | ], |
194 | "time": "2018-06-26T16:51:09+00:00" | 194 | "time": "2018-08-27T15:40:19+00:00" |
195 | }, | 195 | }, |
196 | { | 196 | { |
197 | "name": "gettext/languages", | 197 | "name": "gettext/languages", |
@@ -593,15 +593,16 @@ | |||
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": "5008fc529b057251b48f4d17a10fdb20047ea8f5" | 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/5008fc529b057251b48f4d17a10fdb20047ea8f5", | 600 | "url": "https://api.github.com/repos/pubsubhubbub/php-publisher/zipball/047b0faf6219071527a45942d6fef4dbc6d1d884", |
601 | "reference": "5008fc529b057251b48f4d17a10fdb20047ea8f5", | 601 | "reference": "047b0faf6219071527a45942d6fef4dbc6d1d884", |
602 | "shasum": "" | 602 | "shasum": "" |
603 | }, | 603 | }, |
604 | "require": { | 604 | "require": { |
605 | "ext-curl": "*", | ||
605 | "php": "~5.4 || ~7.0" | 606 | "php": "~5.4 || ~7.0" |
606 | }, | 607 | }, |
607 | "type": "library", | 608 | "type": "library", |
@@ -626,30 +627,31 @@ | |||
626 | "data", | 627 | "data", |
627 | "feeds", | 628 | "feeds", |
628 | "publishers", | 629 | "publishers", |
629 | "pubsubhubbub" | 630 | "pubsubhubbub", |
631 | "websub" | ||
630 | ], | 632 | ], |
631 | "time": "2018-05-22T11:56:26+00:00" | 633 | "time": "2018-10-09T05:20:28+00:00" |
632 | }, | 634 | }, |
633 | { | 635 | { |
634 | "name": "shaarli/netscape-bookmark-parser", | 636 | "name": "shaarli/netscape-bookmark-parser", |
635 | "version": "v2.0.5", | 637 | "version": "v2.1.0", |
636 | "source": { | 638 | "source": { |
637 | "type": "git", | 639 | "type": "git", |
638 | "url": "https://github.com/shaarli/netscape-bookmark-parser.git", | 640 | "url": "https://github.com/shaarli/netscape-bookmark-parser.git", |
639 | "reference": "ea6911a0ea3dd372fa7002593c5aef9c15a49315" | 641 | "reference": "819008ee42c4dd7e45d988176a4a22d6ed689577" |
640 | }, | 642 | }, |
641 | "dist": { | 643 | "dist": { |
642 | "type": "zip", | 644 | "type": "zip", |
643 | "url": "https://api.github.com/repos/shaarli/netscape-bookmark-parser/zipball/ea6911a0ea3dd372fa7002593c5aef9c15a49315", | 645 | "url": "https://api.github.com/repos/shaarli/netscape-bookmark-parser/zipball/819008ee42c4dd7e45d988176a4a22d6ed689577", |
644 | "reference": "ea6911a0ea3dd372fa7002593c5aef9c15a49315", | 646 | "reference": "819008ee42c4dd7e45d988176a4a22d6ed689577", |
645 | "shasum": "" | 647 | "shasum": "" |
646 | }, | 648 | }, |
647 | "require": { | 649 | "require": { |
648 | "katzgrau/klogger": "~1.0", | 650 | "katzgrau/klogger": "~1.0", |
649 | "php": ">=5.3.4" | 651 | "php": ">=5.6" |
650 | }, | 652 | }, |
651 | "require-dev": { | 653 | "require-dev": { |
652 | "phpunit/phpunit": "4.8.*" | 654 | "phpunit/phpunit": "^5.0" |
653 | }, | 655 | }, |
654 | "type": "library", | 656 | "type": "library", |
655 | "autoload": { | 657 | "autoload": { |
@@ -681,22 +683,22 @@ | |||
681 | "bookmark", | 683 | "bookmark", |
682 | "link", | 684 | "link", |
683 | "netscape", | 685 | "netscape", |
684 | "parse" | 686 | "parser" |
685 | ], | 687 | ], |
686 | "time": "2018-01-30T17:34:48+00:00" | 688 | "time": "2018-10-06T14:43:38+00:00" |
687 | }, | 689 | }, |
688 | { | 690 | { |
689 | "name": "slim/slim", | 691 | "name": "slim/slim", |
690 | "version": "3.10.0", | 692 | "version": "3.11.0", |
691 | "source": { | 693 | "source": { |
692 | "type": "git", | 694 | "type": "git", |
693 | "url": "https://github.com/slimphp/Slim.git", | 695 | "url": "https://github.com/slimphp/Slim.git", |
694 | "reference": "d8aabeacc3688b25e2f2dd2db91df91ec6fdd748" | 696 | "reference": "d378e70431e78ee92ee32ddde61ecc72edf5dc0a" |
695 | }, | 697 | }, |
696 | "dist": { | 698 | "dist": { |
697 | "type": "zip", | 699 | "type": "zip", |
698 | "url": "https://api.github.com/repos/slimphp/Slim/zipball/d8aabeacc3688b25e2f2dd2db91df91ec6fdd748", | 700 | "url": "https://api.github.com/repos/slimphp/Slim/zipball/d378e70431e78ee92ee32ddde61ecc72edf5dc0a", |
699 | "reference": "d8aabeacc3688b25e2f2dd2db91df91ec6fdd748", | 701 | "reference": "d378e70431e78ee92ee32ddde61ecc72edf5dc0a", |
700 | "shasum": "" | 702 | "shasum": "" |
701 | }, | 703 | }, |
702 | "require": { | 704 | "require": { |
@@ -754,7 +756,7 @@ | |||
754 | "micro", | 756 | "micro", |
755 | "router" | 757 | "router" |
756 | ], | 758 | ], |
757 | "time": "2018-04-19T19:29:08+00:00" | 759 | "time": "2018-09-16T10:54:21+00:00" |
758 | } | 760 | } |
759 | ], | 761 | ], |
760 | "packages-dev": [ | 762 | "packages-dev": [ |
@@ -858,46 +860,6 @@ | |||
858 | "time": "2017-10-19T19:58:43+00:00" | 860 | "time": "2017-10-19T19:58:43+00:00" |
859 | }, | 861 | }, |
860 | { | 862 | { |
861 | "name": "pdepend/pdepend", | ||
862 | "version": "2.5.2", | ||
863 | "source": { | ||
864 | "type": "git", | ||
865 | "url": "https://github.com/pdepend/pdepend.git", | ||
866 | "reference": "9daf26d0368d4a12bed1cacae1a9f3a6f0adf239" | ||
867 | }, | ||
868 | "dist": { | ||
869 | "type": "zip", | ||
870 | "url": "https://api.github.com/repos/pdepend/pdepend/zipball/9daf26d0368d4a12bed1cacae1a9f3a6f0adf239", | ||
871 | "reference": "9daf26d0368d4a12bed1cacae1a9f3a6f0adf239", | ||
872 | "shasum": "" | ||
873 | }, | ||
874 | "require": { | ||
875 | "php": ">=5.3.7", | ||
876 | "symfony/config": "^2.3.0|^3|^4", | ||
877 | "symfony/dependency-injection": "^2.3.0|^3|^4", | ||
878 | "symfony/filesystem": "^2.3.0|^3|^4" | ||
879 | }, | ||
880 | "require-dev": { | ||
881 | "phpunit/phpunit": "^4.8|^5.7", | ||
882 | "squizlabs/php_codesniffer": "^2.0.0" | ||
883 | }, | ||
884 | "bin": [ | ||
885 | "src/bin/pdepend" | ||
886 | ], | ||
887 | "type": "library", | ||
888 | "autoload": { | ||
889 | "psr-4": { | ||
890 | "PDepend\\": "src/main/php/PDepend" | ||
891 | } | ||
892 | }, | ||
893 | "notification-url": "https://packagist.org/downloads/", | ||
894 | "license": [ | ||
895 | "BSD-3-Clause" | ||
896 | ], | ||
897 | "description": "Official version of pdepend to be handled with Composer", | ||
898 | "time": "2017-12-13T13:21:38+00:00" | ||
899 | }, | ||
900 | { | ||
901 | "name": "phpdocumentor/reflection-common", | 863 | "name": "phpdocumentor/reflection-common", |
902 | "version": "1.0.1", | 864 | "version": "1.0.1", |
903 | "source": { | 865 | "source": { |
@@ -1044,72 +1006,6 @@ | |||
1044 | "time": "2017-07-14T14:27:02+00:00" | 1006 | "time": "2017-07-14T14:27:02+00:00" |
1045 | }, | 1007 | }, |
1046 | { | 1008 | { |
1047 | "name": "phpmd/phpmd", | ||
1048 | "version": "2.6.0", | ||
1049 | "source": { | ||
1050 | "type": "git", | ||
1051 | "url": "https://github.com/phpmd/phpmd.git", | ||
1052 | "reference": "4e9924b2c157a3eb64395460fcf56b31badc8374" | ||
1053 | }, | ||
1054 | "dist": { | ||
1055 | "type": "zip", | ||
1056 | "url": "https://api.github.com/repos/phpmd/phpmd/zipball/4e9924b2c157a3eb64395460fcf56b31badc8374", | ||
1057 | "reference": "4e9924b2c157a3eb64395460fcf56b31badc8374", | ||
1058 | "shasum": "" | ||
1059 | }, | ||
1060 | "require": { | ||
1061 | "ext-xml": "*", | ||
1062 | "pdepend/pdepend": "^2.5", | ||
1063 | "php": ">=5.3.9" | ||
1064 | }, | ||
1065 | "require-dev": { | ||
1066 | "phpunit/phpunit": "^4.0", | ||
1067 | "squizlabs/php_codesniffer": "^2.0" | ||
1068 | }, | ||
1069 | "bin": [ | ||
1070 | "src/bin/phpmd" | ||
1071 | ], | ||
1072 | "type": "project", | ||
1073 | "autoload": { | ||
1074 | "psr-0": { | ||
1075 | "PHPMD\\": "src/main/php" | ||
1076 | } | ||
1077 | }, | ||
1078 | "notification-url": "https://packagist.org/downloads/", | ||
1079 | "license": [ | ||
1080 | "BSD-3-Clause" | ||
1081 | ], | ||
1082 | "authors": [ | ||
1083 | { | ||
1084 | "name": "Manuel Pichler", | ||
1085 | "email": "github@manuel-pichler.de", | ||
1086 | "homepage": "https://github.com/manuelpichler", | ||
1087 | "role": "Project Founder" | ||
1088 | }, | ||
1089 | { | ||
1090 | "name": "Other contributors", | ||
1091 | "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", | ||
1092 | "role": "Contributors" | ||
1093 | }, | ||
1094 | { | ||
1095 | "name": "Marc Würth", | ||
1096 | "email": "ravage@bluewin.ch", | ||
1097 | "homepage": "https://github.com/ravage84", | ||
1098 | "role": "Project Maintainer" | ||
1099 | } | ||
1100 | ], | ||
1101 | "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", | ||
1102 | "homepage": "http://phpmd.org/", | ||
1103 | "keywords": [ | ||
1104 | "mess detection", | ||
1105 | "mess detector", | ||
1106 | "pdepend", | ||
1107 | "phpmd", | ||
1108 | "pmd" | ||
1109 | ], | ||
1110 | "time": "2017-01-20T14:41:10+00:00" | ||
1111 | }, | ||
1112 | { | ||
1113 | "name": "phpspec/prophecy", | 1009 | "name": "phpspec/prophecy", |
1114 | "version": "1.8.0", | 1010 | "version": "1.8.0", |
1115 | "source": { | 1011 | "source": { |
@@ -1988,56 +1884,6 @@ | |||
1988 | "time": "2017-02-18T15:18:39+00:00" | 1884 | "time": "2017-02-18T15:18:39+00:00" |
1989 | }, | 1885 | }, |
1990 | { | 1886 | { |
1991 | "name": "sebastian/phpcpd", | ||
1992 | "version": "3.0.1", | ||
1993 | "source": { | ||
1994 | "type": "git", | ||
1995 | "url": "https://github.com/sebastianbergmann/phpcpd.git", | ||
1996 | "reference": "dfed51c1288790fc957c9433e2f49ab152e8a564" | ||
1997 | }, | ||
1998 | "dist": { | ||
1999 | "type": "zip", | ||
2000 | "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/dfed51c1288790fc957c9433e2f49ab152e8a564", | ||
2001 | "reference": "dfed51c1288790fc957c9433e2f49ab152e8a564", | ||
2002 | "shasum": "" | ||
2003 | }, | ||
2004 | "require": { | ||
2005 | "php": "^5.6|^7.0", | ||
2006 | "phpunit/php-timer": "^1.0.6", | ||
2007 | "sebastian/finder-facade": "^1.1", | ||
2008 | "sebastian/version": "^1.0|^2.0", | ||
2009 | "symfony/console": "^2.7|^3.0|^4.0" | ||
2010 | }, | ||
2011 | "bin": [ | ||
2012 | "phpcpd" | ||
2013 | ], | ||
2014 | "type": "library", | ||
2015 | "extra": { | ||
2016 | "branch-alias": { | ||
2017 | "dev-master": "3.0-dev" | ||
2018 | } | ||
2019 | }, | ||
2020 | "autoload": { | ||
2021 | "classmap": [ | ||
2022 | "src/" | ||
2023 | ] | ||
2024 | }, | ||
2025 | "notification-url": "https://packagist.org/downloads/", | ||
2026 | "license": [ | ||
2027 | "BSD-3-Clause" | ||
2028 | ], | ||
2029 | "authors": [ | ||
2030 | { | ||
2031 | "name": "Sebastian Bergmann", | ||
2032 | "email": "sebastian@phpunit.de", | ||
2033 | "role": "lead" | ||
2034 | } | ||
2035 | ], | ||
2036 | "description": "Copy/Paste Detector (CPD) for PHP code.", | ||
2037 | "homepage": "https://github.com/sebastianbergmann/phpcpd", | ||
2038 | "time": "2017-11-16T08:49:28+00:00" | ||
2039 | }, | ||
2040 | { | ||
2041 | "name": "sebastian/recursion-context", | 1887 | "name": "sebastian/recursion-context", |
2042 | "version": "2.0.0", | 1888 | "version": "2.0.0", |
2043 | "source": { | 1889 | "source": { |
@@ -2254,81 +2100,17 @@ | |||
2254 | "time": "2017-05-22T02:43:20+00:00" | 2100 | "time": "2017-05-22T02:43:20+00:00" |
2255 | }, | 2101 | }, |
2256 | { | 2102 | { |
2257 | "name": "symfony/config", | ||
2258 | "version": "v3.4.14", | ||
2259 | "source": { | ||
2260 | "type": "git", | ||
2261 | "url": "https://github.com/symfony/config.git", | ||
2262 | "reference": "7b08223b7f6abd859651c56bcabf900d1627d085" | ||
2263 | }, | ||
2264 | "dist": { | ||
2265 | "type": "zip", | ||
2266 | "url": "https://api.github.com/repos/symfony/config/zipball/7b08223b7f6abd859651c56bcabf900d1627d085", | ||
2267 | "reference": "7b08223b7f6abd859651c56bcabf900d1627d085", | ||
2268 | "shasum": "" | ||
2269 | }, | ||
2270 | "require": { | ||
2271 | "php": "^5.5.9|>=7.0.8", | ||
2272 | "symfony/filesystem": "~2.8|~3.0|~4.0", | ||
2273 | "symfony/polyfill-ctype": "~1.8" | ||
2274 | }, | ||
2275 | "conflict": { | ||
2276 | "symfony/dependency-injection": "<3.3", | ||
2277 | "symfony/finder": "<3.3" | ||
2278 | }, | ||
2279 | "require-dev": { | ||
2280 | "symfony/dependency-injection": "~3.3|~4.0", | ||
2281 | "symfony/event-dispatcher": "~3.3|~4.0", | ||
2282 | "symfony/finder": "~3.3|~4.0", | ||
2283 | "symfony/yaml": "~3.0|~4.0" | ||
2284 | }, | ||
2285 | "suggest": { | ||
2286 | "symfony/yaml": "To use the yaml reference dumper" | ||
2287 | }, | ||
2288 | "type": "library", | ||
2289 | "extra": { | ||
2290 | "branch-alias": { | ||
2291 | "dev-master": "3.4-dev" | ||
2292 | } | ||
2293 | }, | ||
2294 | "autoload": { | ||
2295 | "psr-4": { | ||
2296 | "Symfony\\Component\\Config\\": "" | ||
2297 | }, | ||
2298 | "exclude-from-classmap": [ | ||
2299 | "/Tests/" | ||
2300 | ] | ||
2301 | }, | ||
2302 | "notification-url": "https://packagist.org/downloads/", | ||
2303 | "license": [ | ||
2304 | "MIT" | ||
2305 | ], | ||
2306 | "authors": [ | ||
2307 | { | ||
2308 | "name": "Fabien Potencier", | ||
2309 | "email": "fabien@symfony.com" | ||
2310 | }, | ||
2311 | { | ||
2312 | "name": "Symfony Community", | ||
2313 | "homepage": "https://symfony.com/contributors" | ||
2314 | } | ||
2315 | ], | ||
2316 | "description": "Symfony Config Component", | ||
2317 | "homepage": "https://symfony.com", | ||
2318 | "time": "2018-07-26T11:19:56+00:00" | ||
2319 | }, | ||
2320 | { | ||
2321 | "name": "symfony/console", | 2103 | "name": "symfony/console", |
2322 | "version": "v3.4.14", | 2104 | "version": "v3.4.17", |
2323 | "source": { | 2105 | "source": { |
2324 | "type": "git", | 2106 | "type": "git", |
2325 | "url": "https://github.com/symfony/console.git", | 2107 | "url": "https://github.com/symfony/console.git", |
2326 | "reference": "6b217594552b9323bcdcfc14f8a0ce126e84cd73" | 2108 | "reference": "3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b" |
2327 | }, | 2109 | }, |
2328 | "dist": { | 2110 | "dist": { |
2329 | "type": "zip", | 2111 | "type": "zip", |
2330 | "url": "https://api.github.com/repos/symfony/console/zipball/6b217594552b9323bcdcfc14f8a0ce126e84cd73", | 2112 | "url": "https://api.github.com/repos/symfony/console/zipball/3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b", |
2331 | "reference": "6b217594552b9323bcdcfc14f8a0ce126e84cd73", | 2113 | "reference": "3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b", |
2332 | "shasum": "" | 2114 | "shasum": "" |
2333 | }, | 2115 | }, |
2334 | "require": { | 2116 | "require": { |
@@ -2384,20 +2166,20 @@ | |||
2384 | ], | 2166 | ], |
2385 | "description": "Symfony Console Component", | 2167 | "description": "Symfony Console Component", |
2386 | "homepage": "https://symfony.com", | 2168 | "homepage": "https://symfony.com", |
2387 | "time": "2018-07-26T11:19:56+00:00" | 2169 | "time": "2018-10-02T16:33:53+00:00" |
2388 | }, | 2170 | }, |
2389 | { | 2171 | { |
2390 | "name": "symfony/debug", | 2172 | "name": "symfony/debug", |
2391 | "version": "v3.4.14", | 2173 | "version": "v3.4.17", |
2392 | "source": { | 2174 | "source": { |
2393 | "type": "git", | 2175 | "type": "git", |
2394 | "url": "https://github.com/symfony/debug.git", | 2176 | "url": "https://github.com/symfony/debug.git", |
2395 | "reference": "d5a058ff6ecad26b30c1ba452241306ea34c65cc" | 2177 | "reference": "0a612e9dfbd2ccce03eb174365f31ecdca930ff6" |
2396 | }, | 2178 | }, |
2397 | "dist": { | 2179 | "dist": { |
2398 | "type": "zip", | 2180 | "type": "zip", |
2399 | "url": "https://api.github.com/repos/symfony/debug/zipball/d5a058ff6ecad26b30c1ba452241306ea34c65cc", | 2181 | "url": "https://api.github.com/repos/symfony/debug/zipball/0a612e9dfbd2ccce03eb174365f31ecdca930ff6", |
2400 | "reference": "d5a058ff6ecad26b30c1ba452241306ea34c65cc", | 2182 | "reference": "0a612e9dfbd2ccce03eb174365f31ecdca930ff6", |
2401 | "shasum": "" | 2183 | "shasum": "" |
2402 | }, | 2184 | }, |
2403 | "require": { | 2185 | "require": { |
@@ -2440,141 +2222,20 @@ | |||
2440 | ], | 2222 | ], |
2441 | "description": "Symfony Debug Component", | 2223 | "description": "Symfony Debug Component", |
2442 | "homepage": "https://symfony.com", | 2224 | "homepage": "https://symfony.com", |
2443 | "time": "2018-07-26T11:19:56+00:00" | 2225 | "time": "2018-10-02T16:33:53+00:00" |
2444 | }, | ||
2445 | { | ||
2446 | "name": "symfony/dependency-injection", | ||
2447 | "version": "v3.4.14", | ||
2448 | "source": { | ||
2449 | "type": "git", | ||
2450 | "url": "https://github.com/symfony/dependency-injection.git", | ||
2451 | "reference": "1c0e679e522591fd744fdf242fec41a43d62b2b1" | ||
2452 | }, | ||
2453 | "dist": { | ||
2454 | "type": "zip", | ||
2455 | "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/1c0e679e522591fd744fdf242fec41a43d62b2b1", | ||
2456 | "reference": "1c0e679e522591fd744fdf242fec41a43d62b2b1", | ||
2457 | "shasum": "" | ||
2458 | }, | ||
2459 | "require": { | ||
2460 | "php": "^5.5.9|>=7.0.8", | ||
2461 | "psr/container": "^1.0" | ||
2462 | }, | ||
2463 | "conflict": { | ||
2464 | "symfony/config": "<3.3.7", | ||
2465 | "symfony/finder": "<3.3", | ||
2466 | "symfony/proxy-manager-bridge": "<3.4", | ||
2467 | "symfony/yaml": "<3.4" | ||
2468 | }, | ||
2469 | "provide": { | ||
2470 | "psr/container-implementation": "1.0" | ||
2471 | }, | ||
2472 | "require-dev": { | ||
2473 | "symfony/config": "~3.3|~4.0", | ||
2474 | "symfony/expression-language": "~2.8|~3.0|~4.0", | ||
2475 | "symfony/yaml": "~3.4|~4.0" | ||
2476 | }, | ||
2477 | "suggest": { | ||
2478 | "symfony/config": "", | ||
2479 | "symfony/expression-language": "For using expressions in service container configuration", | ||
2480 | "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", | ||
2481 | "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", | ||
2482 | "symfony/yaml": "" | ||
2483 | }, | ||
2484 | "type": "library", | ||
2485 | "extra": { | ||
2486 | "branch-alias": { | ||
2487 | "dev-master": "3.4-dev" | ||
2488 | } | ||
2489 | }, | ||
2490 | "autoload": { | ||
2491 | "psr-4": { | ||
2492 | "Symfony\\Component\\DependencyInjection\\": "" | ||
2493 | }, | ||
2494 | "exclude-from-classmap": [ | ||
2495 | "/Tests/" | ||
2496 | ] | ||
2497 | }, | ||
2498 | "notification-url": "https://packagist.org/downloads/", | ||
2499 | "license": [ | ||
2500 | "MIT" | ||
2501 | ], | ||
2502 | "authors": [ | ||
2503 | { | ||
2504 | "name": "Fabien Potencier", | ||
2505 | "email": "fabien@symfony.com" | ||
2506 | }, | ||
2507 | { | ||
2508 | "name": "Symfony Community", | ||
2509 | "homepage": "https://symfony.com/contributors" | ||
2510 | } | ||
2511 | ], | ||
2512 | "description": "Symfony DependencyInjection Component", | ||
2513 | "homepage": "https://symfony.com", | ||
2514 | "time": "2018-07-29T15:19:31+00:00" | ||
2515 | }, | ||
2516 | { | ||
2517 | "name": "symfony/filesystem", | ||
2518 | "version": "v3.4.14", | ||
2519 | "source": { | ||
2520 | "type": "git", | ||
2521 | "url": "https://github.com/symfony/filesystem.git", | ||
2522 | "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6" | ||
2523 | }, | ||
2524 | "dist": { | ||
2525 | "type": "zip", | ||
2526 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/a59f917e3c5d82332514cb4538387638f5bde2d6", | ||
2527 | "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6", | ||
2528 | "shasum": "" | ||
2529 | }, | ||
2530 | "require": { | ||
2531 | "php": "^5.5.9|>=7.0.8", | ||
2532 | "symfony/polyfill-ctype": "~1.8" | ||
2533 | }, | ||
2534 | "type": "library", | ||
2535 | "extra": { | ||
2536 | "branch-alias": { | ||
2537 | "dev-master": "3.4-dev" | ||
2538 | } | ||
2539 | }, | ||
2540 | "autoload": { | ||
2541 | "psr-4": { | ||
2542 | "Symfony\\Component\\Filesystem\\": "" | ||
2543 | }, | ||
2544 | "exclude-from-classmap": [ | ||
2545 | "/Tests/" | ||
2546 | ] | ||
2547 | }, | ||
2548 | "notification-url": "https://packagist.org/downloads/", | ||
2549 | "license": [ | ||
2550 | "MIT" | ||
2551 | ], | ||
2552 | "authors": [ | ||
2553 | { | ||
2554 | "name": "Fabien Potencier", | ||
2555 | "email": "fabien@symfony.com" | ||
2556 | }, | ||
2557 | { | ||
2558 | "name": "Symfony Community", | ||
2559 | "homepage": "https://symfony.com/contributors" | ||
2560 | } | ||
2561 | ], | ||
2562 | "description": "Symfony Filesystem Component", | ||
2563 | "homepage": "https://symfony.com", | ||
2564 | "time": "2018-07-26T11:19:56+00:00" | ||
2565 | }, | 2226 | }, |
2566 | { | 2227 | { |
2567 | "name": "symfony/finder", | 2228 | "name": "symfony/finder", |
2568 | "version": "v3.4.14", | 2229 | "version": "v3.4.17", |
2569 | "source": { | 2230 | "source": { |
2570 | "type": "git", | 2231 | "type": "git", |
2571 | "url": "https://github.com/symfony/finder.git", | 2232 | "url": "https://github.com/symfony/finder.git", |
2572 | "reference": "8a84fcb207451df0013b2c74cbbf1b62d47b999a" | 2233 | "reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d" |
2573 | }, | 2234 | }, |
2574 | "dist": { | 2235 | "dist": { |
2575 | "type": "zip", | 2236 | "type": "zip", |
2576 | "url": "https://api.github.com/repos/symfony/finder/zipball/8a84fcb207451df0013b2c74cbbf1b62d47b999a", | 2237 | "url": "https://api.github.com/repos/symfony/finder/zipball/54ba444dddc5bd5708a34bd095ea67c6eb54644d", |
2577 | "reference": "8a84fcb207451df0013b2c74cbbf1b62d47b999a", | 2238 | "reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d", |
2578 | "shasum": "" | 2239 | "shasum": "" |
2579 | }, | 2240 | }, |
2580 | "require": { | 2241 | "require": { |
@@ -2610,7 +2271,7 @@ | |||
2610 | ], | 2271 | ], |
2611 | "description": "Symfony Finder Component", | 2272 | "description": "Symfony Finder Component", |
2612 | "homepage": "https://symfony.com", | 2273 | "homepage": "https://symfony.com", |
2613 | "time": "2018-07-26T11:19:56+00:00" | 2274 | "time": "2018-10-03T08:46:40+00:00" |
2614 | }, | 2275 | }, |
2615 | { | 2276 | { |
2616 | "name": "symfony/polyfill-ctype", | 2277 | "name": "symfony/polyfill-ctype", |
@@ -2731,16 +2392,16 @@ | |||
2731 | }, | 2392 | }, |
2732 | { | 2393 | { |
2733 | "name": "symfony/yaml", | 2394 | "name": "symfony/yaml", |
2734 | "version": "v3.4.14", | 2395 | "version": "v3.4.17", |
2735 | "source": { | 2396 | "source": { |
2736 | "type": "git", | 2397 | "type": "git", |
2737 | "url": "https://github.com/symfony/yaml.git", | 2398 | "url": "https://github.com/symfony/yaml.git", |
2738 | "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2" | 2399 | "reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f" |
2739 | }, | 2400 | }, |
2740 | "dist": { | 2401 | "dist": { |
2741 | "type": "zip", | 2402 | "type": "zip", |
2742 | "url": "https://api.github.com/repos/symfony/yaml/zipball/810af2d35fc72b6cf5c01116806d2b65ccaaf2e2", | 2403 | "url": "https://api.github.com/repos/symfony/yaml/zipball/640b6c27fed4066d64b64d5903a86043f4a4de7f", |
2743 | "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2", | 2404 | "reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f", |
2744 | "shasum": "" | 2405 | "shasum": "" |
2745 | }, | 2406 | }, |
2746 | "require": { | 2407 | "require": { |
@@ -2786,7 +2447,7 @@ | |||
2786 | ], | 2447 | ], |
2787 | "description": "Symfony Yaml Component", | 2448 | "description": "Symfony Yaml Component", |
2788 | "homepage": "https://symfony.com", | 2449 | "homepage": "https://symfony.com", |
2789 | "time": "2018-07-26T11:19:56+00:00" | 2450 | "time": "2018-10-02T16:33:53+00:00" |
2790 | }, | 2451 | }, |
2791 | { | 2452 | { |
2792 | "name": "theseer/fdomdocument", | 2453 | "name": "theseer/fdomdocument", |
@@ -2882,8 +2543,7 @@ | |||
2882 | "aliases": [], | 2543 | "aliases": [], |
2883 | "minimum-stability": "stable", | 2544 | "minimum-stability": "stable", |
2884 | "stability-flags": { | 2545 | "stability-flags": { |
2885 | "pubsubhubbub/publisher": 20, | 2546 | "pubsubhubbub/publisher": 20 |
2886 | "phpmd/phpmd": 0 | ||
2887 | }, | 2547 | }, |
2888 | "prefer-stable": false, | 2548 | "prefer-stable": false, |
2889 | "prefer-lowest": false, | 2549 | "prefer-lowest": false, |
diff --git a/doc/custom_theme/main.html b/doc/custom_theme/main.html new file mode 100644 index 00000000..cc2a703e --- /dev/null +++ b/doc/custom_theme/main.html | |||
@@ -0,0 +1,23 @@ | |||
1 | {% extends "base.html" %} | ||
2 | |||
3 | {# | ||
4 | The entry point for the ReadTheDocs Theme. | ||
5 | |||
6 | Any theme customisations should override this file to redefine blocks defined in | ||
7 | the various templates. The custom theme should only need to define a main.html | ||
8 | which `{% extends "base.html" %}` and defines various blocks which will replace | ||
9 | the blocks defined in base.html and its included child templates. | ||
10 | #} | ||
11 | |||
12 | {%- block site_meta %} | ||
13 | <meta charset="utf-8"> | ||
14 | <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
15 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
16 | |||
17 | {%- if 'media.readthedocs.org' not in config.extra_css[0] %} | ||
18 | <meta name="robots" content="noindex, nofollow"> | ||
19 | {%- endif %} | ||
20 | |||
21 | {% if page and page.is_homepage %}<meta name="description" content="{{ config.site_description }}">{% endif %} | ||
22 | {% if config.site_author %}<meta name="author" content="{{ config.site_author }}">{% endif %} | ||
23 | {%- endblock %} | ||
diff --git a/doc/md/Community-&-Related-software.md b/doc/md/Community-&-Related-software.md index 49c20c9c..67fdd70f 100644 --- a/doc/md/Community-&-Related-software.md +++ b/doc/md/Community-&-Related-software.md | |||
@@ -51,7 +51,7 @@ See [Theming](Theming) for a list of community-contributed themes, and an instal | |||
51 | - [Shaarlo](https://github.com/DMeloni/shaarlo) - An aggregator for shaarlis with many features (a very popular running instance among French shaarliers: [shaarli.fr](http://shaarli.fr/)) | 51 | - [Shaarlo](https://github.com/DMeloni/shaarlo) - An aggregator for shaarlis with many features (a very popular running instance among French shaarliers: [shaarli.fr](http://shaarli.fr/)) |
52 | - [Shaarlimages](https://github.com/BoboTiG/shaarlimages) - An image-oriented aggregator for Shaarlis | 52 | - [Shaarlimages](https://github.com/BoboTiG/shaarlimages) - An image-oriented aggregator for Shaarlis |
53 | - [mknexen/shaarli-api](https://github.com/mknexen/shaarli-api) - A REST API for Shaarli | 53 | - [mknexen/shaarli-api](https://github.com/mknexen/shaarli-api) - A REST API for Shaarli |
54 | - [Self dead link](https://github.com/qwertygc/shaarli-dev-code/blob/master/self-dead-link.php) - Detect dead links on shaarli. This version use the database of shaarli. [Another version](https://github.com/qwertygc/shaarli-dev-code/blob/master/dead-link.php), can be used for other shaarli instances (but is more resource consuming). | 54 | - [Self dead link](https://framagit.org/qwertygc/shaarli-dev-code/blob/master/self-dead-link.php) - Detect dead links on shaarli. This version use the database of shaarli. [Another version](https://framagit.org/qwertygc/shaarli-dev-code/blob/master/dead-link.php), can be used for other shaarli instances (but is more resource consuming). |
55 | - [Bookmark Archiver](https://github.com/pirate/bookmark-archiver) - Save an archived copy of all websites starred using browser bookmarks/Shaarli/Delicious/Instapaper/Unmark.it/Pocket/Pinboard. Outputs browseable html. | 55 | - [Bookmark Archiver](https://github.com/pirate/bookmark-archiver) - Save an archived copy of all websites starred using browser bookmarks/Shaarli/Delicious/Instapaper/Unmark.it/Pocket/Pinboard. Outputs browseable html. |
56 | 56 | ||
57 | ## Alternatives to Shaarli | 57 | ## Alternatives to Shaarli |
diff --git a/doc/md/Server-configuration.md b/doc/md/Server-configuration.md index e281dc85..78083a46 100644 --- a/doc/md/Server-configuration.md +++ b/doc/md/Server-configuration.md | |||
@@ -18,7 +18,7 @@ Version | Status | Shaarli compatibility | |||
18 | 7.2 | Supported | Yes | 18 | 7.2 | Supported | Yes |
19 | 7.1 | Supported | Yes | 19 | 7.1 | Supported | Yes |
20 | 7.0 | Supported | Yes | 20 | 7.0 | Supported | Yes |
21 | 5.6 | Supported | Yes | 21 | 5.6 | EOL: 2018-12-31 | Yes (up to Shaarli 0.10.x) |
22 | 5.5 | EOL: 2016-07-10 | Yes | 22 | 5.5 | EOL: 2016-07-10 | Yes |
23 | 5.4 | EOL: 2015-09-14 | Yes (up to Shaarli 0.8.x) | 23 | 5.4 | EOL: 2015-09-14 | Yes (up to Shaarli 0.8.x) |
24 | 5.3 | EOL: 2014-08-14 | Yes (up to Shaarli 0.8.x) | 24 | 5.3 | EOL: 2014-08-14 | Yes (up to Shaarli 0.8.x) |
@@ -397,6 +397,7 @@ http { | |||
397 | ``` | 397 | ``` |
398 | 398 | ||
399 | ## Proxies | 399 | ## Proxies |
400 | |||
400 | If Shaarli is served behind a proxy (i.e. there is a proxy server between clients and the web server hosting Shaarli), please refer to the proxy server documentation for proper configuration. In particular, you have to ensure that the following server variables are properly set: | 401 | If Shaarli is served behind a proxy (i.e. there is a proxy server between clients and the web server hosting Shaarli), please refer to the proxy server documentation for proper configuration. In particular, you have to ensure that the following server variables are properly set: |
401 | 402 | ||
402 | - `X-Forwarded-Proto` | 403 | - `X-Forwarded-Proto` |
@@ -405,6 +406,12 @@ If Shaarli is served behind a proxy (i.e. there is a proxy server between client | |||
405 | 406 | ||
406 | See also [proxy-related](https://github.com/shaarli/Shaarli/issues?utf8=%E2%9C%93&q=label%3Aproxy+) issues. | 407 | See also [proxy-related](https://github.com/shaarli/Shaarli/issues?utf8=%E2%9C%93&q=label%3Aproxy+) issues. |
407 | 408 | ||
409 | ## Robots and crawlers | ||
410 | |||
411 | Shaarli disallows indexing and crawling of your local documentation pages by search engines, using `<meta name="robots">` HTML tags. | ||
412 | Your Shaarli instance and other pages you host may still be indexed by various robots on the public Internet. | ||
413 | You may want to setup a robots.txt file or other crawler control mechanism on your server. | ||
414 | See [[1]](https://en.wikipedia.org/wiki/Robots_exclusion_standard), [[2]](https://support.google.com/webmasters/answer/6062608?hl=en) and [[3]](https://developers.google.com/search/reference/robots_meta_tag) | ||
408 | 415 | ||
409 | ## See also | 416 | ## See also |
410 | 417 | ||
diff --git a/doc/md/Sharing-content.md b/doc/md/Sharing-content.md index 4910ff6c..9a16fc62 100644 --- a/doc/md/Sharing-content.md +++ b/doc/md/Sharing-content.md | |||
@@ -15,7 +15,6 @@ While logged in to your Shaarli, you can add new Shaares in several ways: | |||
15 | 15 | ||
16 | * [+Shaare button](#shaare-button) | 16 | * [+Shaare button](#shaare-button) |
17 | * [Bookmarklet](#bookmarklet) | 17 | * [Bookmarklet](#bookmarklet) |
18 | * [Firefox Share](#firefox-share) | ||
19 | * Third-party [apps and browser addons](Community-&-Related-software.md#mobile-apps) | 18 | * Third-party [apps and browser addons](Community-&-Related-software.md#mobile-apps) |
20 | * [REST API](https://shaarli.github.io/api-documentation/) | 19 | * [REST API](https://shaarli.github.io/api-documentation/) |
21 | 20 | ||
@@ -52,22 +51,6 @@ bookmarklet in your browser! The same `New Shaare` dialog as above is displayed. | |||
52 | ![](images/bookmarklet.png) | 51 | ![](images/bookmarklet.png) |
53 | 52 | ||
54 | 53 | ||
55 | ### Firefox Share | ||
56 | |||
57 | Before using Firefox Share, you must first add Shaarli as a sharing provider: | ||
58 | |||
59 | - Click the `Tools` button in the top bar | ||
60 | - Click the `✚Add to Firefox social` button and accept the activation. | ||
61 | |||
62 | Once this is done, you can share any URL you are visiting by clicking the Firefox | ||
63 | _Share_ button ![images/firefoxshare.png](images/firefoxshare.png) | ||
64 | |||
65 | | Note | Firefox Share is no longer available for Firefox 57 and later versions. | | ||
66 | |---------|---------| | ||
67 | |||
68 | | Note | Your Shaarli instance must be hosted on an HTTPS (SSL/TLS secure connection) enabled server for Firefox Share to work. Firefox Share will not work over plaintext HTTP connections. | | ||
69 | |---------|---------| | ||
70 | |||
71 | -------------------------------------------------------------------------------- | 54 | -------------------------------------------------------------------------------- |
72 | 55 | ||
73 | ## Editing Shaares | 56 | ## Editing Shaares |
diff --git a/doc/md/images/icon.png b/doc/md/images/icon.png new file mode 100644 index 00000000..530d7469 --- /dev/null +++ b/doc/md/images/icon.png | |||
Binary files differ | |||
diff --git a/doc/md/index.md b/doc/md/index.md index c18332b4..220eeec1 100644 --- a/doc/md/index.md +++ b/doc/md/index.md | |||
@@ -1,25 +1,19 @@ | |||
1 | # [Shaarli](https://github.com/shaarli/Shaarli/) documentation | 1 | # <img src="images/icon.png" width="20px" height="20px"> Shaarli |
2 | 2 | ||
3 | The personal, minimalist, super-fast, database free, bookmarking service. | 3 | The personal, minimalist, super-fast, database free, bookmarking service. |
4 | 4 | ||
5 | Do you want to share the links you discover? | 5 | Do you want to share the links you discover? |
6 | Shaarli is a minimalist link sharing service that you can install on your own server. | 6 | Shaarli is a minimalist bookmark manager and link sharing service that you can install on your own server. |
7 | It is designed to be personal (single-user), fast and handy. | 7 | It is designed to be personal (single-user), fast and handy. |
8 | 8 | ||
9 | <!-- TODO screenshots --> | 9 | <!-- TODO screenshots --> |
10 | 10 | ||
11 | Here you can find some info on how to use, configure, tweak and solve problems with your Shaarli. | 11 | Visit the pages in the sidebar to find information on how to setup, use, configure, tweak and troubleshoot Shaarli. |
12 | For general information, read the [README](https://github.com/shaarli/Shaarli/blob/master/README.md). | ||
13 | 12 | ||
14 | If you have any questions or ideas, please join the [chat](https://gitter.im/shaarli/Shaarli) (also reachable via [IRC](https://irc.gitter.im/)), post them in our [general discussion](https://github.com/shaarli/Shaarli/issues/308) or read the current [issues](https://github.com/shaarli/Shaarli/issues). | ||
15 | |||
16 | If you've found a bug, please create a [new issue](https://github.com/shaarli/Shaarli/issues/new). | ||
17 | |||
18 | If you would like a feature added to Shaarli, check the issues labeled [`feature`](https://github.com/shaarli/Shaarli/labels/feature), [`enhancement`](https://github.com/shaarli/Shaarli/labels/enhancement), and [`plugin`](https://github.com/shaarli/Shaarli/labels/plugin). | ||
19 | 13 | ||
20 | * [GitHub project page](https://github.com/shaarli/Shaarli) | 14 | * [GitHub project page](https://github.com/shaarli/Shaarli) |
21 | * [Online documentation](https://shaarli.readthedocs.io/) (this page) | 15 | * [Online documentation](https://shaarli.readthedocs.io/) |
22 | * [Latest Shaarli releases](https://github.com/shaarli/Shaarli/releases) | 16 | * [Latest releases](https://github.com/shaarli/Shaarli/releases) |
23 | * [Changelog](https://github.com/shaarli/Shaarli/blob/master/CHANGELOG.md) | 17 | * [Changelog](https://github.com/shaarli/Shaarli/blob/master/CHANGELOG.md) |
24 | 18 | ||
25 | 19 | ||
@@ -30,87 +24,70 @@ It runs the latest development version of Shaarli and is updated/reset daily. | |||
30 | 24 | ||
31 | Login: `demo`; Password: `demo` | 25 | Login: `demo`; Password: `demo` |
32 | 26 | ||
33 | <!-- TODO review everything below this point --> | ||
34 | |||
35 | |||
36 | ## Features | 27 | ## Features |
37 | 28 | ||
38 | Shaarli can be used: | 29 | Shaarli can be used: |
39 | 30 | ||
40 | - to share, comment and save interesting links and news. | 31 | - to share, comment and save interesting links and news |
41 | - to bookmark useful/frequent personal links (as private links) and share them between computers. | 32 | - to bookmark useful/frequent links and share them between computers |
42 | - as a minimal blog/microblog/writing platform (no character limit). | 33 | - as a minimal blog/microblog/writing platform |
43 | - as a read-it-later list (for example items tagged `readlater`). | 34 | - as a read-it-later list |
44 | - to draft and save articles/posts/ideas. | 35 | - to draft and save articles/posts/ideas |
45 | - to keep code snippets. | 36 | - to keep notes, documentation and code snippets |
46 | - to keep notes and documentation. | 37 | - as a shared clipboard/notepad/pastebin between machines |
47 | - as a shared clipboard/notepad/pastebin between machines. | 38 | - as a todo list |
48 | - as a todo list. | 39 | - to store media playlists |
49 | - to store playlists (e.g. with the `music` or `video` tags). | ||
50 | - to keep extracts/comments from webpages that may disappear. | 40 | - to keep extracts/comments from webpages that may disappear. |
51 | - to keep track of ongoing discussions (for example items tagged `discussion`). | 41 | - to keep track of ongoing discussions |
52 | - [to feed RSS aggregators](http://shaarli.chassegnouf.net/?9Efeiw) (planets) with specific tags. | 42 | - to feed other blogs, aggregators, social networks... using RSS feeds |
53 | - to feed other social networks, blogs... using RSS feeds and external services (dlvr.it, ifttt.com ...). | ||
54 | 43 | ||
55 | ### Interface | 44 | ### Edit, view and search your links |
56 | 45 | ||
57 | - minimalist design (simple is beautiful) | 46 | - Minimalist design |
58 | - FAST | 47 | - FAST |
59 | - ATOM and RSS feeds | 48 | - Customizable link titles and descriptions |
60 | - views: | 49 | - Tags to organize your links (features tag autocompletion, renaming, merging and deletion) |
61 | - paginated link list (with image and video thumbnails) | 50 | - Search by tag or using the full-text search |
62 | - tag cloud | 51 | - Public and private links (visible only to logged-in users) |
63 | - picture wall: image and video thumbnails (with lazy loading) | 52 | - Unique permalinks for easy reference |
64 | - daily: newspaper-like daily digest | 53 | - Paginated link list (with image and video thumbnails) |
65 | - daily RSS feed | 54 | - Tag cloud and list views |
66 | - permalinks for easy reference | 55 | - Picture wall: image and video thumbnails view (with lazy loading) |
67 | - links can be public or private | 56 | - ATOM and RSS feeds (can also be filtered using tags or text search) |
68 | - thumbnail generation for images and video services | 57 | - Daily: newspaper-like daily digest (and daily RSS feed) |
69 | - URL cleanup: automatic removal of `?utm_source=...`, `fb=...` | 58 | - URL cleanup: automatic removal of `?utm_source=...`, `fb=...` |
70 | - extensible through [plugins](https://shaarli.readthedocs.io/en/master/Plugins/#plugin-usage) | 59 | - Extensible through [plugins](https://shaarli.readthedocs.io/en/master/Plugins/#plugin-usage) |
71 | |||
72 | ### Tag, view and search your links | ||
73 | |||
74 | - add a custom title and description to archived links | ||
75 | - add tags to classify and search links | ||
76 | - features tag autocompletion, renaming, merging and deletion | ||
77 | - full-text and tag search | ||
78 | 60 | ||
79 | ### Easy setup | 61 | ### Easy setup |
80 | 62 | ||
81 | - dead-simple installation: drop the files, open the page | 63 | - Dead-simple installation: drop the files, open the page |
82 | - links are stored in a file | 64 | - Links are stored in a file (no database required, easy backup: simply copy the datastore file) |
83 | - compact storage | 65 | - Import and export links as Netscape bookmarks compatible with most Web browsers |
84 | - no database required | ||
85 | - easy backup: simply copy the datastore file | ||
86 | - import and export links as Netscape bookmarks | ||
87 | 66 | ||
88 | ### Accessibility | 67 | ### Accessibility |
89 | 68 | ||
90 | - bookmarlet to share links in one click | 69 | - Bookmarklet and other tools to share links in one click |
91 | - support for mobile browsers | 70 | - Support for mobile browsers |
92 | - degrades gracefully with Javascript disabled | 71 | - Degrades gracefully with Javascript disabled |
93 | - easy page customization through HTML/CSS/RainTPL | 72 | - Easy page customization through HTML/CSS/RainTPL |
94 | 73 | ||
95 | ### Security | 74 | ### Security |
96 | 75 | ||
97 | - discreet pop-up notification when a new release is available | 76 | - Discreet pop-up notification when a new release is available |
98 | - bruteforce protection on the login form | 77 | - Bruteforce protection on the login form |
99 | - protected against [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) and session cookie hijacking | 78 | - Protected against [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) and session cookie hijacking |
100 | 79 | ||
101 | <!-- TODO Limitations --> | 80 | <!-- TODO Limitations --> |
102 | 81 | ||
103 | ### REST API | 82 | ### REST API |
104 | 83 | ||
105 | Easily extensible by any client using the REST API exposed by Shaarli. | 84 | - Easily extensible by any client using the REST API exposed by Shaarli ([API documentation](http://shaarli.github.io/api-documentation/)). |
106 | |||
107 | See the [API documentation](http://shaarli.github.io/api-documentation/). | ||
108 | 85 | ||
109 | ## About | 86 | ## About |
110 | 87 | ||
111 | ### Shaarli community fork | 88 | ### Shaarli community fork |
112 | 89 | ||
113 | This friendly fork is maintained by the Shaarli community at https://github.com/shaarli/Shaarli | 90 | This friendly fork is maintained by the Shaarli community at <https://github.com/shaarli/Shaarli> |
114 | 91 | ||
115 | This is a community fork of the original [Shaarli](https://github.com/sebsauvage/Shaarli/) project by [Sébastien Sauvage](http://sebsauvage.net/). | 92 | This is a community fork of the original [Shaarli](https://github.com/sebsauvage/Shaarli/) project by [Sébastien Sauvage](http://sebsauvage.net/). |
116 | 93 | ||
@@ -123,16 +100,15 @@ in this repository, and will keep maintaining the project for the foreseeable | |||
123 | future, while keeping Shaarli simple and efficient. | 100 | future, while keeping Shaarli simple and efficient. |
124 | 101 | ||
125 | 102 | ||
126 | ### Contributing | 103 | ### Contributing and getting help |
127 | 104 | ||
128 | If you'd like to help, please: | 105 | Feedback is very appreciated! |
129 | 106 | ||
130 | - have a look at the open [issues](https://github.com/shaarli/Shaarli/issues) | 107 | - If you have any questions or ideas, please join the [chat](https://gitter.im/shaarli/Shaarli) (also reachable via [IRC](https://irc.gitter.im/)), post them in our [general discussion](https://github.com/shaarli/Shaarli/issues/308) or read the current [issues](https://github.com/shaarli/Shaarli/issues). |
131 | and [pull requests](https://github.com/shaarli/Shaarli/pulls) | 108 | - Have a look at the open [issues](https://github.com/shaarli/Shaarli/issues) and [pull requests](https://github.com/shaarli/Shaarli/pulls) |
132 | - feel free to report bugs (feedback is much appreciated) | 109 | - If you would like a feature added to Shaarli, check the issues labeled [`feature`](https://github.com/shaarli/Shaarli/labels/feature), [`enhancement`](https://github.com/shaarli/Shaarli/labels/enhancement), and [`plugin`](https://github.com/shaarli/Shaarli/labels/plugin). |
133 | - suggest new features and improvements to both code and [documentation](https://github.com/shaarli/Shaarli/tree/master/doc/md/) | 110 | - If you've found a bug, please create a [new issue](https://github.com/shaarli/Shaarli/issues/new). |
134 | - propose solutions to existing problems | 111 | - Feel free to propose solutions to existing problems, help us improve the documentation and translations, and submit pull requests :-) |
135 | - submit pull requests :-) | ||
136 | 112 | ||
137 | 113 | ||
138 | ### License | 114 | ### License |
diff --git a/inc/languages/fr/LC_MESSAGES/shaarli.po b/inc/languages/fr/LC_MESSAGES/shaarli.po index 155eb52e..102c80da 100644 --- a/inc/languages/fr/LC_MESSAGES/shaarli.po +++ b/inc/languages/fr/LC_MESSAGES/shaarli.po | |||
@@ -1,15 +1,15 @@ | |||
1 | msgid "" | 1 | msgid "" |
2 | msgstr "" | 2 | msgstr "" |
3 | "Project-Id-Version: Shaarli\n" | 3 | "Project-Id-Version: Shaarli\n" |
4 | "POT-Creation-Date: 2018-07-17 13:04+0200\n" | 4 | "POT-Creation-Date: 2018-10-06 13:08+0200\n" |
5 | "PO-Revision-Date: 2018-07-17 13:07+0200\n" | 5 | "PO-Revision-Date: 2018-10-06 13:08+0200\n" |
6 | "Last-Translator: \n" | 6 | "Last-Translator: \n" |
7 | "Language-Team: Shaarli\n" | 7 | "Language-Team: Shaarli\n" |
8 | "Language: fr_FR\n" | 8 | "Language: fr_FR\n" |
9 | "MIME-Version: 1.0\n" | 9 | "MIME-Version: 1.0\n" |
10 | "Content-Type: text/plain; charset=UTF-8\n" | 10 | "Content-Type: text/plain; charset=UTF-8\n" |
11 | "Content-Transfer-Encoding: 8bit\n" | 11 | "Content-Transfer-Encoding: 8bit\n" |
12 | "X-Generator: Poedit 2.0.9\n" | 12 | "X-Generator: Poedit 2.1.1\n" |
13 | "X-Poedit-Basepath: ../../../..\n" | 13 | "X-Poedit-Basepath: ../../../..\n" |
14 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" | 14 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" |
15 | "X-Poedit-SourceCharset: UTF-8\n" | 15 | "X-Poedit-SourceCharset: UTF-8\n" |
@@ -48,7 +48,7 @@ msgstr "le fichier n'est pas accessible en écriture" | |||
48 | #: application/Cache.php:16 | 48 | #: application/Cache.php:16 |
49 | #, php-format | 49 | #, php-format |
50 | msgid "Cannot purge %s: no directory" | 50 | msgid "Cannot purge %s: no directory" |
51 | msgstr "Impossible de purger %s: le répertoire n'existe pas" | 51 | msgstr "Impossible de purger %s : le répertoire n'existe pas" |
52 | 52 | ||
53 | #: application/FeedBuilder.php:151 | 53 | #: application/FeedBuilder.php:151 |
54 | msgid "Direct link" | 54 | msgid "Direct link" |
@@ -98,17 +98,15 @@ msgstr "Vous devez utiliser un entier comme clé." | |||
98 | 98 | ||
99 | #: application/LinkDB.php:145 | 99 | #: application/LinkDB.php:145 |
100 | msgid "Array offset and link ID must be equal." | 100 | msgid "Array offset and link ID must be equal." |
101 | msgstr "La clé du tableau et l'ID du lien doivent être égaux." | 101 | msgstr "La clé du tableau et l'ID du lien doivent être identiques." |
102 | 102 | ||
103 | #: application/LinkDB.php:251 | 103 | #: application/LinkDB.php:251 |
104 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | ||
105 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 | ||
106 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14 | 104 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14 |
107 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48 | 105 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48 |
108 | msgid "" | 106 | msgid "" |
109 | "The personal, minimalist, super-fast, database free, bookmarking service" | 107 | "The personal, minimalist, super-fast, database free, bookmarking service" |
110 | msgstr "" | 108 | msgstr "" |
111 | "Le gestionnaire de marque-page personnel, minimaliste, et sans base de " | 109 | "Le gestionnaire de marque-pages personnel, minimaliste, et sans base de " |
112 | "données" | 110 | "données" |
113 | 111 | ||
114 | #: application/LinkDB.php:253 | 112 | #: application/LinkDB.php:253 |
@@ -125,11 +123,11 @@ msgstr "" | |||
125 | "Bienvenue sur Shaarli ! Ceci est votre premier marque-page public. Pour me " | 123 | "Bienvenue sur Shaarli ! Ceci est votre premier marque-page public. Pour me " |
126 | "modifier ou me supprimer, vous devez d'abord vous connecter.\n" | 124 | "modifier ou me supprimer, vous devez d'abord vous connecter.\n" |
127 | "\n" | 125 | "\n" |
128 | "Pour apprendre comment utiliser Shaarli, consultez le lien « Documentation » " | 126 | "Pour apprendre à utiliser Shaarli, consultez le lien « Documentation » en " |
129 | "en bas de page.\n" | 127 | "bas de page.\n" |
130 | "\n" | 128 | "\n" |
131 | "Vous utilisez la version supportée par la communauté du projet original " | 129 | "Vous utilisez la version supportée par la communauté du projet original " |
132 | "Shaarli, de Sébastien Sauvage." | 130 | "Shaarli de Sébastien Sauvage." |
133 | 131 | ||
134 | #: application/LinkDB.php:267 | 132 | #: application/LinkDB.php:267 |
135 | msgid "My secret stuff... - Pastebin.com" | 133 | msgid "My secret stuff... - Pastebin.com" |
@@ -185,14 +183,14 @@ msgid "" | |||
185 | "php-gd extension must be loaded to use thumbnails. Thumbnails are now " | 183 | "php-gd extension must be loaded to use thumbnails. Thumbnails are now " |
186 | "disabled. Please reload the page." | 184 | "disabled. Please reload the page." |
187 | msgstr "" | 185 | msgstr "" |
188 | "php-gd extension must be loaded to use thumbnails. Thumbnails are now " | 186 | "l'extension php-gd doit être chargée pour utiliser les miniatures. Les " |
189 | "disabled. Please reload the page." | 187 | "miniatures sont désormais désactivées. Rechargez la page." |
190 | 188 | ||
191 | #: application/Updater.php:86 | 189 | #: application/Updater.php:86 |
192 | msgid "Couldn't retrieve Updater class methods." | 190 | msgid "Couldn't retrieve Updater class methods." |
193 | msgstr "Impossible de récupérer les méthodes de la classe Updater." | 191 | msgstr "Impossible de récupérer les méthodes de la classe Updater." |
194 | 192 | ||
195 | #: application/Updater.php:514 index.php:1023 | 193 | #: application/Updater.php:514 index.php:1022 |
196 | msgid "" | 194 | msgid "" |
197 | "You have enabled or changed thumbnails mode. <a href=\"?do=thumbs_update" | 195 | "You have enabled or changed thumbnails mode. <a href=\"?do=thumbs_update" |
198 | "\">Please synchronize them</a>." | 196 | "\">Please synchronize them</a>." |
@@ -200,17 +198,17 @@ msgstr "" | |||
200 | "Vous avez activé ou changé le mode de miniatures. <a href=\"?do=thumbs_update" | 198 | "Vous avez activé ou changé le mode de miniatures. <a href=\"?do=thumbs_update" |
201 | "\">Merci de les synchroniser</a>." | 199 | "\">Merci de les synchroniser</a>." |
202 | 200 | ||
203 | #: application/Updater.php:566 | 201 | #: application/Updater.php:586 |
204 | msgid "An error occurred while running the update " | 202 | msgid "An error occurred while running the update " |
205 | msgstr "Une erreur s'est produite lors de l'exécution de la mise à jour " | 203 | msgstr "Une erreur s'est produite lors de l'exécution de la mise à jour " |
206 | 204 | ||
207 | #: application/Updater.php:606 | 205 | #: application/Updater.php:626 |
208 | msgid "Updates file path is not set, can't write updates." | 206 | msgid "Updates file path is not set, can't write updates." |
209 | msgstr "" | 207 | msgstr "" |
210 | "Le chemin vers le fichier de mise à jour n'est pas défini, impossible " | 208 | "Le chemin vers le fichier de mise à jour n'est pas défini, impossible " |
211 | "d'écrire les mises à jour." | 209 | "d'écrire les mises à jour." |
212 | 210 | ||
213 | #: application/Updater.php:611 | 211 | #: application/Updater.php:631 |
214 | msgid "Unable to write updates in " | 212 | msgid "Unable to write updates in " |
215 | msgstr "Impossible d'écrire les mises à jour dans " | 213 | msgstr "Impossible d'écrire les mises à jour dans " |
216 | 214 | ||
@@ -286,74 +284,66 @@ msgstr "NON. Vous êtes banni pour le moment. Revenez plus tard." | |||
286 | 284 | ||
287 | #: index.php:273 | 285 | #: index.php:273 |
288 | msgid "Wrong login/password." | 286 | msgid "Wrong login/password." |
289 | msgstr "Nom d'utilisateur ou mot de passe incorrects." | 287 | msgstr "Nom d'utilisateur ou mot de passe incorrect(s)." |
290 | 288 | ||
291 | #: index.php:483 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46 | 289 | #: index.php:482 tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:46 |
292 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:46 | ||
293 | msgid "Daily" | 290 | msgid "Daily" |
294 | msgstr "Quotidien" | 291 | msgstr "Quotidien" |
295 | 292 | ||
296 | #: index.php:589 tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 | 293 | #: index.php:588 tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 |
297 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 | 294 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 |
298 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:75 | ||
299 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:99 | ||
300 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:75 | 295 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:75 |
301 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:99 | 296 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:99 |
302 | msgid "Login" | 297 | msgid "Login" |
303 | msgstr "Connexion" | 298 | msgstr "Connexion" |
304 | 299 | ||
305 | #: index.php:606 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 | 300 | #: index.php:605 tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:41 |
306 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:41 | ||
307 | msgid "Picture wall" | 301 | msgid "Picture wall" |
308 | msgstr "Mur d'images" | 302 | msgstr "Mur d'images" |
309 | 303 | ||
310 | #: index.php:683 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | 304 | #: index.php:682 tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:36 |
311 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:36 | ||
312 | #: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 | 305 | #: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 |
313 | msgid "Tag cloud" | 306 | msgid "Tag cloud" |
314 | msgstr "Nuage de tags" | 307 | msgstr "Nuage de tags" |
315 | 308 | ||
316 | #: index.php:716 tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 | 309 | #: index.php:715 tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 |
317 | msgid "Tag list" | 310 | msgid "Tag list" |
318 | msgstr "Liste des tags" | 311 | msgstr "Liste des tags" |
319 | 312 | ||
320 | #: index.php:941 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 | 313 | #: index.php:940 tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:31 |
321 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:31 | ||
322 | msgid "Tools" | 314 | msgid "Tools" |
323 | msgstr "Outils" | 315 | msgstr "Outils" |
324 | 316 | ||
325 | #: index.php:950 | 317 | #: index.php:949 |
326 | msgid "You are not supposed to change a password on an Open Shaarli." | 318 | msgid "You are not supposed to change a password on an Open Shaarli." |
327 | msgstr "" | 319 | msgstr "" |
328 | "Vous n'êtes pas censé modifier le mot de passe d'un Shaarli en mode ouvert." | 320 | "Vous n'êtes pas censé modifier le mot de passe d'un Shaarli en mode ouvert." |
329 | 321 | ||
330 | #: index.php:955 index.php:997 index.php:1085 index.php:1116 index.php:1221 | 322 | #: index.php:954 index.php:996 index.php:1084 index.php:1116 index.php:1221 |
331 | msgid "Wrong token." | 323 | msgid "Wrong token." |
332 | msgstr "Jeton invalide." | 324 | msgstr "Jeton invalide." |
333 | 325 | ||
334 | #: index.php:960 | 326 | #: index.php:959 |
335 | msgid "The old password is not correct." | 327 | msgid "The old password is not correct." |
336 | msgstr "L'ancien mot de passe est incorrect." | 328 | msgstr "L'ancien mot de passe est incorrect." |
337 | 329 | ||
338 | #: index.php:980 | 330 | #: index.php:979 |
339 | msgid "Your password has been changed" | 331 | msgid "Your password has been changed" |
340 | msgstr "Votre mot de passe a été modifié" | 332 | msgstr "Votre mot de passe a été modifié" |
341 | 333 | ||
342 | #: index.php:985 | 334 | #: index.php:984 tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 |
343 | #: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 | ||
344 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 | ||
345 | msgid "Change password" | 335 | msgid "Change password" |
346 | msgstr "Modification du mot de passe" | 336 | msgstr "Modifier le mot de passe" |
347 | 337 | ||
348 | #: index.php:1043 | 338 | #: index.php:1042 |
349 | msgid "Configuration was saved." | 339 | msgid "Configuration was saved." |
350 | msgstr "La configuration a été sauvegardé." | 340 | msgstr "La configuration a été sauvegardée." |
351 | 341 | ||
352 | #: index.php:1068 tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 | 342 | #: index.php:1067 tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 |
353 | msgid "Configure" | 343 | msgid "Configure" |
354 | msgstr "Configurer" | 344 | msgstr "Configurer" |
355 | 345 | ||
356 | #: index.php:1079 tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 | 346 | #: index.php:1078 tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 |
357 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | 347 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 |
358 | msgid "Manage tags" | 348 | msgid "Manage tags" |
359 | msgstr "Gérer les tags" | 349 | msgstr "Gérer les tags" |
@@ -381,7 +371,6 @@ msgid "Edit" | |||
381 | msgstr "Modifier" | 371 | msgstr "Modifier" |
382 | 372 | ||
383 | #: index.php:1281 index.php:1351 | 373 | #: index.php:1281 index.php:1351 |
384 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 | ||
385 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:26 | 374 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:26 |
386 | msgid "Shaare" | 375 | msgid "Shaare" |
387 | msgstr "Shaare" | 376 | msgstr "Shaare" |
@@ -390,15 +379,19 @@ msgstr "Shaare" | |||
390 | msgid "Note: " | 379 | msgid "Note: " |
391 | msgstr "Note : " | 380 | msgstr "Note : " |
392 | 381 | ||
393 | #: index.php:1360 tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:65 | 382 | #: index.php:1359 |
383 | msgid "Invalid link ID provided" | ||
384 | msgstr "" | ||
385 | |||
386 | #: index.php:1379 | ||
394 | msgid "Export" | 387 | msgid "Export" |
395 | msgstr "Exporter" | 388 | msgstr "Exporter" |
396 | 389 | ||
397 | #: index.php:1422 tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:83 | 390 | #: index.php:1441 |
398 | msgid "Import" | 391 | msgid "Import" |
399 | msgstr "Importer" | 392 | msgstr "Importer" |
400 | 393 | ||
401 | #: index.php:1432 | 394 | #: index.php:1451 |
402 | #, php-format | 395 | #, php-format |
403 | msgid "" | 396 | msgid "" |
404 | "The file you are trying to upload is probably bigger than what this " | 397 | "The file you are trying to upload is probably bigger than what this " |
@@ -408,20 +401,20 @@ msgstr "" | |||
408 | "le serveur web peut accepter (%s). Merci de l'envoyer en parties plus " | 401 | "le serveur web peut accepter (%s). Merci de l'envoyer en parties plus " |
409 | "légères." | 402 | "légères." |
410 | 403 | ||
411 | #: index.php:1471 tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 | 404 | #: index.php:1490 tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 |
412 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22 | 405 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22 |
413 | msgid "Plugin administration" | 406 | msgid "Plugin administration" |
414 | msgstr "Administration des extensions" | 407 | msgstr "Administration des plugins" |
415 | 408 | ||
416 | #: index.php:1523 tmp/thumbnails.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | 409 | #: index.php:1542 tmp/thumbnails.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 |
417 | msgid "Thumbnails update" | 410 | msgid "Thumbnails update" |
418 | msgstr "Mise à jour des miniatures" | 411 | msgstr "Mise à jour des miniatures" |
419 | 412 | ||
420 | #: index.php:1695 | 413 | #: index.php:1714 |
421 | msgid "Search: " | 414 | msgid "Search: " |
422 | msgstr "Recherche : " | 415 | msgstr "Recherche : " |
423 | 416 | ||
424 | #: index.php:1735 | 417 | #: index.php:1754 |
425 | #, php-format | 418 | #, php-format |
426 | msgid "" | 419 | msgid "" |
427 | "<pre>Sessions do not seem to work correctly on your server.<br>Make sure the " | 420 | "<pre>Sessions do not seem to work correctly on your server.<br>Make sure the " |
@@ -431,16 +424,16 @@ msgid "" | |||
431 | "custom hostname without a dot causes cookie storage to fail. We recommend " | 424 | "custom hostname without a dot causes cookie storage to fail. We recommend " |
432 | "accessing your server via it's IP address or Fully Qualified Domain Name.<br>" | 425 | "accessing your server via it's IP address or Fully Qualified Domain Name.<br>" |
433 | msgstr "" | 426 | msgstr "" |
434 | "<pre>Les sesssions ne semble pas fonctionner sur ce serveur.<br>Assurez vous " | 427 | "<pre>Les sesssions ne semblent pas fonctionner sur ce serveur.<br>Assurez " |
435 | "que la variable « session.save_path » est correctement définie dans votre " | 428 | "vous que la variable « session.save_path » est correctement définie dans " |
436 | "fichier de configuration PHP, et que vous y avez les droits d'écriture." | 429 | "votre fichier de configuration PHP, et que vous avez les droits d'écriture " |
437 | "<br>Ce paramètre pointe actuellement sur %s.<br>Sur certains navigateurs, " | 430 | "dessus.<br>Ce paramètre pointe actuellement sur %s.<br>Sur certains " |
438 | "accéder à votre serveur depuis un nom d'hôte comme « localhost » ou autre " | 431 | "navigateurs, accéder à votre serveur depuis un nom d'hôte comme « localhost " |
439 | "nom personnalisé sans point '.' entraine l'échec de la sauvegarde des " | 432 | "» ou autre nom personnalisé sans point '.' entraine l'échec de la sauvegarde " |
440 | "cookies. Nous vous recommandons d'accéder à votre serveur depuis son adresse " | 433 | "des cookies. Nous vous recommandons d'accéder à votre serveur depuis son " |
441 | "IP ou un <em>Fully Qualified Domain Name</em>.<br>" | 434 | "adresse IP ou un <em>Fully Qualified Domain Name</em>.<br>" |
442 | 435 | ||
443 | #: index.php:1745 | 436 | #: index.php:1764 |
444 | msgid "Click to try again." | 437 | msgid "Click to try again." |
445 | msgstr "Cliquer ici pour réessayer." | 438 | msgstr "Cliquer ici pour réessayer." |
446 | 439 | ||
@@ -455,7 +448,7 @@ msgstr "Shaare" | |||
455 | 448 | ||
456 | #: plugins/addlink_toolbar/addlink_toolbar.php:50 | 449 | #: plugins/addlink_toolbar/addlink_toolbar.php:50 |
457 | msgid "Adds the addlink input on the linklist page." | 450 | msgid "Adds the addlink input on the linklist page." |
458 | msgstr "Ajout le formulaire d'ajout de liens sur la page principale." | 451 | msgstr "Ajoute le formulaire d'ajout de liens sur la page principale." |
459 | 452 | ||
460 | #: plugins/archiveorg/archiveorg.php:23 | 453 | #: plugins/archiveorg/archiveorg.php:23 |
461 | msgid "View on archive.org" | 454 | msgid "View on archive.org" |
@@ -471,7 +464,7 @@ msgid "" | |||
471 | "developers." | 464 | "developers." |
472 | msgstr "" | 465 | msgstr "" |
473 | "Une extension de démonstration couvrant tous les cas d'utilisation pour les " | 466 | "Une extension de démonstration couvrant tous les cas d'utilisation pour les " |
474 | "designers et les développeurs." | 467 | "designers de thèmes et les développeurs d'extensions." |
475 | 468 | ||
476 | #: plugins/isso/isso.php:20 | 469 | #: plugins/isso/isso.php:20 |
477 | msgid "" | 470 | msgid "" |
@@ -481,12 +474,13 @@ msgstr "" | |||
481 | "Erreur de l'extension Isso : Merci de définir le paramètre « ISSO_SERVER » " | 474 | "Erreur de l'extension Isso : Merci de définir le paramètre « ISSO_SERVER » " |
482 | "dans la page d'administration des extensions." | 475 | "dans la page d'administration des extensions." |
483 | 476 | ||
484 | #: plugins/isso/isso.php:63 | 477 | #: plugins/isso/isso.php:90 |
485 | msgid "Let visitor comment your shaares on permalinks with Isso." | 478 | msgid "Let visitor comment your shaares on permalinks with Isso." |
486 | msgstr "" | 479 | msgstr "" |
487 | "Permet aux visiteurs de commenter vos shaares sur les permaliens avec Isso." | 480 | "Permettre aux visiteurs de commenter vos shaares sur les permaliens avec " |
481 | "Isso." | ||
488 | 482 | ||
489 | #: plugins/isso/isso.php:64 | 483 | #: plugins/isso/isso.php:91 |
490 | msgid "Isso server URL (without 'http://')" | 484 | msgid "Isso server URL (without 'http://')" |
491 | msgstr "URL du serveur Isso (sans 'http://')" | 485 | msgstr "URL du serveur Isso (sans 'http://')" |
492 | 486 | ||
@@ -578,7 +572,7 @@ msgstr "Active la publication de flux vers PubSubHubbub." | |||
578 | 572 | ||
579 | #: plugins/qrcode/qrcode.php:69 plugins/wallabag/wallabag.php:68 | 573 | #: plugins/qrcode/qrcode.php:69 plugins/wallabag/wallabag.php:68 |
580 | msgid "For each link, add a QRCode icon." | 574 | msgid "For each link, add a QRCode icon." |
581 | msgstr "Pour chaque liens, ajouter une icône de QRCode." | 575 | msgstr "Pour chaque lien, ajouter une icône de QRCode." |
582 | 576 | ||
583 | #: plugins/wallabag/wallabag.php:21 | 577 | #: plugins/wallabag/wallabag.php:21 |
584 | msgid "" | 578 | msgid "" |
@@ -603,35 +597,17 @@ msgstr "Version de l'API Wallabag (1 ou 2)" | |||
603 | #: tests/LanguagesTest.php:214 tests/LanguagesTest.php:227 | 597 | #: tests/LanguagesTest.php:214 tests/LanguagesTest.php:227 |
604 | #: tests/languages/fr/LanguagesFrTest.php:160 | 598 | #: tests/languages/fr/LanguagesFrTest.php:160 |
605 | #: tests/languages/fr/LanguagesFrTest.php:173 | 599 | #: tests/languages/fr/LanguagesFrTest.php:173 |
606 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:85 | ||
607 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:85 | 600 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:85 |
608 | msgid "Search" | 601 | msgid "Search" |
609 | msgid_plural "Search" | 602 | msgid_plural "Search" |
610 | msgstr[0] "Rechercher" | 603 | msgstr[0] "Rechercher" |
611 | msgstr[1] "Rechercher" | 604 | msgstr[1] "Rechercher" |
612 | 605 | ||
613 | #: tmp/404.b91ef64efc3688266305ea9b42e5017e.rtpl.php:12 | ||
614 | msgid "Sorry, nothing to see here." | ||
615 | msgstr "Désolé, il y a rien à voir ici." | ||
616 | |||
617 | #: tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | 606 | #: tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 |
618 | msgid "URL or leave empty to post a note" | 607 | msgid "URL or leave empty to post a note" |
619 | msgstr "URL ou laisser vide pour créer une note" | 608 | msgstr "URL ou laisser vide pour créer une note" |
620 | 609 | ||
621 | #: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
622 | msgid "Current password" | ||
623 | msgstr "Mot de passe actuel" | ||
624 | |||
625 | #: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 | ||
626 | msgid "New password" | ||
627 | msgstr "Nouveau mot de passe" | ||
628 | |||
629 | #: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:23 | ||
630 | msgid "Change" | ||
631 | msgstr "Changer" | ||
632 | |||
633 | #: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | 610 | #: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 |
634 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:77 | ||
635 | msgid "Tag" | 611 | msgid "Tag" |
636 | msgstr "Tag" | 612 | msgstr "Tag" |
637 | 613 | ||
@@ -661,6 +637,34 @@ msgstr "Vous pouvez aussi modifier les tags dans la" | |||
661 | msgid "tag list" | 637 | msgid "tag list" |
662 | msgstr "liste des tags" | 638 | msgstr "liste des tags" |
663 | 639 | ||
640 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:143 | ||
641 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:296 | ||
642 | msgid "All" | ||
643 | msgstr "Tous" | ||
644 | |||
645 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:147 | ||
646 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:300 | ||
647 | msgid "Only common media hosts" | ||
648 | msgstr "Seulement les hébergeurs de média connus" | ||
649 | |||
650 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:151 | ||
651 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:304 | ||
652 | msgid "None" | ||
653 | msgstr "Aucune" | ||
654 | |||
655 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:158 | ||
656 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:281 | ||
657 | msgid "You need to enable the extension <code>php-gd</code> to use thumbnails." | ||
658 | msgstr "" | ||
659 | "Vous devez activer l'extension <code>php-gd</code> pour utiliser les " | ||
660 | "miniatures." | ||
661 | |||
662 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:162 | ||
663 | #, fuzzy | ||
664 | #| msgid "Enable thumbnails" | ||
665 | msgid "Synchonize thumbnails" | ||
666 | msgstr "Activer les miniatures" | ||
667 | |||
664 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 | 668 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 |
665 | msgid "title" | 669 | msgid "title" |
666 | msgstr "titre" | 670 | msgstr "titre" |
@@ -678,22 +682,18 @@ msgid "Theme" | |||
678 | msgstr "Thème" | 682 | msgstr "Thème" |
679 | 683 | ||
680 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:87 | 684 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:87 |
681 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:78 | ||
682 | msgid "Language" | 685 | msgid "Language" |
683 | msgstr "Langue" | 686 | msgstr "Langue" |
684 | 687 | ||
685 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:116 | 688 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:116 |
686 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:102 | ||
687 | msgid "Timezone" | 689 | msgid "Timezone" |
688 | msgstr "Fuseau horaire" | 690 | msgstr "Fuseau horaire" |
689 | 691 | ||
690 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 | 692 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 |
691 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:103 | ||
692 | msgid "Continent" | 693 | msgid "Continent" |
693 | msgstr "Continent" | 694 | msgstr "Continent" |
694 | 695 | ||
695 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 | 696 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 |
696 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:103 | ||
697 | msgid "City" | 697 | msgid "City" |
698 | msgstr "Ville" | 698 | msgstr "Ville" |
699 | 699 | ||
@@ -734,25 +734,21 @@ msgid "Do not show any links if the user is not logged in" | |||
734 | msgstr "N'afficher aucun lien sans être connecté" | 734 | msgstr "N'afficher aucun lien sans être connecté" |
735 | 735 | ||
736 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:231 | 736 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:231 |
737 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:150 | ||
738 | msgid "Check updates" | 737 | msgid "Check updates" |
739 | msgstr "Vérifier les mises à jour" | 738 | msgstr "Vérifier les mises à jour" |
740 | 739 | ||
741 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:232 | 740 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:232 |
742 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:152 | ||
743 | msgid "Notify me when a new release is ready" | 741 | msgid "Notify me when a new release is ready" |
744 | msgstr "Me notifier lorsqu'une nouvelle version est disponible" | 742 | msgstr "Me notifier lorsqu'une nouvelle version est disponible" |
745 | 743 | ||
746 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:247 | 744 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:247 |
747 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169 | ||
748 | msgid "Enable REST API" | 745 | msgid "Enable REST API" |
749 | msgstr "Activer l'API REST" | 746 | msgstr "Activer l'API REST" |
750 | 747 | ||
751 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:248 | 748 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:248 |
752 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:170 | ||
753 | msgid "Allow third party software to use Shaarli such as mobile application" | 749 | msgid "Allow third party software to use Shaarli such as mobile application" |
754 | msgstr "" | 750 | msgstr "" |
755 | "Permets aux applications tierces d'utiliser Shaarli, par exemple les " | 751 | "Permet aux applications tierces d'utiliser Shaarli, par exemple les " |
756 | "applications mobiles" | 752 | "applications mobiles" |
757 | 753 | ||
758 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:263 | 754 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:263 |
@@ -763,30 +759,11 @@ msgstr "Clé d'API secrète" | |||
763 | msgid "Enable thumbnails" | 759 | msgid "Enable thumbnails" |
764 | msgstr "Activer les miniatures" | 760 | msgstr "Activer les miniatures" |
765 | 761 | ||
766 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:281 | ||
767 | msgid "You need to enable the extension <code>php-gd</code> to use thumbnails." | ||
768 | msgstr "" | ||
769 | "Vous devez activer l'extension <code>php-gd</code> pour utiliser les " | ||
770 | "miniatures." | ||
771 | |||
772 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:285 | 762 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:285 |
773 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:56 | 763 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:56 |
774 | msgid "Synchronize thumbnails" | 764 | msgid "Synchronize thumbnails" |
775 | msgstr "Synchroniser les miniatures" | 765 | msgstr "Synchroniser les miniatures" |
776 | 766 | ||
777 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:296 | ||
778 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 | ||
779 | msgid "All" | ||
780 | msgstr "Tous" | ||
781 | |||
782 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:300 | ||
783 | msgid "Only common media hosts" | ||
784 | msgstr "Seulement les hébergeurs de média connus" | ||
785 | |||
786 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:304 | ||
787 | msgid "None" | ||
788 | msgstr "Aucune" | ||
789 | |||
790 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:312 | 767 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:312 |
791 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 | 768 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 |
792 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139 | 769 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139 |
@@ -847,107 +824,13 @@ msgid "Tags" | |||
847 | msgstr "Tags" | 824 | msgstr "Tags" |
848 | 825 | ||
849 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:57 | 826 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:57 |
850 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | ||
851 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:167 | 827 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:167 |
852 | msgid "Private" | 828 | msgid "Private" |
853 | msgstr "Privé" | 829 | msgstr "Privé" |
854 | 830 | ||
855 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 | 831 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 |
856 | msgid "Apply Changes" | 832 | msgid "Apply Changes" |
857 | msgstr "Appliquer" | 833 | msgstr "Appliquer les changements" |
858 | |||
859 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
860 | msgid "Export Database" | ||
861 | msgstr "Exporter les données" | ||
862 | |||
863 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 | ||
864 | msgid "Selection" | ||
865 | msgstr "Choisir" | ||
866 | |||
867 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 | ||
868 | msgid "Public" | ||
869 | msgstr "Publics" | ||
870 | |||
871 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:52 | ||
872 | msgid "Prepend note permalinks with this Shaarli instance's URL" | ||
873 | msgstr "Préfixer les liens de notes avec l'URL de l'instance de Shaarli" | ||
874 | |||
875 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:53 | ||
876 | msgid "Useful to import bookmarks in a web browser" | ||
877 | msgstr "Utile pour importer les marques-pages dans un navigateur" | ||
878 | |||
879 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
880 | msgid "Import Database" | ||
881 | msgstr "Importer des données" | ||
882 | |||
883 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:23 | ||
884 | msgid "Maximum size allowed:" | ||
885 | msgstr "Taille maximum autorisée :" | ||
886 | |||
887 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 | ||
888 | msgid "Visibility" | ||
889 | msgstr "Visibilité" | ||
890 | |||
891 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | ||
892 | msgid "Use values from the imported file, default to public" | ||
893 | msgstr "" | ||
894 | "Utiliser les valeurs présentes dans le fichier d'import, public par défaut" | ||
895 | |||
896 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 | ||
897 | msgid "Import all bookmarks as private" | ||
898 | msgstr "Importer tous les liens comme privés" | ||
899 | |||
900 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46 | ||
901 | msgid "Import all bookmarks as public" | ||
902 | msgstr "Importer tous les liens comme publics" | ||
903 | |||
904 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:57 | ||
905 | msgid "Overwrite existing bookmarks" | ||
906 | msgstr "Remplacer les liens existants" | ||
907 | |||
908 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:58 | ||
909 | msgid "Duplicates based on URL" | ||
910 | msgstr "Les doublons s'appuient sur les URL" | ||
911 | |||
912 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 | ||
913 | msgid "Add default tags" | ||
914 | msgstr "Ajouter des tags par défaut" | ||
915 | |||
916 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22 | ||
917 | msgid "Install Shaarli" | ||
918 | msgstr "Installation de Shaarli" | ||
919 | |||
920 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:25 | ||
921 | msgid "It looks like it's the first time you run Shaarli. Please configure it." | ||
922 | msgstr "" | ||
923 | "Il semblerait que ça soit la première fois que vous lancez Shaarli. Merci de " | ||
924 | "le configurer." | ||
925 | |||
926 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:33 | ||
927 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:30 | ||
928 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:151 | ||
929 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:151 | ||
930 | msgid "Username" | ||
931 | msgstr "Nom d'utilisateur" | ||
932 | |||
933 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 | ||
934 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 | ||
935 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:152 | ||
936 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:152 | ||
937 | msgid "Password" | ||
938 | msgstr "Mot de passe" | ||
939 | |||
940 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:63 | ||
941 | msgid "Shaarli title" | ||
942 | msgstr "Titre du Shaarli" | ||
943 | |||
944 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:69 | ||
945 | msgid "My links" | ||
946 | msgstr "Mes liens" | ||
947 | |||
948 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:182 | ||
949 | msgid "Install" | ||
950 | msgstr "Installer" | ||
951 | 834 | ||
952 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | 835 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 |
953 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:79 | 836 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:79 |
@@ -964,13 +847,11 @@ msgstr[0] "lien privé" | |||
964 | msgstr[1] "liens privés" | 847 | msgstr[1] "liens privés" |
965 | 848 | ||
966 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:30 | 849 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:30 |
967 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:121 | ||
968 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:121 | 850 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:121 |
969 | msgid "Search text" | 851 | msgid "Search text" |
970 | msgstr "Recherche texte" | 852 | msgstr "Recherche texte" |
971 | 853 | ||
972 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:37 | 854 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:37 |
973 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:128 | ||
974 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:128 | 855 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:128 |
975 | #: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | 856 | #: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 |
976 | #: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:64 | 857 | #: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:64 |
@@ -1011,7 +892,6 @@ msgid "without any tag" | |||
1011 | msgstr "sans tag" | 892 | msgstr "sans tag" |
1012 | 893 | ||
1013 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:173 | 894 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:173 |
1014 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 | ||
1015 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:42 | 895 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:42 |
1016 | msgid "Fold" | 896 | msgid "Fold" |
1017 | msgstr "Replier" | 897 | msgstr "Replier" |
@@ -1028,36 +908,36 @@ msgstr "permalien" | |||
1028 | msgid "Add tag" | 908 | msgid "Add tag" |
1029 | msgstr "Ajouter un tag" | 909 | msgstr "Ajouter un tag" |
1030 | 910 | ||
1031 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:7 | 911 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:183 |
912 | msgid "Toggle sticky" | ||
913 | msgstr "Changer statut épinglé" | ||
914 | |||
915 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:185 | ||
916 | msgid "Sticky" | ||
917 | msgstr "Épinglé" | ||
918 | |||
1032 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:7 | 919 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:7 |
1033 | msgid "Filters" | 920 | msgid "Filters" |
1034 | msgstr "Filtres" | 921 | msgstr "Filtres" |
1035 | 922 | ||
1036 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:12 | ||
1037 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:12 | 923 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:12 |
1038 | msgid "Only display private links" | 924 | msgid "Only display private links" |
1039 | msgstr "Afficher uniquement les liens privés" | 925 | msgstr "Afficher uniquement les liens privés" |
1040 | 926 | ||
1041 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 | ||
1042 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:15 | 927 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:15 |
1043 | msgid "Only display public links" | 928 | msgid "Only display public links" |
1044 | msgstr "Afficher uniquement les liens publics" | 929 | msgstr "Afficher uniquement les liens publics" |
1045 | 930 | ||
1046 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:20 | ||
1047 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:20 | 931 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:20 |
1048 | msgid "Filter untagged links" | 932 | msgid "Filter untagged links" |
1049 | msgstr "Filtrer par liens privés" | 933 | msgstr "Filtrer par liens privés" |
1050 | 934 | ||
1051 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 | ||
1052 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:76 | ||
1053 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:24 | 935 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:24 |
1054 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:76 | 936 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:76 |
1055 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43 | ||
1056 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:43 | 937 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:43 |
1057 | msgid "Fold all" | 938 | msgid "Fold all" |
1058 | msgstr "Replier tout" | 939 | msgstr "Replier tout" |
1059 | 940 | ||
1060 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:69 | ||
1061 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:69 | 941 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:69 |
1062 | msgid "Links per page" | 942 | msgid "Links per page" |
1063 | msgstr "Liens par page" | 943 | msgstr "Liens par page" |
@@ -1066,62 +946,59 @@ msgstr "Liens par page" | |||
1066 | msgid "" | 946 | msgid "" |
1067 | "You have been banned after too many failed login attempts. Try again later." | 947 | "You have been banned after too many failed login attempts. Try again later." |
1068 | msgstr "" | 948 | msgstr "" |
1069 | "Vous avez été banni après trop d'échec d'authentification. Merci de " | 949 | "Vous avez été banni après trop d'échecs d'authentification. Merci de " |
1070 | "réessayer plus tard." | 950 | "réessayer plus tard." |
1071 | 951 | ||
952 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:30 | ||
953 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:151 | ||
954 | msgid "Username" | ||
955 | msgstr "Nom d'utilisateur" | ||
956 | |||
957 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 | ||
958 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:152 | ||
959 | msgid "Password" | ||
960 | msgstr "Mot de passe" | ||
961 | |||
1072 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 | 962 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 |
1073 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:155 | ||
1074 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:155 | 963 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:155 |
1075 | msgid "Remember me" | 964 | msgid "Remember me" |
1076 | msgstr "Rester connecté" | 965 | msgstr "Rester connecté" |
1077 | 966 | ||
1078 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | ||
1079 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 | ||
1080 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14 | 967 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14 |
1081 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48 | 968 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48 |
1082 | msgid "by the Shaarli community" | 969 | msgid "by the Shaarli community" |
1083 | msgstr "par la communauté Shaarli" | 970 | msgstr "par la communauté Shaarli" |
1084 | 971 | ||
1085 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 | ||
1086 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:15 | 972 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:15 |
1087 | msgid "Documentation" | 973 | msgid "Documentation" |
1088 | msgstr "Documentation" | 974 | msgstr "Documentation" |
1089 | 975 | ||
1090 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 | ||
1091 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:44 | 976 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:44 |
1092 | msgid "Expand" | 977 | msgid "Expand" |
1093 | msgstr "Déplier" | 978 | msgstr "Déplier" |
1094 | 979 | ||
1095 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:45 | ||
1096 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:45 | 980 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:45 |
1097 | msgid "Expand all" | 981 | msgid "Expand all" |
1098 | msgstr "Déplier tout" | 982 | msgstr "Déplier tout" |
1099 | 983 | ||
1100 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46 | ||
1101 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:46 | 984 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:46 |
1102 | msgid "Are you sure you want to delete this link?" | 985 | msgid "Are you sure you want to delete this link?" |
1103 | msgstr "Êtes-vous sûr de vouloir supprimer ce lien ?" | 986 | msgstr "Êtes-vous sûr de vouloir supprimer ce lien ?" |
1104 | 987 | ||
1105 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:65 | ||
1106 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:90 | ||
1107 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:65 | 988 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:65 |
1108 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:90 | 989 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:90 |
1109 | msgid "RSS Feed" | 990 | msgid "RSS Feed" |
1110 | msgstr "Flux RSS" | 991 | msgstr "Flux RSS" |
1111 | 992 | ||
1112 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:70 | ||
1113 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:106 | ||
1114 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:70 | 993 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:70 |
1115 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:106 | 994 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:106 |
1116 | msgid "Logout" | 995 | msgid "Logout" |
1117 | msgstr "Déconnexion" | 996 | msgstr "Déconnexion" |
1118 | 997 | ||
1119 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:173 | ||
1120 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:173 | 998 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:173 |
1121 | msgid "is available" | 999 | msgid "is available" |
1122 | msgstr "est disponible" | 1000 | msgstr "est disponible" |
1123 | 1001 | ||
1124 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:180 | ||
1125 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:180 | 1002 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:180 |
1126 | msgid "Error" | 1003 | msgid "Error" |
1127 | msgstr "Erreur" | 1004 | msgstr "Erreur" |
@@ -1221,22 +1098,18 @@ msgstr "tags" | |||
1221 | msgid "List all links with those tags" | 1098 | msgid "List all links with those tags" |
1222 | msgstr "Lister tous les liens avec ces tags" | 1099 | msgstr "Lister tous les liens avec ces tags" |
1223 | 1100 | ||
1224 | #: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:3 | ||
1225 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:3 | 1101 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:3 |
1226 | msgid "Sort by:" | 1102 | msgid "Sort by:" |
1227 | msgstr "Trier par :" | 1103 | msgstr "Trier par :" |
1228 | 1104 | ||
1229 | #: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:5 | ||
1230 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:5 | 1105 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:5 |
1231 | msgid "Cloud" | 1106 | msgid "Cloud" |
1232 | msgstr "Nuage" | 1107 | msgstr "Nuage" |
1233 | 1108 | ||
1234 | #: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:6 | ||
1235 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:6 | 1109 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:6 |
1236 | msgid "Most used" | 1110 | msgid "Most used" |
1237 | msgstr "Plus utilisés" | 1111 | msgstr "Plus utilisés" |
1238 | 1112 | ||
1239 | #: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:7 | ||
1240 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:7 | 1113 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:7 |
1241 | msgid "Alphabetical" | 1114 | msgid "Alphabetical" |
1242 | msgstr "Alphabétique" | 1115 | msgstr "Alphabétique" |
@@ -1251,7 +1124,7 @@ msgstr "Changer les paramètres de Shaarli : titre, fuseau horaire, etc." | |||
1251 | 1124 | ||
1252 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:17 | 1125 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:17 |
1253 | msgid "Configure your Shaarli" | 1126 | msgid "Configure your Shaarli" |
1254 | msgstr "Conguration de Shaarli" | 1127 | msgstr "Configurer Shaarli" |
1255 | 1128 | ||
1256 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:21 | 1129 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:21 |
1257 | msgid "Enable, disable and configure plugins" | 1130 | msgid "Enable, disable and configure plugins" |
@@ -1259,31 +1132,39 @@ msgstr "Activer, désactiver et configurer les extensions" | |||
1259 | 1132 | ||
1260 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 | 1133 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 |
1261 | msgid "Change your password" | 1134 | msgid "Change your password" |
1262 | msgstr "Modification du mot de passe" | 1135 | msgstr "Modifier le mot de passe" |
1263 | 1136 | ||
1264 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35 | 1137 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35 |
1265 | msgid "Rename or delete a tag in all links" | 1138 | msgid "Rename or delete a tag in all links" |
1266 | msgstr "Rename or delete a tag in all links" | 1139 | msgstr "Renommer ou supprimer un tag dans tous les liens" |
1267 | 1140 | ||
1268 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 | 1141 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 |
1142 | #, fuzzy | ||
1143 | #| msgid "" | ||
1144 | #| "Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, " | ||
1145 | #| "delicious…)" | ||
1269 | msgid "" | 1146 | msgid "" |
1270 | "Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, " | 1147 | "Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, " |
1271 | "delicious...)" | 1148 | "delicious...)" |
1272 | msgstr "" | 1149 | msgstr "" |
1273 | "Importer des marques pages au format Netscape HTML (comme exportés depuis " | 1150 | "Importer des marques pages au format Netscape HTML (comme exportés depuis " |
1274 | "Firefox, Chrome, Opera, delicious...)" | 1151 | "Firefox, Chrome, Opera, delicious…)" |
1275 | 1152 | ||
1276 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 | 1153 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 |
1277 | msgid "Import links" | 1154 | msgid "Import links" |
1278 | msgstr "Importer des liens" | 1155 | msgstr "Importer des liens" |
1279 | 1156 | ||
1280 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47 | 1157 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47 |
1158 | #, fuzzy | ||
1159 | #| msgid "" | ||
1160 | #| "Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, " | ||
1161 | #| "Opera, delicious…)" | ||
1281 | msgid "" | 1162 | msgid "" |
1282 | "Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, " | 1163 | "Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, " |
1283 | "Opera, delicious...)" | 1164 | "Opera, delicious...)" |
1284 | msgstr "" | 1165 | msgstr "" |
1285 | "Exporter les marques pages au format Netscape HTML (comme exportés depuis " | 1166 | "Exporter les marques pages au format Netscape HTML (comme exportés depuis " |
1286 | "Firefox, Chrome, Opera, delicious...)" | 1167 | "Firefox, Chrome, Opera, delicious…)" |
1287 | 1168 | ||
1288 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 | 1169 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 |
1289 | msgid "Export database" | 1170 | msgid "Export database" |
@@ -1298,13 +1179,13 @@ msgid "" | |||
1298 | "Drag one of these button to your bookmarks toolbar or right-click it and " | 1179 | "Drag one of these button to your bookmarks toolbar or right-click it and " |
1299 | "\"Bookmark This Link\"" | 1180 | "\"Bookmark This Link\"" |
1300 | msgstr "" | 1181 | msgstr "" |
1301 | "Glisser un de ces bouttons dans votre barre de favoris ou cliquer droit " | 1182 | "Glisser un de ces boutons dans votre barre de favoris ou cliquer droit " |
1302 | "dessus et « Ajouter aux favoris »" | 1183 | "dessus et « Ajouter aux favoris »" |
1303 | 1184 | ||
1304 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:82 | 1185 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:82 |
1305 | msgid "then click on the bookmarklet in any page you want to share." | 1186 | msgid "then click on the bookmarklet in any page you want to share." |
1306 | msgstr "" | 1187 | msgstr "" |
1307 | "puis cliquer sur le marque page depuis un site que vous souhaitez partager." | 1188 | "puis cliquer sur le marque-page depuis un site que vous souhaitez partager." |
1308 | 1189 | ||
1309 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86 | 1190 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86 |
1310 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:110 | 1191 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:110 |
@@ -1339,33 +1220,16 @@ msgstr "" | |||
1339 | msgid "Add Note" | 1220 | msgid "Add Note" |
1340 | msgstr "Ajouter une Note" | 1221 | msgstr "Ajouter une Note" |
1341 | 1222 | ||
1342 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139 | 1223 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:136 |
1343 | msgid "" | ||
1344 | "You need to browse your Shaarli over <strong>HTTPS</strong> to use this " | ||
1345 | "functionality." | ||
1346 | msgstr "" | ||
1347 | "Vous devez utiliser Shaarli en <strong>HTTPS</strong> pour utiliser cette " | ||
1348 | "fonctionalité." | ||
1349 | |||
1350 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:144 | ||
1351 | msgid "Add to" | ||
1352 | msgstr "Ajouter à" | ||
1353 | |||
1354 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:155 | ||
1355 | msgid "3rd party" | 1224 | msgid "3rd party" |
1356 | msgstr "Applications tierces" | 1225 | msgstr "Applications tierces" |
1357 | 1226 | ||
1358 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:157 | 1227 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139 |
1359 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:163 | 1228 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:144 |
1360 | msgid "Plugin" | ||
1361 | msgstr "Extension" | ||
1362 | |||
1363 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:158 | ||
1364 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:164 | ||
1365 | msgid "plugin" | 1229 | msgid "plugin" |
1366 | msgstr "extension" | 1230 | msgstr "extension" |
1367 | 1231 | ||
1368 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:191 | 1232 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169 |
1369 | msgid "" | 1233 | msgid "" |
1370 | "Drag this link to your bookmarks toolbar, or right-click it and choose " | 1234 | "Drag this link to your bookmarks toolbar, or right-click it and choose " |
1371 | "Bookmark This Link" | 1235 | "Bookmark This Link" |
@@ -1373,10 +1237,91 @@ msgstr "" | |||
1373 | "Glisser ce lien dans votre barre de favoris ou cliquer droit dessus et « " | 1237 | "Glisser ce lien dans votre barre de favoris ou cliquer droit dessus et « " |
1374 | "Ajouter aux favoris »" | 1238 | "Ajouter aux favoris »" |
1375 | 1239 | ||
1376 | #, fuzzy | 1240 | #~ msgid "Sorry, nothing to see here." |
1377 | #~| msgid "Enable thumbnails" | 1241 | #~ msgstr "Désolé, il y a rien à voir ici." |
1378 | #~ msgid "Synchonize thumbnails" | 1242 | |
1379 | #~ msgstr "Activer les miniatures" | 1243 | #~ msgid "Current password" |
1244 | #~ msgstr "Mot de passe actuel" | ||
1245 | |||
1246 | #~ msgid "New password" | ||
1247 | #~ msgstr "Nouveau mot de passe" | ||
1248 | |||
1249 | #~ msgid "Change" | ||
1250 | #~ msgstr "Changer" | ||
1251 | |||
1252 | #~ msgid "Export Database" | ||
1253 | #~ msgstr "Exporter les données" | ||
1254 | |||
1255 | #~ msgid "Selection" | ||
1256 | #~ msgstr "Choisir" | ||
1257 | |||
1258 | #~ msgid "Public" | ||
1259 | #~ msgstr "Publics" | ||
1260 | |||
1261 | #~ msgid "Prepend note permalinks with this Shaarli instance's URL" | ||
1262 | #~ msgstr "Préfixer les liens de note avec l'URL de l'instance de Shaarli" | ||
1263 | |||
1264 | #~ msgid "Useful to import bookmarks in a web browser" | ||
1265 | #~ msgstr "Utile pour importer les marques-pages dans un navigateur" | ||
1266 | |||
1267 | #~ msgid "Import Database" | ||
1268 | #~ msgstr "Importer des données" | ||
1269 | |||
1270 | #~ msgid "Maximum size allowed:" | ||
1271 | #~ msgstr "Taille maximum autorisée :" | ||
1272 | |||
1273 | #~ msgid "Visibility" | ||
1274 | #~ msgstr "Visibilité" | ||
1275 | |||
1276 | #~ msgid "Use values from the imported file, default to public" | ||
1277 | #~ msgstr "" | ||
1278 | #~ "Utiliser les valeurs présentes dans le fichier d'import, public par défaut" | ||
1279 | |||
1280 | #~ msgid "Import all bookmarks as private" | ||
1281 | #~ msgstr "Importer tous les liens comme privés" | ||
1282 | |||
1283 | #~ msgid "Import all bookmarks as public" | ||
1284 | #~ msgstr "Importer tous les liens comme publics" | ||
1285 | |||
1286 | #~ msgid "Overwrite existing bookmarks" | ||
1287 | #~ msgstr "Remplacer les liens existants" | ||
1288 | |||
1289 | #~ msgid "Duplicates based on URL" | ||
1290 | #~ msgstr "Les doublons s'appuient sur les URL" | ||
1291 | |||
1292 | #~ msgid "Add default tags" | ||
1293 | #~ msgstr "Ajouter des tags par défaut" | ||
1294 | |||
1295 | #~ msgid "Install Shaarli" | ||
1296 | #~ msgstr "Installation de Shaarli" | ||
1297 | |||
1298 | #~ msgid "" | ||
1299 | #~ "It looks like it's the first time you run Shaarli. Please configure it." | ||
1300 | #~ msgstr "" | ||
1301 | #~ "Il semblerait que ça soit la première fois que vous lancez Shaarli. Merci " | ||
1302 | #~ "de le configurer." | ||
1303 | |||
1304 | #~ msgid "Shaarli title" | ||
1305 | #~ msgstr "Titre du Shaarli" | ||
1306 | |||
1307 | #~ msgid "My links" | ||
1308 | #~ msgstr "Mes liens" | ||
1309 | |||
1310 | #~ msgid "Install" | ||
1311 | #~ msgstr "Installer" | ||
1312 | |||
1313 | #~ msgid "" | ||
1314 | #~ "You need to browse your Shaarli over <strong>HTTPS</strong> to use this " | ||
1315 | #~ "functionality." | ||
1316 | #~ msgstr "" | ||
1317 | #~ "Vous devez utiliser Shaarli en <strong>HTTPS</strong> pour utiliser cette " | ||
1318 | #~ "fonctionalité." | ||
1319 | |||
1320 | #~ msgid "Add to" | ||
1321 | #~ msgstr "Ajouter à" | ||
1322 | |||
1323 | #~ msgid "Plugin" | ||
1324 | #~ msgstr "Extension" | ||
1380 | 1325 | ||
1381 | #~ msgid "Warning: " | 1326 | #~ msgid "Warning: " |
1382 | #~ msgstr "Attention : " | 1327 | #~ msgstr "Attention : " |
@@ -1450,7 +1395,8 @@ msgstr "" | |||
1450 | #~ "\n" | 1395 | #~ "\n" |
1451 | 1396 | ||
1452 | #~ msgid "Sessions do not seem to work correctly on your server." | 1397 | #~ msgid "Sessions do not seem to work correctly on your server." |
1453 | #~ msgstr "Les sessions ne semblent " | 1398 | #~ msgstr "" |
1399 | #~ "Les sessions ne semblent pas fonctionner correctement sur votre serveur." | ||
1454 | 1400 | ||
1455 | #~ msgid "Tag was renamed in " | 1401 | #~ msgid "Tag was renamed in " |
1456 | #~ msgstr "Le tag a été renommé dans " | 1402 | #~ msgstr "Le tag a été renommé dans " |
@@ -28,7 +28,7 @@ if (date_default_timezone_get() == '') { | |||
28 | define('WEB_PATH', substr($_SERVER['REQUEST_URI'], 0, 1+strrpos($_SERVER['REQUEST_URI'], '/', 0))); | 28 | define('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. |
31 | ini_set('max_input_time','60'); | 31 | ini_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 |
34 | ini_set('memory_limit', '128M'); | 34 | ini_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 |
86 | try { | 86 | try { |
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; |
@@ -111,7 +111,7 @@ ini_set('session.use_trans_sid', false); | |||
111 | 111 | ||
112 | session_name('shaarli'); | 112 | session_name('shaarli'); |
113 | // Start session if needed (Some server auto-start sessions). | 113 | // Start session if needed (Some server auto-start sessions). |
114 | if (session_id() == '') { | 114 | if (session_status() == PHP_SESSION_NONE) { |
115 | session_start(); | 115 | session_start(); |
116 | } | 116 | } |
117 | 117 | ||
@@ -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...). |
281 | if (!isset($_SESSION['tokens'])) $_SESSION['tokens']=array(); // Token are attached to the session. | 281 | if (!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 | */ |
291 | function showDailyRSS($conf, $loginManager) { | 293 | function 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 | */ |
495 | function showLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager) { | 498 | function 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')); |
@@ -1084,7 +1094,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1084 | die(t('Wrong token.')); | 1094 | die(t('Wrong token.')); |
1085 | } | 1095 | } |
1086 | 1096 | ||
1087 | $alteredLinks = $LINKSDB->renameTag(escape($_POST['fromtag']), escape($_POST['totag'])); | 1097 | $toTag = isset($_POST['totag']) ? escape($_POST['totag']) : null; |
1098 | $alteredLinks = $LINKSDB->renameTag(escape($_POST['fromtag']), $toTag); | ||
1088 | $LINKSDB->save($conf->get('resource.page_cache')); | 1099 | $LINKSDB->save($conf->get('resource.page_cache')); |
1089 | foreach ($alteredLinks as $link) { | 1100 | foreach ($alteredLinks as $link) { |
1090 | $history->updateLink($link); | 1101 | $history->updateLink($link); |
@@ -1100,16 +1111,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1100 | } | 1111 | } |
1101 | 1112 | ||
1102 | // -------- 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. |
1103 | if ($targetPage == Router::$PAGE_ADDLINK) | 1114 | if ($targetPage == Router::$PAGE_ADDLINK) { |
1104 | { | ||
1105 | $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')); |
1106 | $PAGE->renderPage('addlink'); | 1116 | $PAGE->renderPage('addlink'); |
1107 | exit; | 1117 | exit; |
1108 | } | 1118 | } |
1109 | 1119 | ||
1110 | // -------- 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. |
1111 | if (isset($_POST['save_edit'])) | 1121 | if (isset($_POST['save_edit'])) { |
1112 | { | ||
1113 | // Go away! | 1122 | // Go away! |
1114 | if (! $sessionManager->checkToken($_POST['token'])) { | 1123 | if (! $sessionManager->checkToken($_POST['token'])) { |
1115 | die(t('Wrong token.')); | 1124 | die(t('Wrong token.')); |
@@ -1196,14 +1205,16 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1196 | } | 1205 | } |
1197 | 1206 | ||
1198 | // -------- User clicked the "Cancel" button when editing a link. | 1207 | // -------- User clicked the "Cancel" button when editing a link. |
1199 | if (isset($_POST['cancel_edit'])) | 1208 | if (isset($_POST['cancel_edit'])) { |
1200 | { | ||
1201 | $id = isset($_POST['lf_id']) ? (int) escape($_POST['lf_id']) : false; | 1209 | $id = isset($_POST['lf_id']) ? (int) escape($_POST['lf_id']) : false; |
1202 | if (! isset($LINKSDB[$id])) { | 1210 | if (! isset($LINKSDB[$id])) { |
1203 | header('Location: ?'); | 1211 | header('Location: ?'); |
1204 | } | 1212 | } |
1205 | // 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: |
1206 | 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 | } | ||
1207 | $link = $LINKSDB[$id]; | 1218 | $link = $LINKSDB[$id]; |
1208 | $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); | 1219 | $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); |
1209 | // Scroll to the link which has been edited. | 1220 | // Scroll to the link which has been edited. |
@@ -1214,8 +1225,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1214 | } | 1225 | } |
1215 | 1226 | ||
1216 | // -------- 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. |
1217 | if ($targetPage == Router::$PAGE_DELETELINK) | 1228 | if ($targetPage == Router::$PAGE_DELETELINK) { |
1218 | { | ||
1219 | if (! $sessionManager->checkToken($_GET['token'])) { | 1229 | if (! $sessionManager->checkToken($_GET['token'])) { |
1220 | die(t('Wrong token.')); | 1230 | die(t('Wrong token.')); |
1221 | } | 1231 | } |
@@ -1229,28 +1239,31 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1229 | $ids = [$ids]; | 1239 | $ids = [$ids]; |
1230 | } | 1240 | } |
1231 | // assert at least one id is given | 1241 | // assert at least one id is given |
1232 | if(!count($ids)){ | 1242 | if (!count($ids)) { |
1233 | die('no id provided'); | 1243 | die('no id provided'); |
1234 | } | 1244 | } |
1235 | foreach ($ids as $id) { | 1245 | foreach ($ids as $id) { |
1236 | $id = (int) escape($id); | 1246 | $id = (int) escape($id); |
1237 | $link = $LINKSDB[$id]; | 1247 | $link = $LINKSDB[$id]; |
1238 | $pluginManager->executeHooks('delete_link', $link); | 1248 | $pluginManager->executeHooks('delete_link', $link); |
1249 | $history->deleteLink($link); | ||
1239 | unset($LINKSDB[$id]); | 1250 | unset($LINKSDB[$id]); |
1240 | } | 1251 | } |
1241 | $LINKSDB->save($conf->get('resource.page_cache')); // save to disk | 1252 | $LINKSDB->save($conf->get('resource.page_cache')); // save to disk |
1242 | $history->deleteLink($link); | ||
1243 | 1253 | ||
1244 | // 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: |
1245 | 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 | } | ||
1246 | 1259 | ||
1247 | $location = '?'; | 1260 | $location = '?'; |
1248 | if (isset($_SERVER['HTTP_REFERER'])) { | 1261 | if (isset($_SERVER['HTTP_REFERER'])) { |
1249 | // 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. |
1250 | $location = generateLocation( | 1263 | $location = generateLocation( |
1251 | $_SERVER['HTTP_REFERER'], | 1264 | $_SERVER['HTTP_REFERER'], |
1252 | $_SERVER['HTTP_HOST'], | 1265 | $_SERVER['HTTP_HOST'], |
1253 | ['delete_link', 'edit_link', $link['shorturl']] | 1266 | ['delete_link', 'edit_link', $link['shorturl']] |
1254 | ); | 1267 | ); |
1255 | } | 1268 | } |
1256 | 1269 | ||
@@ -1259,11 +1272,13 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1259 | } | 1272 | } |
1260 | 1273 | ||
1261 | // -------- 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. |
1262 | if (isset($_GET['edit_link'])) | 1275 | if (isset($_GET['edit_link'])) { |
1263 | { | ||
1264 | $id = (int) escape($_GET['edit_link']); | 1276 | $id = (int) escape($_GET['edit_link']); |
1265 | $link = $LINKSDB[$id]; // Read database | 1277 | $link = $LINKSDB[$id]; // Read database |
1266 | if (!$link) { header('Location: ?'); exit; } // Link not found in database. | 1278 | if (!$link) { |
1279 | header('Location: ?'); | ||
1280 | exit; | ||
1281 | } // Link not found in database. | ||
1267 | $link['linkdate'] = $link['created']->format(LinkDB::LINK_DATE_FORMAT); | 1282 | $link['linkdate'] = $link['created']->format(LinkDB::LINK_DATE_FORMAT); |
1268 | $data = array( | 1283 | $data = array( |
1269 | 'link' => $link, | 1284 | 'link' => $link, |
@@ -1289,8 +1304,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1289 | $link_is_new = false; | 1304 | $link_is_new = false; |
1290 | // 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) |
1291 | $link = $LINKSDB->getLinkFromUrl($url); | 1306 | $link = $LINKSDB->getLinkFromUrl($url); |
1292 | if (! $link) | 1307 | if (! $link) { |
1293 | { | ||
1294 | $link_is_new = true; | 1308 | $link_is_new = true; |
1295 | $linkdate = strval(date(LinkDB::LINK_DATE_FORMAT)); | 1309 | $linkdate = strval(date(LinkDB::LINK_DATE_FORMAT)); |
1296 | // Get title if it was provided in URL (by the bookmarklet). | 1310 | // Get title if it was provided in URL (by the bookmarklet). |
@@ -1299,7 +1313,9 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1299 | $description = empty($_GET['description']) ? '' : escape($_GET['description']); | 1313 | $description = empty($_GET['description']) ? '' : escape($_GET['description']); |
1300 | $tags = empty($_GET['tags']) ? '' : escape($_GET['tags']); | 1314 | $tags = empty($_GET['tags']) ? '' : escape($_GET['tags']); |
1301 | $private = !empty($_GET['private']) && $_GET['private'] === "1" ? 1 : 0; | 1315 | $private = !empty($_GET['private']) && $_GET['private'] === "1" ? 1 : 0; |
1302 | // 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.) | ||
1303 | if (empty($title) && strpos(get_url_scheme($url), 'http') !== false) { | 1319 | if (empty($title) && strpos(get_url_scheme($url), 'http') !== false) { |
1304 | // Short timeout to keep the application responsive | 1320 | // Short timeout to keep the application responsive |
1305 | // 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. |
@@ -1352,6 +1368,25 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1352 | exit; | 1368 | exit; |
1353 | } | 1369 | } |
1354 | 1370 | ||
1371 | if ($targetPage == Router::$PAGE_PINLINK) { | ||
1372 | if (! isset($_GET['id']) || empty($LINKSDB[$_GET['id']])) { | ||
1373 | // FIXME! Use a proper error system. | ||
1374 | $msg = t('Invalid link ID provided'); | ||
1375 | echo '<script>alert("'. $msg .'");document.location=\''. index_url($_SERVER) .'\';</script>'; | ||
1376 | exit; | ||
1377 | } | ||
1378 | if (! $sessionManager->checkToken($_GET['token'])) { | ||
1379 | die('Wrong token.'); | ||
1380 | } | ||
1381 | |||
1382 | $link = $LINKSDB[$_GET['id']]; | ||
1383 | $link['sticky'] = ! $link['sticky']; | ||
1384 | $LINKSDB[(int) $_GET['id']] = $link; | ||
1385 | $LINKSDB->save($conf->get('resource.page_cache')); | ||
1386 | header('Location: '.index_url($_SERVER)); | ||
1387 | exit; | ||
1388 | } | ||
1389 | |||
1355 | if ($targetPage == Router::$PAGE_EXPORT) { | 1390 | if ($targetPage == Router::$PAGE_EXPORT) { |
1356 | // Export links as a Netscape Bookmarks file | 1391 | // Export links as a Netscape Bookmarks file |
1357 | 1392 | ||
@@ -1388,7 +1423,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1388 | header('Content-Type: text/html; charset=utf-8'); | 1423 | header('Content-Type: text/html; charset=utf-8'); |
1389 | header( | 1424 | header( |
1390 | 'Content-disposition: attachment; filename=bookmarks_' | 1425 | 'Content-disposition: attachment; filename=bookmarks_' |
1391 | .$selection.'_'.$now->format(LinkDB::LINK_DATE_FORMAT).'.html' | 1426 | .$selection.'_'.$now->format(LinkDB::LINK_DATE_FORMAT).'.html' |
1392 | ); | 1427 | ); |
1393 | $PAGE->assign('date', $now->format(DateTime::RFC822)); | 1428 | $PAGE->assign('date', $now->format(DateTime::RFC822)); |
1394 | $PAGE->assign('eol', PHP_EOL); | 1429 | $PAGE->assign('eol', PHP_EOL); |
@@ -1456,14 +1491,20 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1456 | $pluginMeta = $pluginManager->getPluginsMeta(); | 1491 | $pluginMeta = $pluginManager->getPluginsMeta(); |
1457 | 1492 | ||
1458 | // Split plugins into 2 arrays: ordered enabled plugins and disabled. | 1493 | // Split plugins into 2 arrays: ordered enabled plugins and disabled. |
1459 | $enabledPlugins = array_filter($pluginMeta, function($v) { return $v['order'] !== false; }); | 1494 | $enabledPlugins = array_filter($pluginMeta, function ($v) { |
1495 | return $v['order'] !== false; | ||
1496 | }); | ||
1460 | // Load parameters. | 1497 | // Load parameters. |
1461 | $enabledPlugins = load_plugin_parameter_values($enabledPlugins, $conf->get('plugins', array())); | 1498 | $enabledPlugins = load_plugin_parameter_values($enabledPlugins, $conf->get('plugins', array())); |
1462 | uasort( | 1499 | uasort( |
1463 | $enabledPlugins, | 1500 | $enabledPlugins, |
1464 | function($a, $b) { return $a['order'] - $b['order']; } | 1501 | function ($a, $b) { |
1502 | return $a['order'] - $b['order']; | ||
1503 | } | ||
1465 | ); | 1504 | ); |
1466 | $disabledPlugins = array_filter($pluginMeta, function($v) { return $v['order'] === false; }); | 1505 | $disabledPlugins = array_filter($pluginMeta, function ($v) { |
1506 | return $v['order'] === false; | ||
1507 | }); | ||
1467 | 1508 | ||
1468 | $PAGE->assign('enabledPlugins', $enabledPlugins); | 1509 | $PAGE->assign('enabledPlugins', $enabledPlugins); |
1469 | $PAGE->assign('disabledPlugins', $disabledPlugins); | 1510 | $PAGE->assign('disabledPlugins', $disabledPlugins); |
@@ -1480,21 +1521,23 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1480 | foreach ($_POST as $param => $value) { | 1521 | foreach ($_POST as $param => $value) { |
1481 | $conf->set('plugins.'. $param, escape($value)); | 1522 | $conf->set('plugins.'. $param, escape($value)); |
1482 | } | 1523 | } |
1483 | } | 1524 | } else { |
1484 | else { | ||
1485 | $conf->set('general.enabled_plugins', save_plugin_config($_POST)); | 1525 | $conf->set('general.enabled_plugins', save_plugin_config($_POST)); |
1486 | } | 1526 | } |
1487 | $conf->write($loginManager->isLoggedIn()); | 1527 | $conf->write($loginManager->isLoggedIn()); |
1488 | $history->updateSettings(); | 1528 | $history->updateSettings(); |
1489 | } | 1529 | } catch (Exception $e) { |
1490 | catch (Exception $e) { | ||
1491 | error_log( | 1530 | error_log( |
1492 | 'ERROR while saving plugin configuration:.' . PHP_EOL . | 1531 | 'ERROR while saving plugin configuration:.' . PHP_EOL . |
1493 | $e->getMessage() | 1532 | $e->getMessage() |
1494 | ); | 1533 | ); |
1495 | 1534 | ||
1496 | // TODO: do not handle exceptions/errors in JS. | 1535 | // TODO: do not handle exceptions/errors in JS. |
1497 | 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>'; | ||
1498 | exit; | 1541 | exit; |
1499 | } | 1542 | } |
1500 | header('Location: ?do='. Router::$PAGE_PLUGINSADMIN); | 1543 | header('Location: ?do='. Router::$PAGE_PLUGINSADMIN); |
@@ -1615,8 +1658,7 @@ function buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager) | |||
1615 | } | 1658 | } |
1616 | 1659 | ||
1617 | $linkDisp = array(); | 1660 | $linkDisp = array(); |
1618 | while ($i<$end && $i<count($keys)) | 1661 | while ($i<$end && $i<count($keys)) { |
1619 | { | ||
1620 | $link = $linksToDisplay[$keys[$i]]; | 1662 | $link = $linksToDisplay[$keys[$i]]; |
1621 | $link['description'] = format_description( | 1663 | $link['description'] = format_description( |
1622 | $link['description'], | 1664 | $link['description'], |
@@ -1719,16 +1761,19 @@ function buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager) | |||
1719 | * @param SessionManager $sessionManager SessionManager instance | 1761 | * @param SessionManager $sessionManager SessionManager instance |
1720 | * @param LoginManager $loginManager LoginManager instance | 1762 | * @param LoginManager $loginManager LoginManager instance |
1721 | */ | 1763 | */ |
1722 | function install($conf, $sessionManager, $loginManager) { | 1764 | function install($conf, $sessionManager, $loginManager) |
1765 | { | ||
1723 | // 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. |
1724 | 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 | } | ||
1725 | 1770 | ||
1726 | 1771 | ||
1727 | // This part makes sure sessions works correctly. | 1772 | // This part makes sure sessions works correctly. |
1728 | // (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, |
1729 | // or we may not have write access to it.) | 1774 | // or we may not have write access to it.) |
1730 | if (isset($_GET['test_session']) && ( !isset($_SESSION) || !isset($_SESSION['session_tested']) || $_SESSION['session_tested']!='Working')) | 1775 | if (isset($_GET['test_session']) |
1731 | { | 1776 | && ( !isset($_SESSION) || !isset($_SESSION['session_tested']) || $_SESSION['session_tested']!='Working')) { |
1732 | // Step 2: Check if data in session is correct. | 1777 | // Step 2: Check if data in session is correct. |
1733 | $msg = t( | 1778 | $msg = t( |
1734 | '<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>'. |
@@ -1744,19 +1789,18 @@ function install($conf, $sessionManager, $loginManager) { | |||
1744 | echo '<br><a href="?">'. t('Click to try again.') .'</a></pre>'; | 1789 | echo '<br><a href="?">'. t('Click to try again.') .'</a></pre>'; |
1745 | die; | 1790 | die; |
1746 | } | 1791 | } |
1747 | if (!isset($_SESSION['session_tested'])) | 1792 | if (!isset($_SESSION['session_tested'])) { |
1748 | { // Step 1 : Try to store data in session and reload page. | 1793 | // Step 1 : Try to store data in session and reload page. |
1749 | $_SESSION['session_tested'] = 'Working'; // Try to set a variable in session. | 1794 | $_SESSION['session_tested'] = 'Working'; // Try to set a variable in session. |
1750 | 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. |
1751 | } | 1796 | } |
1752 | if (isset($_GET['test_session'])) | 1797 | if (isset($_GET['test_session'])) { |
1753 | { // Step 3: Sessions are OK. Remove test parameter from URL. | 1798 | // Step 3: Sessions are OK. Remove test parameter from URL. |
1754 | header('Location: '.index_url($_SERVER)); | 1799 | header('Location: '.index_url($_SERVER)); |
1755 | } | 1800 | } |
1756 | 1801 | ||
1757 | 1802 | ||
1758 | if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) | 1803 | if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) { |
1759 | { | ||
1760 | $tz = 'UTC'; | 1804 | $tz = 'UTC'; |
1761 | if (!empty($_POST['continent']) && !empty($_POST['city']) | 1805 | if (!empty($_POST['continent']) && !empty($_POST['city']) |
1762 | && isTimeZoneValid($_POST['continent'], $_POST['city']) | 1806 | && isTimeZoneValid($_POST['continent'], $_POST['city']) |
@@ -1787,18 +1831,20 @@ function install($conf, $sessionManager, $loginManager) { | |||
1787 | try { | 1831 | try { |
1788 | // Everything is ok, let's create config file. | 1832 | // Everything is ok, let's create config file. |
1789 | $conf->write($loginManager->isLoggedIn()); | 1833 | $conf->write($loginManager->isLoggedIn()); |
1790 | } | 1834 | } catch (Exception $e) { |
1791 | catch(Exception $e) { | ||
1792 | error_log( | 1835 | error_log( |
1793 | 'ERROR while writing config file after installation.' . PHP_EOL . | 1836 | 'ERROR while writing config file after installation.' . PHP_EOL . |
1794 | $e->getMessage() | 1837 | $e->getMessage() |
1795 | ); | 1838 | ); |
1796 | 1839 | ||
1797 | // TODO: do not handle exceptions/errors in JS. | 1840 | // TODO: do not handle exceptions/errors in JS. |
1798 | echo '<script>alert("'. $e->getMessage() .'");document.location=\'?\';</script>'; | 1841 | echo '<script>alert("'. $e->getMessage() .'");document.location=\'?\';</script>'; |
1799 | exit; | 1842 | exit; |
1800 | } | 1843 | } |
1801 | 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>'; | ||
1802 | exit; | 1848 | exit; |
1803 | } | 1849 | } |
1804 | 1850 | ||
@@ -1822,7 +1868,7 @@ if (!isset($_SESSION['LINKS_PER_PAGE'])) { | |||
1822 | 1868 | ||
1823 | try { | 1869 | try { |
1824 | $history = new History($conf->get('resource.history')); | 1870 | $history = new History($conf->get('resource.history')); |
1825 | } catch(Exception $e) { | 1871 | } catch (Exception $e) { |
1826 | die($e->getMessage()); | 1872 | die($e->getMessage()); |
1827 | } | 1873 | } |
1828 | 1874 | ||
@@ -1841,7 +1887,7 @@ $container['history'] = $history; | |||
1841 | $app = new \Slim\App($container); | 1887 | $app = new \Slim\App($container); |
1842 | 1888 | ||
1843 | // REST API routes | 1889 | // REST API routes |
1844 | $app->group('/api/v1', function() { | 1890 | $app->group('/api/v1', function () { |
1845 | $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo')->setName('getInfo'); | 1891 | $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo')->setName('getInfo'); |
1846 | $this->get('/links', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks'); | 1892 | $this->get('/links', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks'); |
1847 | $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'); |
@@ -1858,6 +1904,7 @@ $app->group('/api/v1', function() { | |||
1858 | })->add('\Shaarli\Api\ApiMiddleware'); | 1904 | })->add('\Shaarli\Api\ApiMiddleware'); |
1859 | 1905 | ||
1860 | $response = $app->run(true); | 1906 | $response = $app->run(true); |
1907 | |||
1861 | // Hack to make Slim and Shaarli router work together: | 1908 | // Hack to make Slim and Shaarli router work together: |
1862 | // If a Slim route isn't found and NOT API call, we call renderPage(). | 1909 | // If a Slim route isn't found and NOT API call, we call renderPage(). |
1863 | if ($response->getStatusCode() == 404 && strpos($_SERVER['REQUEST_URI'], '/api/v1') === false) { | 1910 | if ($response->getStatusCode() == 404 && strpos($_SERVER['REQUEST_URI'], '/api/v1') === false) { |
@@ -1865,5 +1912,12 @@ if ($response->getStatusCode() == 404 && strpos($_SERVER['REQUEST_URI'], '/api/v | |||
1865 | header('Content-Type: text/html; charset=utf-8'); | 1912 | header('Content-Type: text/html; charset=utf-8'); |
1866 | renderPage($conf, $pluginManager, $linkDb, $history, $sessionManager, $loginManager); | 1913 | renderPage($conf, $pluginManager, $linkDb, $history, $sessionManager, $loginManager); |
1867 | } else { | 1914 | } else { |
1915 | $response = $response | ||
1916 | ->withHeader('Access-Control-Allow-Origin', '*') | ||
1917 | ->withHeader( | ||
1918 | 'Access-Control-Allow-Headers', | ||
1919 | 'X-Requested-With, Content-Type, Accept, Origin, Authorization' | ||
1920 | ) | ||
1921 | ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); | ||
1868 | $app->respond($response); | 1922 | $app->respond($response); |
1869 | } | 1923 | } |
@@ -2,7 +2,9 @@ site_name: Shaarli Documentation | |||
2 | repo_url: https://github.com/shaarli/Shaarli | 2 | repo_url: https://github.com/shaarli/Shaarli |
3 | edit_uri: edit/master/doc/md | 3 | edit_uri: edit/master/doc/md |
4 | site_description: The personal, minimalist, super-fast, database free, bookmarking service | 4 | site_description: The personal, minimalist, super-fast, database free, bookmarking service |
5 | theme: readthedocs | 5 | theme: |
6 | name: readthedocs | ||
7 | custom_dir: doc/custom_theme/ | ||
6 | docs_dir: doc/md | 8 | docs_dir: doc/md |
7 | site_dir: doc/html | 9 | site_dir: doc/html |
8 | # Disable strict mode until ReadTheDocs provides up-to-date MkDocs settings: | 10 | # Disable strict mode until ReadTheDocs provides up-to-date MkDocs settings: |
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/isso/comment.png b/plugins/isso/comment.png new file mode 100644 index 00000000..0158c03b --- /dev/null +++ b/plugins/isso/comment.png | |||
Binary files differ | |||
diff --git a/plugins/isso/isso.php b/plugins/isso/isso.php index 5bc1cce2..378c11af 100644 --- a/plugins/isso/isso.php +++ b/plugins/isso/isso.php | |||
@@ -46,9 +46,36 @@ function hook_isso_render_linklist($data, $conf) | |||
46 | 46 | ||
47 | $isso = sprintf($issoHtml, $issoUrl, $issoUrl, $link['id'], $link['id']); | 47 | $isso = sprintf($issoHtml, $issoUrl, $issoUrl, $link['id'], $link['id']); |
48 | $data['plugin_end_zone'][] = $isso; | 48 | $data['plugin_end_zone'][] = $isso; |
49 | } else { | ||
50 | $button = '<span><a href="?%s#isso-thread">'; | ||
51 | // For the default theme we use a FontAwesome icon which is better than an image | ||
52 | if ($conf->get('resource.theme') === 'default') { | ||
53 | $button .= '<i class="linklist-plugin-icon fa fa-comment"></i>'; | ||
54 | } else { | ||
55 | $button .= '<img class="linklist-plugin-icon" src="plugins/isso/comment.png" '; | ||
56 | $button .= 'title="Comment on this shaare" alt="Comments" />'; | ||
57 | } | ||
58 | $button .= '</a></span>'; | ||
59 | foreach ($data['links'] as &$value) { | ||
60 | $commentLink = sprintf($button, $value['shorturl']); | ||
61 | $value['link_plugin'][] = $commentLink; | ||
62 | } | ||
63 | } | ||
49 | 64 | ||
50 | // Hackish way to include this CSS file only when necessary. | 65 | return $data; |
51 | $data['plugins_includes']['css_files'][] = PluginManager::$PLUGINS_PATH . '/isso/isso.css'; | 66 | } |
67 | |||
68 | /** | ||
69 | * When linklist is displayed, include isso CSS file. | ||
70 | * | ||
71 | * @param array $data - header data. | ||
72 | * | ||
73 | * @return mixed - header data with isso CSS file added. | ||
74 | */ | ||
75 | function hook_isso_render_includes($data) | ||
76 | { | ||
77 | if ($data['_PAGE_'] == Router::$PAGE_LINKLIST) { | ||
78 | $data['css_files'][] = PluginManager::$PLUGINS_PATH . '/isso/isso.css'; | ||
52 | } | 79 | } |
53 | 80 | ||
54 | return $data; | 81 | return $data; |
diff --git a/plugins/isso/isso_button.html b/plugins/isso/isso_button.html new file mode 100644 index 00000000..3f828480 --- /dev/null +++ b/plugins/isso/isso_button.html | |||
@@ -0,0 +1,5 @@ | |||
1 | <span> | ||
2 | <a href="?%s#isso-thread"> | ||
3 | <img class="linklist-plugin-icon" src="plugins/archiveorg/internetarchive.png" title="%s" alt="archive.org" /> | ||
4 | </a> | ||
5 | </span> | ||
diff --git a/plugins/markdown/markdown.php b/plugins/markdown/markdown.php index 821bb125..8823af91 100644 --- a/plugins/markdown/markdown.php +++ b/plugins/markdown/markdown.php | |||
@@ -28,6 +28,7 @@ function hook_markdown_render_linklist($data, $conf) | |||
28 | $value = stripNoMarkdownTag($value); | 28 | $value = stripNoMarkdownTag($value); |
29 | continue; | 29 | continue; |
30 | } | 30 | } |
31 | $value['description_src'] = $value['description']; | ||
31 | $value['description'] = process_markdown( | 32 | $value['description'] = process_markdown( |
32 | $value['description'], | 33 | $value['description'], |
33 | $conf->get('security.markdown_escape', true), | 34 | $conf->get('security.markdown_escape', true), |
@@ -138,7 +139,6 @@ function hook_markdown_render_includes($data) | |||
138 | || $data['_PAGE_'] == Router::$PAGE_DAILY | 139 | || $data['_PAGE_'] == Router::$PAGE_DAILY |
139 | || $data['_PAGE_'] == Router::$PAGE_EDITLINK | 140 | || $data['_PAGE_'] == Router::$PAGE_EDITLINK |
140 | ) { | 141 | ) { |
141 | |||
142 | $data['css_files'][] = PluginManager::$PLUGINS_PATH . '/markdown/markdown.css'; | 142 | $data['css_files'][] = PluginManager::$PLUGINS_PATH . '/markdown/markdown.css'; |
143 | } | 143 | } |
144 | 144 | ||
@@ -194,8 +194,7 @@ function reverse_text2clickable($description) | |||
194 | // Detect and toggle block of code | 194 | // Detect and toggle block of code |
195 | if (!$codeBlockOn) { | 195 | if (!$codeBlockOn) { |
196 | $codeBlockOn = preg_match('/^```/', $descriptionLine) > 0; | 196 | $codeBlockOn = preg_match('/^```/', $descriptionLine) > 0; |
197 | } | 197 | } elseif (preg_match('/^```/', $descriptionLine) > 0) { |
198 | elseif (preg_match('/^```/', $descriptionLine) > 0) { | ||
199 | $codeBlockOn = false; | 198 | $codeBlockOn = false; |
200 | } | 199 | } |
201 | 200 | ||
@@ -215,6 +214,15 @@ function reverse_text2clickable($description) | |||
215 | $descriptionLine | 214 | $descriptionLine |
216 | ); | 215 | ); |
217 | 216 | ||
217 | // Make hashtag links markdown ready, otherwise the links will be ignored with escape set to true | ||
218 | if (!$codeBlockOn && !$codeLineOn) { | ||
219 | $descriptionLine = preg_replace( | ||
220 | '#<a href="([^ ]*)"'. $hashtagTitle .'>([^<]+)</a>#m', | ||
221 | '[$2]($1)', | ||
222 | $descriptionLine | ||
223 | ); | ||
224 | } | ||
225 | |||
218 | $descriptionOut .= $descriptionLine; | 226 | $descriptionOut .= $descriptionLine; |
219 | if ($lineCount++ < count($descriptionLines) - 1) { | 227 | if ($lineCount++ < count($descriptionLines) - 1) { |
220 | $descriptionOut .= PHP_EOL; | 228 | $descriptionOut .= PHP_EOL; |
@@ -292,13 +300,17 @@ function sanitize_html($description) | |||
292 | foreach ($escapeTags as $tag) { | 300 | foreach ($escapeTags as $tag) { |
293 | $description = preg_replace_callback( | 301 | $description = preg_replace_callback( |
294 | '#<\s*'. $tag .'[^>]*>(.*</\s*'. $tag .'[^>]*>)?#is', | 302 | '#<\s*'. $tag .'[^>]*>(.*</\s*'. $tag .'[^>]*>)?#is', |
295 | function ($match) { return escape($match[0]); }, | 303 | function ($match) { |
296 | $description); | 304 | return escape($match[0]); |
305 | }, | ||
306 | $description | ||
307 | ); | ||
297 | } | 308 | } |
298 | $description = preg_replace( | 309 | $description = preg_replace( |
299 | '#(<[^>]+\s)on[a-z]*="?[^ "]*"?#is', | 310 | '#(<[^>]+\s)on[a-z]*="?[^ "]*"?#is', |
300 | '$1', | 311 | '$1', |
301 | $description); | 312 | $description |
313 | ); | ||
302 | return $description; | 314 | return $description; |
303 | } | 315 | } |
304 | 316 | ||
@@ -331,7 +343,7 @@ function process_markdown($description, $escape = true, $allowedProtocols = []) | |||
331 | ->text($processedDescription); | 343 | ->text($processedDescription); |
332 | $processedDescription = sanitize_html($processedDescription); | 344 | $processedDescription = sanitize_html($processedDescription); |
333 | 345 | ||
334 | if(!empty($processedDescription)){ | 346 | if (!empty($processedDescription)) { |
335 | $processedDescription = '<div class="markdown">'. $processedDescription . '</div>'; | 347 | $processedDescription = '<div class="markdown">'. $processedDescription . '</div>'; |
336 | } | 348 | } |
337 | 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 | ||
12 | use pubsubhubbub\publisher\Publisher; | 12 | use 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 | */ |
85 | function nocurl_http_post($url, $postString) { | 85 | function 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/shaarli_version.php b/shaarli_version.php index 912ca530..215fc76f 100644 --- a/shaarli_version.php +++ b/shaarli_version.php | |||
@@ -1 +1 @@ | |||
<?php /* 0.10.2 */ ?> | <?php /* 0.10.3 */ ?> | ||
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/FeedBuilderTest.php b/tests/FeedBuilderTest.php index a590306d..4ca58e5a 100644 --- a/tests/FeedBuilderTest.php +++ b/tests/FeedBuilderTest.php | |||
@@ -82,8 +82,8 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase | |||
82 | $this->assertFalse($data['usepermalinks']); | 82 | $this->assertFalse($data['usepermalinks']); |
83 | $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); | 83 | $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); |
84 | 84 | ||
85 | // Test first link (note link) | 85 | // Test first not pinned link (note link) |
86 | $link = reset($data['links']); | 86 | $link = $data['links'][array_keys($data['links'])[2]]; |
87 | $this->assertEquals(41, $link['id']); | 87 | $this->assertEquals(41, $link['id']); |
88 | $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']); | 88 | $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']); |
89 | $this->assertEquals('http://host.tld/?WDWyig', $link['guid']); | 89 | $this->assertEquals('http://host.tld/?WDWyig', $link['guid']); |
@@ -119,7 +119,7 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase | |||
119 | $data = $feedBuilder->buildData(); | 119 | $data = $feedBuilder->buildData(); |
120 | $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); | 120 | $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); |
121 | $this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['last_update']); | 121 | $this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['last_update']); |
122 | $link = reset($data['links']); | 122 | $link = $data['links'][array_keys($data['links'])[2]]; |
123 | $this->assertRegExp('/2015-03-10T11:46:51\+\d{2}:\d{2}/', $link['pub_iso_date']); | 123 | $this->assertRegExp('/2015-03-10T11:46:51\+\d{2}:\d{2}/', $link['pub_iso_date']); |
124 | $this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['links'][8]['up_iso_date']); | 124 | $this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['links'][8]['up_iso_date']); |
125 | } | 125 | } |
@@ -148,13 +148,13 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase | |||
148 | public function testBuildDataCount() | 148 | public function testBuildDataCount() |
149 | { | 149 | { |
150 | $criteria = array( | 150 | $criteria = array( |
151 | 'nb' => '1', | 151 | 'nb' => '3', |
152 | ); | 152 | ); |
153 | $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, $criteria, false); | 153 | $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, $criteria, false); |
154 | $feedBuilder->setLocale(self::$LOCALE); | 154 | $feedBuilder->setLocale(self::$LOCALE); |
155 | $data = $feedBuilder->buildData(); | 155 | $data = $feedBuilder->buildData(); |
156 | $this->assertEquals(1, count($data['links'])); | 156 | $this->assertEquals(3, count($data['links'])); |
157 | $link = array_shift($data['links']); | 157 | $link = $data['links'][array_keys($data['links'])[2]]; |
158 | $this->assertEquals(41, $link['id']); | 158 | $this->assertEquals(41, $link['id']); |
159 | $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']); | 159 | $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']); |
160 | } | 160 | } |
@@ -171,7 +171,7 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase | |||
171 | $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); | 171 | $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); |
172 | $this->assertTrue($data['usepermalinks']); | 172 | $this->assertTrue($data['usepermalinks']); |
173 | // First link is a permalink | 173 | // First link is a permalink |
174 | $link = array_shift($data['links']); | 174 | $link = $data['links'][array_keys($data['links'])[2]]; |
175 | $this->assertEquals(41, $link['id']); | 175 | $this->assertEquals(41, $link['id']); |
176 | $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']); | 176 | $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']); |
177 | $this->assertEquals('http://host.tld/?WDWyig', $link['guid']); | 177 | $this->assertEquals('http://host.tld/?WDWyig', $link['guid']); |
@@ -179,7 +179,7 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase | |||
179 | $this->assertContains('Direct link', $link['description']); | 179 | $this->assertContains('Direct link', $link['description']); |
180 | $this->assertContains('http://host.tld/?WDWyig', $link['description']); | 180 | $this->assertContains('http://host.tld/?WDWyig', $link['description']); |
181 | // Second link is a direct link | 181 | // Second link is a direct link |
182 | $link = array_shift($data['links']); | 182 | $link = $data['links'][array_keys($data['links'])[3]]; |
183 | $this->assertEquals(8, $link['id']); | 183 | $this->assertEquals(8, $link['id']); |
184 | $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114633'), $link['created']); | 184 | $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114633'), $link['created']); |
185 | $this->assertEquals('http://host.tld/?RttfEw', $link['guid']); | 185 | $this->assertEquals('http://host.tld/?RttfEw', $link['guid']); |
@@ -237,7 +237,7 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase | |||
237 | ); | 237 | ); |
238 | 238 | ||
239 | // Test first link (note link) | 239 | // Test first link (note link) |
240 | $link = array_shift($data['links']); | 240 | $link = $data['links'][array_keys($data['links'])[2]]; |
241 | $this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['guid']); | 241 | $this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['guid']); |
242 | $this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['url']); | 242 | $this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['url']); |
243 | $this->assertContains('http://host.tld:8080/~user/shaarli/?addtag=hashtag', $link['description']); | 243 | $this->assertContains('http://host.tld:8080/~user/shaarli/?addtag=hashtag', $link['description']); |
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 | */ |
8 | class GetIpAdressFromProxyTest extends PHPUnit_Framework_TestCase { | 8 | class 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 3b980878..c763c0cb 100644 --- a/tests/LinkDBTest.php +++ b/tests/LinkDBTest.php | |||
@@ -239,12 +239,12 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
239 | public function testDays() | 239 | public function testDays() |
240 | { | 240 | { |
241 | $this->assertEquals( | 241 | $this->assertEquals( |
242 | array('20100310', '20121206', '20130614', '20150310'), | 242 | array('20100309', '20100310', '20121206', '20121207', '20130614', '20150310'), |
243 | self::$publicLinkDB->days() | 243 | self::$publicLinkDB->days() |
244 | ); | 244 | ); |
245 | 245 | ||
246 | $this->assertEquals( | 246 | $this->assertEquals( |
247 | array('20100310', '20121206', '20130614', '20141125', '20150310'), | 247 | array('20100309', '20100310', '20121206', '20121207', '20130614', '20141125', '20150310'), |
248 | self::$privateLinkDB->days() | 248 | self::$privateLinkDB->days() |
249 | ); | 249 | ); |
250 | } | 250 | } |
@@ -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 | } |
@@ -475,13 +475,15 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
475 | public function testReorderLinksDesc() | 475 | public function testReorderLinksDesc() |
476 | { | 476 | { |
477 | self::$privateLinkDB->reorder('ASC'); | 477 | self::$privateLinkDB->reorder('ASC'); |
478 | $linkIds = array(42, 4, 9, 1, 0, 7, 6, 8, 41); | 478 | $stickyIds = [11, 10]; |
479 | $standardIds = [42, 4, 9, 1, 0, 7, 6, 8, 41]; | ||
480 | $linkIds = array_merge($stickyIds, $standardIds); | ||
479 | $cpt = 0; | 481 | $cpt = 0; |
480 | foreach (self::$privateLinkDB as $key => $value) { | 482 | foreach (self::$privateLinkDB as $key => $value) { |
481 | $this->assertEquals($linkIds[$cpt++], $key); | 483 | $this->assertEquals($linkIds[$cpt++], $key); |
482 | } | 484 | } |
483 | self::$privateLinkDB->reorder('DESC'); | 485 | self::$privateLinkDB->reorder('DESC'); |
484 | $linkIds = array_reverse($linkIds); | 486 | $linkIds = array_merge(array_reverse($stickyIds), array_reverse($standardIds)); |
485 | $cpt = 0; | 487 | $cpt = 0; |
486 | foreach (self::$privateLinkDB as $key => $value) { | 488 | foreach (self::$privateLinkDB as $key => $value) { |
487 | $this->assertEquals($linkIds[$cpt++], $key); | 489 | $this->assertEquals($linkIds[$cpt++], $key); |
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/NetscapeBookmarkUtils/BookmarkExportTest.php b/tests/NetscapeBookmarkUtils/BookmarkExportTest.php index 6a47bbb9..77fbd5f3 100644 --- a/tests/NetscapeBookmarkUtils/BookmarkExportTest.php +++ b/tests/NetscapeBookmarkUtils/BookmarkExportTest.php | |||
@@ -110,7 +110,7 @@ class BookmarkExportTest extends PHPUnit_Framework_TestCase | |||
110 | $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'public', false, ''); | 110 | $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'public', false, ''); |
111 | $this->assertEquals( | 111 | $this->assertEquals( |
112 | '?WDWyig', | 112 | '?WDWyig', |
113 | $links[0]['url'] | 113 | $links[2]['url'] |
114 | ); | 114 | ); |
115 | } | 115 | } |
116 | 116 | ||
@@ -128,7 +128,7 @@ class BookmarkExportTest extends PHPUnit_Framework_TestCase | |||
128 | ); | 128 | ); |
129 | $this->assertEquals( | 129 | $this->assertEquals( |
130 | $indexUrl . '?WDWyig', | 130 | $indexUrl . '?WDWyig', |
131 | $links[0]['url'] | 131 | $links[2]['url'] |
132 | ); | 132 | ); |
133 | } | 133 | } |
134 | } | 134 | } |
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 cacee2d2..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 | /** |
@@ -688,6 +700,7 @@ $GLOBALS[\'privateLinkByDefault\'] = true;'; | |||
688 | } | 700 | } |
689 | 701 | ||
690 | /** | 702 | /** |
703 | <<<<<<< HEAD | ||
691 | * Test updateMethodWebThumbnailer with thumbnails enabled. | 704 | * Test updateMethodWebThumbnailer with thumbnails enabled. |
692 | */ | 705 | */ |
693 | public function testUpdateMethodWebThumbnailerEnabled() | 706 | public function testUpdateMethodWebThumbnailerEnabled() |
@@ -732,4 +745,64 @@ $GLOBALS[\'privateLinkByDefault\'] = true;'; | |||
732 | $this->assertEquals(53, $this->conf->get('thumbnails.height')); | 745 | $this->assertEquals(53, $this->conf->get('thumbnails.height')); |
733 | $this->assertTrue(empty($_SESSION['warnings'])); | 746 | $this->assertTrue(empty($_SESSION['warnings'])); |
734 | } | 747 | } |
748 | |||
749 | /** | ||
750 | * Test updateMethodSetSticky(). | ||
751 | */ | ||
752 | public function testUpdateStickyValid() | ||
753 | { | ||
754 | $blank = [ | ||
755 | 'id' => 1, | ||
756 | 'url' => 'z', | ||
757 | 'title' => '', | ||
758 | 'description' => '', | ||
759 | 'tags' => '', | ||
760 | 'created' => new DateTime(), | ||
761 | ]; | ||
762 | $links = [ | ||
763 | 1 => ['id' => 1] + $blank, | ||
764 | 2 => ['id' => 2] + $blank, | ||
765 | ]; | ||
766 | $refDB = new ReferenceLinkDB(); | ||
767 | $refDB->setLinks($links); | ||
768 | $refDB->write(self::$testDatastore); | ||
769 | $linkDB = new LinkDB(self::$testDatastore, true, false); | ||
770 | |||
771 | $updater = new Updater(array(), $linkDB, $this->conf, true); | ||
772 | $this->assertTrue($updater->updateMethodSetSticky()); | ||
773 | |||
774 | $linkDB = new LinkDB(self::$testDatastore, true, false); | ||
775 | foreach ($linkDB as $link) { | ||
776 | $this->assertFalse($link['sticky']); | ||
777 | } | ||
778 | } | ||
779 | |||
780 | /** | ||
781 | * Test updateMethodSetSticky(). | ||
782 | */ | ||
783 | public function testUpdateStickyNothingToDo() | ||
784 | { | ||
785 | $blank = [ | ||
786 | 'id' => 1, | ||
787 | 'url' => 'z', | ||
788 | 'title' => '', | ||
789 | 'description' => '', | ||
790 | 'tags' => '', | ||
791 | 'created' => new DateTime(), | ||
792 | ]; | ||
793 | $links = [ | ||
794 | 1 => ['id' => 1, 'sticky' => true] + $blank, | ||
795 | 2 => ['id' => 2] + $blank, | ||
796 | ]; | ||
797 | $refDB = new ReferenceLinkDB(); | ||
798 | $refDB->setLinks($links); | ||
799 | $refDB->write(self::$testDatastore); | ||
800 | $linkDB = new LinkDB(self::$testDatastore, true, false); | ||
801 | |||
802 | $updater = new Updater(array(), $linkDB, $this->conf, true); | ||
803 | $this->assertTrue($updater->updateMethodSetSticky()); | ||
804 | |||
805 | $linkDB = new LinkDB(self::$testDatastore, true, false); | ||
806 | $this->assertTrue($linkDB[1]['sticky']); | ||
807 | } | ||
735 | } | 808 | } |
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 | ||
5 | use Shaarli\Base64Url; | 5 | use 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 | ||
4 | namespace Shaarli\Api\Controllers; | 4 | namespace Shaarli\Api\Controllers; |
5 | 5 | ||
6 | |||
7 | use Shaarli\Config\ConfigManager; | 6 | use Shaarli\Config\ConfigManager; |
8 | use Slim\Container; | 7 | use Slim\Container; |
9 | use Slim\Http\Environment; | 8 | use 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 | */ |
18 | class InfoTest extends \PHPUnit_Framework_TestCase | 18 | class InfoTest extends \PHPUnit_Framework_TestCase |
diff --git a/tests/api/controllers/links/GetLinksTest.php b/tests/api/controllers/links/GetLinksTest.php index d22ed3bf..64f02774 100644 --- a/tests/api/controllers/links/GetLinksTest.php +++ b/tests/api/controllers/links/GetLinksTest.php | |||
@@ -95,7 +95,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase | |||
95 | $this->assertEquals($this->refDB->countLinks(), count($data)); | 95 | $this->assertEquals($this->refDB->countLinks(), count($data)); |
96 | 96 | ||
97 | // Check order | 97 | // Check order |
98 | $order = [41, 8, 6, 7, 0, 1, 9, 4, 42]; | 98 | $order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42]; |
99 | $cpt = 0; | 99 | $cpt = 0; |
100 | foreach ($data as $link) { | 100 | foreach ($data as $link) { |
101 | $this->assertEquals(self::NB_FIELDS_LINK, count($link)); | 101 | $this->assertEquals(self::NB_FIELDS_LINK, count($link)); |
@@ -103,7 +103,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase | |||
103 | } | 103 | } |
104 | 104 | ||
105 | // Check first element fields | 105 | // Check first element fields |
106 | $first = $data[0]; | 106 | $first = $data[2]; |
107 | $this->assertEquals('http://domain.tld/?WDWyig', $first['url']); | 107 | $this->assertEquals('http://domain.tld/?WDWyig', $first['url']); |
108 | $this->assertEquals('WDWyig', $first['shorturl']); | 108 | $this->assertEquals('WDWyig', $first['shorturl']); |
109 | $this->assertEquals('Link title: @website', $first['title']); | 109 | $this->assertEquals('Link title: @website', $first['title']); |
@@ -120,7 +120,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase | |||
120 | $this->assertEmpty($first['updated']); | 120 | $this->assertEmpty($first['updated']); |
121 | 121 | ||
122 | // Multi tags | 122 | // Multi tags |
123 | $link = $data[1]; | 123 | $link = $data[3]; |
124 | $this->assertEquals(7, count($link['tags'])); | 124 | $this->assertEquals(7, count($link['tags'])); |
125 | 125 | ||
126 | // Update date | 126 | // Update date |
@@ -138,7 +138,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase | |||
138 | { | 138 | { |
139 | $env = Environment::mock([ | 139 | $env = Environment::mock([ |
140 | 'REQUEST_METHOD' => 'GET', | 140 | 'REQUEST_METHOD' => 'GET', |
141 | 'QUERY_STRING' => 'offset=1&limit=1' | 141 | 'QUERY_STRING' => 'offset=3&limit=1' |
142 | ]); | 142 | ]); |
143 | $request = Request::createFromEnvironment($env); | 143 | $request = Request::createFromEnvironment($env); |
144 | $response = $this->controller->getLinks($request, new Response()); | 144 | $response = $this->controller->getLinks($request, new Response()); |
@@ -164,7 +164,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase | |||
164 | $data = json_decode((string) $response->getBody(), true); | 164 | $data = json_decode((string) $response->getBody(), true); |
165 | $this->assertEquals($this->refDB->countLinks(), count($data)); | 165 | $this->assertEquals($this->refDB->countLinks(), count($data)); |
166 | // Check order | 166 | // Check order |
167 | $order = [41, 8, 6, 7, 0, 1, 9, 4, 42]; | 167 | $order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42]; |
168 | $cpt = 0; | 168 | $cpt = 0; |
169 | foreach ($data as $link) { | 169 | foreach ($data as $link) { |
170 | $this->assertEquals(self::NB_FIELDS_LINK, count($link)); | 170 | $this->assertEquals(self::NB_FIELDS_LINK, count($link)); |
@@ -205,7 +205,8 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase | |||
205 | $this->assertEquals(200, $response->getStatusCode()); | 205 | $this->assertEquals(200, $response->getStatusCode()); |
206 | $data = json_decode((string)$response->getBody(), true); | 206 | $data = json_decode((string)$response->getBody(), true); |
207 | $this->assertEquals($this->refDB->countLinks(), count($data)); | 207 | $this->assertEquals($this->refDB->countLinks(), count($data)); |
208 | $this->assertEquals(41, $data[0]['id']); | 208 | $this->assertEquals(10, $data[0]['id']); |
209 | $this->assertEquals(41, $data[2]['id']); | ||
209 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | 210 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); |
210 | } | 211 | } |
211 | 212 | ||
@@ -243,7 +244,8 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase | |||
243 | $this->assertEquals(200, $response->getStatusCode()); | 244 | $this->assertEquals(200, $response->getStatusCode()); |
244 | $data = json_decode((string)$response->getBody(), true); | 245 | $data = json_decode((string)$response->getBody(), true); |
245 | $this->assertEquals($this->refDB->countPublicLinks(), count($data)); | 246 | $this->assertEquals($this->refDB->countPublicLinks(), count($data)); |
246 | $this->assertEquals(41, $data[0]['id']); | 247 | $this->assertEquals(10, $data[0]['id']); |
248 | $this->assertEquals(41, $data[2]['id']); | ||
247 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | 249 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); |
248 | } | 250 | } |
249 | 251 | ||
@@ -413,8 +415,9 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase | |||
413 | $response = $this->controller->getLinks($request, new Response()); | 415 | $response = $this->controller->getLinks($request, new Response()); |
414 | $this->assertEquals(200, $response->getStatusCode()); | 416 | $this->assertEquals(200, $response->getStatusCode()); |
415 | $data = json_decode((string) $response->getBody(), true); | 417 | $data = json_decode((string) $response->getBody(), true); |
416 | $this->assertEquals(9, count($data)); | 418 | $this->assertEquals(\ReferenceLinkDB::$NB_LINKS_TOTAL, count($data)); |
417 | $this->assertEquals(41, $data[0]['id']); | 419 | $this->assertEquals(10, $data[0]['id']); |
420 | $this->assertEquals(41, $data[2]['id']); | ||
418 | 421 | ||
419 | // wildcard: optional ('*' does not need to expand) | 422 | // wildcard: optional ('*' does not need to expand) |
420 | $env = Environment::mock([ | 423 | $env = Environment::mock([ |
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 | ||
3 | namespace Shaarli\Api\Controllers; | 3 | namespace Shaarli\Api\Controllers; |
4 | 4 | ||
5 | |||
6 | use PHPUnit\Framework\TestCase; | 5 | use PHPUnit\Framework\TestCase; |
7 | use Shaarli\Config\ConfigManager; | 6 | use Shaarli\Config\ConfigManager; |
8 | use Slim\Container; | 7 | use 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 | ||
4 | namespace Shaarli\Api\Controllers; | 4 | namespace Shaarli\Api\Controllers; |
5 | 5 | ||
6 | |||
7 | use Shaarli\Config\ConfigManager; | 6 | use Shaarli\Config\ConfigManager; |
8 | use Slim\Container; | 7 | use Slim\Container; |
9 | use Slim\Http\Environment; | 8 | use 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 | ||
4 | namespace Shaarli\Api\Controllers; | 4 | namespace Shaarli\Api\Controllers; |
5 | 5 | ||
6 | |||
7 | use Shaarli\Api\Exceptions\ApiBadParametersException; | 6 | use Shaarli\Api\Exceptions\ApiBadParametersException; |
8 | use Shaarli\Config\ConfigManager; | 7 | use Shaarli\Config\ConfigManager; |
9 | use Slim\Container; | 8 | use 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 | ||
4 | namespace Shaarli; | 4 | namespace Shaarli; |
5 | 5 | ||
6 | |||
7 | use Shaarli\Config\ConfigManager; | 6 | use Shaarli\Config\ConfigManager; |
8 | 7 | ||
9 | /** | 8 | /** |
diff --git a/tests/plugins/PluginIssoTest.php b/tests/plugins/PluginIssoTest.php index 0ae73183..2c9efbcd 100644 --- a/tests/plugins/PluginIssoTest.php +++ b/tests/plugins/PluginIssoTest.php | |||
@@ -21,7 +21,7 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase | |||
21 | /** | 21 | /** |
22 | * Test Isso init without errors. | 22 | * Test Isso init without errors. |
23 | */ | 23 | */ |
24 | public function testWallabagInitNoError() | 24 | public function testIssoInitNoError() |
25 | { | 25 | { |
26 | $conf = new ConfigManager(''); | 26 | $conf = new ConfigManager(''); |
27 | $conf->set('plugins.ISSO_SERVER', 'value'); | 27 | $conf->set('plugins.ISSO_SERVER', 'value'); |
@@ -32,7 +32,7 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase | |||
32 | /** | 32 | /** |
33 | * Test Isso init with errors. | 33 | * Test Isso init with errors. |
34 | */ | 34 | */ |
35 | public function testWallabagInitError() | 35 | public function testIssoInitError() |
36 | { | 36 | { |
37 | $conf = new ConfigManager(''); | 37 | $conf = new ConfigManager(''); |
38 | $errors = isso_init($conf); | 38 | $errors = isso_init($conf); |
@@ -96,19 +96,22 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase | |||
96 | array( | 96 | array( |
97 | 'id' => 12, | 97 | 'id' => 12, |
98 | 'url' => $str, | 98 | 'url' => $str, |
99 | 'shorturl' => $short1 = 'abcd', | ||
99 | 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $date1), | 100 | 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $date1), |
100 | ), | 101 | ), |
101 | array( | 102 | array( |
102 | 'id' => 13, | 103 | 'id' => 13, |
103 | 'url' => $str . '2', | 104 | 'url' => $str . '2', |
105 | 'shorturl' => $short2 = 'efgh', | ||
104 | 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $date2), | 106 | 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $date2), |
105 | ), | 107 | ), |
106 | ) | 108 | ) |
107 | ); | 109 | ); |
108 | 110 | ||
109 | $processed = hook_isso_render_linklist($data, $conf); | 111 | $processed = hook_isso_render_linklist($data, $conf); |
110 | // data shouldn't be altered | 112 | // link_plugin should be added for the icon |
111 | $this->assertEquals($data, $processed); | 113 | $this->assertContains('<a href="?'. $short1 .'#isso-thread">', $processed['links'][0]['link_plugin'][0]); |
114 | $this->assertContains('<a href="?'. $short2 .'#isso-thread">', $processed['links'][1]['link_plugin'][0]); | ||
112 | } | 115 | } |
113 | 116 | ||
114 | /** | 117 | /** |
@@ -127,6 +130,7 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase | |||
127 | array( | 130 | array( |
128 | 'id' => 12, | 131 | 'id' => 12, |
129 | 'url' => $str, | 132 | 'url' => $str, |
133 | 'shorturl' => $short1 = 'abcd', | ||
130 | 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $date), | 134 | 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $date), |
131 | ) | 135 | ) |
132 | ), | 136 | ), |
@@ -135,8 +139,8 @@ class PluginIssoTest extends PHPUnit_Framework_TestCase | |||
135 | 139 | ||
136 | $processed = hook_isso_render_linklist($data, $conf); | 140 | $processed = hook_isso_render_linklist($data, $conf); |
137 | 141 | ||
138 | // data shouldn't be altered | 142 | // link_plugin should be added for the icon |
139 | $this->assertEquals($data, $processed); | 143 | $this->assertContains('<a href="?'. $short1 .'#isso-thread">', $processed['links'][0]['link_plugin'][0]); |
140 | } | 144 | } |
141 | 145 | ||
142 | /** | 146 | /** |
diff --git a/tests/plugins/PluginMarkdownTest.php b/tests/plugins/PluginMarkdownTest.php index b31e817f..44364b05 100644 --- a/tests/plugins/PluginMarkdownTest.php +++ b/tests/plugins/PluginMarkdownTest.php | |||
@@ -47,6 +47,8 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase | |||
47 | $data = hook_markdown_render_linklist($data, $this->conf); | 47 | $data = hook_markdown_render_linklist($data, $this->conf); |
48 | $this->assertNotFalse(strpos($data['links'][0]['description'], '<h1>')); | 48 | $this->assertNotFalse(strpos($data['links'][0]['description'], '<h1>')); |
49 | $this->assertNotFalse(strpos($data['links'][0]['description'], '<p>')); | 49 | $this->assertNotFalse(strpos($data['links'][0]['description'], '<p>')); |
50 | |||
51 | $this->assertEquals($markdown, $data['links'][0]['description_src']); | ||
50 | } | 52 | } |
51 | 53 | ||
52 | /** | 54 | /** |
@@ -107,6 +109,18 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase | |||
107 | } | 109 | } |
108 | 110 | ||
109 | /** | 111 | /** |
112 | * Test reverse_text2clickable(). | ||
113 | */ | ||
114 | public function testReverseText2clickableHashtags() | ||
115 | { | ||
116 | $text = file_get_contents('tests/plugins/resources/hashtags.raw'); | ||
117 | $md = file_get_contents('tests/plugins/resources/hashtags.md'); | ||
118 | $clickableText = hashtag_autolink($text); | ||
119 | $reversedText = reverse_text2clickable($clickableText); | ||
120 | $this->assertEquals($md, $reversedText); | ||
121 | } | ||
122 | |||
123 | /** | ||
110 | * Test reverse_nl2br(). | 124 | * Test reverse_nl2br(). |
111 | */ | 125 | */ |
112 | public function testReverseNl2br() | 126 | public function testReverseNl2br() |
@@ -246,7 +260,7 @@ class PluginMarkdownTest extends PHPUnit_Framework_TestCase | |||
246 | $this->conf->get('security.markdown_escape', true), | 260 | $this->conf->get('security.markdown_escape', true), |
247 | $this->conf->get('security.allowed_protocols') | 261 | $this->conf->get('security.allowed_protocols') |
248 | ); | 262 | ); |
249 | $this->assertEquals($html, $data); | 263 | $this->assertEquals($html, $data . PHP_EOL); |
250 | } | 264 | } |
251 | 265 | ||
252 | /** | 266 | /** |
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/plugins/resources/hashtags.md b/tests/plugins/resources/hashtags.md new file mode 100644 index 00000000..46326de3 --- /dev/null +++ b/tests/plugins/resources/hashtags.md | |||
@@ -0,0 +1,10 @@ | |||
1 | [#lol](?addtag=lol) | ||
2 | |||
3 | #test | ||
4 | |||
5 | `#test2` | ||
6 | |||
7 | ``` | ||
8 | bla #bli blo | ||
9 | #bla | ||
10 | ``` | ||
diff --git a/tests/plugins/resources/hashtags.raw b/tests/plugins/resources/hashtags.raw new file mode 100644 index 00000000..9d2dc98a --- /dev/null +++ b/tests/plugins/resources/hashtags.raw | |||
@@ -0,0 +1,10 @@ | |||
1 | #lol | ||
2 | |||
3 | #test | ||
4 | |||
5 | `#test2` | ||
6 | |||
7 | ``` | ||
8 | bla #bli blo | ||
9 | #bla | ||
10 | ``` | ||
diff --git a/tests/plugins/resources/markdown.html b/tests/plugins/resources/markdown.html index f1df4e7e..c3460bf7 100644 --- a/tests/plugins/resources/markdown.html +++ b/tests/plugins/resources/markdown.html | |||
@@ -12,11 +12,11 @@ | |||
12 | <li><a href="http://link.tld">two</a></li> | 12 | <li><a href="http://link.tld">two</a></li> |
13 | <li><a href="http://link.tld">three</a></li> | 13 | <li><a href="http://link.tld">three</a></li> |
14 | <li><a href="http://link.tld">four</a></li> | 14 | <li><a href="http://link.tld">four</a></li> |
15 | <li>foo <a href="?addtag=foobar" title="Hashtag foobar">#foobar</a></li> | 15 | <li>foo <a href="?addtag=foobar">#foobar</a></li> |
16 | </ol></li> | 16 | </ol></li> |
17 | </ol> | 17 | </ol> |
18 | <p><a href="?addtag=foobar" title="Hashtag foobar">#foobar</a> foo <code>lol #foo</code> <a href="?addtag=bar" title="Hashtag bar">#bar</a></p> | 18 | <p><a href="?addtag=foobar">#foobar</a> foo <code>lol #foo</code> <a href="?addtag=bar">#bar</a></p> |
19 | <p>fsdfs <a href="http://link.tld">http://link.tld</a> <a href="?addtag=foobar" title="Hashtag foobar">#foobar</a> <code>http://link.tld</code></p> | 19 | <p>fsdfs <a href="http://link.tld">http://link.tld</a> <a href="?addtag=foobar">#foobar</a> <code>http://link.tld</code></p> |
20 | <pre><code>http://link.tld #foobar | 20 | <pre><code>http://link.tld #foobar |
21 | next #foo</code></pre> | 21 | next #foo</code></pre> |
22 | <p>Block:</p> | 22 | <p>Block:</p> |
@@ -30,4 +30,4 @@ next #foo</code></pre> | |||
30 | <a href="ftp://test.tld/path/?query=value#hash">link</a><br /> | 30 | <a href="ftp://test.tld/path/?query=value#hash">link</a><br /> |
31 | <a href="magnet:test.tld/path/?query=value#hash">link</a><br /> | 31 | <a href="magnet:test.tld/path/?query=value#hash">link</a><br /> |
32 | <a href="http://alert('xss')">link</a><br /> | 32 | <a href="http://alert('xss')">link</a><br /> |
33 | <a href="http://test.tld/path/?query=value#hash">link</a></p></div> \ No newline at end of file | 33 | <a href="http://test.tld/path/?query=value#hash">link</a></p></div> |
diff --git a/tests/plugins/resources/markdown.md b/tests/plugins/resources/markdown.md index b8ebd934..9350a8c7 100644 --- a/tests/plugins/resources/markdown.md +++ b/tests/plugins/resources/markdown.md | |||
@@ -31,4 +31,4 @@ lorem ipsum #foobar http://link.tld | |||
31 | [link](ftp://test.tld/path/?query=value#hash) | 31 | [link](ftp://test.tld/path/?query=value#hash) |
32 | [link](magnet:test.tld/path/?query=value#hash) | 32 | [link](magnet:test.tld/path/?query=value#hash) |
33 | [link](javascript:alert('xss')) | 33 | [link](javascript:alert('xss')) |
34 | [link](other://test.tld/path/?query=value#hash) \ No newline at end of file | 34 | [link](other://test.tld/path/?query=value#hash) |
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(); | |||
8 | use \Shaarli\Security\SessionManager; | 8 | use \Shaarli\Security\SessionManager; |
9 | use \PHPUnit\Framework\TestCase; | 9 | use \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 e887aa78..59679e38 100644 --- a/tests/utils/ReferenceLinkDB.php +++ b/tests/utils/ReferenceLinkDB.php | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | class ReferenceLinkDB | 5 | class ReferenceLinkDB |
6 | { | 6 | { |
7 | public static $NB_LINKS_TOTAL = 9; | 7 | public static $NB_LINKS_TOTAL = 11; |
8 | 8 | ||
9 | private $_links = array(); | 9 | private $_links = array(); |
10 | private $_publicCount = 0; | 10 | private $_publicCount = 0; |
@@ -16,6 +16,32 @@ class ReferenceLinkDB | |||
16 | public function __construct() | 16 | public function __construct() |
17 | { | 17 | { |
18 | $this->addLink( | 18 | $this->addLink( |
19 | 11, | ||
20 | 'Pined older', | ||
21 | '?PCRizQ', | ||
22 | 'This is an older pinned link', | ||
23 | 0, | ||
24 | DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20100309_101010'), | ||
25 | '', | ||
26 | null, | ||
27 | 'PCRizQ', | ||
28 | true | ||
29 | ); | ||
30 | |||
31 | $this->addLink( | ||
32 | 10, | ||
33 | 'Pined', | ||
34 | '?0gCTjQ', | ||
35 | 'This is a pinned link', | ||
36 | 0, | ||
37 | DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121207_152312'), | ||
38 | '', | ||
39 | null, | ||
40 | '0gCTjQ', | ||
41 | true | ||
42 | ); | ||
43 | |||
44 | $this->addLink( | ||
19 | 41, | 45 | 41, |
20 | 'Link title: @website', | 46 | 'Link title: @website', |
21 | '?WDWyig', | 47 | '?WDWyig', |
@@ -114,8 +140,18 @@ class ReferenceLinkDB | |||
114 | /** | 140 | /** |
115 | * Adds a new link | 141 | * Adds a new link |
116 | */ | 142 | */ |
117 | protected function addLink($id, $title, $url, $description, $private, $date, $tags, $updated = '', $shorturl = '') | 143 | protected function addLink( |
118 | { | 144 | $id, |
145 | $title, | ||
146 | $url, | ||
147 | $description, | ||
148 | $private, | ||
149 | $date, | ||
150 | $tags, | ||
151 | $updated = '', | ||
152 | $shorturl = '', | ||
153 | $pinned = false | ||
154 | ) { | ||
119 | $link = array( | 155 | $link = array( |
120 | 'id' => $id, | 156 | 'id' => $id, |
121 | 'title' => $title, | 157 | 'title' => $title, |
@@ -126,6 +162,7 @@ class ReferenceLinkDB | |||
126 | 'created' => $date, | 162 | 'created' => $date, |
127 | 'updated' => $updated, | 163 | 'updated' => $updated, |
128 | 'shorturl' => $shorturl ? $shorturl : smallHash($date->format(LinkDB::LINK_DATE_FORMAT) . $id), | 164 | 'shorturl' => $shorturl ? $shorturl : smallHash($date->format(LinkDB::LINK_DATE_FORMAT) . $id), |
165 | 'sticky' => $pinned | ||
129 | ); | 166 | ); |
130 | $this->_links[$id] = $link; | 167 | $this->_links[$id] = $link; |
131 | 168 | ||
@@ -164,7 +201,11 @@ class ReferenceLinkDB | |||
164 | 201 | ||
165 | $order = $order === 'ASC' ? -1 : 1; | 202 | $order = $order === 'ASC' ? -1 : 1; |
166 | // Reorder array by dates. | 203 | // Reorder array by dates. |
167 | 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']) { | ||
206 | return $a['sticky'] ? -1 : 1; | ||
207 | } | ||
208 | |||
168 | return $a['created'] < $b['created'] ? 1 * $order : -1 * $order; | 209 | return $a['created'] < $b['created'] ? 1 * $order : -1 * $order; |
169 | }); | 210 | }); |
170 | } | 211 | } |
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'; |
diff --git a/tpl/default/addlink.html b/tpl/default/addlink.html index 2f956e06..55864a02 100644 --- a/tpl/default/addlink.html +++ b/tpl/default/addlink.html | |||
@@ -11,7 +11,8 @@ | |||
11 | <h2 class="window-title">{"Shaare a new link"|t}</h2> | 11 | <h2 class="window-title">{"Shaare a new link"|t}</h2> |
12 | <form method="GET" action="#" name="addform" class="addform"> | 12 | <form method="GET" action="#" name="addform" class="addform"> |
13 | <div> | 13 | <div> |
14 | <input type="text" name="post" placeholder="{'URL or leave empty to post a note'|t}" class="autofocus"> | 14 | <label for="shaare">{'URL or leave empty to post a note'|t}</label> |
15 | <input type="text" name="post" id="shaare" class="autofocus"> | ||
15 | </div> | 16 | </div> |
16 | <div> | 17 | <div> |
17 | <input type="submit" value="{'Add link'|t}"> | 18 | <input type="submit" value="{'Add link'|t}"> |
diff --git a/tpl/default/daily.html b/tpl/default/daily.html index 816e5d0a..2c409478 100644 --- a/tpl/default/daily.html +++ b/tpl/default/daily.html | |||
@@ -72,7 +72,7 @@ | |||
72 | {if="$thumbnails_enabled && !empty($link.thumbnail)"} | 72 | {if="$thumbnails_enabled && !empty($link.thumbnail)"} |
73 | <div class="daily-entry-thumbnail"> | 73 | <div class="daily-entry-thumbnail"> |
74 | <img data-src="{$link.thumbnail}#" class="b-lazy" | 74 | <img data-src="{$link.thumbnail}#" class="b-lazy" |
75 | src="#" | 75 | src="" |
76 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> | 76 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> |
77 | </div> | 77 | </div> |
78 | {/if} | 78 | {/if} |
diff --git a/tpl/default/includes.html b/tpl/default/includes.html index 5ccacaaf..6c30d1bf 100644 --- a/tpl/default/includes.html +++ b/tpl/default/includes.html | |||
@@ -15,3 +15,23 @@ | |||
15 | <link type="text/css" rel="stylesheet" href="data/user.css#" /> | 15 | <link type="text/css" rel="stylesheet" href="data/user.css#" /> |
16 | {/if} | 16 | {/if} |
17 | <link rel="search" type="application/opensearchdescription+xml" href="?do=opensearch#" title="Shaarli search - {$shaarlititle}"/> | 17 | <link rel="search" type="application/opensearchdescription+xml" href="?do=opensearch#" title="Shaarli search - {$shaarlititle}"/> |
18 | {if="! empty($links) && count($links) === 1"} | ||
19 | {$link=reset($links)} | ||
20 | <meta property="og:title" content="{$link.title}" /> | ||
21 | <meta property="og:type" content="article" /> | ||
22 | <meta property="og:url" content="{$index_url}?{$link.shorturl}" /> | ||
23 | {$ogDescription=isset($link.description_src) ? $link.description_src : $link.description} | ||
24 | <meta property="og:description" content="{function="substr(strip_tags($ogDescription), 0, 300)"}" /> | ||
25 | {if="$link.thumbnail"} | ||
26 | <meta property="og:image" content="{$index_url}{$link.thumbnail}" /> | ||
27 | {/if} | ||
28 | {if="!$hide_timestamps || $is_logged_in"} | ||
29 | <meta property="article:published_time" content="{$link.created->format(DateTime::ATOM)}" /> | ||
30 | {if="$link.updated"} | ||
31 | <meta property="article:modified_time" content="{$link.updated->format(DateTime::ATOM)}" /> | ||
32 | {/if} | ||
33 | {/if} | ||
34 | {loop="link.taglist"} | ||
35 | <meta property="article:tag" content="{$value}" /> | ||
36 | {/loop} | ||
37 | {/if} | ||
diff --git a/tpl/default/linklist.html b/tpl/default/linklist.html index 8ea2ce66..ed78f40a 100644 --- a/tpl/default/linklist.html +++ b/tpl/default/linklist.html | |||
@@ -125,6 +125,8 @@ | |||
125 | {$strPermalink=t('Permalink')} | 125 | {$strPermalink=t('Permalink')} |
126 | {$strPermalinkLc=t('permalink')} | 126 | {$strPermalinkLc=t('permalink')} |
127 | {$strAddTag=t('Add tag')} | 127 | {$strAddTag=t('Add tag')} |
128 | {$strToggleSticky=t('Toggle sticky')} | ||
129 | {$strSticky=t('Sticky')} | ||
128 | {ignore}End of translations{/ignore} | 130 | {ignore}End of translations{/ignore} |
129 | {loop="links"} | 131 | {loop="links"} |
130 | <div class="anchor" id="{$value.shorturl}"></div> | 132 | <div class="anchor" id="{$value.shorturl}"></div> |
@@ -137,7 +139,7 @@ | |||
137 | <a href="{$value.real_url}"> | 139 | <a href="{$value.real_url}"> |
138 | {ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore} | 140 | {ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore} |
139 | <img data-src="{$value.thumbnail}#" class="b-lazy" | 141 | <img data-src="{$value.thumbnail}#" class="b-lazy" |
140 | src="#" | 142 | src="" |
141 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> | 143 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> |
142 | </a> | 144 | </a> |
143 | </div> | 145 | </div> |
@@ -190,7 +192,7 @@ | |||
190 | {if="$is_logged_in"} | 192 | {if="$is_logged_in"} |
191 | <div class="linklist-item-infos-controls-group pure-u-0 pure-u-lg-visible"> | 193 | <div class="linklist-item-infos-controls-group pure-u-0 pure-u-lg-visible"> |
192 | <span class="linklist-item-infos-controls-item ctrl-checkbox"> | 194 | <span class="linklist-item-infos-controls-item ctrl-checkbox"> |
193 | <input type="checkbox" class="delete-checkbox" value="{$value.id}"> | 195 | <input type="checkbox" class="link-checkbox" value="{$value.id}"> |
194 | </span> | 196 | </span> |
195 | <span class="linklist-item-infos-controls-item ctrl-edit"> | 197 | <span class="linklist-item-infos-controls-item ctrl-edit"> |
196 | <a href="?edit_link={$value.id}" title="{$strEdit}"><i class="fa fa-pencil-square-o edit-link"></i></a> | 198 | <a href="?edit_link={$value.id}" title="{$strEdit}"><i class="fa fa-pencil-square-o edit-link"></i></a> |
@@ -201,7 +203,23 @@ | |||
201 | <i class="fa fa-trash"></i> | 203 | <i class="fa fa-trash"></i> |
202 | </a> | 204 | </a> |
203 | </span> | 205 | </span> |
206 | <span class="linklist-item-infos-controls-item ctrl-pin"> | ||
207 | <a href="?do=pin&id={$value.id}&token={$token}" | ||
208 | title="{$strToggleSticky}" class="pin-link {if="$value.sticky"}pinned-link{/if} pure-u-0 pure-u-lg-visible"> | ||
209 | <i class="fa fa-thumb-tack"></i> | ||
210 | </a> | ||
211 | </span> | ||
204 | </div> | 212 | </div> |
213 | {else} | ||
214 | {if="$value.sticky"} | ||
215 | <div class="linklist-item-infos-controls-group pure-u-0 pure-u-lg-visible"> | ||
216 | <span class="linklist-item-infos-controls-item ctrl-pin"> | ||
217 | <span title="{$strSticky}" class="pin-link pinned-link pure-u-0 pure-u-lg-visible"> | ||
218 | <i class="fa fa-thumb-tack"></i> | ||
219 | </span> | ||
220 | </span> | ||
221 | </div> | ||
222 | {/if} | ||
205 | {/if} | 223 | {/if} |
206 | <a href="?{$value.shorturl}" title="{$strPermalink}"> | 224 | <a href="?{$value.shorturl}" title="{$strPermalink}"> |
207 | {if="!$hide_timestamps || $is_logged_in"} | 225 | {if="!$hide_timestamps || $is_logged_in"} |
diff --git a/tpl/default/linklist.paging.html b/tpl/default/linklist.paging.html index 5309e348..fe665a84 100644 --- a/tpl/default/linklist.paging.html +++ b/tpl/default/linklist.paging.html | |||
@@ -16,6 +16,9 @@ | |||
16 | <a href="?untaggedonly" title="{'Filter untagged links'|t}" | 16 | <a href="?untaggedonly" title="{'Filter untagged links'|t}" |
17 | class={if="$untaggedonly"}"filter-on"{else}"filter-off"{/if} | 17 | class={if="$untaggedonly"}"filter-on"{else}"filter-off"{/if} |
18 | ><i class="fa fa-tag"></i></a> | 18 | ><i class="fa fa-tag"></i></a> |
19 | <a href="#" title="{'Select all'|t}" | ||
20 | class="filter-off select-all-button" | ||
21 | ><i class="fa fa-check-square-o"></i></a> | ||
19 | <a href="#" class="filter-off fold-all pure-u-lg-0" title="{'Fold all'|t}"> | 22 | <a href="#" class="filter-off fold-all pure-u-lg-0" title="{'Fold all'|t}"> |
20 | <i class="fa fa-chevron-up"></i> | 23 | <i class="fa fa-chevron-up"></i> |
21 | </a> | 24 | </a> |
diff --git a/tpl/default/page.header.html b/tpl/default/page.header.html index 3b43a611..4f6dd4d8 100644 --- a/tpl/default/page.header.html +++ b/tpl/default/page.header.html | |||
@@ -118,7 +118,7 @@ | |||
118 | <div id="actions" class="subheader-form"> | 118 | <div id="actions" class="subheader-form"> |
119 | <div class="pure-g"> | 119 | <div class="pure-g"> |
120 | <div class="pure-u-1"> | 120 | <div class="pure-u-1"> |
121 | <a href="" id="actions-delete" class="button">Delete</a> | 121 | <a href="" id="actions-delete" class="button">{'Delete'|t}</a> |
122 | </div> | 122 | </div> |
123 | </div> | 123 | </div> |
124 | </div> | 124 | </div> |
diff --git a/tpl/default/picwall.html b/tpl/default/picwall.html index 9a0b10dc..4c325487 100644 --- a/tpl/default/picwall.html +++ b/tpl/default/picwall.html | |||
@@ -37,7 +37,7 @@ | |||
37 | <div class="picwall-pictureframe"> | 37 | <div class="picwall-pictureframe"> |
38 | {ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore} | 38 | {ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore} |
39 | <img data-src="{$value.thumbnail}#" class="b-lazy" | 39 | <img data-src="{$value.thumbnail}#" class="b-lazy" |
40 | src="#" | 40 | src="" |
41 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> | 41 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> |
42 | <a href="{$value.real_url}"><span class="info">{$value.title}</span></a> | 42 | <a href="{$value.real_url}"><span class="info">{$value.title}</span></a> |
43 | {loop="$value.picwall_plugin"} | 43 | {loop="$value.picwall_plugin"} |
diff --git a/tpl/vintage/daily.html b/tpl/vintage/daily.html index 00148a58..71d84475 100644 --- a/tpl/vintage/daily.html +++ b/tpl/vintage/daily.html | |||
@@ -71,7 +71,7 @@ | |||
71 | {if="$thumbnails_enabled && !empty($link.thumbnail)"} | 71 | {if="$thumbnails_enabled && !empty($link.thumbnail)"} |
72 | <div class="dailyEntryThumbnail"> | 72 | <div class="dailyEntryThumbnail"> |
73 | <img data-src="{$link.thumbnail}#" class="b-lazy" | 73 | <img data-src="{$link.thumbnail}#" class="b-lazy" |
74 | src="#" | 74 | src="" |
75 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> | 75 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> |
76 | </div> | 76 | </div> |
77 | {/if} | 77 | {/if} |
diff --git a/tpl/vintage/includes.html b/tpl/vintage/includes.html index 410b466b..2efb6b10 100644 --- a/tpl/vintage/includes.html +++ b/tpl/vintage/includes.html | |||
@@ -12,3 +12,23 @@ | |||
12 | {/loop} | 12 | {/loop} |
13 | {if="is_file('data/user.css')"}<link type="text/css" rel="stylesheet" href="data/user.css#" />{/if} | 13 | {if="is_file('data/user.css')"}<link type="text/css" rel="stylesheet" href="data/user.css#" />{/if} |
14 | <link rel="search" type="application/opensearchdescription+xml" href="?do=opensearch#" title="Shaarli search - {$shaarlititle|htmlspecialchars}"/> | 14 | <link rel="search" type="application/opensearchdescription+xml" href="?do=opensearch#" title="Shaarli search - {$shaarlititle|htmlspecialchars}"/> |
15 | {if="! empty($links) && count($links) === 1"} | ||
16 | {$link=reset($links)} | ||
17 | <meta property="og:title" content="{$link.title}" /> | ||
18 | <meta property="og:type" content="article" /> | ||
19 | <meta property="og:url" content="{$index_url}?{$link.shorturl}" /> | ||
20 | {$ogDescription=isset($link.description_src) ? $link.description_src : $link.description} | ||
21 | <meta property="og:description" content="{function="mb_substr(strip_tags($ogDescription), 0, 300)"}" /> | ||
22 | {if="$link.thumbnail"} | ||
23 | <meta property="og:image" content="{$index_url}{$link.thumbnail}" /> | ||
24 | {/if} | ||
25 | {if="!$hide_timestamps || $is_logged_in"} | ||
26 | <meta property="article:published_time" content="{$link.created->format(DateTime::ATOM)}" /> | ||
27 | {if="$link.updated"} | ||
28 | <meta property="article:modified_time" content="{$link.updated->format(DateTime::ATOM)}" /> | ||
29 | {/if} | ||
30 | {/if} | ||
31 | {loop="link.taglist"} | ||
32 | <meta property="article:tag" content="{$value}" /> | ||
33 | {/loop} | ||
34 | {/if} | ||
diff --git a/tpl/vintage/linklist.html b/tpl/vintage/linklist.html index 3f202849..dcb14e90 100644 --- a/tpl/vintage/linklist.html +++ b/tpl/vintage/linklist.html | |||
@@ -85,7 +85,7 @@ | |||
85 | <a href="{$value.real_url}"> | 85 | <a href="{$value.real_url}"> |
86 | {ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore} | 86 | {ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore} |
87 | <img data-src="{$value.thumbnail}#" class="b-lazy" | 87 | <img data-src="{$value.thumbnail}#" class="b-lazy" |
88 | src="#" | 88 | src="" |
89 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> | 89 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> |
90 | </a> | 90 | </a> |
91 | </div> | 91 | </div> |
diff --git a/tpl/vintage/picwall.html b/tpl/vintage/picwall.html index 5f1d266e..b3a16791 100644 --- a/tpl/vintage/picwall.html +++ b/tpl/vintage/picwall.html | |||
@@ -17,7 +17,7 @@ | |||
17 | <div class="picwall_pictureframe"> | 17 | <div class="picwall_pictureframe"> |
18 | {ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore} | 18 | {ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore} |
19 | <img data-src="{$value.thumbnail}#" class="b-lazy" | 19 | <img data-src="{$value.thumbnail}#" class="b-lazy" |
20 | src="#" | 20 | src="" |
21 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> | 21 | alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" /> |
22 | <a href="{$value.real_url}"><span class="info">{$value.title}</span></a> | 22 | <a href="{$value.real_url}"><span class="info">{$value.title}</span></a> |
23 | {loop="$value.picwall_plugin"} | 23 | {loop="$value.picwall_plugin"} |