]> git.immae.eu Git - github/shaarli/Shaarli.git/commitdiff
Merge pull request #1575 from ArthurHoaro/feature/php8
authorArthurHoaro <arthur@hoa.ro>
Sat, 3 Oct 2020 10:59:16 +0000 (12:59 +0200)
committerGitHub <noreply@github.com>
Sat, 3 Oct 2020 10:59:16 +0000 (12:59 +0200)
12 files changed:
.github/mailmap
.htaccess
AUTHORS
CHANGELOG.md
Makefile
application/api/ApiMiddleware.php
application/bookmark/LinkUtils.php
application/front/controller/admin/ManageShaareController.php
doc/md/dev/Unit-tests.md
tests/api/ApiMiddlewareTest.php
tests/bookmark/LinkUtilsTest.php
tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php

index 366946e8c791e281a5be66258436545dfa2d712f..15a25e43cbb562f1f96fb2b6a39e6d234678c39d 100644 (file)
@@ -3,6 +3,7 @@ ArthurHoaro <arthur@hoa.ro> Arthur
 Florian Eula <eula.florian@gmail.com> feula
 Florian Eula <eula.florian@gmail.com> <mr.pikzen@gmail.com>
 Immánuel Fodor <immanuelfactor+github@gmail.com>
+Immánuel Fodor <immanuelfactor+github@gmail.com> Immánuel! <21174107+immanuelfodor@users.noreply.github.com>
 kalvn <kalvnthereal@gmail.com> <kalvn@users.noreply.github.com>
 kalvn <kalvnthereal@gmail.com> <kalvn@pm.me>
 Neros <contact@neros.fr> <NerosTie@users.noreply.github.com>
index af2dc5a7ff24a244d731a5d2382dc496f62d1eda..25fcfb034ee3e1bf1149eafdfccc5b9d27803fe2 100644 (file)
--- a/.htaccess
+++ b/.htaccess
@@ -10,8 +10,12 @@ RewriteRule ^(.git|doxygen|vendor) - [F]
 # fixes JWT token not correctly forwarded on some Apache/FastCGI setups
 RewriteCond %{HTTP:Authorization} ^(.*)
 RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
+# Alternative (if the 2 lines above don't work)
+# SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0
 
 # REST API
+# Ionos Hosting needs RewriteBase /
+# RewriteBase /
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteRule ^ index.php [QSA,L]
diff --git a/AUTHORS b/AUTHORS
index 9c5028ebeb5250387744ada1f546faebd5d0796c..fe2aa88242fded3b5ca87ac70631b4f2440139af 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,22 +1,24 @@
-   903 ArthurHoaro <arthur@hoa.ro>
+   973 ArthurHoaro <arthur@hoa.ro>
    402 VirtualTam <virtualtam@flibidi.net>
-   250 nodiscc <nodiscc@gmail.com>
+   291 nodiscc <nodiscc@gmail.com>
     56 Sébastien Sauvage <sebsauvage@sebsauvage.net>
     16 Luce Carević <lcarevic@access42.net>
     15 Florian Eula <eula.florian@gmail.com>
     13 Emilien Klein <emilien@klein.st>
     12 Nicolas Danelon <hi@nicolasmd.com.ar>
+     9 Lucas Cimon <lucas.cimon@gmail.com>
      9 Willi Eggeling <thewilli@gmail.com>
      8 Christophe HENRY <christophe.henry@sbgodin.fr>
-     7 Lucas Cimon <lucas.cimon@gmail.com>
      6 B. van Berkum <dev@dotmpe.com>
+     6 Immánuel Fodor <immanuelfactor+github@gmail.com>
+     6 Keith Carangelo <mail@kcaran.com>
      6 kalvn <kalvnthereal@gmail.com>
      6 llune <llune@users.noreply.github.com>
      5 Mark Schmitz <kramred@gmail.com>
      5 Sébastien NOBILI <code@pipoprods.org>
+     5 dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
      4 Alexandre Alapetite <alexandre@alapetite.fr>
      4 David Sferruzza <david.sferruzza@gmail.com>
-     4 Immánuel Fodor <immanuelfactor+github@gmail.com>
      3 Agurato <mail.vmonot@gmail.com>
      3 Teromene <teromene@teromene.fr>
      2 Alexandre G.-Raymond <alex@ndre.gr>
