diff options
-rw-r--r-- | .github/mailmap | 1 | ||||
-rw-r--r-- | .htaccess | 4 | ||||
-rw-r--r-- | AUTHORS | 12 | ||||
-rw-r--r-- | CHANGELOG.md | 20 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | application/api/ApiMiddleware.php | 10 | ||||
-rw-r--r-- | application/bookmark/LinkUtils.php | 2 | ||||
-rw-r--r-- | application/front/controller/admin/ManageShaareController.php | 4 | ||||
-rw-r--r-- | doc/md/dev/Unit-tests.md | 15 | ||||
-rw-r--r-- | tests/api/ApiMiddlewareTest.php | 47 | ||||
-rw-r--r-- | tests/bookmark/LinkUtilsTest.php | 13 | ||||
-rw-r--r-- | tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php | 24 |
12 files changed, 131 insertions, 25 deletions
diff --git a/.github/mailmap b/.github/mailmap index 366946e8..15a25e43 100644 --- a/.github/mailmap +++ b/.github/mailmap | |||
@@ -3,6 +3,7 @@ ArthurHoaro <arthur@hoa.ro> Arthur | |||
3 | Florian Eula <eula.florian@gmail.com> feula | 3 | Florian Eula <eula.florian@gmail.com> feula |
4 | Florian Eula <eula.florian@gmail.com> <mr.pikzen@gmail.com> | 4 | Florian Eula <eula.florian@gmail.com> <mr.pikzen@gmail.com> |
5 | Immánuel Fodor <immanuelfactor+github@gmail.com> | 5 | Immánuel Fodor <immanuelfactor+github@gmail.com> |
6 | Immánuel Fodor <immanuelfactor+github@gmail.com> Immánuel! <21174107+immanuelfodor@users.noreply.github.com> | ||
6 | kalvn <kalvnthereal@gmail.com> <kalvn@users.noreply.github.com> | 7 | kalvn <kalvnthereal@gmail.com> <kalvn@users.noreply.github.com> |
7 | kalvn <kalvnthereal@gmail.com> <kalvn@pm.me> | 8 | kalvn <kalvnthereal@gmail.com> <kalvn@pm.me> |
8 | Neros <contact@neros.fr> <NerosTie@users.noreply.github.com> | 9 | Neros <contact@neros.fr> <NerosTie@users.noreply.github.com> |
@@ -10,8 +10,12 @@ RewriteRule ^(.git|doxygen|vendor) - [F] | |||
10 | # fixes JWT token not correctly forwarded on some Apache/FastCGI setups | 10 | # fixes JWT token not correctly forwarded on some Apache/FastCGI setups |
11 | RewriteCond %{HTTP:Authorization} ^(.*) | 11 | RewriteCond %{HTTP:Authorization} ^(.*) |
12 | RewriteRule .* - [e=HTTP_AUTHORIZATION:%1] | 12 | RewriteRule .* - [e=HTTP_AUTHORIZATION:%1] |
13 | # Alternative (if the 2 lines above don't work) | ||
14 | # SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0 | ||
13 | 15 | ||
14 | # REST API | 16 | # REST API |
17 | # Ionos Hosting needs RewriteBase / | ||
18 | # RewriteBase / | ||
15 | RewriteCond %{REQUEST_FILENAME} !-f | 19 | RewriteCond %{REQUEST_FILENAME} !-f |
16 | RewriteCond %{REQUEST_FILENAME} !-d | 20 | RewriteCond %{REQUEST_FILENAME} !-d |
17 | RewriteRule ^ index.php [QSA,L] | 21 | RewriteRule ^ index.php [QSA,L] |
@@ -1,22 +1,24 @@ | |||
1 | 903 ArthurHoaro <arthur@hoa.ro> | 1 | 973 ArthurHoaro <arthur@hoa.ro> |
2 | 402 VirtualTam <virtualtam@flibidi.net> | 2 | 402 VirtualTam <virtualtam@flibidi.net> |
3 | 250 nodiscc <nodiscc@gmail.com> | 3 | 291 nodiscc <nodiscc@gmail.com> |
4 | 56 Sébastien Sauvage <sebsauvage@sebsauvage.net> | 4 | 56 Sébastien Sauvage <sebsauvage@sebsauvage.net> |
5 | 16 Luce Carević <lcarevic@access42.net> | 5 | 16 Luce Carević <lcarevic@access42.net> |
6 | 15 Florian Eula <eula.florian@gmail.com> | 6 | 15 Florian Eula <eula.florian@gmail.com> |
7 | 13 Emilien Klein <emilien@klein.st> | 7 | 13 Emilien Klein <emilien@klein.st> |
8 | 12 Nicolas Danelon <hi@nicolasmd.com.ar> | 8 | 12 Nicolas Danelon <hi@nicolasmd.com.ar> |
9 | 9 Lucas Cimon <lucas.cimon@gmail.com> | ||
9 | 9 Willi Eggeling <thewilli@gmail.com> | 10 | 9 Willi Eggeling <thewilli@gmail.com> |
10 | 8 Christophe HENRY <christophe.henry@sbgodin.fr> | 11 | 8 Christophe HENRY <christophe.henry@sbgodin.fr> |
11 | 7 Lucas Cimon <lucas.cimon@gmail.com> | ||
12 | 6 B. van Berkum <dev@dotmpe.com> | 12 | 6 B. van Berkum <dev@dotmpe.com> |
13 | 6 Immánuel Fodor <immanuelfactor+github@gmail.com> | ||
14 | 6 Keith Carangelo <mail@kcaran.com> | ||
13 | 6 kalvn <kalvnthereal@gmail.com> | 15 | 6 kalvn <kalvnthereal@gmail.com> |
14 | 6 llune <llune@users.noreply.github.com> | 16 | 6 llune <llune@users.noreply.github.com> |
15 | 5 Mark Schmitz <kramred@gmail.com> | 17 | 5 Mark Schmitz <kramred@gmail.com> |
16 | 5 Sébastien NOBILI <code@pipoprods.org> | 18 | 5 Sébastien NOBILI <code@pipoprods.org> |
19 | 5 dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> | ||
17 | 4 Alexandre Alapetite <alexandre@alapetite.fr> | 20 | 4 Alexandre Alapetite <alexandre@alapetite.fr> |
18 | 4 David Sferruzza <david.sferruzza@gmail.com> | 21 | 4 David Sferruzza <david.sferruzza@gmail.com> |
19 | 4 Immánuel Fodor <immanuelfactor+github@gmail.com> | ||
20 | 3 Agurato <mail.vmonot@gmail.com> | 22 | 3 Agurato <mail.vmonot@gmail.com> |
21 | 3 Teromene <teromene@teromene.fr> | 23 | 3 Teromene <teromene@teromene.fr> |
22 | 2 Alexandre G.-Raymond <alex@ndre.gr> | 24 | 2 Alexandre G.-Raymond <alex@ndre.gr> |
@@ -30,7 +32,6 @@ | |||
30 | 2 Qwerty <champlywood@free.fr> | 32 | 2 Qwerty <champlywood@free.fr> |
31 | 2 Stephen Muth <smuth4@gmail.com> | 33 | 2 Stephen Muth <smuth4@gmail.com> |
32 | 2 Timo Van Neerden <fire@lehollandaisvolant.net> | 34 | 2 Timo Van Neerden <fire@lehollandaisvolant.net> |
33 | 2 dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> | ||
34 | 2 flow.gunso <flow.gunso@gmail.com> | 35 | 2 flow.gunso <flow.gunso@gmail.com> |
35 | 2 julienCXX <software@chmodplusx.eu> | 36 | 2 julienCXX <software@chmodplusx.eu> |
36 | 2 philipp-r <philipp-r@users.noreply.github.com> | 37 | 2 philipp-r <philipp-r@users.noreply.github.com> |
@@ -75,4 +76,5 @@ | |||
75 | 1 dimtion <zizou.xena@gmail.com> | 76 | 1 dimtion <zizou.xena@gmail.com> |
76 | 1 durcheinandr <jochen@durcheinandr.de> | 77 | 1 durcheinandr <jochen@durcheinandr.de> |
77 | 1 lapineige <lapineige@users.noreply.github.com> | 78 | 1 lapineige <lapineige@users.noreply.github.com> |
79 | 1 owen bell <66233223+xfnw@users.noreply.github.com> | ||
78 | 1 rfolo9li <50079896+rfolo9li@users.noreply.github.com> | 80 | 1 rfolo9li <50079896+rfolo9li@users.noreply.github.com> |
diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bae5b48..e2fb480b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md | |||
@@ -4,7 +4,7 @@ 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 | ## [v0.12.0](https://github.com/shaarli/Shaarli/releases/tag/v0.12.0-beta) - UNRELEASED [beta 2020-08-27] | 7 | ## [v0.12.0](https://github.com/shaarli/Shaarli/releases/tag/v0.12.0-beta) - UNRELEASED [beta 2020-08-27 - beta-1 2020-09-30] |
8 | 8 | ||
9 | **Save you `data/` folder before updating!** | 9 | **Save you `data/` folder before updating!** |
10 | 10 | ||
@@ -16,6 +16,8 @@ Be aware that by using a beta version you might encounter bugs, and that 3rd par | |||
16 | - Markdown rendering is now integrated into Shaarli core | 16 | - Markdown rendering is now integrated into Shaarli core |
17 | - Add autofocus on tag cloud filter input | 17 | - Add autofocus on tag cloud filter input |
18 | - Japanese translations | 18 | - Japanese translations |
19 | - Japanese translation: add language to admin configuration page | ||
20 | - Support for PHP 8.0 | ||
19 | - Support for local anchor URL (startting with `#`) | 21 | - Support for local anchor URL (startting with `#`) |
20 | - LDAP authentication | 22 | - LDAP authentication |
21 | - Encapsulated PageCacheManager | 23 | - Encapsulated PageCacheManager |
@@ -24,18 +26,22 @@ Be aware that by using a beta version you might encounter bugs, and that 3rd par | |||
24 | - section about mkdocs | 26 | - section about mkdocs |
25 | - Ulauncher extension | 27 | - Ulauncher extension |
26 | - CI: run against PHP 7.4 | 28 | - CI: run against PHP 7.4 |
29 | - Added $links_per_page variable to template and display on default | ||
30 | - Inject BookmarkServiceInterface in plugins data | ||
31 | - Add manual configuration for root URL | ||
32 | - Added PATCH to the allowed Apache request methods. | ||
27 | 33 | ||
28 | ### Changed | 34 | ### Changed |
29 | - Introduce Bookmark object and Service layer | 35 | - Introduce Bookmark object and Service layer |
30 | - Save bookmark as objects in the datastore | 36 | - Save bookmark as objects in the datastore |
31 | - Handle bookmark as objects across the whole codebase (except templates and plugins) | 37 | - Handle bookmark as objects across the whole codebase (except templates and plugins) |
32 | - Process all Shaarli page through Slim controller, with proper URL rewriting (see #1516) | 38 | - Process all Shaarli page through Slim controller, with proper URL rewriting (see #1516) |
39 | - Docs: the entire documentation has been reviewed, updated and improved, thanks to @nodiscc! | ||
33 | - ATOM feed: use instance name as author name instead of URL | 40 | - ATOM feed: use instance name as author name instead of URL |
34 | - Updated French translation | 41 | - Updated French translation |
35 | - Docs: | 42 | - Default colors plugin: generate CSS file during initialization |
36 | - Troubleshooting page rewritten | 43 | - Improve default bookmarks after install |
37 | - Updated unit tests page | 44 | - Upgrade all front end dependencies and webpack build |
38 | - Updated Server security page | ||
39 | 45 | ||
40 | ### Fixed | 46 | ### Fixed |
41 | - Undefined index: thumbnail in daily page | 47 | - Undefined index: thumbnail in daily page |
@@ -54,6 +60,8 @@ Be aware that by using a beta version you might encounter bugs, and that 3rd par | |||
54 | - Division by zero in tag cloud | 60 | - Division by zero in tag cloud |
55 | - CI: deprecated linux distribution and sudo directive | 61 | - CI: deprecated linux distribution and sudo directive |
56 | - Docker build: gcc is no longer included in python alpine image | 62 | - Docker build: gcc is no longer included in python alpine image |
63 | - Default template: display pin button in mobile view | ||
64 | - Pinned bookmarks are not longer displayed first in ATOM/RSS feeds | ||
57 | - Docs: | 65 | - Docs: |
58 | - Outdated Docker documentation for stable branch | 66 | - Outdated Docker documentation for stable branch |
59 | - Outdated links | 67 | - Outdated links |
@@ -63,6 +71,8 @@ Be aware that by using a beta version you might encounter bugs, and that 3rd par | |||
63 | - Markdown plugin | 71 | - Markdown plugin |
64 | - Docs: | 72 | - Docs: |
65 | - emojione & twemoji removed | 73 | - emojione & twemoji removed |
74 | - Makefile: remove static_analysis_summary from all: target | ||
75 | - doc/Makefile: remove references to composer update | ||
66 | 76 | ||
67 | ## [v0.11.1](https://github.com/shaarli/Shaarli/releases/tag/v0.11.1) - 2019-08-03 | 77 | ## [v0.11.1](https://github.com/shaarli/Shaarli/releases/tag/v0.11.1) - 2019-08-03 |
68 | 78 | ||
@@ -85,6 +85,10 @@ all_tests: test locale_test_de_DE locale_test_en_US locale_test_fr_FR | |||
85 | @# --text doesn't work with phpunit 4.* (v5 requires PHP 5.6) | 85 | @# --text doesn't work with phpunit 4.* (v5 requires PHP 5.6) |
86 | @#$(BIN)/phpcov merge --text coverage/txt coverage | 86 | @#$(BIN)/phpcov merge --text coverage/txt coverage |
87 | 87 | ||
88 | ### download 3rd-party PHP libraries, including dev dependencies | ||
89 | composer_dependencies_dev: clean | ||
90 | composer install --prefer-dist | ||
91 | |||
88 | ## | 92 | ## |
89 | # Custom release archive generation | 93 | # Custom release archive generation |
90 | # | 94 | # |
diff --git a/application/api/ApiMiddleware.php b/application/api/ApiMiddleware.php index 09ce6445..f5b53b01 100644 --- a/application/api/ApiMiddleware.php +++ b/application/api/ApiMiddleware.php | |||
@@ -107,7 +107,9 @@ class ApiMiddleware | |||
107 | */ | 107 | */ |
108 | protected function checkToken($request) | 108 | protected function checkToken($request) |
109 | { | 109 | { |
110 | if (! $request->hasHeader('Authorization')) { | 110 | if (!$request->hasHeader('Authorization') |
111 | && !isset($this->container->environment['REDIRECT_HTTP_AUTHORIZATION']) | ||
112 | ) { | ||
111 | throw new ApiAuthorizationException('JWT token not provided'); | 113 | throw new ApiAuthorizationException('JWT token not provided'); |
112 | } | 114 | } |
113 | 115 | ||
@@ -115,7 +117,11 @@ class ApiMiddleware | |||
115 | throw new ApiAuthorizationException('Token secret must be set in Shaarli\'s administration'); | 117 | throw new ApiAuthorizationException('Token secret must be set in Shaarli\'s administration'); |
116 | } | 118 | } |
117 | 119 | ||
118 | $authorization = $request->getHeaderLine('Authorization'); | 120 | if (isset($this->container->environment['REDIRECT_HTTP_AUTHORIZATION'])) { |
121 | $authorization = $this->container->environment['REDIRECT_HTTP_AUTHORIZATION']; | ||
122 | } else { | ||
123 | $authorization = $request->getHeaderLine('Authorization'); | ||
124 | } | ||
119 | 125 | ||
120 | if (! preg_match('/^Bearer (.*)/i', $authorization, $matches)) { | 126 | if (! preg_match('/^Bearer (.*)/i', $authorization, $matches)) { |
121 | throw new ApiAuthorizationException('Invalid JWT header'); | 127 | throw new ApiAuthorizationException('Invalid JWT header'); |
diff --git a/application/bookmark/LinkUtils.php b/application/bookmark/LinkUtils.php index 68914fca..e7af4d55 100644 --- a/application/bookmark/LinkUtils.php +++ b/application/bookmark/LinkUtils.php | |||
@@ -26,7 +26,7 @@ function html_extract_title($html) | |||
26 | */ | 26 | */ |
27 | function header_extract_charset($header) | 27 | function header_extract_charset($header) |
28 | { | 28 | { |
29 | preg_match('/charset="?([^; ]+)/i', $header, $match); | 29 | preg_match('/charset=["\']?([^; "\']+)/i', $header, $match); |
30 | if (! empty($match[1])) { | 30 | if (! empty($match[1])) { |
31 | return strtolower(trim($match[1])); | 31 | return strtolower(trim($match[1])); |
32 | } | 32 | } |
diff --git a/application/front/controller/admin/ManageShaareController.php b/application/front/controller/admin/ManageShaareController.php index ca2da9b5..59ba2de9 100644 --- a/application/front/controller/admin/ManageShaareController.php +++ b/application/front/controller/admin/ManageShaareController.php | |||
@@ -69,7 +69,7 @@ class ManageShaareController extends ShaarliAdminController | |||
69 | $retrieveDescription | 69 | $retrieveDescription |
70 | ) | 70 | ) |
71 | ); | 71 | ); |
72 | if (! empty($title) && strtolower($charset) !== 'utf-8') { | 72 | if (! empty($title) && strtolower($charset) !== 'utf-8' && mb_check_encoding($charset)) { |
73 | $title = mb_convert_encoding($title, 'utf-8', $charset); | 73 | $title = mb_convert_encoding($title, 'utf-8', $charset); |
74 | } | 74 | } |
75 | } | 75 | } |
@@ -127,7 +127,7 @@ class ManageShaareController extends ShaarliAdminController | |||
127 | $this->checkToken($request); | 127 | $this->checkToken($request); |
128 | 128 | ||
129 | // lf_id should only be present if the link exists. | 129 | // lf_id should only be present if the link exists. |
130 | $id = $request->getParam('lf_id') ? intval(escape($request->getParam('lf_id'))) : null; | 130 | $id = $request->getParam('lf_id') !== null ? intval(escape($request->getParam('lf_id'))) : null; |
131 | if (null !== $id && true === $this->container->bookmarkService->exists($id)) { | 131 | if (null !== $id && true === $this->container->bookmarkService->exists($id)) { |
132 | // Edit | 132 | // Edit |
133 | $bookmark = $this->container->bookmarkService->get($id); | 133 | $bookmark = $this->container->bookmarkService->get($id); |
diff --git a/doc/md/dev/Unit-tests.md b/doc/md/dev/Unit-tests.md index 25af82d7..fd286bf0 100644 --- a/doc/md/dev/Unit-tests.md +++ b/doc/md/dev/Unit-tests.md | |||
@@ -10,21 +10,16 @@ You can either use: | |||
10 | - a local version, downloadable [here](https://getcomposer.org/download/). | 10 | - a local version, downloadable [here](https://getcomposer.org/download/). |
11 | 11 | ||
12 | ```bash | 12 | ```bash |
13 | # system-wide version | 13 | # for Debian-based distros |
14 | $ composer install | 14 | sudo apt install composer |
15 | $ composer update | ||
16 | |||
17 | # local version | ||
18 | $ php composer.phar self-update | ||
19 | $ php composer.phar install | ||
20 | $ php composer.phar update | ||
21 | ``` | 15 | ``` |
22 | 16 | ||
17 | |||
23 | ## Install Shaarli dev dependencies | 18 | ## Install Shaarli dev dependencies |
24 | 19 | ||
25 | ```bash | 20 | ```bash |
26 | $ cd /path/to/shaarli | 21 | $ cd /path/to/shaarli |
27 | $ composer update | 22 | $ make composer_dependencies_dev |
28 | ``` | 23 | ``` |
29 | 24 | ||
30 | ## Install and enable Xdebug to generate PHPUnit coverage reports | 25 | ## Install and enable Xdebug to generate PHPUnit coverage reports |
@@ -34,7 +29,7 @@ $ composer update | |||
34 | 29 | ||
35 | ```bash | 30 | ```bash |
36 | # for Debian-based distros: | 31 | # for Debian-based distros: |
37 | sudo aptitude install php5-xdebug | 32 | sudo apt install php-xdebug |
38 | 33 | ||
39 | # for ArchLinux: | 34 | # for ArchLinux: |
40 | pacman -S xdebug | 35 | pacman -S xdebug |
diff --git a/tests/api/ApiMiddlewareTest.php b/tests/api/ApiMiddlewareTest.php index 7386e435..86700840 100644 --- a/tests/api/ApiMiddlewareTest.php +++ b/tests/api/ApiMiddlewareTest.php | |||
@@ -67,6 +67,53 @@ class ApiMiddlewareTest extends \Shaarli\TestCase | |||
67 | } | 67 | } |
68 | 68 | ||
69 | /** | 69 | /** |
70 | * Invoke the middleware with a valid token | ||
71 | */ | ||
72 | public function testInvokeMiddlewareWithValidToken(): void | ||
73 | { | ||
74 | $next = function (Request $request, Response $response): Response { | ||
75 | return $response; | ||
76 | }; | ||
77 | $mw = new ApiMiddleware($this->container); | ||
78 | $env = Environment::mock([ | ||
79 | 'REQUEST_METHOD' => 'GET', | ||
80 | 'REQUEST_URI' => '/echo', | ||
81 | 'HTTP_AUTHORIZATION'=> 'Bearer ' . ApiUtilsTest::generateValidJwtToken('NapoleonWasALizard'), | ||
82 | ]); | ||
83 | $request = Request::createFromEnvironment($env); | ||
84 | $response = new Response(); | ||
85 | /** @var Response $response */ | ||
86 | $response = $mw($request, $response, $next); | ||
87 | |||
88 | $this->assertEquals(200, $response->getStatusCode()); | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * Invoke the middleware with a valid token | ||
93 | * Using specific Apache CGI redirected authorization. | ||
94 | */ | ||
95 | public function testInvokeMiddlewareWithValidTokenFromRedirectedHeader(): void | ||
96 | { | ||
97 | $next = function (Request $request, Response $response): Response { | ||
98 | return $response; | ||
99 | }; | ||
100 | |||
101 | $token = 'Bearer ' . ApiUtilsTest::generateValidJwtToken('NapoleonWasALizard'); | ||
102 | $this->container->environment['REDIRECT_HTTP_AUTHORIZATION'] = $token; | ||
103 | $mw = new ApiMiddleware($this->container); | ||
104 | $env = Environment::mock([ | ||
105 | 'REQUEST_METHOD' => 'GET', | ||
106 | 'REQUEST_URI' => '/echo', | ||
107 | ]); | ||
108 | $request = Request::createFromEnvironment($env); | ||
109 | $response = new Response(); | ||
110 | /** @var Response $response */ | ||
111 | $response = $mw($request, $response, $next); | ||
112 | |||
113 | $this->assertEquals(200, $response->getStatusCode()); | ||
114 | } | ||
115 | |||
116 | /** | ||
70 | * Invoke the middleware with the API disabled: | 117 | * Invoke the middleware with the API disabled: |
71 | * should return a 401 error Unauthorized. | 118 | * should return a 401 error Unauthorized. |
72 | */ | 119 | */ |
diff --git a/tests/bookmark/LinkUtilsTest.php b/tests/bookmark/LinkUtilsTest.php index a7087953..ef00b92f 100644 --- a/tests/bookmark/LinkUtilsTest.php +++ b/tests/bookmark/LinkUtilsTest.php | |||
@@ -43,6 +43,19 @@ class LinkUtilsTest extends TestCase | |||
43 | } | 43 | } |
44 | 44 | ||
45 | /** | 45 | /** |
46 | * Test headers_extract_charset() when the charset is found with odd quotes. | ||
47 | */ | ||
48 | public function testHeadersExtractExistentCharsetWithQuotes() | ||
49 | { | ||
50 | $charset = 'x-MacCroatian'; | ||
51 | $headers = 'text/html; charset="' . $charset . '"otherstuff="test"'; | ||
52 | $this->assertEquals(strtolower($charset), header_extract_charset($headers)); | ||
53 | |||
54 | $headers = 'text/html; charset=\'' . $charset . '\'otherstuff="test"'; | ||
55 | $this->assertEquals(strtolower($charset), header_extract_charset($headers)); | ||
56 | } | ||
57 | |||
58 | /** | ||
46 | * Test headers_extract_charset() when the charset is not found. | 59 | * Test headers_extract_charset() when the charset is not found. |
47 | */ | 60 | */ |
48 | public function testHeadersExtractNonExistentCharset() | 61 | public function testHeadersExtractNonExistentCharset() |
diff --git a/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php index 3999b44e..f7a68226 100644 --- a/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php +++ b/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php | |||
@@ -241,6 +241,30 @@ class SaveBookmarkTest extends TestCase | |||
241 | } | 241 | } |
242 | 242 | ||
243 | /** | 243 | /** |
244 | * Test save a bookmark - with ID #0 | ||
245 | */ | ||
246 | public function testSaveBookmarkWithIdZero(): void | ||
247 | { | ||
248 | $parameters = ['lf_id' => '0']; | ||
249 | |||
250 | $request = $this->createMock(Request::class); | ||
251 | $request | ||
252 | ->method('getParam') | ||
253 | ->willReturnCallback(function (string $key) use ($parameters): ?string { | ||
254 | return $parameters[$key] ?? null; | ||
255 | }) | ||
256 | ; | ||
257 | $response = new Response(); | ||
258 | |||
259 | $this->container->bookmarkService->expects(static::once())->method('exists')->with(0)->willReturn(true); | ||
260 | $this->container->bookmarkService->expects(static::once())->method('get')->with(0)->willReturn(new Bookmark()); | ||
261 | |||
262 | $result = $this->controller->save($request, $response); | ||
263 | |||
264 | static::assertSame(302, $result->getStatusCode()); | ||
265 | } | ||
266 | |||
267 | /** | ||
244 | * Change the password with a wrong existing password | 268 | * Change the password with a wrong existing password |
245 | */ | 269 | */ |
246 | public function testSaveBookmarkFromBookmarklet(): void | 270 | public function testSaveBookmarkFromBookmarklet(): void |