From d3fee4f40b87d18ba8009244e57e2d91c3cd3c6e Mon Sep 17 00:00:00 2001 From: VirtualTam Date: Wed, 23 Aug 2017 01:22:07 +0200 Subject: [PATCH 01/36] documentation: update installation instructions for 0.9.1 Signed-off-by: VirtualTam --- AUTHORS | 6 +++--- README.md | 2 +- doc/md/Download-and-Installation.md | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/AUTHORS b/AUTHORS index 9c0ca3d..2181ec9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,14 +1,14 @@ - 506 ArthurHoaro - 204 VirtualTam + 518 ArthurHoaro + 231 VirtualTam 147 nodiscc 56 Sébastien Sauvage 15 Florian Eula 13 Emilien Klein 12 Nicolas Danelon 8 Christophe HENRY + 5 Lucas Cimon 4 Alexandre Alapetite 4 David Sferruzza - 3 Lucas Cimon 3 Teromene 3 kalvn 2 Chris Kuethe diff --git a/README.md b/README.md index 5ca2572..100ff46 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ _It is designed to be personal (single-user), fast and handy._ [![](https://img.shields.io/badge/stable-v0.8.4-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.8.4) [![](https://img.shields.io/travis/shaarli/Shaarli/stable.svg?label=stable)](https://travis-ci.org/shaarli/Shaarli) • -[![](https://img.shields.io/badge/latest-v0.9.0-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.9.0) +[![](https://img.shields.io/badge/latest-v0.9.1-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.9.1) [![](https://img.shields.io/travis/shaarli/Shaarli/latest.svg?label=latest)](https://travis-ci.org/shaarli/Shaarli) • [![](https://img.shields.io/badge/master-v0.9.x-blue.svg)](https://github.com/shaarli/Shaarli) diff --git a/doc/md/Download-and-Installation.md b/doc/md/Download-and-Installation.md index 135f063..e5e929e 100644 --- a/doc/md/Download-and-Installation.md +++ b/doc/md/Download-and-Installation.md @@ -18,13 +18,13 @@ Get the latest released version from the [releases](https://github.com/shaarli/S **Download our *shaarli-full* archive** to include dependencies. -The current latest released version is `v0.9.0` +The current latest released version is `v0.9.1` Or in command lines: ```bash -$ wget https://github.com/shaarli/Shaarli/releases/download/v0.9.0/shaarli-v0.9.0-full.zip -$ unzip shaarli-v0.9.0-full.zip +$ wget https://github.com/shaarli/Shaarli/releases/download/v0.9.1/shaarli-v0.9.1-full.zip +$ unzip shaarli-v0.9.1-full.zip $ mv Shaarli /path/to/shaarli/ ``` From 958fc15fecfe353a2cb2cf1cb4c7d10591ab74f9 Mon Sep 17 00:00:00 2001 From: Willi Eggeling Date: Thu, 24 Aug 2017 10:20:32 +0200 Subject: [PATCH 02/36] fixed note bookmarklet - the double quotes used in the alert() call of the note bookmarklet in the default template collided with the ones of the href tag - replaced the double quotes with single ones (just like the link bookmarklet) --- tpl/default/tools.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tpl/default/tools.html b/tpl/default/tools.html index 35173d1..72fd58a 100644 --- a/tpl/default/tools.html +++ b/tpl/default/tools.html @@ -97,7 +97,7 @@ var%20desc=document.getSelection().toString(); if(desc.length>4000){ desc=desc.substr(0,4000)+'...'; - alert("{function="str_replace(' ', '%20', t('The selected text is too long, it will be truncated.'))"}"); + alert('{function="str_replace(' ', '%20', t('The selected text is too long, it will be truncated.'))"}'); } window.open( '{$pageabsaddr}?private=1&post='+ From f32ec5fb3c2139546caec5d26bff3eb5b7d37255 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Fri, 25 Aug 2017 19:25:00 +0200 Subject: [PATCH 03/36] Sort tag cloud in alphabetical order Fixes #932 --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index b4c4347..76526bd 100644 --- a/index.php +++ b/index.php @@ -803,7 +803,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) $maxcount = max($maxcount, $value); } - alphabetical_sort($tags, true, true); + alphabetical_sort($tags, false, true); $tagList = array(); foreach($tags as $key => $value) { From c27f2f36f228240d50b55d36fe97f0ba7833bc77 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Fri, 25 Aug 2017 20:08:07 +0200 Subject: [PATCH 04/36] Generates a permalinks URL if the URL is set to blank Fixes #926 --- index.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.php b/index.php index b4c4347..23c8d47 100644 --- a/index.php +++ b/index.php @@ -1256,6 +1256,9 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) // Remove duplicates. $tags = implode(' ', array_unique(explode(' ', $tags))); + if (empty(trim($_POST['lf_url']))) { + $_POST['lf_url'] = '?' . smallHash($linkdate . $id); + } $url = whitelist_protocols(trim($_POST['lf_url']), $conf->get('security.allowed_protocols')); $link = array( From cc8f572bc063aa1e9d0368c8a8361f15efe04c9b Mon Sep 17 00:00:00 2001 From: Willi Eggeling Date: Sat, 26 Aug 2017 09:40:57 +0200 Subject: [PATCH 05/36] migrated Github wiki links to readthedocs --- CHANGELOG.md | 2 +- CONTRIBUTING.md | 2 +- application/LinkDB.php | 2 +- application/config/ConfigManager.php | 4 ++-- composer.json | 2 +- doc/md/Plugin-System.md | 4 ++-- doc/md/Plugins.md | 2 +- doc/md/index.md | 2 +- index.php | 6 +++--- plugins/playvideos/README.md | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b018cb..60262d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,7 +61,7 @@ The documentation has been migrated to ReadTheDocs: This release introduces the REST API, and requires updating HTTP server configuration to enable URL rewriting, see: - https://shaarli.github.io/api-documentation/ -- https://github.com/shaarli/Shaarli/wiki/Server-configuration +- https://shaarli.readthedocs.io/en/master/Server-configuration/ **WARNING**: Shaarli now requires PHP 5.5+. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bb82951..03564fd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -54,7 +54,7 @@ Please report any problem you might find. * starting from branch ` master`, switch to a new branch (eg. `git checkout -b my-awesome-feature`) * edit the required files (from the Github web interface or your text editor) * add and commit your changes with a meaningful commit message (eg `Cool new feature, fixes issue #1001`) - * run unit tests against your patched version, see [Running unit tests](https://github.com/shaarli/Shaarli/wiki/Running-unit-tests) + * run unit tests against your patched version, see [Running unit tests](https://shaarli.readthedocs.io/en/master/Unit-tests/#run-unit-tests) * Open your fork in the Github web interface and click the "Compare and Pull Request" button, enter required info and submit your Pull Request. All changes you will do on the `my-awesome-feature` in the future will be added to your Pull Request. Don't work directly on the master branch, don't do unrelated work on your `my-awesome-feature` branch. diff --git a/application/LinkDB.php b/application/LinkDB.php index 9308164..22c1f0a 100644 --- a/application/LinkDB.php +++ b/application/LinkDB.php @@ -249,7 +249,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess $link = array( 'id' => 1, 'title'=>' Shaarli: the personal, minimalist, super-fast, no-database delicious clone', - 'url'=>'https://github.com/shaarli/Shaarli/wiki', + 'url'=>'https://shaarli.readthedocs.io', 'description'=>'Welcome to Shaarli! This is your first public bookmark. To edit or delete me, you must first login. To learn how to use Shaarli, consult the link "Help/documentation" at the bottom of this page. diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php index 8eab26f..0fc5a5c 100644 --- a/application/config/ConfigManager.php +++ b/application/config/ConfigManager.php @@ -9,8 +9,8 @@ use Shaarli\Config\Exception\UnauthorizedConfigException; * * Manages all Shaarli's settings. * See the documentation for more information on settings: - * - doc/Shaarli-configuration.html - * - https://github.com/shaarli/Shaarli/wiki/Shaarli-configuration + * - doc/md/Shaarli-configuration.md + * - https://shaarli.readthedocs.io/en/master/Shaarli-configuration/#configuration */ class ConfigManager { diff --git a/composer.json b/composer.json index 756ea58..afb8aca 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "homepage": "https://github.com/shaarli/Shaarli", "support": { "issues": "https://github.com/shaarli/Shaarli/issues", - "wiki": "https://github.com/shaarli/Shaarli/wiki" + "wiki": "https://shaarli.readthedocs.io" }, "keywords": ["bookmark", "link", "share", "web"], "config": { diff --git a/doc/md/Plugin-System.md b/doc/md/Plugin-System.md index 30f0ae7..cbec04c 100644 --- a/doc/md/Plugin-System.md +++ b/doc/md/Plugin-System.md @@ -49,10 +49,10 @@ hook__($data, $conf) Parameters: -- data: see [$data section](https://github.com/shaarli/Shaarli/wiki/Plugin-System#plugins-data) +- data: see [$data section](https://shaarli.readthedocs.io/en/master/Plugin-System/#plugins-data) - conf: the `ConfigManager` instance. -For exemple, if my plugin want to add data to the header, this function is needed: +For example, if my plugin want to add data to the header, this function is needed: hook_demo_plugin_render_header diff --git a/doc/md/Plugins.md b/doc/md/Plugins.md index 7d40637..463dae1 100644 --- a/doc/md/Plugins.md +++ b/doc/md/Plugins.md @@ -72,4 +72,4 @@ Usage of each plugin is documented in it's README file: #### Third party plugins -See [Community & related software](https://github.com/shaarli/Shaarli/wiki/Community-%26-Related-software#third-party-plugins) +See [Community & related software](https://shaarli.readthedocs.io/en/master/Community-&-Related-software/) diff --git a/doc/md/index.md b/doc/md/index.md index b10e3cf..24ada6c 100644 --- a/doc/md/index.md +++ b/doc/md/index.md @@ -37,7 +37,7 @@ Login: `demo`; Password: `demo` - daily RSS feed - permalinks for easy reference - links can be public or private -- extensible through [plugins](https://github.com/shaarli/Shaarli/wiki/Plugins#plugin-usage) +- extensible through [plugins](https://shaarli.readthedocs.io/en/master/Plugins/#plugin-usage) ### Tag, view and search your links! - add a custom title and description to archived links diff --git a/index.php b/index.php index 76526bd..42ce1d7 100644 --- a/index.php +++ b/index.php @@ -48,8 +48,8 @@ if (! file_exists(__DIR__ . '/vendor/autoload.php')) { ."If you installed Shaarli through Git or using the development branch,\n" ."please refer to the installation documentation to install PHP" ." dependencies using Composer:\n" - ."- https://github.com/shaarli/Shaarli/wiki/Server-requirements\n" - ."- https://github.com/shaarli/Shaarli/wiki/Download-and-Installation"; + ."- https://shaarli.readthedocs.io/en/master/Server-requirements/\n" + ."- https://shaarli.readthedocs.io/en/master/Download-and-Installation/"; exit; } require_once 'inc/rain.tpl.class.php'; @@ -1233,7 +1233,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) // Linkdate is kept here to: // - use the same permalink for notes as they're displayed when creating them // - let users hack creation date of their posts - // See: https://github.com/shaarli/Shaarli/wiki/Datastore-hacks#changing-the-timestamp-for-a-link + // See: https://shaarli.readthedocs.io/en/master/Various-hacks/#changing-the-timestamp-for-a-shaare $linkdate = escape($_POST['lf_linkdate']); if (isset($LINKSDB[$id])) { // Edit diff --git a/plugins/playvideos/README.md b/plugins/playvideos/README.md index b169847..ab4be22 100644 --- a/plugins/playvideos/README.md +++ b/plugins/playvideos/README.md @@ -8,7 +8,7 @@ This uses code from https://zaius.github.io/youtube_playlist/ and is currently o #### Installation and setup -This is a default Shaarli plugin, you just have to enable it. See https://github.com/shaarli/Shaarli/wiki/Shaarli-configuration/ +This is a default Shaarli plugin, you just have to enable it. See https://shaarli.readthedocs.io/en/master/Shaarli-configuration/ #### Troubleshooting From 94c035ff717c4c836bb76109b013ffaa78f64ef1 Mon Sep 17 00:00:00 2001 From: Willi Eggeling Date: Sat, 26 Aug 2017 11:27:18 +0200 Subject: [PATCH 06/36] removed doc and code references to magic quotes - removed all references to magic quotes - magic quotes are not supported on PHP >= 5.4 (https://secure.php.net/manual/en/security.magicquotes.php) - Shaarli does not support PHP < 5.5 --- doc/md/Security.md | 3 --- index.php | 9 --------- 2 files changed, 12 deletions(-) diff --git a/doc/md/Security.md b/doc/md/Security.md index 36f629a..65db422 100644 --- a/doc/md/Security.md +++ b/doc/md/Security.md @@ -1,9 +1,6 @@ ## Client browser - Shaarli relies on `HTTP_REFERER` for some functions (like redirects and clicking on tags). If you have disabled or masqueraded `HTTP_REFERER` in your browser, some features of Shaarli may not work -## PHP -- `magic_quotes` is an horrible option of PHP which is often activated on servers. No serious developer should rely on this horror to secure their code against SQL injections. You should disable it (and Shaarli expects this option to be disabled). Nevertheless, I have added code to cope with `magic_quotes` on, so you should not be bothered even on crappy hosts. - ## Server and sessions - Directories are protected using `.htaccess` files - Forms are protected against XSRF (Cross-site requests forgery): diff --git a/index.php b/index.php index 76526bd..b1d0c99 100644 --- a/index.php +++ b/index.php @@ -133,15 +133,6 @@ date_default_timezone_set($conf->get('general.timezone', 'UTC')); ob_start(); // Output buffering for the page cache. -// In case stupid admin has left magic_quotes enabled in php.ini: -if (get_magic_quotes_gpc()) -{ - function stripslashes_deep($value) { $value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value); return $value; } - $_POST = array_map('stripslashes_deep', $_POST); - $_GET = array_map('stripslashes_deep', $_GET); - $_COOKIE = array_map('stripslashes_deep', $_COOKIE); -} - // Prevent caching on client side or proxy: (yes, it's ugly) header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); From a544b113f203d3359db51cf886f5aab98605624c Mon Sep 17 00:00:00 2001 From: Willi Eggeling Date: Sat, 26 Aug 2017 12:20:38 +0200 Subject: [PATCH 07/36] code clean: cookie expiration - unified code style (spaces around operators) - prevented expiration time to be calculated twice - replaced tabs with spaces --- index.php | 83 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/index.php b/index.php index b1d0c99..1ed1ef2 100644 --- a/index.php +++ b/index.php @@ -177,42 +177,42 @@ if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { */ function setup_login_state($conf) { - if ($conf->get('security.open_shaarli')) { - return true; - } - $userIsLoggedIn = false; // By default, we do not consider the user as logged in; - $loginFailure = false; // If set to true, every attempt to authenticate the user will fail. This indicates that an important condition isn't met. - if (! $conf->exists('credentials.login')) { - $userIsLoggedIn = false; // Shaarli is not configured yet. - $loginFailure = true; - } - if (isset($_COOKIE['shaarli_staySignedIn']) && - $_COOKIE['shaarli_staySignedIn']===STAY_SIGNED_IN_TOKEN && - !$loginFailure) - { - fillSessionInfo($conf); - $userIsLoggedIn = true; - } - // If session does not exist on server side, or IP address has changed, or session has expired, logout. - if (empty($_SESSION['uid']) + if ($conf->get('security.open_shaarli')) { + return true; + } + $userIsLoggedIn = false; // By default, we do not consider the user as logged in; + $loginFailure = false; // If set to true, every attempt to authenticate the user will fail. This indicates that an important condition isn't met. + if (! $conf->exists('credentials.login')) { + $userIsLoggedIn = false; // Shaarli is not configured yet. + $loginFailure = true; + } + if (isset($_COOKIE['shaarli_staySignedIn']) && + $_COOKIE['shaarli_staySignedIn']===STAY_SIGNED_IN_TOKEN && + !$loginFailure) + { + fillSessionInfo($conf); + $userIsLoggedIn = true; + } + // If session does not exist on server side, or IP address has changed, or session has expired, logout. + if (empty($_SESSION['uid']) || ($conf->get('security.session_protection_disabled') === false && $_SESSION['ip'] != allIPs()) || time() >= $_SESSION['expires_on']) - { - logout(); - $userIsLoggedIn = false; - $loginFailure = true; - } - if (!empty($_SESSION['longlastingsession'])) { - $_SESSION['expires_on']=time()+$_SESSION['longlastingsession']; // In case of "Stay signed in" checked. - } - else { - $_SESSION['expires_on']=time()+INACTIVITY_TIMEOUT; // Standard session expiration date. - } - if (!$loginFailure) { - $userIsLoggedIn = true; - } + { + logout(); + $userIsLoggedIn = false; + $loginFailure = true; + } + if (!empty($_SESSION['longlastingsession'])) { + $_SESSION['expires_on']=time()+$_SESSION['longlastingsession']; // In case of "Stay signed in" checked. + } + else { + $_SESSION['expires_on']=time()+INACTIVITY_TIMEOUT; // Standard session expiration date. + } + if (!$loginFailure) { + $userIsLoggedIn = true; + } - return $userIsLoggedIn; + return $userIsLoggedIn; } $userIsLoggedIn = setup_login_state($conf); @@ -236,10 +236,10 @@ function allIPs() */ function fillSessionInfo($conf) { - $_SESSION['uid'] = sha1(uniqid('',true).'_'.mt_rand()); // Generate unique random number (different than phpsessionid) - $_SESSION['ip']=allIPs(); // We store IP address(es) of the client to make sure session is not hijacked. - $_SESSION['username']= $conf->get('credentials.login'); - $_SESSION['expires_on']=time()+INACTIVITY_TIMEOUT; // Set session expiration. + $_SESSION['uid'] = sha1(uniqid('',true).'_'.mt_rand()); // Generate unique random number (different than phpsessionid) + $_SESSION['ip']=allIPs(); // We store IP address(es) of the client to make sure session is not hijacked. + $_SESSION['username']= $conf->get('credentials.login'); + $_SESSION['expires_on']=time()+INACTIVITY_TIMEOUT; // Set session expiration. } /** @@ -256,7 +256,7 @@ function check_auth($login, $password, $conf) $hash = sha1($password . $login . $conf->get('credentials.salt')); if ($login == $conf->get('credentials.login') && $hash == $conf->get('credentials.hash')) { // Login/password is correct. - fillSessionInfo($conf); + fillSessionInfo($conf); logm($conf->get('resource.log'), $_SERVER['REMOTE_ADDR'], 'Login successful'); return true; } @@ -385,9 +385,10 @@ if (isset($_POST['login'])) // If user wants to keep the session cookie even after the browser closes: if (!empty($_POST['longlastingsession'])) { - setcookie('shaarli_staySignedIn', STAY_SIGNED_IN_TOKEN, time()+31536000, WEB_PATH); - $_SESSION['longlastingsession']=31536000; // (31536000 seconds = 1 year) - $_SESSION['expires_on']=time()+$_SESSION['longlastingsession']; // Set session expiration on server-side. + $_SESSION['longlastingsession'] = 31536000; // (31536000 seconds = 1 year) + $expiration = time() + $_SESSION['longlastingsession']; // calculate relative cookie expiration (1 year from now) + setcookie('shaarli_staySignedIn', STAY_SIGNED_IN_TOKEN, $expiration, WEB_PATH); + $_SESSION['expires_on'] = $expiration; // Set session expiration on server-side. $cookiedir = ''; if(dirname($_SERVER['SCRIPT_NAME'])!='/') $cookiedir=dirname($_SERVER["SCRIPT_NAME"]).'/'; session_set_cookie_params($_SESSION['longlastingsession'],$cookiedir,$_SERVER['SERVER_NAME']); // Set session cookie expiration on client side From 2e07e77573a379f9af006b2c523117eef9fdf9b2 Mon Sep 17 00:00:00 2001 From: Willi Eggeling Date: Sat, 26 Aug 2017 09:27:10 +0200 Subject: [PATCH 08/36] new setting: default value for 'remember me' checkbox - the default state for the login page's 'remember me' checkbox can now be configured - adapted the default and vintage theme to consider the new setting - added documentation for the new setting --- application/config/ConfigManager.php | 2 ++ doc/md/Shaarli-configuration.md | 5 ++++- index.php | 2 ++ tpl/default/loginform.html | 3 ++- tpl/vintage/loginform.html | 4 +++- 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php index 8eab26f..c94d92a 100644 --- a/application/config/ConfigManager.php +++ b/application/config/ConfigManager.php @@ -328,6 +328,8 @@ class ConfigManager $this->setEmpty('privacy.default_private_links', false); $this->setEmpty('privacy.hide_public_links', false); $this->setEmpty('privacy.hide_timestamps', false); + // default state of the 'remember me' checkbox of the login form + $this->setEmpty('privacy.remember_user_default', true); $this->setEmpty('thumbnail.enable_thumbnails', true); $this->setEmpty('thumbnail.enable_localcache', true); diff --git a/doc/md/Shaarli-configuration.md b/doc/md/Shaarli-configuration.md index 188a3c0..d90e95e 100644 --- a/doc/md/Shaarli-configuration.md +++ b/doc/md/Shaarli-configuration.md @@ -91,6 +91,8 @@ _These settings should not be edited_ - **default_private_links**: Check the private checkbox by default for every new link. - **hide_public_links**: All links are hidden while logged out. - **hide_timestamps**: Timestamps are hidden. +- **remember_user_default**: Default state of the login page's *remember me* checkbox + - `true`: checked by default, `false`: unchecked by default ### Feed @@ -192,7 +194,8 @@ _These settings should not be edited_ "privacy": { "default_private_links": true, "hide_public_links": false, - "hide_timestamps": false + "hide_timestamps": false, + "remember_user_default": true }, "thumbnail": { "enable_thumbnails": true, diff --git a/index.php b/index.php index 76526bd..f2f3b93 100644 --- a/index.php +++ b/index.php @@ -745,6 +745,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) $PAGE->assign('username', escape($_GET['username'])); } $PAGE->assign('returnurl',(isset($_SERVER['HTTP_REFERER']) ? escape($_SERVER['HTTP_REFERER']):'')); + // add default state of the 'remember me' checkbox + $PAGE->assign('remember_user_default', $conf->get('privacy.remember_user_default')); $PAGE->renderPage('loginform'); exit; } diff --git a/tpl/default/loginform.html b/tpl/default/loginform.html index eb6d837..5777a21 100644 --- a/tpl/default/loginform.html +++ b/tpl/default/loginform.html @@ -30,7 +30,8 @@
+ {if="$remember_user_default"}checked="checked"{/if} + tabindex="22">
diff --git a/tpl/vintage/loginform.html b/tpl/vintage/loginform.html index 8417638..1becd44 100644 --- a/tpl/vintage/loginform.html +++ b/tpl/vintage/loginform.html @@ -24,7 +24,9 @@ {if="$returnurl"}{/if} From dc37a482edd7d164de4a0f5458de4c7f65ebc763 Mon Sep 17 00:00:00 2001 From: VirtualTam Date: Tue, 29 Aug 2017 19:46:23 +0200 Subject: [PATCH 09/36] Documentation+Makefile: update AUTHORS generation Fixes https://github.com/shaarli/Shaarli/issues/935 Signed-off-by: VirtualTam --- Makefile | 14 ++++---------- doc/md/Release-Shaarli.md | 6 ++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 6483fca..40badb1 100644 --- a/Makefile +++ b/Makefile @@ -159,14 +159,14 @@ composer_dependencies: clean find vendor/ -name ".git" -type d -exec rm -rf {} + ### generate a release tarball and include 3rd-party dependencies -release_tar: composer_dependencies doc_html +release_tar: composer_dependencies htmldoc git archive --prefix=$(ARCHIVE_PREFIX) -o $(ARCHIVE_VERSION).tar HEAD tar rvf $(ARCHIVE_VERSION).tar --transform "s|^vendor|$(ARCHIVE_PREFIX)vendor|" vendor/ tar rvf $(ARCHIVE_VERSION).tar --transform "s|^doc/html|$(ARCHIVE_PREFIX)doc/html|" doc/html/ gzip $(ARCHIVE_VERSION).tar ### generate a release zip and include 3rd-party dependencies -release_zip: composer_dependencies doc_html +release_zip: composer_dependencies htmldoc git archive --prefix=$(ARCHIVE_PREFIX) -o $(ARCHIVE_VERSION).zip -9 HEAD mkdir -p $(ARCHIVE_PREFIX)/{doc,vendor} rsync -a doc/html/ $(ARCHIVE_PREFIX)doc/html/ @@ -195,17 +195,11 @@ doxygen: clean @rm -rf doxygen @( cat Doxyfile ; echo "PROJECT_NUMBER=`git describe`" ) | doxygen - -### Convert local markdown documentation to HTML -# -# For all pages: -# - convert GitHub-flavoured relative links to standard Markdown -# - generate html documentation with mkdocs -htmlpages: +### generate HTML documentation from Markdown pages with MkDocs +htmldoc: python3 -m venv venv/ bash -c 'source venv/bin/activate; \ pip install mkdocs; \ mkdocs build' find doc/html/ -type f -exec chmod a-x '{}' \; rm -r venv - -doc_html: authors htmlpages diff --git a/doc/md/Release-Shaarli.md b/doc/md/Release-Shaarli.md index 974a743..e22eabc 100644 --- a/doc/md/Release-Shaarli.md +++ b/doc/md/Release-Shaarli.md @@ -46,6 +46,12 @@ TBA ## Increment the version code, update docs, create and push a signed tag +### Update the list of Git contributors +```bash +$ make authors +$ git commit -s -m "Update AUTHORS" +``` + ### Create and merge a Pull Request This one is pretty straightforward ;-) From 5a0045be79644078150957a65bc2c6aa9a6871b0 Mon Sep 17 00:00:00 2001 From: Willi Eggeling Date: Sun, 27 Aug 2017 19:36:48 +0200 Subject: [PATCH 10/36] fixed daily links if there are no links - the previous code tried to use links from a previous day if there are no one for the current one - the new code skips this part if there are no entries (i.e. days) at all - modified showDaily() to fit PSR-1 and PSR-2 --- index.php | 58 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/index.php b/index.php index 7df6d81..b36ce9f 100644 --- a/index.php +++ b/index.php @@ -583,20 +583,29 @@ function showDailyRSS($conf) { */ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager) { - $day=date('Ymd',strtotime('-1 day')); // Yesterday, in format YYYYMMDD. - if (isset($_GET['day'])) $day=$_GET['day']; - - $days = $LINKSDB->days(); - $i = array_search($day,$days); - if ($i===false) { $i=count($days)-1; $day=$days[$i]; } - $previousday=''; - $nextday=''; - if ($i!==false) - { - if ($i>=1) $previousday=$days[$i-1]; - if ($idays(); + $i = array_search($day, $days); + if ($i === false && count($days)) { + // no links for day, but at least one day with links + $i = count($days) - 1; + $day = $days[$i]; + } + $previousday = ''; + $nextday = ''; + + if ($i !== false) { + if ($i >= 1) { + $previousday=$days[$i - 1]; + } + if ($i < count($days) - 1) { + $nextday = $days[$i + 1]; + } + } try { $linksToDisplay = $LINKSDB->filterDay($day); } catch (Exception $exc) { @@ -605,9 +614,7 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager) } // We pre-format some fields for proper output. - foreach($linksToDisplay as $key=>$link) - { - + foreach($linksToDisplay as $key => $link) { $taglist = explode(' ',$link['tags']); uasort($taglist, 'strcasecmp'); $linksToDisplay[$key]['taglist']=$taglist; @@ -621,21 +628,22 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager) so I manually spread entries with a simple method: I roughly evaluate the height of a div according to title and description length. */ - $columns=array(array(),array(),array()); // Entries to display, for each column. - $fill=array(0,0,0); // Rough estimate of columns fill. - foreach($linksToDisplay as $key=>$link) - { + $columns = array(array(), array(), array()); // Entries to display, for each column. + $fill = array(0, 0, 0); // Rough estimate of columns fill. + foreach($linksToDisplay as $key => $link) { // Roughly estimate length of entry (by counting characters) // Title: 30 chars = 1 line. 1 line is 30 pixels height. // Description: 836 characters gives roughly 342 pixel height. // This is not perfect, but it's usually OK. - $length=strlen($link['title'])+(342*strlen($link['description']))/836; - if ($link['thumbnail']) $length +=100; // 1 thumbnails roughly takes 100 pixels height. + $length = strlen($link['title']) + (342 * strlen($link['description'])) / 836; + if ($link['thumbnail']) { + $length += 100; // 1 thumbnails roughly takes 100 pixels height. + } // Then put in column which is the less filled: - $smallest=min($fill); // find smallest value in array. - $index=array_search($smallest,$fill); // find index of this smallest value. - array_push($columns[$index],$link); // Put entry in this column. - $fill[$index]+=$length; + $smallest = min($fill); // find smallest value in array. + $index = array_search($smallest, $fill); // find index of this smallest value. + array_push($columns[$index], $link); // Put entry in this column. + $fill[$index] += $length; } $dayDate = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $day.'_000000'); From a74f52a8d206a6d5c3fe27667f1633bf2fc1374d Mon Sep 17 00:00:00 2001 From: Willi Eggeling Date: Sun, 27 Aug 2017 19:19:59 +0200 Subject: [PATCH 11/36] fixed link deletion When deleting links, the js of the default theme separated ids by an escaped space ('+'). There was a trailing '+' after the ids which led to the php code detecting multiple values even for single values. In combination with the id '0' this could led to no id found at all and a resulting php error. this commit fixes the behavior and adds an additional error handling and trimming to the php code. --- index.php | 13 ++++++++++--- tpl/default/js/shaarli.js | 6 +++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/index.php b/index.php index 7df6d81..b2f4ded 100644 --- a/index.php +++ b/index.php @@ -1320,10 +1320,17 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) die('Wrong token.'); } - if (strpos($_GET['lf_linkdate'], ' ') !== false) { - $ids = array_values(array_filter(preg_split('/\s+/', escape($_GET['lf_linkdate'])))); + $ids = trim($_GET['lf_linkdate']); + if (strpos($ids, ' ') !== false) { + // multiple, space-separated ids provided + $ids = array_values(array_filter(preg_split('/\s+/', escape($ids)))); } else { - $ids = [$_GET['lf_linkdate']]; + // only a single id provided + $ids = [$ids]; + } + // assert at least one id is given + if(!count($ids)){ + die('no id provided'); } foreach ($ids as $id) { $id = (int) escape($id); diff --git a/tpl/default/js/shaarli.js b/tpl/default/js/shaarli.js index 4f49aff..f38ba62 100644 --- a/tpl/default/js/shaarli.js +++ b/tpl/default/js/shaarli.js @@ -401,14 +401,14 @@ window.onload = function () { var message = 'Are you sure you want to delete '+ links.length +' links?\n'; message += 'This action is IRREVERSIBLE!\n\nTitles:\n'; - var ids = ''; + var ids = []; links.forEach(function(item) { message += ' - '+ item['title'] +'\n'; - ids += item['id'] +'+'; + ids.push(item['id']); }); if (window.confirm(message)) { - window.location = '?delete_link&lf_linkdate='+ ids +'&token='+ token.value; + window.location = '?delete_link&lf_linkdate='+ ids.join('+') +'&token='+ token.value; } }); } From 341527bae96e0d1c6a0cb5dfc790eacb3ef58bf8 Mon Sep 17 00:00:00 2001 From: Willi Eggeling Date: Sat, 26 Aug 2017 23:05:02 +0200 Subject: [PATCH 12/36] wildcard tag search support - when searching for tags you can now include '*' as wildcard placeholder - new search reduces overall overhead when filtering for tags - fixed combination with description tag search ('#' prefix) - tests added --- application/LinkFilter.php | 131 ++++++++++++++++--------- tests/api/controllers/GetLinksTest.php | 83 ++++++++++++++++ 2 files changed, 167 insertions(+), 47 deletions(-) diff --git a/application/LinkFilter.php b/application/LinkFilter.php index 9551952..99ecd1e 100644 --- a/application/LinkFilter.php +++ b/application/LinkFilter.php @@ -249,6 +249,51 @@ class LinkFilter return $filtered; } + /** + * generate a regex fragment out of a tag + * @param string $tag to to generate regexs from. may start with '-' to negate, contain '*' as wildcard + * @return string generated regex fragment + */ + private static function tag2regex($tag) + { + $len = strlen($tag); + if(!$len || $tag === "-" || $tag === "*"){ + // nothing to search, return empty regex + return ''; + } + if($tag[0] === "-") { + // query is negated + $i = 1; // use offset to start after '-' character + $regex = '(?!'; // create negative lookahead + } else { + $i = 0; // start at first character + $regex = '(?='; // use positive lookahead + } + $regex .= '.*(?:^| )'; // before tag may only be a space or the beginning + // iterate over string, separating it into placeholder and content + for(; $i < $len; $i++){ + if($tag[$i] === '*'){ + // placeholder found + $regex .= '[^ ]*?'; + } else { + // regular characters + $offset = strpos($tag, '*', $i); + if($offset === false){ + // no placeholder found, set offset to end of string + $offset = $len; + } + // subtract one, as we want to get before the placeholder or end of string + $offset -= 1; + // we got a tag name that we want to search for. escape any regex characters to prevent conflicts. + $regex .= preg_quote(substr($tag, $i, $offset - $i + 1), '/'); + // move $i on + $i = $offset; + } + } + $regex .= '(?:$| ))'; // after the tag may only be a space or the end + return $regex; + } + /** * Returns the list of links associated with a given list of tags * @@ -263,20 +308,32 @@ class LinkFilter */ public function filterTags($tags, $casesensitive = false, $visibility = 'all') { - // Implode if array for clean up. - $tags = is_array($tags) ? trim(implode(' ', $tags)) : $tags; - if (empty($tags)) { + // get single tags (we may get passed an array, even though the docs say different) + $inputTags = $tags; + if(!is_array($tags)) { + // we got an input string, split tags + $inputTags = preg_split('/(?:\s+)|,/', $inputTags, -1, PREG_SPLIT_NO_EMPTY); + } + + if(!count($inputTags)){ + // no input tags return $this->noFilter($visibility); } - $searchtags = self::tagsStrToArray($tags, $casesensitive); - $filtered = array(); - if (empty($searchtags)) { - return $filtered; + // build regex from all tags + $re = '/^' . implode(array_map("self::tag2regex", $inputTags)) . '.*$/'; + if(!$casesensitive) { + // make regex case insensitive + $re .= 'i'; } + // create resulting array + $filtered = array(); + + // iterate over each link foreach ($this->links as $key => $link) { - // ignore non private links when 'privatonly' is on. + // check level of visibility + // ignore non private links when 'privateonly' is on. if ($visibility !== 'all') { if (! $link['private'] && $visibility === 'private') { continue; @@ -284,25 +341,27 @@ class LinkFilter continue; } } - - $linktags = self::tagsStrToArray($link['tags'], $casesensitive); - - $found = true; - for ($i = 0 ; $i < count($searchtags) && $found; $i++) { - // Exclusive search, quit if tag found. - // Or, tag not found in the link, quit. - if (($searchtags[$i][0] == '-' - && $this->searchTagAndHashTag(substr($searchtags[$i], 1), $linktags, $link['description'])) - || ($searchtags[$i][0] != '-') - && ! $this->searchTagAndHashTag($searchtags[$i], $linktags, $link['description']) - ) { - $found = false; + $search = $link['tags']; // build search string, start with tags of current link + if(strlen(trim($link['description'])) && strpos($link['description'], '#') !== false){ + // description given and at least one possible tag found + $descTags = array(); + // find all tags in the form of #tag in the description + preg_match_all( + '/(? 0) { - return true; - } - - return false; - } - /** * Convert a list of tags (str) to an array. Also * - handle case sensitivity. diff --git a/tests/api/controllers/GetLinksTest.php b/tests/api/controllers/GetLinksTest.php index 4cb7022..d22ed3b 100644 --- a/tests/api/controllers/GetLinksTest.php +++ b/tests/api/controllers/GetLinksTest.php @@ -367,6 +367,89 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase $this->assertEquals(1, count($data)); $this->assertEquals(41, $data[0]['id']); $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); + + // wildcard: placeholder at the start + $env = Environment::mock([ + 'REQUEST_METHOD' => 'GET', + 'QUERY_STRING' => 'searchtags=*Tuff', + ]); + $request = Request::createFromEnvironment($env); + $response = $this->controller->getLinks($request, new Response()); + $this->assertEquals(200, $response->getStatusCode()); + $data = json_decode((string) $response->getBody(), true); + $this->assertEquals(2, count($data)); + $this->assertEquals(41, $data[0]['id']); + + // wildcard: placeholder at the end + $env = Environment::mock([ + 'REQUEST_METHOD' => 'GET', + 'QUERY_STRING' => 'searchtags=c*', + ]); + $request = Request::createFromEnvironment($env); + $response = $this->controller->getLinks($request, new Response()); + $this->assertEquals(200, $response->getStatusCode()); + $data = json_decode((string) $response->getBody(), true); + $this->assertEquals(4, count($data)); + $this->assertEquals(6, $data[0]['id']); + + // wildcard: placeholder at the middle + $env = Environment::mock([ + 'REQUEST_METHOD' => 'GET', + 'QUERY_STRING' => 'searchtags=w*b', + ]); + $request = Request::createFromEnvironment($env); + $response = $this->controller->getLinks($request, new Response()); + $this->assertEquals(200, $response->getStatusCode()); + $data = json_decode((string) $response->getBody(), true); + $this->assertEquals(4, count($data)); + $this->assertEquals(6, $data[0]['id']); + + // wildcard: match all + $env = Environment::mock([ + 'REQUEST_METHOD' => 'GET', + 'QUERY_STRING' => 'searchtags=*', + ]); + $request = Request::createFromEnvironment($env); + $response = $this->controller->getLinks($request, new Response()); + $this->assertEquals(200, $response->getStatusCode()); + $data = json_decode((string) $response->getBody(), true); + $this->assertEquals(9, count($data)); + $this->assertEquals(41, $data[0]['id']); + + // wildcard: optional ('*' does not need to expand) + $env = Environment::mock([ + 'REQUEST_METHOD' => 'GET', + 'QUERY_STRING' => 'searchtags=*stuff*', + ]); + $request = Request::createFromEnvironment($env); + $response = $this->controller->getLinks($request, new Response()); + $this->assertEquals(200, $response->getStatusCode()); + $data = json_decode((string) $response->getBody(), true); + $this->assertEquals(2, count($data)); + $this->assertEquals(41, $data[0]['id']); + + // wildcard: exclusions + $env = Environment::mock([ + 'REQUEST_METHOD' => 'GET', + 'QUERY_STRING' => 'searchtags=*a*+-*e*', + ]); + $request = Request::createFromEnvironment($env); + $response = $this->controller->getLinks($request, new Response()); + $this->assertEquals(200, $response->getStatusCode()); + $data = json_decode((string) $response->getBody(), true); + $this->assertEquals(1, count($data)); + $this->assertEquals(41, $data[0]['id']); // finds '#hashtag' in descr. + + // wildcard: exclude all + $env = Environment::mock([ + 'REQUEST_METHOD' => 'GET', + 'QUERY_STRING' => 'searchtags=-*', + ]); + $request = Request::createFromEnvironment($env); + $response = $this->controller->getLinks($request, new Response()); + $this->assertEquals(200, $response->getStatusCode()); + $data = json_decode((string) $response->getBody(), true); + $this->assertEquals(0, count($data)); } /** From a3130d2c2f27052710d4dbd51d0001190b19b383 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Fri, 25 Aug 2017 19:47:57 +0200 Subject: [PATCH 13/36] Make work behind a reverse proxy Without HTTP_X_FORWARDED_PORT check, might be set to false even though the user is using HTTPS, thus disabling Firefox Social block display --- application/HttpUtils.php | 28 +++++++++++++++++++++++++ index.php | 6 +++--- tests/HttpUtils/IsHttpsTest.php | 36 +++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 tests/HttpUtils/IsHttpsTest.php diff --git a/application/HttpUtils.php b/application/HttpUtils.php index 88a1efd..0083596 100644 --- a/application/HttpUtils.php +++ b/application/HttpUtils.php @@ -401,3 +401,31 @@ function getIpAddressFromProxy($server, $trustedIps) return array_pop($ips); } + +/** + * Returns true if Shaarli's currently browsed in HTTPS. + * Supports reverse proxies (if the headers are correctly set). + * + * @param array $server $_SERVER. + * + * @return bool true if HTTPS, false otherwise. + */ +function is_https($server) +{ + + if (isset($server['HTTP_X_FORWARDED_PORT'])) { + // Keep forwarded port + if (strpos($server['HTTP_X_FORWARDED_PORT'], ',') !== false) { + $ports = explode(',', $server['HTTP_X_FORWARDED_PORT']); + $port = trim($ports[0]); + } else { + $port = $server['HTTP_X_FORWARDED_PORT']; + } + + if ($port == '443') { + return true; + } + } + + return ! empty($server['HTTPS']); +} diff --git a/index.php b/index.php index b4c4347..de993f1 100644 --- a/index.php +++ b/index.php @@ -1063,10 +1063,10 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) // -------- Display the Tools menu if requested (import/export/bookmarklet...) if ($targetPage == Router::$PAGE_TOOLS) { - $data = array( + $data = [ 'pageabsaddr' => index_url($_SERVER), - 'sslenabled' => !empty($_SERVER['HTTPS']) - ); + 'sslenabled' => is_https($_SERVER), + ]; $pluginManager->executeHooks('render_tools', $data); foreach ($data as $key => $value) { diff --git a/tests/HttpUtils/IsHttpsTest.php b/tests/HttpUtils/IsHttpsTest.php new file mode 100644 index 0000000..097f2bc --- /dev/null +++ b/tests/HttpUtils/IsHttpsTest.php @@ -0,0 +1,36 @@ +assertTrue(is_https(['HTTPS' => true])); + $this->assertTrue(is_https(['HTTPS' => '1'])); + $this->assertTrue(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => 443])); + $this->assertTrue(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => '443'])); + $this->assertTrue(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => '443,123,456,'])); + } + + /** + * Test is_https with HTTP values. + */ + public function testIsHttpsFalse() + { + $this->assertFalse(is_https([])); + $this->assertFalse(is_https(['HTTPS' => false])); + $this->assertFalse(is_https(['HTTPS' => '0'])); + $this->assertFalse(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => 123])); + $this->assertFalse(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => '123'])); + $this->assertFalse(is_https(['HTTPS' => false, 'HTTP_X_FORWARDED_PORT' => ',123,456,'])); + } +} From 206c45bd05a79b5e6d0c51452a6ac69e85cca0b2 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 2 Sep 2017 13:50:03 +0200 Subject: [PATCH 14/36] Firefox Social title: Use document.title instead of RainTPL variable Fixes #929 --- tpl/default/js/shaarli.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tpl/default/js/shaarli.js b/tpl/default/js/shaarli.js index 4f49aff..e0b4c75 100644 --- a/tpl/default/js/shaarli.js +++ b/tpl/default/js/shaarli.js @@ -607,10 +607,11 @@ function htmlEntities(str) function activateFirefoxSocial(node) { var loc = location.href; var baseURL = loc.substring(0, loc.lastIndexOf("/") + 1); + var title = document.title; // Keeping the data separated (ie. not in the DOM) so that it's maintainable and diffable. var data = { - name: "{$shaarlititle}", + name: title, description: "The personal, minimalist, super-fast, database free, bookmarking service by the Shaarli community.", author: "Shaarli", version: "1.0.0", From 27e21231e168e5a2a89563b2538a4f86df24e582 Mon Sep 17 00:00:00 2001 From: Willi Eggeling Date: Thu, 31 Aug 2017 00:39:15 +0200 Subject: [PATCH 15/36] added option to redirect all anonymous users to login page - new setting *force_login* added and documented - if both, *force_login* and *hide_public_links* are set to true, all requests (except for the feeds) are redirected to the login page --- application/config/ConfigManager.php | 1 + doc/md/Shaarli-configuration.md | 2 ++ index.php | 17 +++++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php index fdd5b3d..32f6ef6 100644 --- a/application/config/ConfigManager.php +++ b/application/config/ConfigManager.php @@ -327,6 +327,7 @@ class ConfigManager $this->setEmpty('privacy.default_private_links', false); $this->setEmpty('privacy.hide_public_links', false); + $this->setEmpty('privacy.force_login', false); $this->setEmpty('privacy.hide_timestamps', false); // default state of the 'remember me' checkbox of the login form $this->setEmpty('privacy.remember_user_default', true); diff --git a/doc/md/Shaarli-configuration.md b/doc/md/Shaarli-configuration.md index d90e95e..3748641 100644 --- a/doc/md/Shaarli-configuration.md +++ b/doc/md/Shaarli-configuration.md @@ -90,6 +90,7 @@ _These settings should not be edited_ - **default_private_links**: Check the private checkbox by default for every new link. - **hide_public_links**: All links are hidden while logged out. +- **force_login**: if **hide_public_links** and this are set to `true`, all anonymous users are redirected to the login page. - **hide_timestamps**: Timestamps are hidden. - **remember_user_default**: Default state of the login page's *remember me* checkbox - `true`: checked by default, `false`: unchecked by default @@ -194,6 +195,7 @@ _These settings should not be edited_ "privacy": { "default_private_links": true, "hide_public_links": false, + "force_login": false, "hide_timestamps": false, "remember_user_default": true }, diff --git a/index.php b/index.php index 218d317..fb00a9f 100644 --- a/index.php +++ b/index.php @@ -718,6 +718,23 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) $query = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : ''; $targetPage = Router::findPage($query, $_GET, isLoggedIn()); + if ( + // if the user isn't logged in + !isLoggedIn() && + // and Shaarli doesn't have public content... + $conf->get('privacy.hide_public_links') && + // and is configured to enforce the login + $conf->get('privacy.force_login') && + // and the current page isn't already the login page + $targetPage !== Router::$PAGE_LOGIN && + // and the user is not requesting a feed (which would lead to a different content-type as expected) + $targetPage !== Router::$PAGE_FEED_ATOM && + $targetPage !== Router::$PAGE_FEED_RSS + ) { + // force current page to be the login page + $targetPage = Router::$PAGE_LOGIN; + } + // Call plugin hooks for header, footer and includes, specifying which page will be rendered. // Then assign generated data to RainTPL. $common_hooks = array( From ceb738c59163b47e9c875764c9d3223bbc1eba24 Mon Sep 17 00:00:00 2001 From: nodiscc Date: Mon, 4 Sep 2017 22:36:21 +0200 Subject: [PATCH 16/36] visited links color: same hue as unvisited links, darkened Related to https://github.com/shaarli/Shaarli/issues/877 Plain grey links would lead to think that the link is somehow disabled/inaccessible/private This slightly improves clarity/usability --- tpl/default/css/shaarli.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tpl/default/css/shaarli.css b/tpl/default/css/shaarli.css index e1868c5..ba58972 100644 --- a/tpl/default/css/shaarli.css +++ b/tpl/default/css/shaarli.css @@ -539,7 +539,7 @@ body, .pure-g [class*="pure-u"] { } .linklist-item-title a:visited .linklist-link { - color: #555555; + color: #2a4c41; } .linklist-item-title a:hover, .linklist-item-title .linklist-link:hover{ From d691604080cc920e7d1d7ad5c98f4e3fae779524 Mon Sep 17 00:00:00 2001 From: VirtualTam Date: Tue, 30 May 2017 23:45:17 +0200 Subject: [PATCH 17/36] docker: add alpine,debian,ubuntu test images Relates to https://github.com/shaarli/Shaarli/issues/843 Added: - Makefile target to run commands in a Docker test context - Docker images to run Shaarli test suites: - Alpine 3.6 - Debian 8 - Debian 9 - Ubuntu 16.04 - Documentation Signed-off-by: VirtualTam --- Makefile | 10 ++++++ doc/md/Unit-tests-Docker.md | 56 +++++++++++++++++++++++++++++++++ docker/test/alpine36/Dockerfile | 34 ++++++++++++++++++++ docker/test/debian8/Dockerfile | 35 +++++++++++++++++++++ docker/test/debian9/Dockerfile | 36 +++++++++++++++++++++ docker/test/ubuntu16/Dockerfile | 36 +++++++++++++++++++++ mkdocs.yml | 1 + 7 files changed, 208 insertions(+) create mode 100644 doc/md/Unit-tests-Docker.md create mode 100644 docker/test/alpine36/Dockerfile create mode 100644 docker/test/debian8/Dockerfile create mode 100644 docker/test/debian9/Dockerfile create mode 100644 docker/test/ubuntu16/Dockerfile diff --git a/Makefile b/Makefile index 40badb1..a3696ec 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,16 @@ PHP_COMMA_SOURCE = index.php,application,tests,plugins all: static_analysis_summary check_permissions test +## +# Docker test adapter +# +# Shaarli sources and vendored libraries are copied from a shared volume +# to a user-owned directory to enable running tests as a non-root user. +## +docker_%: + rsync -az /shaarli/ ~/shaarli/ + cd ~/shaarli && make $* + ## # Concise status of the project # These targets are non-blocking: || exit 0 diff --git a/doc/md/Unit-tests-Docker.md b/doc/md/Unit-tests-Docker.md new file mode 100644 index 0000000..c2de7cc --- /dev/null +++ b/doc/md/Unit-tests-Docker.md @@ -0,0 +1,56 @@ +## Running tests inside Docker containers + +Read first: + +- [Docker 101](docker/docker-101.md) +- [Docker resources](docker/resources.md) +- [Unit tests](Unit-tests.md) + +### Docker test images + +Test Dockerfiles are located under `docker/tests//Dockerfile`, +and can be used to build Docker images to run Shaarli test suites under common +Linux environments. + +Dockerfiles are provided for the following environments: + +- `alpine36` - [Alpine 3.6](https://www.alpinelinux.org/downloads/) +- `debian8` - [Debian 8 Jessie](https://www.debian.org/DebianJessie) (oldstable) +- `debian9` - [Debian 9 Stretch](https://wiki.debian.org/DebianStretch) (stable) +- `ubuntu16` - [Ubuntu 16.04 Xenial Xerus](http://releases.ubuntu.com/16.04/) (LTS) + +What's behind the curtains: + +- each image provides: + - a base Linux OS + - Shaarli PHP dependencies (OS packages) + - test PHP dependencies (OS packages) + - Composer +- the local workspace is mapped to the container's `/shaarli/` directory, +- the files are rsync'd to so tests are run using a standard Linux user account + (running tests as `root` would bypass permission checks and may hide issues) +- the tests are run inside the container. + +### Building test images + +```bash +# build the Debian 9 Docker image +$ cd /path/to/shaarli +$ cd docker/test/debian9 +$ docker build -t shaarli-test:debian9 . +``` + +### Running tests + +```bash +$ cd /path/to/shaarli + +# install/update 3rd-party test dependencies +$ composer install --prefer-dist + +# run tests using the freshly built image +$ docker run -v $PWD:/shaarli shaarli-test:debian9 docker_test + +# run the full test campaign +$ docker run -v $PWD:/shaarli shaarli-test:debian9 docker_all_tests +``` diff --git a/docker/test/alpine36/Dockerfile b/docker/test/alpine36/Dockerfile new file mode 100644 index 0000000..fa84f6e --- /dev/null +++ b/docker/test/alpine36/Dockerfile @@ -0,0 +1,34 @@ +FROM alpine:3.6 +MAINTAINER Shaarli Community + +RUN apk --update --no-cache add \ + ca-certificates \ + curl \ + make \ + php7 \ + php7-ctype \ + php7-curl \ + php7-dom \ + php7-gd \ + php7-iconv \ + php7-intl \ + php7-json \ + php7-mbstring \ + php7-openssl \ + php7-phar \ + php7-session \ + php7-simplexml \ + php7-tokenizer \ + php7-xdebug \ + php7-xml \ + php7-zlib \ + rsync + +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +RUN mkdir /shaarli +WORKDIR /shaarli +VOLUME /shaarli + +ENTRYPOINT ["make"] +CMD [] diff --git a/docker/test/debian8/Dockerfile b/docker/test/debian8/Dockerfile new file mode 100644 index 0000000..eaa34e9 --- /dev/null +++ b/docker/test/debian8/Dockerfile @@ -0,0 +1,35 @@ +FROM debian:jessie +MAINTAINER Shaarli Community + +ENV TERM dumb +ENV DEBIAN_FRONTEND noninteractive +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en + +RUN apt-get update \ + && apt-get install --no-install-recommends -y \ + ca-certificates \ + curl \ + locales \ + make \ + php5 \ + php5-curl \ + php5-gd \ + php5-intl \ + php5-xdebug \ + rsync \ + && apt-get clean + +RUN locale-gen en_US.UTF-8 \ + && locale-gen de_DE.UTF-8 \ + && locale-gen fr_FR.UTF-8 + +ADD https://getcomposer.org/composer.phar /usr/local/bin/composer +RUN chmod 755 /usr/local/bin/composer + +RUN mkdir /shaarli +WORKDIR /shaarli +VOLUME /shaarli + +ENTRYPOINT ["make"] +CMD [] diff --git a/docker/test/debian9/Dockerfile b/docker/test/debian9/Dockerfile new file mode 100644 index 0000000..3ab4b93 --- /dev/null +++ b/docker/test/debian9/Dockerfile @@ -0,0 +1,36 @@ +FROM debian:stretch +MAINTAINER Shaarli Community + +ENV TERM dumb +ENV DEBIAN_FRONTEND noninteractive +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en + +RUN apt-get update \ + && apt-get install --no-install-recommends -y \ + ca-certificates \ + curl \ + locales \ + make \ + php7.0 \ + php7.0-curl \ + php7.0-gd \ + php7.0-intl \ + php7.0-xml \ + php-xdebug \ + rsync \ + && apt-get clean + +RUN locale-gen en_US.UTF-8 \ + && locale-gen de_DE.UTF-8 \ + && locale-gen fr_FR.UTF-8 + +ADD https://getcomposer.org/composer.phar /usr/local/bin/composer +RUN chmod 755 /usr/local/bin/composer + +RUN mkdir /shaarli +WORKDIR /shaarli +VOLUME /shaarli + +ENTRYPOINT ["make"] +CMD [] diff --git a/docker/test/ubuntu16/Dockerfile b/docker/test/ubuntu16/Dockerfile new file mode 100644 index 0000000..e53ed9e --- /dev/null +++ b/docker/test/ubuntu16/Dockerfile @@ -0,0 +1,36 @@ +FROM ubuntu:16.04 +MAINTAINER Shaarli Community + +ENV TERM dumb +ENV DEBIAN_FRONTEND noninteractive +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en + +RUN apt-get update \ + && apt-get install --no-install-recommends -y \ + ca-certificates \ + curl \ + language-pack-de \ + language-pack-en \ + language-pack-fr \ + locales \ + make \ + php7.0 \ + php7.0-curl \ + php7.0-gd \ + php7.0-intl \ + php7.0-xml \ + php-xdebug \ + rsync \ + && apt-get clean + +ADD https://getcomposer.org/composer.phar /usr/local/bin/composer +RUN chmod 755 /usr/local/bin/composer + +RUN useradd -m dev \ + && mkdir /shaarli +USER dev +WORKDIR /shaarli + +ENTRYPOINT ["make"] +CMD [] diff --git a/mkdocs.yml b/mkdocs.yml index 648d8f6..03a7a34 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -45,6 +45,7 @@ pages: - Static analysis: Static-analysis.md - Theming: Theming.md - Unit tests: Unit-tests.md + - Unit tests inside Docker: Unit-tests-Docker.md - About: - FAQ: FAQ.md - Community & Related software: Community-&-Related-software.md From dfc2c3353d95ffd095ef02f1060ea7ebe99a18d2 Mon Sep 17 00:00:00 2001 From: VirtualTam Date: Tue, 19 Sep 2017 18:36:41 +0200 Subject: [PATCH 18/36] Travis: switch to Ubuntu Trusty build environment Relates to https://github.com/shaarli/Shaarli/issues/970 Relates to https://github.com/shaarli/Shaarli/pull/912 See: - https://docs.travis-ci.com/user/reference/trusty/ - https://blog.travis-ci.com/2017-07-11-trusty-as-default-linux-is-coming Added: - print available locales before running tests Removed: - do not install extra language packs Signed-off-by: VirtualTam --- .travis.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 26535ad..7240138 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,6 @@ sudo: false -dist: precise +dist: trusty language: php -addons: - apt: - packages: - - locales - - language-pack-de - - language-pack-fr cache: directories: - $HOME/.composer/cache @@ -19,6 +13,7 @@ install: - composer self-update - composer install --prefer-dist script: + - locale -a - make clean - make check_permissions - make all_tests From b5c33d702ac973e7bc1401e484c6b8799eea1e91 Mon Sep 17 00:00:00 2001 From: VirtualTam Date: Tue, 19 Sep 2017 19:17:16 +0200 Subject: [PATCH 19/36] Tests: update localization tests Rely on `mag_IN` (Magahi - INDIA) being unavailable when running localization test suites, instead of `pt_BR` that is now available from Travis build images. Signed-off-by: VirtualTam --- .travis.yml | 2 +- tests/languages/de/UtilsDeTest.php | 12 ++++++------ tests/languages/en/UtilsEnTest.php | 12 ++++++------ tests/languages/fr/UtilsFrTest.php | 12 ++++++------ 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7240138..b6b9bdd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,8 +12,8 @@ php: install: - composer self-update - composer install --prefer-dist -script: - locale -a +script: - make clean - make check_permissions - make all_tests diff --git a/tests/languages/de/UtilsDeTest.php b/tests/languages/de/UtilsDeTest.php index 6c9c9ad..4569c92 100644 --- a/tests/languages/de/UtilsDeTest.php +++ b/tests/languages/de/UtilsDeTest.php @@ -81,12 +81,12 @@ class UtilsDeTest extends UtilsTest } /** - * Test autoLocale with multiples value, the second one is valid + * Test autoLocale with multiples value, the second one is available */ - public function testAutoLocaleMultipleSecondValid() + public function testAutoLocaleMultipleSecondAvailable() { $current = setlocale(LC_ALL, 0); - $header = 'pt_BR,fr-fr'; + $header = 'mag_IN,fr-fr'; autoLocale($header); $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0)); @@ -106,12 +106,12 @@ class UtilsDeTest extends UtilsTest } /** - * Test autoLocale with an invalid value: defaults to en_US. + * Test autoLocale with an unavailable value: defaults to en_US. */ - public function testAutoLocaleInvalid() + public function testAutoLocaleUnavailable() { $current = setlocale(LC_ALL, 0); - autoLocale('pt_BR'); + autoLocale('mag_IN'); $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); setlocale(LC_ALL, $current); diff --git a/tests/languages/en/UtilsEnTest.php b/tests/languages/en/UtilsEnTest.php index d8680b2..a74063a 100644 --- a/tests/languages/en/UtilsEnTest.php +++ b/tests/languages/en/UtilsEnTest.php @@ -81,12 +81,12 @@ class UtilsEnTest extends UtilsTest } /** - * Test autoLocale with multiples value, the second one is valid + * Test autoLocale with multiples value, the second one is available */ - public function testAutoLocaleMultipleSecondValid() + public function testAutoLocaleMultipleSecondAvailable() { $current = setlocale(LC_ALL, 0); - $header = 'pt_BR,fr-fr'; + $header = 'mag_IN,fr-fr'; autoLocale($header); $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0)); @@ -106,12 +106,12 @@ class UtilsEnTest extends UtilsTest } /** - * Test autoLocale with an invalid value: defaults to en_US. + * Test autoLocale with an unavailable value: defaults to en_US. */ - public function testAutoLocaleInvalid() + public function testAutoLocaleUnavailable() { $current = setlocale(LC_ALL, 0); - autoLocale('pt_BR'); + autoLocale('mag_IN'); $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); setlocale(LC_ALL, $current); diff --git a/tests/languages/fr/UtilsFrTest.php b/tests/languages/fr/UtilsFrTest.php index 0d50a87..3dbb126 100644 --- a/tests/languages/fr/UtilsFrTest.php +++ b/tests/languages/fr/UtilsFrTest.php @@ -81,12 +81,12 @@ class UtilsFrTest extends UtilsTest } /** - * Test autoLocale with multiples value, the second one is valid + * Test autoLocale with multiples value, the second one is available */ - public function testAutoLocaleMultipleSecondValid() + public function testAutoLocaleMultipleSecondAvailable() { $current = setlocale(LC_ALL, 0); - $header = 'pt_BR,de-de'; + $header = 'mag_IN,de-de'; autoLocale($header); $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); @@ -106,12 +106,12 @@ class UtilsFrTest extends UtilsTest } /** - * Test autoLocale with an invalid value: defaults to en_US. + * Test autoLocale with an unavailable value: defaults to en_US. */ - public function testAutoLocaleInvalid() + public function testAutoLocaleUnavailable() { $current = setlocale(LC_ALL, 0); - autoLocale('pt_BR'); + autoLocale('mag_IN'); $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); setlocale(LC_ALL, $current); From e4325b1517c3d9769c8e0141e37b2845bf8e4d09 Mon Sep 17 00:00:00 2001 From: VirtualTam Date: Tue, 19 Sep 2017 20:21:28 +0200 Subject: [PATCH 20/36] Robustness: safer RainTPL directory handling Relates to https://github.com/shaarli/Shaarli/issues/845 Relates to https://github.com/shaarli/Shaarli/issues/846 Relates to https://github.com/shaarli/Shaarli/pull/909 Signed-off-by: VirtualTam --- application/ApplicationUtils.php | 5 +++-- application/ThemeUtils.php | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/application/ApplicationUtils.php b/application/ApplicationUtils.php index 85dcbee..123cc0b 100644 --- a/application/ApplicationUtils.php +++ b/application/ApplicationUtils.php @@ -168,14 +168,15 @@ class ApplicationUtils public static function checkResourcePermissions($conf) { $errors = array(); + $rainTplDir = rtrim($conf->get('resource.raintpl_tpl'), '/'); // Check script and template directories are readable foreach (array( 'application', 'inc', 'plugins', - $conf->get('resource.raintpl_tpl'), - $conf->get('resource.raintpl_tpl').'/'.$conf->get('resource.theme'), + $rainTplDir, + $rainTplDir.'/'.$conf->get('resource.theme'), ) as $path) { if (! is_readable(realpath($path))) { $errors[] = '"'.$path.'" directory is not readable'; diff --git a/application/ThemeUtils.php b/application/ThemeUtils.php index 2718ed1..16f2f6a 100644 --- a/application/ThemeUtils.php +++ b/application/ThemeUtils.php @@ -22,6 +22,7 @@ class ThemeUtils */ public static function getThemes($tplDir) { + $tplDir = rtrim($tplDir, '/'); $allTheme = glob($tplDir.'/*', GLOB_ONLYDIR); $themes = []; foreach ($allTheme as $value) { From 8c322aaba197bab1a9992b731db80d9faa133bc4 Mon Sep 17 00:00:00 2001 From: VirtualTam Date: Tue, 19 Sep 2017 22:08:29 +0200 Subject: [PATCH 21/36] Robustness: safer gzinflate/zlib usage Relates to https://github.com/shaarli/Shaarli/pull/846 PHP's `gzinflate()` fails with an error when being passed an empty string See: - https://bugs.php.net/bug.php?id=71395 Signed-off-by: VirtualTam --- application/FileUtils.php | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/application/FileUtils.php b/application/FileUtils.php index a167f64..918cb83 100644 --- a/application/FileUtils.php +++ b/application/FileUtils.php @@ -50,7 +50,8 @@ class FileUtils /** * Read data from a file containing Shaarli database format content. - * If the file isn't readable or doesn't exists, default data will be returned. + * + * If the file isn't readable or doesn't exist, default data will be returned. * * @param string $file File path. * @param mixed $default The default value to return if the file isn't readable. @@ -61,16 +62,21 @@ class FileUtils { // Note that gzinflate is faster than gzuncompress. // See: http://www.php.net/manual/en/function.gzdeflate.php#96439 - if (is_readable($file)) { - return unserialize( - gzinflate( - base64_decode( - substr(file_get_contents($file), strlen(self::$phpPrefix), -strlen(self::$phpSuffix)) - ) - ) - ); + if (! is_readable($file)) { + return $default; } - return $default; + $data = file_get_contents($file); + if ($data == '') { + return $default; + } + + return unserialize( + gzinflate( + base64_decode( + substr($data, strlen(self::$phpPrefix), -strlen(self::$phpSuffix)) + ) + ) + ); } } From 601faf97516a836e4ae57dc4cecb9225c0a04338 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Fri, 29 Sep 2017 18:52:38 +0200 Subject: [PATCH 22/36] Fix parsing for description links with parentheses With markdown plugin disabled relates to #966 --- application/LinkUtils.php | 2 +- tests/LinkUtilsTest.php | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/application/LinkUtils.php b/application/LinkUtils.php index 976474d..267e62c 100644 --- a/application/LinkUtils.php +++ b/application/LinkUtils.php @@ -109,7 +109,7 @@ function count_private($links) */ function text2clickable($text, $redirector = '') { - $regex = '!(((?:https?|ftp|file)://|apt:|magnet:)\S+[[:alnum:]]/?)!si'; + $regex = '!(((?:https?|ftp|file)://|apt:|magnet:)\S+[a-z0-9\(\)]/?)!si'; if (empty($redirector)) { return preg_replace($regex, '$1', $text); diff --git a/tests/LinkUtilsTest.php b/tests/LinkUtilsTest.php index 7c0d4b0..c77922e 100644 --- a/tests/LinkUtilsTest.php +++ b/tests/LinkUtilsTest.php @@ -103,6 +103,16 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase $expectedText = 'stuff http://hello.there/is=someone#here otherstuff'; $processedText = text2clickable($text, ''); $this->assertEquals($expectedText, $processedText); + + $text = 'stuff http://hello.there/is=someone#here(please) otherstuff'; + $expectedText = 'stuff http://hello.there/is=someone#here(please) otherstuff'; + $processedText = text2clickable($text, ''); + $this->assertEquals($expectedText, $processedText); + + $text = 'stuff http://hello.there/is=someone#here(please)&no otherstuff'; + $expectedText = 'stuff http://hello.there/is=someone#here(please)&no otherstuff'; + $processedText = text2clickable($text, ''); + $this->assertEquals($expectedText, $processedText); } /** From bfe4f536bbfe03f38e0c801bfbd26587a2b64a7f Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sun, 1 Oct 2017 11:02:48 +0200 Subject: [PATCH 23/36] Add a version hash for asset loading to prevent browser's cache issue The hash is generated using the same salt as the one used for credentials (1 salt per instance) in order to avoid exposing the instance version. Fixes #965 --- application/ApplicationUtils.php | 15 +++++++++++++++ application/PageBuilder.php | 5 +++++ tpl/default/includes.html | 14 +++++++------- tpl/default/page.footer.html | 6 +++--- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/application/ApplicationUtils.php b/application/ApplicationUtils.php index 85dcbee..20fec37 100644 --- a/application/ApplicationUtils.php +++ b/application/ApplicationUtils.php @@ -220,4 +220,19 @@ class ApplicationUtils return $errors; } + + /** + * Returns a salted hash representing the current Shaarli version. + * + * Useful for assets browser cache. + * + * @param string $currentVersion of Shaarli + * @param string $salt User personal salt, also used for the authentication + * + * @return string version hash + */ + public static function getVersionHash($currentVersion, $salt) + { + return hash_hmac('sha256', $currentVersion, $salt); + } } diff --git a/application/PageBuilder.php b/application/PageBuilder.php index 7a42400..c91b662 100644 --- a/application/PageBuilder.php +++ b/application/PageBuilder.php @@ -76,6 +76,10 @@ class PageBuilder $this->tpl->assign('searchcrits', $searchcrits); $this->tpl->assign('source', index_url($_SERVER)); $this->tpl->assign('version', shaarli_version); + $this->tpl->assign( + 'version_hash', + ApplicationUtils::getVersionHash(SHAARLI_VERSION, $this->conf->get('credentials.salt')) + ); $this->tpl->assign('scripturl', index_url($_SERVER)); $this->tpl->assign('privateonly', !empty($_SESSION['privateonly'])); // Show only private links? $this->tpl->assign('untaggedonly', !empty($_SESSION['untaggedonly'])); @@ -89,6 +93,7 @@ class PageBuilder $this->tpl->assign('feed_type', $this->conf->get('feed.show_atom', true) !== false ? 'atom' : 'rss'); $this->tpl->assign('hide_timestamps', $this->conf->get('privacy.hide_timestamps', false)); $this->tpl->assign('token', getToken($this->conf)); + if ($this->linkDB !== null) { $this->tpl->assign('tags', $this->linkDB->linksCountPerTag()); } diff --git a/tpl/default/includes.html b/tpl/default/includes.html index 0350ef6..80c0833 100644 --- a/tpl/default/includes.html +++ b/tpl/default/includes.html @@ -5,16 +5,16 @@ - - - - - - + + + + + + {if="is_file('data/user.css')"} {/if} {loop="$plugins_includes.css_files"} - + {/loop} \ No newline at end of file diff --git a/tpl/default/page.footer.html b/tpl/default/page.footer.html index 94f771a..54b16e8 100644 --- a/tpl/default/page.footer.html +++ b/tpl/default/page.footer.html @@ -27,6 +27,6 @@ {/loop} - - - + + + From b3e1f92e9cd0cae35bc726ca3a2356b4e631ccfa Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sun, 1 Oct 2017 11:09:12 +0200 Subject: [PATCH 24/36] Rename shaarli_version constant to uppercase --- application/PageBuilder.php | 4 ++-- application/Updater.php | 4 ++-- index.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/application/PageBuilder.php b/application/PageBuilder.php index c91b662..291860a 100644 --- a/application/PageBuilder.php +++ b/application/PageBuilder.php @@ -49,7 +49,7 @@ class PageBuilder try { $version = ApplicationUtils::checkUpdate( - shaarli_version, + SHAARLI_VERSION, $this->conf->get('resource.update_check'), $this->conf->get('updates.check_updates_interval'), $this->conf->get('updates.check_updates'), @@ -75,7 +75,7 @@ class PageBuilder } $this->tpl->assign('searchcrits', $searchcrits); $this->tpl->assign('source', index_url($_SERVER)); - $this->tpl->assign('version', shaarli_version); + $this->tpl->assign('version', SHAARLI_VERSION); $this->tpl->assign( 'version_hash', ApplicationUtils::getVersionHash(SHAARLI_VERSION, $this->conf->get('credentials.salt')) diff --git a/application/Updater.php b/application/Updater.php index 40a1590..72b2def 100644 --- a/application/Updater.php +++ b/application/Updater.php @@ -398,7 +398,7 @@ class Updater */ public function updateMethodCheckUpdateRemoteBranch() { - if (shaarli_version === 'dev' || $this->conf->get('updates.check_updates_branch') === 'latest') { + if (SHAARLI_VERSION === 'dev' || $this->conf->get('updates.check_updates_branch') === 'latest') { return true; } @@ -413,7 +413,7 @@ class Updater $latestMajor = $matches[1]; // Get current major version digit - preg_match('/(\d+)\.\d+$/', shaarli_version, $matches); + preg_match('/(\d+)\.\d+$/', SHAARLI_VERSION, $matches); $currentMajor = $matches[1]; if ($currentMajor === $latestMajor) { diff --git a/index.php b/index.php index fb00a9f..12cccea 100644 --- a/index.php +++ b/index.php @@ -88,7 +88,7 @@ try { exit; } -define('shaarli_version', ApplicationUtils::getVersion(__DIR__ .'/'. ApplicationUtils::$VERSION_FILE)); +define('SHAARLI_VERSION', ApplicationUtils::getVersion(__DIR__ .'/'. ApplicationUtils::$VERSION_FILE)); // Force cookie path (but do not change lifetime) $cookie = session_get_cookie_params(); From 9c46b347b8118a127ca965106f66bb4d4d43f427 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sun, 1 Oct 2017 11:49:17 +0200 Subject: [PATCH 25/36] Fix jumpy textarea with long content in post edit We manually reset the scroll position, to avoid height = 'auto' jump to the top Fixes #971 --- tpl/default/js/shaarli.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tpl/default/js/shaarli.js b/tpl/default/js/shaarli.js index 1c66ebb..55656f8 100644 --- a/tpl/default/js/shaarli.js +++ b/tpl/default/js/shaarli.js @@ -275,8 +275,14 @@ window.onload = function () { }; function init () { function resize () { + /* Fix jumpy resizing: https://stackoverflow.com/a/18262927/1484919 */ + var scrollTop = window.pageYOffset || + (document.documentElement || document.body.parentNode || document.body).scrollTop; + description.style.height = 'auto'; description.style.height = description.scrollHeight+10+'px'; + + window.scrollTo(0, scrollTop); } /* 0-timeout to get the already changed text */ function delayedResize () { From 722caa209005a23b0cfba31aa10cd34a45880cec Mon Sep 17 00:00:00 2001 From: Mark Gerarts Date: Sun, 1 Oct 2017 14:19:57 +0200 Subject: [PATCH 26/36] Allow setting of a default note title, see #963 --- application/config/ConfigManager.php | 1 + doc/md/Shaarli-configuration.md | 1 + index.php | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php index 32f6ef6..7ff2fe6 100644 --- a/application/config/ConfigManager.php +++ b/application/config/ConfigManager.php @@ -317,6 +317,7 @@ class ConfigManager $this->setEmpty('general.header_link', '?'); $this->setEmpty('general.links_per_page', 20); $this->setEmpty('general.enabled_plugins', self::$DEFAULT_PLUGINS); + $this->setEmpty('general.default_note_title', 'Note: '); $this->setEmpty('updates.check_updates', false); $this->setEmpty('updates.check_updates_branch', 'stable'); diff --git a/doc/md/Shaarli-configuration.md b/doc/md/Shaarli-configuration.md index 3748641..99b25ba 100644 --- a/doc/md/Shaarli-configuration.md +++ b/doc/md/Shaarli-configuration.md @@ -55,6 +55,7 @@ _These settings should not be edited_ - **links_per_page**: Number of shaares displayed per page. - **timezone**: See [the list of supported timezones](http://php.net/manual/en/timezones.php). - **enabled_plugins**: List of enabled plugins. +- **default_note_title**: Default title of a new note. ### Security diff --git a/index.php b/index.php index fb00a9f..43aab30 100644 --- a/index.php +++ b/index.php @@ -1443,7 +1443,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) if ($url == '') { $url = '?' . smallHash($linkdate . $LINKSDB->getNextId()); - $title = 'Note: '; + $title = $conf->get('general.default_note_title', 'Note: '); } $url = escape($url); $title = escape($title); From 02ff7897c0bcb48521ddd0c494f346b6df275ab4 Mon Sep 17 00:00:00 2001 From: "B. van Berkum" Date: Tue, 3 Oct 2017 00:23:34 +0200 Subject: [PATCH 27/36] Added docker quickstart example, with user-data volume --- doc/md/index.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/md/index.md b/doc/md/index.md index 24ada6c..5f10227 100644 --- a/doc/md/index.md +++ b/doc/md/index.md @@ -22,6 +22,18 @@ It runs the latest development version of Shaarli and is updated/reset daily. Login: `demo`; Password: `demo` +Docker users can start a personal instance from an [autobuild image](https://hub.docker.com/r/shaarli/shaarli/). For an example to start a temporary Shaarli at ``localhost:8000``, and to keeps the data you create (config, storage) during the session: +``` +MY_SHAARLI_VOLUME=$(cd /path/to/shaarli/data/ && pwd -P) +docker run -ti --rm \ + -p 8000:80 \ + -v $MY_SHAARLI_VOLUME:/var/www/shaarli/data \ + shaarli/shaarli +``` + +A brief guide on getting starting using docker is given in [Docker 101](docker/docker-101). + +To learn more about user data and how to keep it across versions, please see [Upgrade and Migration](Upgrade-and-migration) documentation. ## Features From 22a30602cb31f9b1e36aabae4259561625b7ffe3 Mon Sep 17 00:00:00 2001 From: "B. van Berkum" Date: Tue, 3 Oct 2017 00:24:23 +0200 Subject: [PATCH 28/36] Docker 101: container start and cleanup --- doc/md/docker/docker-101.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/doc/md/docker/docker-101.md b/doc/md/docker/docker-101.md index b02dd14..d12a132 100644 --- a/doc/md/docker/docker-101.md +++ b/doc/md/docker/docker-101.md @@ -60,3 +60,40 @@ wheezy: Pulling from debian Digest: sha256:c584131da2ac1948aa3e66468a4424b6aea2f33acba7cec0b631bdb56254c4fe Status: Downloaded newer image for debian:wheezy ``` + +Docker re-uses layers already downloaded. Iow. if you have only images based on some Alpine or Ubuntu version for example, those can share disk space. + +### Start a container +A container is an instance created from an image, that can be run and that keeps running until its main process exits. Or until the user stops the container. + +The simplest way to start a container from image is ``docker run``. It also pulls the image for you if it is not locally available. For more advanced use, refer to ``docker create``. + +Note that stopped containers are not destroyed, unless you specify ``--rm``. +To view all created, running and stopped containers, enter: + +```bash +$ docker ps -a +``` + +Some containers may be designed or configured to be restarted, others are not. Note that both network ports and volumes of a container are created on start, and not editable later. + +### Access a running container +A running container is accessible using ``docker exec``, or ``docker copy``. +You can use ``exec`` to start a root shell in the Shaarli container: +```bash +$ docker exec -ti bash +``` +Note the names and ID's of containers are list in ``docker ps``. You an even type only one or two letters of the ID, given they are unique. + +Access can also be through one or more network ports, or disk volumes. Both are specified on and fixed on ``docker create`` or ``run``. + +### Docker disk use +Trying out different images can fill some gigabytes of disk quickly. Besides images, the docker volumes usually take up most disk space. + +If you care only about trying out docker and not about what is running or saved, +the following commands should help you out quickly: + +```bash +$ docker rmi -f $(docker images -aq) # remove or mark all images for disposal +$ docker volume rm $(docker volume ls -q) # remove all volumes +``` From 60ed9b8f4142e99114661b5b8a5562aa75bffb48 Mon Sep 17 00:00:00 2001 From: "B. van Berkum" Date: Tue, 3 Oct 2017 00:33:39 +0200 Subject: [PATCH 29/36] Typo's, unified structure a bit. - Fixes inevitable typo that crept in. - Removed some blank lines, newlines, to match established whitespace use better. - Minor grammar improvement. --- doc/md/docker/docker-101.md | 12 ++++-------- doc/md/index.md | 3 +-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/doc/md/docker/docker-101.md b/doc/md/docker/docker-101.md index d12a132..271dcd5 100644 --- a/doc/md/docker/docker-101.md +++ b/doc/md/docker/docker-101.md @@ -61,16 +61,14 @@ Digest: sha256:c584131da2ac1948aa3e66468a4424b6aea2f33acba7cec0b631bdb56254c4fe Status: Downloaded newer image for debian:wheezy ``` -Docker re-uses layers already downloaded. Iow. if you have only images based on some Alpine or Ubuntu version for example, those can share disk space. +Docker re-uses layers already downloaded. Iow. if you have images based only Alpine or some Ubuntu version for example, those can share disk space. ### Start a container A container is an instance created from an image, that can be run and that keeps running until its main process exits. Or until the user stops the container. The simplest way to start a container from image is ``docker run``. It also pulls the image for you if it is not locally available. For more advanced use, refer to ``docker create``. -Note that stopped containers are not destroyed, unless you specify ``--rm``. -To view all created, running and stopped containers, enter: - +Note that stopped containers are not destroyed, unless you specify ``--rm``. To view all created, running and stopped containers, enter: ```bash $ docker ps -a ``` @@ -78,8 +76,7 @@ $ docker ps -a Some containers may be designed or configured to be restarted, others are not. Note that both network ports and volumes of a container are created on start, and not editable later. ### Access a running container -A running container is accessible using ``docker exec``, or ``docker copy``. -You can use ``exec`` to start a root shell in the Shaarli container: +A running container is accessible using ``docker exec``, or ``docker copy``. You can use ``exec`` to start a root shell in the Shaarli container: ```bash $ docker exec -ti bash ``` @@ -90,8 +87,7 @@ Access can also be through one or more network ports, or disk volumes. Both are ### Docker disk use Trying out different images can fill some gigabytes of disk quickly. Besides images, the docker volumes usually take up most disk space. -If you care only about trying out docker and not about what is running or saved, -the following commands should help you out quickly: +If you care only about trying out docker and not about what is running or saved, the following commands should help you out quickly: ```bash $ docker rmi -f $(docker images -aq) # remove or mark all images for disposal diff --git a/doc/md/index.md b/doc/md/index.md index 5f10227..f83d170 100644 --- a/doc/md/index.md +++ b/doc/md/index.md @@ -22,7 +22,7 @@ It runs the latest development version of Shaarli and is updated/reset daily. Login: `demo`; Password: `demo` -Docker users can start a personal instance from an [autobuild image](https://hub.docker.com/r/shaarli/shaarli/). For an example to start a temporary Shaarli at ``localhost:8000``, and to keeps the data you create (config, storage) during the session: +Docker users can start a personal instance from an [autobuild image](https://hub.docker.com/r/shaarli/shaarli/). For an example to start a temporary Shaarli at ``localhost:8000``, and keep the data you create (config, storage) during the session: ``` MY_SHAARLI_VOLUME=$(cd /path/to/shaarli/data/ && pwd -P) docker run -ti --rm \ @@ -32,7 +32,6 @@ docker run -ti --rm \ ``` A brief guide on getting starting using docker is given in [Docker 101](docker/docker-101). - To learn more about user data and how to keep it across versions, please see [Upgrade and Migration](Upgrade-and-migration) documentation. ## Features From 62a8b0ff6eafddcd091e3f6676b258f44b5f9e5c Mon Sep 17 00:00:00 2001 From: "B. van Berkum" Date: Tue, 3 Oct 2017 00:57:46 +0200 Subject: [PATCH 30/36] Docker-101: added working systemd config example --- doc/md/docker/docker-101.md | 47 +++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/doc/md/docker/docker-101.md b/doc/md/docker/docker-101.md index 271dcd5..35a6877 100644 --- a/doc/md/docker/docker-101.md +++ b/doc/md/docker/docker-101.md @@ -84,6 +84,11 @@ Note the names and ID's of containers are list in ``docker ps``. You an even typ Access can also be through one or more network ports, or disk volumes. Both are specified on and fixed on ``docker create`` or ``run``. +You can view the console output of the main container process too: +```bash +$ docker logs -f +``` + ### Docker disk use Trying out different images can fill some gigabytes of disk quickly. Besides images, the docker volumes usually take up most disk space. @@ -93,3 +98,45 @@ If you care only about trying out docker and not about what is running or saved, $ docker rmi -f $(docker images -aq) # remove or mark all images for disposal $ docker volume rm $(docker volume ls -q) # remove all volumes ``` + +### SystemD config +Systemd is the process manager of choice on ubuntu. Once you have a ``docker`` service installed, you can add use the following steps to set up Shaarli to run on system start. + +```bash +systemctl enable /etc/systemd/system/docker.shaarli.service +systemctl start docker.shaarli +systemctl status docker.* +journalctl -f # inspect system log if needed +``` + +You will need sudo or a root terminal to perform some or all of the steps above. Here are the contents for the service file: +``` +[Unit] +Description=Shaarli Bookmark Manager Container +After=docker.service +Requires=docker.service + + +[Service] +Restart=always + +# Put any environment you want in here, like $host- or $domainname in this example +EnvironmentFile=/etc/sysconfig/box-environment + +# It's just an example.. +ExecStart=/usr/bin/docker run \ + -p 28010:80 \ + --name ${hostname}-shaarli \ + --hostname shaarli.${domainname} \ + \ + -v /srv/docker-volumes-local/shaarli-data:/var/www/shaarli/data:rw \ + -v /etc/localtime:/etc/localtime:ro \ + \ + shaarli/shaarli:latest + +ExecStop=/usr/bin/docker rm -f ${hostname}-shaarli + + +[Install] +WantedBy=multi-user.target +``` From 2f65b3dd532be9f7a7054095ba3e8fd06be45883 Mon Sep 17 00:00:00 2001 From: "B. van Berkum" Date: Tue, 3 Oct 2017 01:03:27 +0200 Subject: [PATCH 31/36] Docker quickstart: one more grammar mistake. Made it a bit more terse. --- doc/md/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/md/index.md b/doc/md/index.md index f83d170..2b7d0f0 100644 --- a/doc/md/index.md +++ b/doc/md/index.md @@ -22,7 +22,7 @@ It runs the latest development version of Shaarli and is updated/reset daily. Login: `demo`; Password: `demo` -Docker users can start a personal instance from an [autobuild image](https://hub.docker.com/r/shaarli/shaarli/). For an example to start a temporary Shaarli at ``localhost:8000``, and keep the data you create (config, storage) during the session: +Docker users can start a personal instance from an [autobuild image](https://hub.docker.com/r/shaarli/shaarli/). For example to start a temporary Shaarli at ``localhost:8000``, and keep session data (config, storage): ``` MY_SHAARLI_VOLUME=$(cd /path/to/shaarli/data/ && pwd -P) docker run -ti --rm \ From df8becac4fc810d78917a9896dc72a1f7b336fb9 Mon Sep 17 00:00:00 2001 From: "B. van Berkum" Date: Fri, 6 Oct 2017 00:25:50 +0200 Subject: [PATCH 32/36] Minor docker-101 doc updates, typos fixed #983 --- doc/md/docker/docker-101.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/doc/md/docker/docker-101.md b/doc/md/docker/docker-101.md index 35a6877..a9c00b8 100644 --- a/doc/md/docker/docker-101.md +++ b/doc/md/docker/docker-101.md @@ -61,26 +61,26 @@ Digest: sha256:c584131da2ac1948aa3e66468a4424b6aea2f33acba7cec0b631bdb56254c4fe Status: Downloaded newer image for debian:wheezy ``` -Docker re-uses layers already downloaded. Iow. if you have images based only Alpine or some Ubuntu version for example, those can share disk space. +Docker re-uses layers already downloaded. In other words if you have images based on Alpine or some Ubuntu version for example, those can share disk space. ### Start a container A container is an instance created from an image, that can be run and that keeps running until its main process exits. Or until the user stops the container. The simplest way to start a container from image is ``docker run``. It also pulls the image for you if it is not locally available. For more advanced use, refer to ``docker create``. -Note that stopped containers are not destroyed, unless you specify ``--rm``. To view all created, running and stopped containers, enter: +Stopped containers are not destroyed, unless you specify ``--rm``. To view all created, running and stopped containers, enter: ```bash $ docker ps -a ``` -Some containers may be designed or configured to be restarted, others are not. Note that both network ports and volumes of a container are created on start, and not editable later. +Some containers may be designed or configured to be restarted, others are not. Also remember both network ports and volumes of a container are created on start, and not editable later. ### Access a running container A running container is accessible using ``docker exec``, or ``docker copy``. You can use ``exec`` to start a root shell in the Shaarli container: ```bash $ docker exec -ti bash ``` -Note the names and ID's of containers are list in ``docker ps``. You an even type only one or two letters of the ID, given they are unique. +Note the names and ID's of containers are listed in ``docker ps``. You can even type only one or two letters of the ID, given they are unique. Access can also be through one or more network ports, or disk volumes. Both are specified on and fixed on ``docker create`` or ``run``. @@ -92,15 +92,15 @@ $ docker logs -f ### Docker disk use Trying out different images can fill some gigabytes of disk quickly. Besides images, the docker volumes usually take up most disk space. -If you care only about trying out docker and not about what is running or saved, the following commands should help you out quickly: +If you care only about trying out docker and not about what is running or saved, the following commands should help you out quickly if you run low on disk space: ```bash $ docker rmi -f $(docker images -aq) # remove or mark all images for disposal $ docker volume rm $(docker volume ls -q) # remove all volumes ``` -### SystemD config -Systemd is the process manager of choice on ubuntu. Once you have a ``docker`` service installed, you can add use the following steps to set up Shaarli to run on system start. +### Systemd config +Systemd is the process manager of choice on Debian-based distributions. Once you have a ``docker`` service installed, you can use the following steps to set up Shaarli to run on system start. ```bash systemctl enable /etc/systemd/system/docker.shaarli.service @@ -120,7 +120,7 @@ Requires=docker.service [Service] Restart=always -# Put any environment you want in here, like $host- or $domainname in this example +# Put any environment you want in an included file, like $host- or $domainname in this example EnvironmentFile=/etc/sysconfig/box-environment # It's just an example.. @@ -128,11 +128,9 @@ ExecStart=/usr/bin/docker run \ -p 28010:80 \ --name ${hostname}-shaarli \ --hostname shaarli.${domainname} \ - \ -v /srv/docker-volumes-local/shaarli-data:/var/www/shaarli/data:rw \ -v /etc/localtime:/etc/localtime:ro \ - \ - shaarli/shaarli:latest + shaarli/shaarli:latest ExecStop=/usr/bin/docker rm -f ${hostname}-shaarli From d14555a3dfdc0d16badefcc54054802ae83752a4 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 7 Oct 2017 11:27:44 +0200 Subject: [PATCH 33/36] Fix security issue reported by @chbi Vulnerability introduced by 6ccd0b218fbd34de750f55b78f3dc43bb3d9fa8e - release with Shaarli v0.9.1. --- index.php | 4 ++-- tpl/default/tag.cloud.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index fb00a9f..8f0179e 100644 --- a/index.php +++ b/index.php @@ -840,7 +840,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) } $data = array( - 'search_tags' => implode(' ', $filteringTags), + 'search_tags' => implode(' ', escape($filteringTags)), 'tags' => $tagList, ); $pluginManager->executeHooks('render_tagcloud', $data, array('loggedin' => isLoggedIn())); @@ -870,7 +870,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) } $data = [ - 'search_tags' => implode(' ', $filteringTags), + 'search_tags' => implode(' ', escape($filteringTags)), 'tags' => $tags, ]; $pluginManager->executeHooks('render_taglist', $data, ['loggedin' => isLoggedIn()]); diff --git a/tpl/default/tag.cloud.html b/tpl/default/tag.cloud.html index 96b357a..68335c7 100644 --- a/tpl/default/tag.cloud.html +++ b/tpl/default/tag.cloud.html @@ -26,7 +26,7 @@ Date: Sat, 7 Oct 2017 12:05:07 +0200 Subject: [PATCH 34/36] Changelog v0.9.2 --- CHANGELOG.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60262d5..120c5d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,44 @@ 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.9.2](https://github.com/shaarli/Shaarli/releases/tag/v0.9.2) - 2017-10-07 + +**Major security issue fixed. Please update.** + +### Added +- Tag search now supports wildcards `*` +- New setting `privacy.force_login` which can be used with `privacy.hide_public_links` to redirect anonymous users to the login page. +- New setting `general.default_note_title` used to override default `Note:` title prefix for notes. +- Add a version hash for asset loading to prevent browser's cache issue + +### Changed +- The "Remember me" checkbox is unchecked by default +- The default value of the "Remember me" checkbox can be configured under `data/config.json.php` + +### Removed +- Remove obsolete PHP magic quote support + +### Fixed +- Generates a permalink URL if the URL is set to blank +- Replace links to the old GitHub wiki with ReadTheDocs URIs +- Use single quotes in the note bookmarklet +- Daily page if there is no link +- Bulk link deletion with a single link +- HTTPS detection behind a reverse proxy +- Travis tests environment and localization +- Improve template paths robustness (trailing slash) +- Robustness: safer gzinflate/zlib usage +- Description links parsing with parenthesis (without Markdown) +- Templates: + - Sort the tag cloud alphabetically + - Firefox social title + - Improved visited link color + - Fix jumpy textarea with long content in post edit + +### Security + +- Vulnerability introduced in v0.9.1 fixed. + ## [v0.9.1](https://github.com/shaarli/Shaarli/releases/tag/v0.9.1) - 2017-08-23 The documentation has been migrated to ReadTheDocs: From 6770135b0aca9ca3399c74afa6f2f9ce47fd6a05 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 7 Oct 2017 12:06:29 +0200 Subject: [PATCH 35/36] Update AUTHORS Signed-off-by: ArthurHoaro --- .github/mailmap | 2 ++ AUTHORS | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/mailmap b/.github/mailmap index 41d91e4..bbdb790 100644 --- a/.github/mailmap +++ b/.github/mailmap @@ -11,3 +11,5 @@ Timo Van Neerden lehollandaisvolant VirtualTam VirtualTam +Willi Eggeling +Willi Eggeling diff --git a/AUTHORS b/AUTHORS index 2181ec9..105561c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,11 +1,13 @@ - 518 ArthurHoaro - 231 VirtualTam - 147 nodiscc + 537 ArthurHoaro + 252 VirtualTam + 148 nodiscc 56 Sébastien Sauvage 15 Florian Eula 13 Emilien Klein 12 Nicolas Danelon + 9 Willi Eggeling 8 Christophe HENRY + 6 B. van Berkum 5 Lucas Cimon 4 Alexandre Alapetite 4 David Sferruzza @@ -37,6 +39,7 @@ 1 Kevin Canévet 1 Knah Tsaeb 1 Lionel Martin + 1 Mark Gerarts 1 Marsup 1 Sbgodin 1 TsT From ecccb14e2ab4e5f372ea9946b29995c3c7122a5c Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 7 Oct 2017 12:23:44 +0200 Subject: [PATCH 36/36] Bump Shaarli version to v0.9.2 Signed-off-by: ArthurHoaro --- shaarli_version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shaarli_version.php b/shaarli_version.php index 102289f..035a86a 100644 --- a/shaarli_version.php +++ b/shaarli_version.php @@ -1 +1 @@ - +