@@ -30,7 +32,6 @@
      2 Qwerty <champlywood@free.fr>
      2 Stephen Muth <smuth4@gmail.com>
      2 Timo Van Neerden <fire@lehollandaisvolant.net>
-     2 dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
      2 flow.gunso <flow.gunso@gmail.com>
      2 julienCXX <software@chmodplusx.eu>
      2 philipp-r <philipp-r@users.noreply.github.com>
@@ -75,4 +76,5 @@
      1 dimtion <zizou.xena@gmail.com>
      1 durcheinandr <jochen@durcheinandr.de>
      1 lapineige <lapineige@users.noreply.github.com>
+     1 owen bell <66233223+xfnw@users.noreply.github.com>
      1 rfolo9li <50079896+rfolo9li@users.noreply.github.com>
index 4bae5b487a846243ca282a6f88889bd36829cff8..e2fb480b520fb957a718b2834496f2a485235d33 100644 (file)
@@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](http://keepachangelog.com/)
 and this project adheres to [Semantic Versioning](http://semver.org/).
 
-## [v0.12.0](https://github.com/shaarli/Shaarli/releases/tag/v0.12.0-beta) - UNRELEASED [beta 2020-08-27]
+## [v0.12.0](https://github.com/shaarli/Shaarli/releases/tag/v0.12.0-beta) - UNRELEASED [beta 2020-08-27 - beta-1 2020-09-30]
 
 **Save you `data/` folder before updating!**
 
@@ -16,6 +16,8 @@ Be aware that by using a beta version you might encounter bugs, and that 3rd par
 - Markdown rendering is now integrated into Shaarli core
 - Add autofocus on tag cloud filter input
 - Japanese translations
+- Japanese translation: add language to admin configuration page
+- Support for PHP 8.0
 - Support for local anchor URL (startting with `#`)
 - LDAP authentication
 - Encapsulated PageCacheManager
@@ -24,18 +26,22 @@ Be aware that by using a beta version you might encounter bugs, and that 3rd par
   - section about mkdocs
   - Ulauncher extension
 - CI: run against PHP 7.4
+- Added $links_per_page variable to template and display on default
+- Inject BookmarkServiceInterface in plugins data
+- Add manual configuration for root URL
+- Added PATCH to the allowed Apache request methods.
 
 ### Changed
 - Introduce Bookmark object and Service layer
   - Save bookmark as objects in the datastore
   - Handle bookmark as objects across the whole codebase (except templates and plugins)
 - Process all Shaarli page through Slim controller, with proper URL rewriting (see #1516)
+- Docs: the entire documentation has been reviewed, updated and improved, thanks to @nodiscc!
 - ATOM feed: use instance name as author name instead of URL
 - Updated French translation
-- Docs:
-  - Troubleshooting page rewritten
-  - Updated unit tests page
-  - Updated Server security page
+- Default colors plugin: generate CSS file during initialization
+- Improve default bookmarks after install
+- Upgrade all front end dependencies and webpack build
 
 ### Fixed
 - 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
 - Division by zero in tag cloud
 - CI: deprecated linux distribution and sudo directive
 - Docker build: gcc is no longer included in python alpine image
+- Default template: display pin button in mobile view
+- Pinned bookmarks are not longer displayed first in ATOM/RSS feeds
 - Docs:
   - Outdated Docker documentation for stable branch
   - Outdated links
@@ -63,6 +71,8 @@ Be aware that by using a beta version you might encounter bugs, and that 3rd par
 - Markdown plugin
 - Docs:
   - emojione & twemoji removed
+- Makefile: remove static_analysis_summary from all: target
+- doc/Makefile: remove references to composer update
 
 ## [v0.11.1](https://github.com/shaarli/Shaarli/releases/tag/v0.11.1) - 2019-08-03
 
index 4c9a9c832d8bf428830f2037923f7d34e15431bf..0ff6bd3f7a5ef59ed7900b29a3b093855352b928 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -85,6 +85,10 @@ all_tests: test locale_test_de_DE locale_test_en_US locale_test_fr_FR
        @# --text doesn't work with phpunit 4.* (v5 requires PHP 5.6)
        @#$(BIN)/phpcov merge --text coverage/txt coverage
 
+### download 3rd-party PHP libraries, including dev dependencies
+composer_dependencies_dev: clean
+       composer install --prefer-dist
+
 ##
 # Custom release archive generation
 #
index 09ce6445303bf5f9280e033c6004bf5e56f725c9..f5b53b01fcc5f5f16c5d477d054c9483d2e142d9 100644 (file)
@@ -107,7 +107,9 @@ class ApiMiddleware
      */
     protected function checkToken($request)
     {
-        if (! $request->hasHeader('Authorization')) {
+        if (!$request->hasHeader('Authorization')
+            && !isset($this->container->environment['REDIRECT_HTTP_AUTHORIZATION'])
+        ) {
             throw new ApiAuthorizationException('JWT token not provided');
         }
 
@@ -115,7 +117,11 @@ class ApiMiddleware
             throw new ApiAuthorizationException('Token secret must be set in Shaarli\'s administration');
         }
 
-        $authorization = $request->getHeaderLine('Authorization');
+        if (isset($this->container->environment['REDIRECT_HTTP_AUTHORIZATION'])) {
+            $authorization = $this->container->environment['REDIRECT_HTTP_AUTHORIZATION'];
+        } else {
+            $authorization = $request->getHeaderLine('Authorization');
+        }
 
         if (! preg_match('/^Bearer (.*)/i', $authorization, $matches)) {
             throw new ApiAuthorizationException('Invalid JWT header');
index 68914fcab749a19b1ba15193decd99247158375a..e7af4d552b409b77595985cc635273a6a1d8e448 100644 (file)
@@ -26,7 +26,7 @@ function html_extract_title($html)
  */
 function header_extract_charset($header)
 {
-    preg_match('/charset="?([^; ]+)/i', $header, $match);
+    preg_match('/charset=["\']?([^; "\']+)/i', $header, $match);
     if (! empty($match[1])) {
         return strtolower(trim($match[1]));
     }
index ca2da9b53b7edb4e545ba7b337f04138313ab3f3..59ba2de9547b3abf09ee55f0880d489b35f2c1cf 100644 (file)
@@ -69,7 +69,7 @@ class ManageShaareController extends ShaarliAdminController
                         $retrieveDescription
                     )
                 );
-                if (! empty($title) && strtolower($charset) !== 'utf-8') {
+                if (! empty($title) && strtolower($charset) !== 'utf-8' && mb_check_encoding($charset)) {
                     $title = mb_convert_encoding($title, 'utf-8', $charset);
                 }
             }
@@ -127,7 +127,7 @@ class ManageShaareController extends ShaarliAdminController
         $this->checkToken($request);
 
         // lf_id should only be present if the link exists.
-        $id = $request->getParam('lf_id') ? intval(escape($request->getParam('lf_id'))) : null;
+        $id = $request->getParam('lf_id') !== null ? intval(escape($request->getParam('lf_id'))) : null;
         if (null !== $id && true === $this->container->bookmarkService->exists($id)) {
             // Edit
             $bookmark = $this->container->bookmarkService->get($id);
index 25af82d73096741b3d5be5954b93ced57bb311de..fd286bf0fd4f9df2b19f693a821c4c3c526b2535 100644 (file)
@@ -10,21 +10,16 @@ You can either use:
 - a local version, downloadable [here](https://getcomposer.org/download/).
 
 ```bash
-# system-wide version
-$ composer install
-$ composer update
-
-# local version
-$ php composer.phar self-update
-$ php composer.phar install
-$ php composer.phar update
+# for Debian-based distros
+sudo apt install composer
 ```
 
+
 ## Install Shaarli dev dependencies
 
 ```bash
 $ cd /path/to/shaarli
-$ composer update
+$ make composer_dependencies_dev
 ```
 
 ## Install and enable Xdebug to generate PHPUnit coverage reports
@@ -34,7 +29,7 @@ $ composer update
 
 ```bash
 # for Debian-based distros:
-sudo aptitude install php5-xdebug
+sudo apt install php-xdebug
 
 # for ArchLinux:
 pacman -S xdebug
index 7386e435c2a83f4ab438b4389bbe5202195309e0..86700840b35dfc03ef75e052e0365b4e8ee89e29 100644 (file)
@@ -66,6 +66,53 @@ class ApiMiddlewareTest extends \Shaarli\TestCase
         @unlink(self::$testDatastore);
     }
 
+    /**
+     * Invoke the middleware with a valid token
+     */
+    public function testInvokeMiddlewareWithValidToken(): void
+    {
+        $next = function (Request $request, Response $response): Response {
+            return $response;
+        };
+        $mw = new ApiMiddleware($this->container);
+        $env = Environment::mock([
+            'REQUEST_METHOD' => 'GET',
+            'REQUEST_URI' => '/echo',
+            'HTTP_AUTHORIZATION'=> 'Bearer ' . ApiUtilsTest::generateValidJwtToken('NapoleonWasALizard'),
+        ]);
+        $request = Request::createFromEnvironment($env);
+        $response = new Response();
+        /** @var Response $response */
+        $response = $mw($request, $response, $next);
+
+        $this->assertEquals(200, $response->getStatusCode());
+    }
+
+    /**
+     * Invoke the middleware with a valid token
+     * Using specific Apache CGI redirected authorization.
+     */
+    public function testInvokeMiddlewareWithValidTokenFromRedirectedHeader(): void
+    {
+        $next = function (Request $request, Response $response): Response {
+            return $response;
+        };
+
+        $token = 'Bearer ' . ApiUtilsTest::generateValidJwtToken('NapoleonWasALizard');
+        $this->container->environment['REDIRECT_HTTP_AUTHORIZATION'] = $token;
+        $mw = new ApiMiddleware($this->container);
+        $env = Environment::mock([
+            'REQUEST_METHOD' => 'GET',
+            'REQUEST_URI' => '/echo',
+        ]);
+        $request = Request::createFromEnvironment($env);
+        $response = new Response();
+        /** @var Response $response */
+        $response = $mw($request, $response, $next);
+
+        $this->assertEquals(200, $response->getStatusCode());
+    }
+
     /**
      * Invoke the middleware with the API disabled:
      * should return a 401 error Unauthorized.
index a708795381f21925bae4609656048a979644f2d1..ef00b92f8c3bce554b2dd56e518fa27bb4578a59 100644 (file)
@@ -42,6 +42,19 @@ class LinkUtilsTest extends TestCase
         $this->assertEquals(strtolower($charset), header_extract_charset($headers));
     }
 
+    /**
+     * Test headers_extract_charset() when the charset is found with odd quotes.
+     */
+    public function testHeadersExtractExistentCharsetWithQuotes()
+    {
+        $charset = 'x-MacCroatian';
+        $headers = 'text/html; charset="' . $charset . '"otherstuff="test"';
+        $this->assertEquals(strtolower($charset), header_extract_charset($headers));
+
+        $headers = 'text/html; charset=\'' . $charset . '\'otherstuff="test"';
+        $this->assertEquals(strtolower($charset), header_extract_charset($headers));
+    }
+
     /**
      * Test headers_extract_charset() when the charset is not found.
      */
index 3999b44e5bf546268d979a6a04fbf670560fb25e..f7a68226148e4b9434649b8fb409956745322416 100644 (file)
@@ -240,6 +240,30 @@ class SaveBookmarkTest extends TestCase
         static::assertSame(302, $result->getStatusCode());
     }
 
+    /**
+     * Test save a bookmark - with ID #0
+     */
+    public function testSaveBookmarkWithIdZero(): void
+    {
+        $parameters = ['lf_id' => '0'];
+
+        $request = $this->createMock(Request::class);
+        $request
+            ->method('getParam')
+            ->willReturnCallback(function (string $key) use ($parameters): ?string {
+                return $parameters[$key] ?? null;
+            })
+        ;
+        $response = new Response();
+
+        $this->container->bookmarkService->expects(static::once())->method('exists')->with(0)->willReturn(true);
+        $this->container->bookmarkService->expects(static::once())->method('get')->with(0)->willReturn(new Bookmark());
+
+        $result = $this->controller->save($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+    }
+
     /**
      * Change the password with a wrong existing password
      */