aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.htaccess1
-rw-r--r--.travis.yml13
-rw-r--r--application/bookmark/BookmarkInitializer.php74
-rw-r--r--application/front/controller/admin/PluginsController.php1
-rw-r--r--application/plugin/PluginManager.php29
-rw-r--r--doc/md/3rd-party-libraries.md21
-rw-r--r--doc/md/Backup-and-restore.md11
-rw-r--r--doc/md/Browsing-and-searching.md37
-rw-r--r--doc/md/Community-and-related-software.md (renamed from doc/md/Community-&-Related-software.md)60
-rw-r--r--doc/md/Continuous-integration-tools.md32
-rw-r--r--doc/md/Development-guidelines.md13
-rw-r--r--doc/md/Directory-structure.md54
-rw-r--r--doc/md/Docker.md227
-rw-r--r--doc/md/Download-and-Installation.md124
-rw-r--r--doc/md/FAQ.md46
-rw-r--r--doc/md/Installation.md78
-rw-r--r--doc/md/Link-structure.md18
-rw-r--r--doc/md/Plugins.md61
-rw-r--r--doc/md/REST-API.md159
-rw-r--r--doc/md/RSS-feeds.md28
-rw-r--r--doc/md/Release-Shaarli.md161
-rw-r--r--doc/md/Reverse-proxy.md141
-rw-r--r--doc/md/Security.md25
-rw-r--r--doc/md/Server-configuration.md644
-rw-r--r--doc/md/Server-security.md76
-rw-r--r--doc/md/Shaarli-configuration.md216
-rw-r--r--doc/md/Sharing-content.md71
-rw-r--r--doc/md/Static-analysis.md13
-rw-r--r--doc/md/Troubleshooting.md140
-rw-r--r--doc/md/Unit-tests.md119
-rw-r--r--doc/md/Upgrade-and-migration.md144
-rw-r--r--doc/md/Usage.md111
-rw-r--r--doc/md/dev/Development.md179
-rw-r--r--doc/md/dev/GnuPG-signature.md (renamed from doc/md/GnuPG-signature.md)20
-rw-r--r--doc/md/dev/Plugin-system.md (renamed from doc/md/Plugin-System.md)72
-rw-r--r--doc/md/dev/Release-Shaarli.md145
-rw-r--r--doc/md/dev/Theming.md (renamed from doc/md/Theming.md)3
-rw-r--r--doc/md/dev/Translations.md (renamed from doc/md/Translations.md)71
-rw-r--r--doc/md/dev/Unit-tests.md138
-rw-r--r--doc/md/dev/Versioning.md (renamed from doc/md/Versioning-and-Branches.md)28
-rw-r--r--doc/md/dev/images/poedit-1.jpg (renamed from doc/md/images/poedit-1.jpg)bin72956 -> 72956 bytes
-rw-r--r--doc/md/docker/docker-101.md140
-rw-r--r--doc/md/docker/resources.md19
-rw-r--r--doc/md/docker/reverse-proxy-configuration.md123
-rw-r--r--doc/md/docker/shaarli-images.md118
-rw-r--r--doc/md/guides/backup-restore-import-export.md64
-rw-r--r--doc/md/guides/images/01-create-droplet-distro.jpgbin20909 -> 0 bytes
-rw-r--r--doc/md/guides/images/02-create-droplet-region.jpgbin21603 -> 0 bytes
-rw-r--r--doc/md/guides/images/03-create-droplet-size.jpgbin20860 -> 0 bytes
-rw-r--r--doc/md/guides/images/04-finalize.jpgbin28233 -> 0 bytes
-rw-r--r--doc/md/guides/images/05-droplet.jpgbin11977 -> 0 bytes
-rw-r--r--doc/md/guides/images/06-domain.jpgbin4499 -> 0 bytes
-rw-r--r--doc/md/guides/install-shaarli-with-debian9-and-docker.md257
-rw-r--r--doc/md/guides/various-hacks.md24
-rw-r--r--doc/md/images/07-installation.jpg (renamed from doc/md/guides/images/07-installation.jpg)bin42832 -> 42832 bytes
-rw-r--r--doc/md/images/bookmarklet.pngbin53346 -> 0 bytes
-rw-r--r--doc/md/images/firefoxshare.pngbin715 -> 0 bytes
-rw-r--r--doc/md/images/install-shaarli.pngbin33827 -> 0 bytes
-rw-r--r--doc/md/index.md127
-rw-r--r--inc/languages/fr/LC_MESSAGES/shaarli.po269
-rw-r--r--mkdocs.yml46
-rw-r--r--plugins/playvideos/README.md9
-rw-r--r--tests/PluginManagerTest.php44
-rw-r--r--tests/bookmark/BookmarkFileServiceTest.php18
-rw-r--r--tests/bookmark/BookmarkInitializerTest.php70
-rw-r--r--tests/front/controller/admin/PluginsControllerTest.php5
-rw-r--r--tests/plugins/test/test.php3
67 files changed, 2316 insertions, 2624 deletions
diff --git a/.htaccess b/.htaccess
index 4c004271..8876e346 100644
--- a/.htaccess
+++ b/.htaccess
@@ -7,6 +7,7 @@ RewriteEngine On
7RewriteRule ^(.git|doxygen|vendor) - [F] 7RewriteRule ^(.git|doxygen|vendor) - [F]
8 8
9# Forward the "Authorization" HTTP header 9# Forward the "Authorization" HTTP header
10# fixes JWT token not correctly forwarded on some Apache/FastCGI setups
10RewriteCond %{HTTP:Authorization} ^(.*) 11RewriteCond %{HTTP:Authorization} ^(.*)
11RewriteRule .* - [e=HTTP_AUTHORIZATION:%1] 12RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
12 13
diff --git a/.travis.yml b/.travis.yml
index d04a45d1..c414967b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,6 +2,7 @@ dist: bionic
2 2
3matrix: 3matrix:
4 include: 4 include:
5 # jobs for each supported php version
5 - language: php 6 - language: php
6 php: 7.4 7 php: 7.4
7 - language: php 8 - language: php
@@ -10,23 +11,22 @@ matrix:
10 php: 7.2 11 php: 7.2
11 - language: php 12 - language: php
12 php: 7.1 13 php: 7.1
14 # jobs for frontend builds
13 - language: node_js 15 - language: node_js
14 node_js: 8 16 node_js: 8
15 cache: 17 cache:
16 yarn: true 18 yarn: true
17 directories: 19 directories:
18 - $HOME/.cache/yarn 20 - $HOME/.cache/yarn
19
20 install: 21 install:
21 - yarn install 22 - yarn install
22
23 before_script: 23 before_script:
24 - PATH=${PATH//:\.\/node_modules\/\.bin/} 24 - PATH=${PATH//:\.\/node_modules\/\.bin/}
25
26 script: 25 script:
27 - yarn run build # Just to be sure that the build isn't broken 26 - yarn run build # verify successful frontend builds
28 - make eslint 27 - make eslint # javascript static analysis
29 - make sasslint 28 - make sasslint # linter for SASS syntax
29 # jobs for documentation builds
30 - language: python 30 - language: python
31 python: 3.6 31 python: 3.6
32 cache: 32 cache:
@@ -42,6 +42,7 @@ cache:
42 - $HOME/.composer/cache 42 - $HOME/.composer/cache
43 43
44install: 44install:
45 # install/update composer and php dependencies
45 - composer install --prefer-dist 46 - composer install --prefer-dist
46 47
47before_script: 48before_script:
diff --git a/application/bookmark/BookmarkInitializer.php b/application/bookmark/BookmarkInitializer.php
index cd2d1724..815047e3 100644
--- a/application/bookmark/BookmarkInitializer.php
+++ b/application/bookmark/BookmarkInitializer.php
@@ -34,25 +34,77 @@ class BookmarkInitializer
34 public function initialize() 34 public function initialize()
35 { 35 {
36 $bookmark = new Bookmark(); 36 $bookmark = new Bookmark();
37 $bookmark->setTitle(t('My secret stuff... - Pastebin.com')); 37 $bookmark->setTitle('quicksilver (loop) on Vimeo ' . t('(private bookmark with thumbnail demo)'));
38 $bookmark->setUrl('http://sebsauvage.net/paste/?8434b27936c09649#bR7XsXhoTiLcqCpQbmOpBi3rq2zzQUC5hBI7ZT1O3x8='); 38 $bookmark->setUrl('https://vimeo.com/153493904');
39 $bookmark->setDescription(t('Shhhh! I\'m a private link only YOU can see. You can delete me too.')); 39 $bookmark->setDescription(t(
40 $bookmark->setTagsString('secretstuff'); 40'Shaarli will automatically pick up the thumbnail for links to a variety of websites.
41
42Explore your new Shaarli instance by trying out controls and menus.
43Visit the project on [Github](https://github.com/shaarli/Shaarli) or [the documentation](https://shaarli.readthedocs.io/en/master/) to learn more about Shaarli.
44
45Now you can edit or delete the default shaares.
46'
47 ));
48 $bookmark->setTagsString('shaarli help thumbnail');
49 $bookmark->setPrivate(true);
50 $this->bookmarkService->add($bookmark, false);
51
52 $bookmark = new Bookmark();
53 $bookmark->setTitle(t('Note: Shaare descriptions'));
54 $bookmark->setDescription(t(
55'Adding a shaare without entering a URL creates a text-only "note" post such as this one.
56This note is private, so you are the only one able to see it while logged in.
57
58You can use this to keep notes, post articles, code snippets, and much more.
59
60The Markdown formatting setting allows you to format your notes and bookmark description:
61
62### Title headings
63
64#### Multiple headings levels
65 * bullet lists
66 * _italic_ text
67 * **bold** text
68 * ~~strike through~~ text
69 * `code` blocks
70 * images
71 * [links](https://en.wikipedia.org/wiki/Markdown)
72
73Markdown also supports tables:
74
75| Name | Type | Color | Qty |
76| ------- | --------- | ------ | ----- |
77| Orange | Fruit | Orange | 126 |
78| Apple | Fruit | Any | 62 |
79| Lemon | Fruit | Yellow | 30 |
80| Carrot | Vegetable | Red | 14 |
81'
82 ));
83 $bookmark->setTagsString('shaarli help');
41 $bookmark->setPrivate(true); 84 $bookmark->setPrivate(true);
42 $this->bookmarkService->add($bookmark, false); 85 $this->bookmarkService->add($bookmark, false);
43 86
44 $bookmark = new Bookmark(); 87 $bookmark = new Bookmark();
45 $bookmark->setTitle(t('The personal, minimalist, super-fast, database free, bookmarking service')); 88 $bookmark->setTitle(
46 $bookmark->setUrl('https://shaarli.readthedocs.io', []); 89 'Shaarli - ' . t('The personal, minimalist, super-fast, database free, bookmarking service')
90 );
47 $bookmark->setDescription(t( 91 $bookmark->setDescription(t(
48 'Welcome to Shaarli! This is your first public bookmark. ' 92'Welcome to Shaarli!
49 . 'To edit or delete me, you must first login. 93
94Shaarli allows you to bookmark your favorite pages, and share them with others or store them privately.
95You can add a description to your bookmarks, such as this one, and tag them.
96
97Create a new shaare by clicking the `+Shaare` button, or using any of the recommended tools (browser extension, mobile app, bookmarklet, REST API, etc.).
50 98
51To learn how to use Shaarli, consult the link "Documentation" at the bottom of this page. 99You can easily retrieve your links, even with thousands of them, using the internal search engine, or search through tags (e.g. this Shaare is tagged with `shaarli` and `help`).
100Hashtags such as #shaarli #help are also supported.
101You can also filter the available [RSS feed](/feed/atom) and picture wall by tag or plaintext search.
52 102
53You use the community supported version of the original Shaarli project, by Sebastien Sauvage.' 103We hope that you will enjoy using Shaarli, maintained with ❤️ by the community!
104Feel free to open [an issue](https://github.com/shaarli/Shaarli/issues) if you have a suggestion or encounter an issue.
105'
54 )); 106 ));
55 $bookmark->setTagsString('opensource software'); 107 $bookmark->setTagsString('shaarli help');
56 $this->bookmarkService->add($bookmark, false); 108 $this->bookmarkService->add($bookmark, false);
57 } 109 }
58} 110}
diff --git a/application/front/controller/admin/PluginsController.php b/application/front/controller/admin/PluginsController.php
index 0e09116e..8e059681 100644
--- a/application/front/controller/admin/PluginsController.php
+++ b/application/front/controller/admin/PluginsController.php
@@ -62,6 +62,7 @@ class PluginsController extends ShaarliAdminController
62 62
63 if (isset($parameters['parameters_form'])) { 63 if (isset($parameters['parameters_form'])) {
64 unset($parameters['parameters_form']); 64 unset($parameters['parameters_form']);
65 unset($parameters['token']);
65 foreach ($parameters as $param => $value) { 66 foreach ($parameters as $param => $value) {
66 $this->container->conf->set('plugins.'. $param, escape($value)); 67 $this->container->conf->set('plugins.'. $param, escape($value));
67 } 68 }
diff --git a/application/plugin/PluginManager.php b/application/plugin/PluginManager.php
index 7881e3be..1b2197c9 100644
--- a/application/plugin/PluginManager.php
+++ b/application/plugin/PluginManager.php
@@ -100,20 +100,17 @@ class PluginManager
100 */ 100 */
101 public function executeHooks($hook, &$data, $params = array()) 101 public function executeHooks($hook, &$data, $params = array())
102 { 102 {
103 if (!empty($params['target'])) { 103 $metadataParameters = [
104 $data['_PAGE_'] = $params['target']; 104 'target' => '_PAGE_',
105 } 105 'loggedin' => '_LOGGEDIN_',
106 106 'basePath' => '_BASE_PATH_',
107 if (isset($params['loggedin'])) { 107 'bookmarkService' => '_BOOKMARK_SERVICE_',
108 $data['_LOGGEDIN_'] = $params['loggedin']; 108 ];
109 } 109
110 110 foreach ($metadataParameters as $parameter => $metaKey) {
111 if (isset($params['basePath'])) { 111 if (array_key_exists($parameter, $params)) {
112 $data['_BASE_PATH_'] = $params['basePath']; 112 $data[$metaKey] = $params[$parameter];
113 } 113 }
114
115 if (isset($params['bookmarkService'])) {
116 $data['_BOOKMARK_SERVICE_'] = $params['bookmarkService'];
117 } 114 }
118 115
119 foreach ($this->loadedPlugins as $plugin) { 116 foreach ($this->loadedPlugins as $plugin) {
@@ -128,6 +125,10 @@ class PluginManager
128 } 125 }
129 } 126 }
130 } 127 }
128
129 foreach ($metadataParameters as $metaKey) {
130 unset($data[$metaKey]);
131 }
131 } 132 }
132 133
133 /** 134 /**
diff --git a/doc/md/3rd-party-libraries.md b/doc/md/3rd-party-libraries.md
deleted file mode 100644
index 7e7dd334..00000000
--- a/doc/md/3rd-party-libraries.md
+++ /dev/null
@@ -1,21 +0,0 @@
1## CSS
2
3- Yahoo UI [CSS Reset](http://yuilibrary.com/yui/docs/cssreset/) - standardize cross-browser rendering
4
5## Javascript
6
7- [Awesomeplete](https://leaverou.github.io/awesomplete/) ([GitHub](https://github.com/LeaVerou/awesomplete)) - autocompletion in input forms
8- [bLazy](http://dinbror.dk/blazy/) ([GitHub](https://github.com/dinbror/blazy)) - lazy loading for thumbnails
9- [qr.js](http://neocotic.com/qr.js/) ([GitHub](https://github.com/neocotic/qr.js)) - QR code generation
10
11## PHP
12
13- [RainTPL](https://github.com/rainphp/raintpl) - HTML templating for PHP
14
15### Composer
16
17Library | Usage
18---|---
19[`shaarli/netscape-bookmark-parser`](https://packagist.org/packages/shaarli/netscape-bookmark-parser) | Import bookmarks from Netscape files
20[`erusev/parsedown`](https://packagist.org/packages/erusev/parsedown) | Parse MarkDown syntax for the MarkDown plugin
21[`slim/slim`](https://packagist.org/packages/slim/slim) | Handle routes and middleware for the REST API
diff --git a/doc/md/Backup-and-restore.md b/doc/md/Backup-and-restore.md
new file mode 100644
index 00000000..e7e2775c
--- /dev/null
+++ b/doc/md/Backup-and-restore.md
@@ -0,0 +1,11 @@
1## Backup and restore
2
3All data and [configuration](Shaarli-configuration.md) is kept in the `data` directory. Backup this directory:
4
5```bash
6rsync -avzP my.server.com:/var/www/shaarli.mydomain.org/data ~/backups/shaarli-data-$(date +%Y-%m-%d_%H%M)
7```
8
9It is strongly recommended to do periodic, automatic backups to a seperate machine. You can automate the command above using a cron job or full-featured backup solutions such as [rsnapshot](https://rsnapshot.org/)
10
11To restore a backup, simply put back the `data/` directory in place, owerwriting any existing files. \ No newline at end of file
diff --git a/doc/md/Browsing-and-searching.md b/doc/md/Browsing-and-searching.md
deleted file mode 100644
index 16c69855..00000000
--- a/doc/md/Browsing-and-searching.md
+++ /dev/null
@@ -1,37 +0,0 @@
1## Plain text search
2
3Use the `Search text` field to search in _any_ of the fields of all links (Title, URL, Description...)
4
5**Exclude text/tags:** Use the `-` operator before a word or tag (example `-uninteresting`) to prevent entries containing (or tagged) `uninteresting` from showing up in the search results.
6
7**Exact text search:** Use double-quotes (example `"exact search"`) to search for the exact expression.
8
9Both exclude patterns and exact searches can be combined with normal searches (example `"exact search" term otherterm -notthis "very exact" stuff -notagain`)
10
11## Tags search
12
13Use the `Filter by tags` field to restrict displayed links to entries tagged with one or multiple tags (use space to separate tags).
14
15**Hidden tags:** Tags starting with a dot `.` (example `.secret`) are private. They can only be seen and searched when logged in.
16
17### Tag cloud
18
19The `Tag cloud` page diplays a "cloud" view of all tags in your Shaarli.
20
21 * The most frequently used tags are displayed with a bigger font size.
22 * When sorting by `Most used` or `Alphabetical`, tags are displayed as a _list_, along with counters and edit/delete buttons for each tag.
23 * Clicking on any tag will display a list of all Shaares matching this tag.
24 * Clicking on the counter next to a tag `example`, will filter the tag cloud to only display tags found in Shaares tagged `example`. Repeat this any number of times to further filter the tag cloud. Click `List all links with those tags` to display Shaares matching your current tag filter.
25
26## Filtering RSS feeds/Picture wall
27
28RSS feeds can also be restricted to only return items matching a text/tag search: see [RSS feeds](RSS-feeds).
29
30## Filter buttons
31
32Filter buttons can be found at the top left of the link list. They allow you to apply different filters to the list:
33
34 * **Private links:** When this toggle button is enabled, only shaares set to `private` will be shown.
35 * **Untagged links:** When the this toggle button is enabled (top left of the link list), only shaares _without any tags_ will be shown in the link list.
36
37Filter buttons are only available when logged in.
diff --git a/doc/md/Community-&-Related-software.md b/doc/md/Community-and-related-software.md
index 54f18c8e..53a7555e 100644
--- a/doc/md/Community-&-Related-software.md
+++ b/doc/md/Community-and-related-software.md
@@ -1,66 +1,87 @@
1# Community & related software
2
1_Unofficial but related work on Shaarli. If you maintain one of these, 3_Unofficial but related work on Shaarli. If you maintain one of these,
2please get in touch with us to help us find a way to adapt your work to our fork._ 4please get in touch with us to help us find a way to adapt your work to our fork._
3 5
4## Related software
5 6
7## Related software
6 8
7### REST API clients 9### REST API clients
8See [REST API](REST-API) for a list of official and community clients. 10See [REST API](REST-API) for a list of official and community clients.
9 11
10 12
11### Third party plugins 13### Third party plugins
12- [autosave](https://github.com/kalvn/shaarli-plugin-autosave) by [@kalvn](https://github.com/kalvn): Automatically saves data when editing a link to avoid any loss in case of crash or unexpected shutdown. 14
13- [Code Coloration](https://github.com/ArthurHoaro/code-coloration) by [@ArthurHoaro](https://github.com/ArthurHoaro): client side code syntax highlighter. 15- [autosave](https://github.com/kalvn/shaarli-plugin-autosave) by [@kalvn](https://github.com/kalvn): Automatically saves data when editing a Shaare to avoid any loss in case of crash or unexpected shutdown.
14- [Disqus](https://github.com/kalvn/shaarli-plugin-disqus) by [@kalvn](https://github.com/kalvn): Adds Disqus comment system to your Shaarli. 16- [code-coloration](https://github.com/ArthurHoaro/code-coloration) by [@ArthurHoaro](https://github.com/ArthurHoaro): client side code syntax highlighter.
17- [custom-css](https://github.com/immanuelfodor/shaarli-custom-css) by [@immanuelfodor](https://github.com/immanuelfodor) - Customize the look and feel of the UI with custom CSS rules
18- [disqus](https://github.com/kalvn/shaarli-plugin-disqus) by [@kalvn](https://github.com/kalvn): Adds Disqus comment system to your Shaarli.
19- [emojione](https://github.com/immanuelfodor/emojione) by [@immanuelfodor](https://github.com/immanuelfodor) - Resurrected fork of the original emojione project
20- [favicons](https://github.com/trailjeep/shaarli-favicons) by [@trailjeep](https://github.com/trailjeep) - Shaarli plugin to add favicon/filetype icons to Shaares.
15- [google analytics](https://github.com/ericjuden/Shaarli-Google-Analytics-Plugin) by [@ericjuden](http://github.com/ericjuden): Adds Google Analytics tracking support 21- [google analytics](https://github.com/ericjuden/Shaarli-Google-Analytics-Plugin) by [@ericjuden](http://github.com/ericjuden): Adds Google Analytics tracking support
16- [launch](https://github.com/ArthurHoaro/launch-plugin) - Launch Plugin is a plugin designed to enhance and customize Launch Theme for Shaarli. 22- [launch](https://github.com/ArthurHoaro/launch-plugin) - Launch Plugin is a plugin designed to enhance and customize Launch Theme for Shaarli.
17- [markdown-toolbar](https://github.com/immanuelfodor/shaarli-markdown-toolbar) by [@immanuelfodor](https://github.com/immanuelfodor) - Easily insert markdown syntax into the Description field when editing a link. 23- [markdown-toolbar](https://github.com/immanuelfodor/shaarli-markdown-toolbar) by [@immanuelfodor](https://github.com/immanuelfodor) - Easily insert markdown syntax into the Description field when editing a Shaare.
18- [related](https://github.com/ilesinge/shaarli-related) by [@ilesinge](https://github.com/ilesinge) - Show related links based on the number of identical tags. 24- [related](https://github.com/ilesinge/shaarli-related) by [@ilesinge](https://github.com/ilesinge) - Show related Shaares based on the number of identical tags.
19- [social](https://github.com/alexisju/social) by [@alexisju](https://github.com/alexisju): share links to social networks. 25- [shaarli-descriptor](https://github.com/immanuelfodor/shaarli-descriptor) by [@immanuelfodor](https://github.com/immanuelfodor) - Customize the default height/number of rows of the Description field when editing a Shaare.
20- [shaarli2twitter](https://github.com/ArthurHoaro/shaarli2twitter) by [@ArthurHoaro](https://github.com/ArthurHoaro) - Automatically tweet your shared links from Shaarli
21- [shaarli2mastodon](https://github.com/kalvn/shaarli2mastodon) by [@kalvn](https://github.com/kalvn) - This Shaarli plugin allows you to automatically publish links you post on your Mastodon timeline. 26- [shaarli2mastodon](https://github.com/kalvn/shaarli2mastodon) by [@kalvn](https://github.com/kalvn) - This Shaarli plugin allows you to automatically publish links you post on your Mastodon timeline.
22- [shaarli-descriptor](https://github.com/immanuelfodor/shaarli-descriptor) by [@immanuelfodor](https://github.com/immanuelfodor) - Customize the default height/number of rows of the Description field when editing a link. 27- [shaarli2twitter](https://github.com/ArthurHoaro/shaarli2twitter) by [@ArthurHoaro](https://github.com/ArthurHoaro) - Automatically tweet your Shaares from Shaarli
28- [social](https://github.com/alexisju/social) by [@alexisju](https://github.com/alexisju): share links to social networks.
23- [urlextern](https://github.com/trailjeep/shaarli-urlextern) by [@trailjeep](https://github.com/trailjeep) - Shaarli plugin to open external links in a new tab/window. 29- [urlextern](https://github.com/trailjeep/shaarli-urlextern) by [@trailjeep](https://github.com/trailjeep) - Shaarli plugin to open external links in a new tab/window.
24- [favicons](https://github.com/trailjeep/shaarli-favicons) by [@trailjeep](https://github.com/trailjeep) - Shaarli plugin to add favicon/filetype icons to links. 30- [webhooks](https://gitlab.com/flow.gunso/shaarli-webhooks) by [@flow.gunso](https://gitlab.com/flow.gunso) - Shaarli plugin that enables user-defined callback URL, i.e. webhooks, for specific Shaarli events (link saving, deletion...)
31
25 32
26### Third-party themes 33### Third-party themes
34
27See [Theming](Theming) for a list of community-contributed themes, and an installation guide. 35See [Theming](Theming) for a list of community-contributed themes, and an installation guide.
28 36
29 37
30### Integration with other platforms 38### Integration with other platforms
39
31- [tt-rss-shaarli](https://github.com/jcsaaddupuy/tt-rss-shaarli) - [Tiny-Tiny RSS](http://tt-rss.org/) plugin that adds support for sharing articles with Shaarli 40- [tt-rss-shaarli](https://github.com/jcsaaddupuy/tt-rss-shaarli) - [Tiny-Tiny RSS](http://tt-rss.org/) plugin that adds support for sharing articles with Shaarli
32- [octopress-shaarli](https://github.com/ahmet2mir/octopress-shaarli) - Octopress plugin to retrieve Shaarli links on the sidebar 41- [octopress-shaarli](https://github.com/ahmet2mir/octopress-shaarli) - Octopress plugin to retrieve Shaarli Shaares on the sidebar
33- [Scuttle to Shaarli](https://github.com/q2apro/scuttle-to-shaarli) - Import bookmarks from Scuttle 42- [Scuttle to Shaarli](https://github.com/q2apro/scuttle-to-shaarli) - Import bookmarks from Scuttle
34- [Shaarli app for Cloudron](https://git.cloudron.io/cloudron/shaarli-app) - Effortlessly run Shaarli with the help of [Cloudron](https://cloudron.io/) [![Install](https://cloudron.io/img/button.svg)](https://cloudron.io/button.html?app=com.github.shaarli) 43- [Shaarli app for Cloudron](https://git.cloudron.io/cloudron/shaarli-app) - Effortlessly run Shaarli with the help of [Cloudron](https://cloudron.io/) [![Install](https://cloudron.io/img/button.svg)](https://cloudron.io/button.html?app=com.github.shaarli)
35- [Shaarli_ynh](https://github.com/YunoHost-Apps/shaarli_ynh) - Shaarli is available as a [Yunohost](https://yunohost.org) app [![Install Shaarli with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=shaarli) 44- [Shaarli_ynh](https://github.com/YunoHost-Apps/shaarli_ynh) - Shaarli is available as a [Yunohost](https://yunohost.org) app [![Install Shaarli with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=shaarli)
36- [pelican](https://blog.getpelican.com) static blog generator plugin to auto-post articles on a Shaarli instance: [shaarli_poster](https://github.com/getpelican/pelican-plugins/tree/master/shaarli_poster) 45- [pelican](https://blog.getpelican.com) static blog generator plugin to auto-post articles on a Shaarli instance: [shaarli_poster](https://github.com/getpelican/pelican-plugins/tree/master/shaarli_poster)
37 46
47
38### Mobile Apps 48### Mobile Apps
49
39- [ShaarliOS](https://github.com/mro/ShaarliOS) - Apple iOS share extension. 50- [ShaarliOS](https://github.com/mro/ShaarliOS) - Apple iOS share extension.
40- [Shaarli for Android](http://sebsauvage.net/links/?ZAyDzg) - Android application that adds Shaarli as a sharing provider 51- [Shaarli for Android](http://sebsauvage.net/links/?ZAyDzg) - Android application that adds Shaarli as a sharing provider
41- [Shaarlier for Android](https://github.com/dimtion/Shaarlier) - Android application to simply add links directly into your Shaarli 52- [Shaarlier for Android](https://github.com/dimtion/Shaarlier) - Android application to simply add Shaares directly into your Shaarli
42- [Stakali for Android](https://stakali.toneiv.eu) - Stakali is a personal bookmark manager which synchronizes with Shaarli 53- [Stakali for Android](https://stakali.toneiv.eu) - Stakali is a personal bookmark manager which synchronizes with Shaarli
43 54
55
44### Desktop Apps 56### Desktop Apps
57
45- [Ulauncher Extension](https://github.com/sebw/ulauncher-shaarli) - Ulauncher is an an application launcher for Linux, this extension allows research in your Shaarli 58- [Ulauncher Extension](https://github.com/sebw/ulauncher-shaarli) - Ulauncher is an an application launcher for Linux, this extension allows research in your Shaarli
46 59
60
47### Browser addons 61### Browser addons
62
48- [Shaarli Firefox Extension](https://github.com/ikipatang/shaarli-web-extension) - toolbar button to share your current tab with Shaarli. 63- [Shaarli Firefox Extension](https://github.com/ikipatang/shaarli-web-extension) - toolbar button to share your current tab with Shaarli.
49- [Shaarli Chrome Extension](https://github.com/octplane/Shiny-Shaarli) - toolbar button to share your current tab with Shaarli. 64- [Shaarli Chrome Extension](https://github.com/octplane/Shiny-Shaarli) - toolbar button to share your current tab with Shaarli.
50 65
66
51### Server apps 67### Server apps
68
52- [shaarchiver](https://github.com/nodiscc/shaarchiver) - Archive your Shaarli bookmarks and their content 69- [shaarchiver](https://github.com/nodiscc/shaarchiver) - Archive your Shaarli bookmarks and their content
53- [shaarli-river](https://github.com/mknexen/shaarli-river) - An aggregator for shaarlis with many features 70- [shaarli-river](https://github.com/mknexen/shaarli-river) - An aggregator for shaarlis with many features
54- [Shaarlo](https://github.com/DMeloni/shaarlo) - An aggregator for shaarlis with many features (a very popular running instance among French shaarliers: [shaarli.fr](http://shaarli.fr/)) 71- [Shaarlo](https://github.com/DMeloni/shaarlo) - An aggregator for shaarlis with many features
55- [Shaarlimages](https://github.com/BoboTiG/shaarlimages) - An image-oriented aggregator for Shaarlis 72- [Shaarlimages](https://github.com/BoboTiG/shaarlimages) - An image-oriented aggregator for Shaarlis
56- [mknexen/shaarli-api](https://github.com/mknexen/shaarli-api) - A REST API for Shaarli 73- [mknexen/shaarli-api](https://github.com/mknexen/shaarli-api) - A REST API for Shaarli
57- [Self dead link](https://framagit.org/qwertygc/shaarli-dev-code/blob/master/self-dead-link.php) - Detect dead links on shaarli. This version use the database of shaarli. [Another version](https://framagit.org/qwertygc/shaarli-dev-code/blob/master/dead-link.php), can be used for other shaarli instances (but is more resource consuming). 74- [Self dead link](https://framagit.org/qwertygc/shaarli-dev-code/blob/master/self-dead-link.php) - Detect dead links on shaarli. This version use the database of shaarli. [Another version](https://framagit.org/qwertygc/shaarli-dev-code/blob/master/dead-link.php), can be used for other shaarli instances (but is more resource consuming).
58- [Bookmark Archiver](https://github.com/pirate/bookmark-archiver) - Save an archived copy of all websites starred using browser bookmarks/Shaarli/Delicious/Instapaper/Unmark.it/Pocket/Pinboard. Outputs browseable html. 75- [Bookmark Archiver](https://github.com/pirate/bookmark-archiver) - Save an archived copy of all websites starred using browser bookmarks/Shaarli/Delicious/Instapaper/Unmark.it/Pocket/Pinboard. Outputs browseable html.
59 76
77
60## Alternatives to Shaarli 78## Alternatives to Shaarli
79
61See [awesome-selfhosted: bookmarks & link sharing](https://github.com/Kickball/awesome-selfhosted/#bookmarks--link-sharing). 80See [awesome-selfhosted: bookmarks & link sharing](https://github.com/Kickball/awesome-selfhosted/#bookmarks--link-sharing).
62 81
82
63## Community 83## Community
84
64- [Liens en vrac de sebsauvage](http://sebsauvage.net/links/) - the original Shaarli 85- [Liens en vrac de sebsauvage](http://sebsauvage.net/links/) - the original Shaarli
65- [A large list of Shaarlis](http://porneia.free.fr/pub/links/ou-est-shaarli.html) 86- [A large list of Shaarlis](http://porneia.free.fr/pub/links/ou-est-shaarli.html)
66- [A list of working Shaarli aggregators](https://raw.githubusercontent.com/Oros42/find_shaarlis/master/annuaires.json) 87- [A list of working Shaarli aggregators](https://raw.githubusercontent.com/Oros42/find_shaarlis/master/annuaires.json)
@@ -71,8 +92,17 @@ See [awesome-selfhosted: bookmarks & link sharing](https://github.com/Kickball/a
71- [Original revisions history](http://sebsauvage.net/wiki/doku.php?id=php:shaarli:history) 92- [Original revisions history](http://sebsauvage.net/wiki/doku.php?id=php:shaarli:history)
72- [Shaarli.fr/my](https://www.shaarli.fr/my.php) - Unofficial, unsupported (old fork) hosted Shaarlis provider, courtesy of [DMeloni](https://github.com/DMeloni) 93- [Shaarli.fr/my](https://www.shaarli.fr/my.php) - Unofficial, unsupported (old fork) hosted Shaarlis provider, courtesy of [DMeloni](https://github.com/DMeloni)
73 94
95
74### Articles and social media discussions 96### Articles and social media discussions
75- 2016-09-22 - Hacker News - https://news.ycombinator.com/item?id=12552176 97- 2020-04-05 - Hacker News - [Self-hosted instance of Shaarli - it is simple, fast and reliable](https://news.ycombinator.com/item?id=22780219)
98- 2016-10-10 - Framasoft - [MyFrama : vos favoris partout, avec vous, rien qu’à vous !](https://framablog.org/2016/10/10/myframa-vos-favoris-et-framasofteries-partout-avec-vous-rien-qua-vous/)
99- 2016-09-22 - Hacker News - [Shaarli – Personal, minimalist, database-free, bookmarking service (github.com)](https://news.ycombinator.com/item?id=12552176)
76- 2015-08-15 - Reddit - [Question about migrating from WordPress to Shaarli.](https://www.reddit.com/r/selfhosted/comments/3h3zwh/question_about_migrating_from_wordpress_to_shaarli/) 100- 2015-08-15 - Reddit - [Question about migrating from WordPress to Shaarli.](https://www.reddit.com/r/selfhosted/comments/3h3zwh/question_about_migrating_from_wordpress_to_shaarli/)
77- 2015-06-22 - Hacker News - https://news.ycombinator.com/item?id=9755366 101- 2015-06-22 - Hacker News - [Shaarli: Self-hosted del.icio.us alternative (sebsauvage.net)](https://news.ycombinator.com/item?id=9755366)
78- 2015-05-12 - Reddit - [shaarli - Self hosted Bookmarking / Delicious (PHP, MySQL)](https://www.reddit.com/r/selfhosted/comments/35pkkc/shaarli_self_hosted_bookmarking_delicious_php/) 102- 2015-05-12 - Reddit - [shaarli - Self hosted Bookmarking / Delicious (PHP, MySQL)](https://www.reddit.com/r/selfhosted/comments/35pkkc/shaarli_self_hosted_bookmarking_delicious_php/)
103- 2014-10-15 - OpenSource.com - [Five open source alternatives to popular web apps](https://opensource.com/life/14/10/five-open-source-alternatives-popular-web-apps)
104
105It also appears in the following recommendation lists:
106- [AlternativeTo](https://alternativeto.net/software/shaarli/)
107- [FramaLibre](https://framalibre.org/content/shaarli)
108- [Project Awesome: Selfhosted Bookmarks and Link Sharing](https://project-awesome.org/Kickball/awesome-selfhosted)
diff --git a/doc/md/Continuous-integration-tools.md b/doc/md/Continuous-integration-tools.md
deleted file mode 100644
index f7819d5a..00000000
--- a/doc/md/Continuous-integration-tools.md
+++ /dev/null
@@ -1,32 +0,0 @@
1## Local development
2A [`Makefile`](https://github.com/shaarli/Shaarli/blob/master/Makefile) is available to perform project-related operations:
3
4- Documentation - generate a local HTML copy of the GitHub wiki
5- [Static analysis](Static-analysis) - check that the code is compliant to PHP conventions
6- [Unit tests](Unit-tests) - ensure there are no regressions introduced by new commits
7
8## Automatic builds
9[Travis CI](http://docs.travis-ci.com/) is a Continuous Integration build server, that runs a build:
10
11- each time a commit is merged to the mainline (`master` branch)
12- each time a Pull Request is submitted or updated
13
14A build is composed of several jobs: one for each supported PHP version (see [Server requirements](Server requirements)).
15
16Each build job:
17
18- updates Composer
19- installs 3rd-party test dependencies with Composer
20- runs [Unit tests](Unit-tests)
21- runs ESLint check
22
23After all jobs have finished, Travis returns the results to GitHub:
24
25- a status icon represents the result for the `master` branch: [![](https://api.travis-ci.org/shaarli/Shaarli.svg)](https://travis-ci.org/shaarli/Shaarli)
26- Pull Requests are updated with the Travis result
27 - Green: all tests have passed
28 - Red: some tests failed
29 - Orange: tests are pending
30
31## Documentation
32[mkdocs](https://www.mkdocs.org/) is used to convert markdown documentation to HTML pages. The [public documentation](https://shaarli.readthedocs.io/en/master/) website is rendered and hosted by [readthedocs.org](https://readthedocs.org/). A copy of the documentation is also included in prebuilt [release archives](https://github.com/shaarli/Shaarli/releases) (`doc/html/` path in your Shaarli installation). To generate the HTML documentation locally, install a recent version of Python `setuptools` and run `make doc`.
diff --git a/doc/md/Development-guidelines.md b/doc/md/Development-guidelines.md
deleted file mode 100644
index 46b7c6f8..00000000
--- a/doc/md/Development-guidelines.md
+++ /dev/null
@@ -1,13 +0,0 @@
1## Development guidelines
2
3Please have a look at the following pages:
4
5- [Contributing to Shaarli](https://github.com/shaarli/Shaarli/tree/master/CONTRIBUTING.md)
6- [Static analysis](Static-analysis) - patches should try to stick to the
7[PHP Standard Recommendations](http://www.php-fig.org/psr/) (PSR), especially:
8 - [PSR-1](http://www.php-fig.org/psr/psr-1/) - Basic Coding Standard
9 - [PSR-2](http://www.php-fig.org/psr/psr-2/) - Coding Style Guide
10- [Unit tests](Unit-tests)
11- Javascript linting - Shaarli uses [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript).
12Run `make eslint` to check JS style.
13- [GnuPG signature](GnuPG-signature) for tags/releases
diff --git a/doc/md/Directory-structure.md b/doc/md/Directory-structure.md
deleted file mode 100644
index c0b49393..00000000
--- a/doc/md/Directory-structure.md
+++ /dev/null
@@ -1,54 +0,0 @@
1## Directory structure
2
3Here is the directory structure of Shaarli and the purpose of the different files:
4
5```bash
6 index.php # Main program
7 application/ # Shaarli classes
8 ├── LinkDB.php
9
10 ...
11
12 └── Utils.php
13 tests/ # Shaarli unitary & functional tests
14 ├── LinkDBTest.php
15
16 ...
17
18 ├── utils # utilities to ease testing
19 │ └── ReferenceLinkDB.php
20 └── UtilsTest.php
21 assets/
22 ├── common/ # Assets shared by multiple themes
23 ├── ...
24 ├── default/ # Assets for the default template, before compilation
25 ├── fonts/ # Font files
26 ├── img/ # Images used by the default theme
27 ├── js/ # JavaScript files in ES6 syntax
28 ├── scss/ # SASS files
29 └── vintage/ # Assets for the vintage template, before compilation
30 └── ...
31 COPYING # Shaarli license
32 inc/ # static assets and 3rd party libraries
33 └── rain.tpl.class.php # RainTPL templating library
34 images/ # Images and icons used in Shaarli
35 data/ # data storage: bookmark database, configuration, logs, banlist...
36 ├── config.json.php # Shaarli configuration (login, password, timezone, title...)
37 ├── datastore.php # Your link database (compressed).
38 ├── ipban.php # IP address ban system data
39 ├── lastupdatecheck.txt # Update check timestamp file
40 └── log.txt # login/IPban log.
41 tpl/ # RainTPL templates for Shaarli. They are used to build the pages.
42 ├── default/ # Default Shaarli theme
43 ├── fonts/ # Font files
44 ├── img/ # Images
45 ├── js/ # JavaScript files compiled by Babel and compatible with all browsers
46 ├── css/ # CSS files compiled with SASS
47 └── vintage/ # Legacy Shaarli theme
48 └── ...
49 cache/ # thumbnails cache
50 # This directory is automatically created. You can erase it anytime you want.
51 tmp/ # Temporary directory for compiled RainTPL templates.
52 # This directory is automatically created. You can erase it anytime you want.
53 vendor/ # Third-party dependencies. This directory is created by Composer
54```
diff --git a/doc/md/Docker.md b/doc/md/Docker.md
new file mode 100644
index 00000000..c152fe92
--- /dev/null
+++ b/doc/md/Docker.md
@@ -0,0 +1,227 @@
1# Docker
2
3[Docker](https://docs.docker.com/get-started/overview/) is an open platform for developing, shipping, and running applications
4
5## Install Docker
6
7Install [Docker](https://docs.docker.com/engine/install/), by following the instructions relevant to your OS / distribution, and start the service. For example on [Debian](https://docs.docker.com/engine/install/debian/):
8
9```bash
10# update your package lists
11sudo apt update
12# remove old versions
13sudo apt-get remove docker docker-engine docker.io containerd runc
14# install requirements
15sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
16# add docker's GPG signing key
17curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
18# add the repository
19sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
20# install docker engine
21sudo apt-get update
22sudo apt-get install docker-ce docker-ce-cli containerd.io
23# Start and enable Docker service
24sudo systemctl enable docker && sudo systemctl start docker
25# verify that Docker is properly configured
26sudo docker run hello-world
27```
28
29In order to run Docker commands as a non-root user, you must add the `docker` group to this user:
30
31```bash
32# Add docker group as secondary group
33sudo usermod -aG docker your-user
34# Reboot or logout
35# Then verify that Docker is properly configured, as "your-user"
36docker run hello-world
37```
38
39## Get and run a Shaarli image
40
41Shaarli images are available on [DockerHub](https://hub.docker.com/r/shaarli/shaarli/) `shaarli/shaarli`:
42
43- `latest`: latest branch (last release)
44- `stable`: stable branch (last release in previous major version)
45- `master`: master branch (development branch)
46
47These images are built automatically on DockerHub and rely on:
48
49- [Alpine Linux](https://www.alpinelinux.org/)
50- [PHP7-FPM](http://php-fpm.org/)
51- [Nginx](http://nginx.org/)
52
53Additional Dockerfiles are provided for the `arm32v7` platform, relying on [Linuxserver.io Alpine armhf images](https://hub.docker.com/r/lsiobase/alpine.armhf/). These images must be built using [`docker build`](https://docs.docker.com/engine/reference/commandline/build/) on an `arm32v7` machine or using an emulator such as [qemu](https://resin.io/blog/building-arm-containers-on-any-x86-machine-even-dockerhub/).
54
55Here is an example of how to run Shaarli latest image using Docker:
56
57```bash
58# download the 'latest' image from dockerhub
59docker pull shaarli/shaarli
60
61# create persistent data volumes/directories on the host
62docker volume create shaarli-data
63docker volume create shaarli-cache
64
65# create a new container using the Shaarli image
66# --detach: run the container in background
67# --name: name of the created container/instance
68# --publish: map the host's :8000 port to the container's :80 port
69# --rm: automatically remove the container when it exits
70# --volume: mount persistent volumes in the container ($volume_name:$volume_mountpoint)
71docker run --detach \
72 --name myshaarli \
73 --publish 8000:80 \
74 --rm \
75 --volume shaarli-data:/var/www/shaarli/data \
76 --volume shaarli-cache:/var/www/shaarli/cache \
77 shaarli/shaarli:latest
78
79# verify that the container is running
80docker ps | grep myshaarli
81
82# to completely remove the container
83docker stop myshaarli # stop the running container
84docker ps | grep myshaarli # verify the container is no longer running
85docker ps -a | grep myshaarli # verify the container is stopped
86docker rm myshaarli # destroy the container
87docker ps -a | grep myshaarli # verify th container has been destroyed
88
89```
90
91After running `docker run` command, your Shaarli instance should be available on the host machine at [localhost:8000](http://localhost:8000). In order to access your instance through a reverse proxy, we recommend using our [Docker Compose](#docker-compose) build.
92
93## Docker Compose
94
95A [Compose file](https://docs.docker.com/compose/compose-file/) is a common format for defining and running multi-container Docker applications.
96
97A `docker-compose.yml` file can be used to run a persistent/autostarted shaarli service using [Docker Compose](https://docs.docker.com/compose/) or in a [Docker stack](https://docs.docker.com/engine/reference/commandline/stack_deploy/).
98
99Shaarli provides configuration file for Docker Compose, that will setup a Shaarli instance, a [Træfik](https://containo.us/traefik/) instance (reverse proxy) with [Let's Encrypt](https://letsencrypt.org/) certificates, a Docker network, and volumes for Shaarli data and Træfik TLS configuration and certificates.
100
101Download docker-compose from the [release page](https://docs.docker.com/compose/install/):
102
103```bash
104$ sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
105$ sudo chmod +x /usr/local/bin/docker-compose
106```
107
108To run Shaarli container and its reverse proxy, you can execute the following commands:
109
110```bash
111# create a new directory to store the configuration:
112$ mkdir shaarli && cd shaarli
113# Download the latest version of Shaarli's docker-compose.yml
114$ curl -L https://raw.githubusercontent.com/shaarli/Shaarli/latest/docker-compose.yml -o docker-compose.yml
115# Create the .env file and fill in your VPS and domain information
116# (replace <MY_SHAARLI_DOMAIN> and <MY_CONTACT_EMAIL> with your actual information)
117$ echo 'SHAARLI_VIRTUAL_HOST=shaarli.mydomain.org' > .env
118$ echo 'SHAARLI_LETSENCRYPT_EMAIL=admin@mydomain.org' >> .env
119# Pull the Docker images
120$ docker-compose pull
121# Run!
122$ docker-compose up -d
123```
124
125After a few seconds, you should be able to access your Shaarli instance at [https://shaarli.mydomain.org](https://shaarli.mydomain.org) (replace your own domain name).
126
127## Running dockerized Shaarli as a systemd service
128
129It is possible to start a dockerized Shaarli instance as a systemd service (systemd is the service management tool on several distributions). After installing Docker, use the following steps to run your shaarli container Shaarli to run on system start.
130
131As root, create `/etc/systemd/system/docker.shaarli.service`:
132
133```ini
134[Unit]
135Description=Shaarli Bookmark Manager Container
136After=docker.service
137Requires=docker.service
138
139
140[Service]
141Restart=always
142
143# Put any environment you want in an included file, like $host- or $domainname in this example
144EnvironmentFile=/etc/sysconfig/box-environment
145
146# It's just an example..
147ExecStart=/usr/bin/docker run \
148 -p 28010:80 \
149 --name ${hostname}-shaarli \
150 --hostname shaarli.${domainname} \
151 -v /srv/docker-volumes-local/shaarli-data:/var/www/shaarli/data:rw \
152 -v /etc/localtime:/etc/localtime:ro \
153 shaarli/shaarli:latest
154
155ExecStop=/usr/bin/docker rm -f ${hostname}-shaarli
156
157[Install]
158WantedBy=multi-user.target
159```
160
161```bash
162# reload systemd services definitions
163systemctl daemon-reload
164# start the servie and enable it a boot time
165systemctl enable docker.shaarli.service --now
166# verify that the service is running
167systemctl status docker.*
168# inspect system log if needed
169journalctl -f
170```
171
172
173
174## Docker cheatsheet
175
176```bash
177# pull/update an image
178$ docker pull shaarli/shaarli:release
179# run a container from an image
180$ docker run shaarli/shaarli:latest
181# list available images
182$ docker images ls
183# list running containers
184$ docker ps
185# list running AND stopped containers
186$ docker ps -a
187# run a command in a running container
188$ docker exec -ti <container-name-or-first-letters-of-id> bash
189# follow logs of a running container
190$ docker logs -f <container-name-or-first-letters-of-id>
191# delete unused images to free up disk space
192$ docker system prune --images
193# delete unused volumes to free up disk space (CAUTION all data in unused volumes will be lost)
194$ docker system prunt --volumes
195# delete unused containers
196$ docker system prune
197```
198
199
200## References
201
202- [Docker: using volumes](https://docs.docker.com/storage/volumes/)
203- [Dockerfile best practices](https://docs.docker.com/articles/dockerfile_best-practices/)
204- [Dockerfile reference](https://docs.docker.com/reference/builder/)
205- [DockerHub: GitHub automated build](https://docs.docker.com/docker-hub/github/)
206- [DockerHub: Repositories](https://docs.docker.com/userguide/dockerrepos/)
207- [DockerHub: Teams and organizations](https://docs.docker.com/docker-hub/orgs/)
208- [Get Docker CE for Debian](https://docs.docker.com/install/linux/docker-ce/debian/)
209- [Install Docker Compose](https://docs.docker.com/compose/install/)
210- [Interactive Docker training portal](https://www.katacoda.com/courses/docker/) on [Katakoda](https://www.katacoda.com/)
211- [Service management: Nginx in the foreground](http://nginx.org/en/docs/ngx_core_module.html#daemon)
212- [Service management: Using supervisord](https://docs.docker.com/articles/using_supervisord/)
213- [Volumes](https://docs.docker.com/storage/volumes/)
214- [Volumes](https://docs.docker.com/userguide/dockervolumes/)
215- [Where are Docker images stored?](http://blog.thoward37.me/articles/where-are-docker-images-stored/)
216- [docker create](https://docs.docker.com/engine/reference/commandline/create/)
217- [Docker Documentation](https://docs.docker.com/)
218- [docker exec](https://docs.docker.com/engine/reference/commandline/exec/)
219- [docker images](https://docs.docker.com/engine/reference/commandline/images/)
220- [docker logs](https://docs.docker.com/engine/reference/commandline/logs/)
221- [docker logs](https://docs.docker.com/engine/reference/commandline/logs/)
222- [Docker Overview](https://docs.docker.com/engine/docker-overview/)
223- [docker ps](https://docs.docker.com/engine/reference/commandline/ps/)
224- [docker pull](https://docs.docker.com/engine/reference/commandline/pull/)
225- [docker run](https://docs.docker.com/engine/reference/commandline/run/)
226- [docker-compose logs](https://docs.docker.com/compose/reference/logs/)
227- Træfik: [Getting Started](https://docs.traefik.io/), [Docker backend](https://docs.traefik.io/configuration/backends/docker/), [Let's Encrypt](https://docs.traefik.io/user-guide/docker-and-lets-encrypt/), [Docker image](https://hub.docker.com/_/traefik/) \ No newline at end of file
diff --git a/doc/md/Download-and-Installation.md b/doc/md/Download-and-Installation.md
deleted file mode 100644
index ec68762e..00000000
--- a/doc/md/Download-and-Installation.md
+++ /dev/null
@@ -1,124 +0,0 @@
1To install Shaarli, simply place the files in a directory under your webserver's
2Document Root (or directly at the document root).
3
4Also, please make sure your server is properly [configured](Server-configuration.md).
5
6Multiple releases branches are available:
7
8- latest (last release)
9- stable (previous major release)
10- master (development)
11
12Using one of the following methods:
13
14- by downloading full release archives including all dependencies
15- by downloading Github archives
16- by cloning the Git repository
17- using Docker: [see the documentation](docker/shaarli-images.md)
18
19--------------------------------------------------------------------------------
20
21## Latest release (recommended)
22
23### Download as an archive
24
25In most cases, you should download the latest Shaarli release from the [releases](https://github.com/shaarli/Shaarli/releases) page. Download our **shaarli-full** archive to include dependencies.
26
27The current latest released version is `v0.10.4`
28
29```bash
30$ wget https://github.com/shaarli/Shaarli/releases/download/v0.10.4/shaarli-v0.10.4-full.zip
31$ unzip shaarli-v0.10.4-full.zip
32$ mv Shaarli /path/to/shaarli/
33```
34
35### Using git
36
37Cloning using `git` or downloading Github branches as zip files requires additional steps:
38
39 * Install [Composer](Unit-tests.md#install_composer) to manage third-party [PHP dependencies](3rd-party-libraries.md#composer).
40 * Install [yarn](https://yarnpkg.com/lang/en/docs/install/) to build the frontend dependencies.
41 * Install [python3-virtualenv](https://pypi.python.org/pypi/virtualenv) to build the local HTML documentation.
42
43```
44$ mkdir -p /path/to/shaarli && cd /path/to/shaarli/
45$ git clone -b latest https://github.com/shaarli/Shaarli.git .
46$ composer install --no-dev --prefer-dist
47$ make build_frontend
48$ make translate
49$ make htmldoc
50```
51
52--------------------------------------------------------------------------------
53
54## Stable version
55
56The stable version has been experienced by Shaarli users, and will receive security updates.
57
58
59### Download as an archive
60
61As a .zip archive:
62
63```bash
64$ wget https://github.com/shaarli/Shaarli/archive/stable.zip
65$ unzip stable.zip
66$ mv Shaarli-stable /path/to/shaarli/
67```
68
69As a .tar.gz archive :
70
71```bash
72$ wget https://github.com/shaarli/Shaarli/archive/stable.tar.gz
73$ tar xvf stable.tar.gz
74$ mv Shaarli-stable /path/to/shaarli/
75```
76
77### Using git
78
79Install [Composer](Unit-tests.md#install_composer) to manage Shaarli dependencies.
80
81```bash
82$ git clone https://github.com/shaarli/Shaarli.git -b stable /path/to/shaarli/
83# install/update third-party dependencies
84$ cd /path/to/shaarli/
85$ composer install --no-dev --prefer-dist
86```
87
88
89--------------------------------------------------------------------------------
90
91## Development version (mainline)
92
93_Use at your own risk!_
94
95Install [Composer](Unit-tests.md#install_composer) to manage Shaarli PHP dependencies,
96and [yarn](https://yarnpkg.com/lang/en/docs/install/)
97for front-end dependencies.
98
99To get the latest changes from the `master` branch:
100
101```bash
102# clone the repository
103$ git clone https://github.com/shaarli/Shaarli.git -b master /path/to/shaarli/
104# install/update third-party dependencies
105$ cd /path/to/shaarli
106$ composer install --no-dev --prefer-dist
107$ make build_frontend
108$ make translate
109$ make htmldoc
110```
111
112-------------------------------------------------------------------------------
113
114## Finish Installation
115
116Once Shaarli is downloaded and files have been placed at the correct location, open it this location your favorite browser.
117
118![install screenshot](images/install-shaarli.png)
119
120Setup your Shaarli installation, and it's ready to use!
121
122## Updating Shaarli
123
124See [Upgrade and Migration](Upgrade-and-migration)
diff --git a/doc/md/FAQ.md b/doc/md/FAQ.md
deleted file mode 100644
index a2ec7d57..00000000
--- a/doc/md/FAQ.md
+++ /dev/null
@@ -1,46 +0,0 @@
1### Why did you create Shaarli ?
2
3I was a StumbleUpon user. Then I got fed up with they big toolbar. I switched to delicious, which was lighter, faster and more beautiful. Until Yahoo bought it. Then the export API broke all the time, delicious became slow and was ditched by Yahoo. I switched to Diigo, which is not bad, but does too much. And Diigo is sslllooooowww and their Firefox extension a bit buggy. And… oh… **their Firefox addon sends to Diigo every single URL you visit** (Don't believe me ? Use [Tamper Data](https://addons.mozilla.org/en-US/firefox/addon/tamper-data/) and open any page).
4
5Enough is enough. Saving simple links should not be a complicated heavy thing. I ditched them all and wrote my own: Shaarli. It's simple, but it does the job and does it well. And my data is not hosted on a foreign server, but on my server.
6
7### Why use Shaarli and not Delicious/Diigo ?
8
9With Shaarli:
10
11- The data is yours: It's hosted on your server.
12- Never fear of having your data locked-in.
13- Never fear to have your data sold to third party.
14- Your private links are not hosted on a third party server.
15- You are not tracked by browser addons (like Diigo does)
16- You can change the look and feel of the pages if you want.
17- You can change the behaviour of the program.
18- It's magnitude faster than most bookmarking services.
19
20### What does Shaarli mean?
21
22Shaarli stands for _shaaring_ your _links_.
23
24### My Shaarli is broken!
25First of all, ensure that both the [web server](Server-configuration) and
26[Shaarli](Shaarli-configuration) are correctly configured, and that your
27installation is [supported](Server-configuration).
28
29If everything looks right but the issue(s) remain(s), please:
30
31- take a look at the [troubleshooting](Troubleshooting) section
32- come [chat with us](https://gitter.im/shaarli/Shaarli) on Gitter, we'll be happy to help ;-)
33- browse active [issues](https://github.com/shaarli/Shaarli/issues) and [Pull Requests](https://github.com/shaarli/Shaarli/pulls)
34 - if you find one that is related to the issue, feel free to comment and provide additional details (host/Shaarli setup)
35 - else, [open a new issue](https://github.com/shaarli/Shaarli/issues/new), and provide information about the problem:
36 - _what happens?_ - display glitches, invalid data, security flaws...
37 - _what is your configuration?_ - OS, server version, activated extensions, web browser...
38 - _is it reproducible?_
39
40### Why not use a real database? Files are slow!
41
42Does browsing [this page](http://sebsauvage.net/links/) feel slow? Try browsing older pages, too.
43
44It's not slow at all, is it? And don't forget the database contains more than 16000 links, and it's on a shared host, with 32000 visitors/day for my website alone. And it's still damn fast. Why?
45
46The data file is only 3.7 Mb. It's read 99% of the time, and is probably already in the operation system disk cache. So generating a page involves no I/O at all most of the time.
diff --git a/doc/md/Installation.md b/doc/md/Installation.md
new file mode 100644
index 00000000..11b5da85
--- /dev/null
+++ b/doc/md/Installation.md
@@ -0,0 +1,78 @@
1# Installation
2
3Once your server is [configured](Server-configuration.md), install Shaarli:
4
5## From release ZIP
6
7To install Shaarli, simply place the files from the latest [release .zip archive](https://github.com/shaarli/Shaarli/releases) under your webserver's document root (directly at the document root, or in a subdirectory). Download the **shaarli-vX.X.X-full** archive to include dependencies.
8
9```bash
10wget https://github.com/shaarli/Shaarli/releases/download/v0.11.1/shaarli-v0.11.1-full.zip
11unzip shaarli-v0.11.1-full.zip
12sudo rsync -avP Shaarli/ /var/www/shaarli.mydomain.org/
13```
14
15## From sources
16
17These components are required to build Shaarli:
18
19- [Composer](dev/Development.md#install-composer) to manage third-party [PHP dependencies](dev/Development#third-party-libraries).
20- [yarn](https://yarnpkg.com/lang/en/docs/install/) to build frontend dependencies.
21- [python3-virtualenv](https://pypi.python.org/pypi/virtualenv) to build local HTML documentation.
22
23Clone the repository, either pointing to:
24
25- any [tagged release](https://github.com/shaarli/Shaarli/releases)
26- `latest`: the latest tagged release
27- `master`: development branch
28
29```bash
30# clone the branch/tag of your choice
31$ git clone -b latest https://github.com/shaarli/Shaarli.git /home/me/Shaarli
32# OR download/extract the tar.gz/zip: wget https://github.com/shaarli/Shaarli/archive/latest.tar.gz...
33
34# enter the directory
35$ cd /home/me/Shaarli
36# install 3rd-party PHP dependencies
37$ composer install --no-dev --prefer-dist
38# build frontend static assets
39$ make build_frontend
40# build translations
41$ make translate
42# build HTML documentation
43$ make htmldoc
44# copy the resulting shaarli directory under your webserver's document root
45$ rsync -avP /home/me/Shaarli/ /var/www/shaarli.mydomain.org/
46```
47
48## Set file permissions
49
50Regardless of the installation method, appropriate [file permissions](dev/Development.md#directory-structure) must be set:
51
52```bash
53sudo chown -R root:www-data /var/www/shaarli.mydomain.org
54sudo chmod -R g+rX /var/www/shaarli.mydomain.org
55sudo chmod -R g+rwX /var/www/shaarli.mydomain.org/{cache/,data/,pagecache/,tmp/}
56```
57
58## Using Docker
59
60[See the documentation](Docker.md)
61
62
63## Finish Installation
64
65Once Shaarli is downloaded and files have been placed at the correct location, open this location your web browser.
66
67Enter basic settings for your Shaarli installation, and it's ready to use!
68
69![](images/07-installation.jpg)
70
71Congratulations! Your Shaarli is now available at `https://shaarli.mydomain.org`.
72
73You can further [configure Shaarli](Shaarli-configuration.md), setup [Plugins](Plugins.md) or [additional software](Community-and-related-software.md).
74
75
76## Upgrading Shaarli
77
78See [Upgrade and Migration](Upgrade-and-migration)
diff --git a/doc/md/Link-structure.md b/doc/md/Link-structure.md
deleted file mode 100644
index 0a2d0f88..00000000
--- a/doc/md/Link-structure.md
+++ /dev/null
@@ -1,18 +0,0 @@
1## Link structure
2
3Every link available through the `LinkDB` object is represented as an array
4containing the following fields:
5
6 * `id` (integer): Unique identifier.
7 * `title` (string): Title of the link.
8 * `url` (string): URL of the link. Used for displayable links (without redirector, url encoding, etc.).
9 Can be absolute or relative for Notes.
10 * `real_url` (string): Real destination URL, can be redirected, encoded, etc.
11 * `shorturl` (string): Permalink small hash.
12 * `description` (string): Link text description.
13 * `private` (boolean): whether the link is private or not.
14 * `tags` (string): all link tags separated by a single space
15 * `thumbnail` (string|boolean): relative path of the thumbnail cache file, or false if there isn't any.
16 * `created` (DateTime): link creation date time.
17 * `updated` (DateTime): last modification date time.
18 \ No newline at end of file
diff --git a/doc/md/Plugins.md b/doc/md/Plugins.md
index 3e261815..a9f5f1a8 100644
--- a/doc/md/Plugins.md
+++ b/doc/md/Plugins.md
@@ -1,14 +1,13 @@
1## Plugin installation 1# Plugins
2 2
3There is a bunch of plugins shipped with Shaarli, where there is nothing to do to install them. 3## Installation
4 4
5If you want to install a third party plugin: 5For plugins shipped with Shaarli, no installation is required.
6 6
7- Download it. 7If you want to install a third party plugin, download it to the `plugins` directory in Shaarli's installation folder:
8- Put it in the `plugins` directory in Shaarli's installation folder.
9- Make sure you put it correctly:
10 8
11``` 9```bash
10# example directory structure
12| index.php 11| index.php
13| plugins/ 12| plugins/
14|---| custom_plugin/ 13|---| custom_plugin/
@@ -17,63 +16,47 @@ If you want to install a third party plugin:
17 16
18``` 17```
19 18
20 * Make sure your webserver can read and write the files in your plugin folder. 19Make sure your webserver can read and write the files in your plugin folder.
21 20
22## Plugin configuration
23 21
24In Shaarli's administration page (`Tools` link), go to `Plugin administration`. 22## Configuration
25 23
26Here you can enable and disable all plugins available, and configure them. 24From Shaarli's administration page (`Tools` link), go to `Plugin administration`. Here you can enable and disable all plugins available, and configure them.
27 25
28![administration screenshot](https://camo.githubusercontent.com/5da68e191969007492ca0fbeb25f3b2357b748cc/687474703a2f2f692e696d6775722e636f6d2f766837544643712e706e67) 26![administration screenshot](https://camo.githubusercontent.com/5da68e191969007492ca0fbeb25f3b2357b748cc/687474703a2f2f692e696d6775722e636f6d2f766837544643712e706e67)
29 27
30## Plugin order 28
29## Order
31 30
32In the plugin administration page, you can move enabled plugins to the top or bottom of the list. The first plugins in the list will be processed first. 31In the plugin administration page, you can move enabled plugins to the top or bottom of the list. The first plugins in the list will be processed first.
33 32
34This is important in case plugins are depending on each other. Read plugins README details for more information. 33This is important in case plugins depend on each other. Read plugins READMEs for more information.
35 34
36**Use case**: The (non existent) plugin `shaares_footer` adds a footer to every shaare in Markdown syntax. It needs to be processed *before* (higher in the list) the Markdown plugin. Otherwise its syntax won't be translated in HTML. 35**Use case**: The (non existent) plugin `shaares_footer` adds a footer to every shaare in Markdown syntax. It needs to be processed *before* (higher in the list) the Markdown plugin. Otherwise its syntax won't be translated in HTML.
37 36
38## File mode
39 37
40Enabled plugin are stored in your `config.json.php` parameters file, under the `array`: 38## Configuration file
41 39
42```php 40Enabled plugins are stored in your [Configuration file](Shaarli-configuration).
43$GLOBALS['config']['ENABLED_PLUGINS']
44```
45 41
46You can edit them manually here. 42## Usage
47Example:
48 43
49```php 44### Official plugins
50$GLOBALS['config']['ENABLED_PLUGINS'] = array(
51 'qrcode',
52 'archiveorg',
53 'wallabag',
54 'markdown',
55);
56```
57
58### Plugin usage
59
60#### Official plugins
61 45
62Usage of each plugin is documented in it's README file: 46Usage of each plugin is documented in it's README file:
63 47
64 * `addlink-toolbar`: Adds the addlink input on the linklist page 48 * `addlink-toolbar`: Adds the addlink input on the Shaares list page
65 * `archiveorg`: For each link, add an Archive.org icon 49 * `archiveorg`: For each Shaare, add a link to the archived page on Archive.org
66 * `default_colors`: Override default theme colors. 50 * `default_colors`: Override default theme colors.
67 * `isso`: Let visitor comment your shaares on permalinks with Isso. 51 * `isso`: Let visitor comment your shaares on permalinks with Isso.
68 * [`markdown`](https://github.com/shaarli/Shaarli/blob/master/plugins/markdown/README.md): Render shaare description with Markdown syntax. 52 * [`markdown`](https://github.com/shaarli/Shaarli/blob/master/plugins/markdown/README.md): Render shaare description with Markdown syntax.
69 * `piwik`: A plugin that adds Piwik tracking code to Shaarli pages. 53 * `piwik`: A plugin that adds Piwik tracking code to Shaarli pages.
70 * [`playvideos`](https://github.com/shaarli/Shaarli/blob/master/plugins/playvideos/README.md): Add a button in the toolbar allowing to watch all videos. 54 * [`playvideos`](https://github.com/shaarli/Shaarli/blob/master/plugins/playvideos/README.md): Add a button in the toolbar allowing to watch all videos.
71 * `pubsubhubbub`: Enable PubSubHubbub feed publishing 55 * `pubsubhubbub`: Enable PubSubHubbub feed publishing
72 * `qrcode`: For each link, add a QRCode icon. 56 * `qrcode`: For each Shaare, add a QRCode icon.
73 * [`wallabag`](https://github.com/shaarli/Shaarli/blob/master/plugins/wallabag/README.md): For each link, add a Wallabag icon to save it in your instance. 57 * [`wallabag`](https://github.com/shaarli/Shaarli/blob/master/plugins/wallabag/README.md): For each Shaare, add a Wallabag icon to save it in your instance.
74
75 58
76 59
77#### Third party plugins 60### Third party plugins
78 61
79See [Community & related software](https://shaarli.readthedocs.io/en/master/Community-&-Related-software/) 62See [Community & related software](https://shaarli.readthedocs.io/en/master/Community-and-Related-software/)
diff --git a/doc/md/REST-API.md b/doc/md/REST-API.md
index 11bd1cd2..01071d8e 100644
--- a/doc/md/REST-API.md
+++ b/doc/md/REST-API.md
@@ -1,101 +1,24 @@
1## Usage and Prerequisites 1# REST API
2 2
3See the [REST API documentation](http://shaarli.github.io/api-documentation/) 3## Server requirements
4for a list of available endpoints and parameters.
5 4
6Please ensure that your server meets the 5See the **[REST API documentation](http://shaarli.github.io/api-documentation/)** for a list of available endpoints and parameters.
7[requirements](Server-configuration#prerequisites) and is properly 6
8[configured](Server-configuration): 7Please ensure that your server meets the requirements and is properly [configured](Server-configuration):
9 8
10- URL rewriting is enabled (see specific Apache and Nginx sections) 9- URL rewriting is enabled (see specific Apache and Nginx sections)
11- the server's timezone is properly defined 10- the server's timezone is properly defined
12- the server's clock is synchronized with 11- the server's clock is synchronized with [NTP](https://en.wikipedia.org/wiki/Network_Time_Protocol)
13 [NTP](https://en.wikipedia.org/wiki/Network_Time_Protocol)
14
15The host where the API client is invoked should also be synchronized with NTP,
16see [token expiration](#payload).
17
18## Authentication
19
20All requests to Shaarli's API must include a JWT token to verify their authenticity.
21
22This token has to be included as an HTTP header called `Authentication: Bearer <jwt token>`.
23
24JWT resources :
25
26- [jwt.io](https://jwt.io) (including a list of client per language).
27- RFC : https://tools.ietf.org/html/rfc7519
28- https://float-middle.com/json-web-tokens-jwt-vs-sessions/
29- HackerNews thread: https://news.ycombinator.com/item?id=11929267
30
31
32### Shaarli JWT Token
33
34JWT tokens are composed by three parts, separated by a dot `.` and encoded in base64:
35
36```
37[header].[payload].[signature]
38```
39
40#### Header
41
42Shaarli only allow one hash algorithm, so the header will always be the same:
43
44```json
45{
46 "typ": "JWT",
47 "alg": "HS512"
48}
49```
50
51Encoded in base64, it gives:
52
53```
54ewogICAgICAgICJ0eXAiOiAiSldUIiwKICAgICAgICAiYWxnIjogIkhTNTEyIgogICAgfQ==
55```
56
57#### Payload
58
59**Token expiration**
60
61To avoid infinite token validity, JWT tokens must include their creation date
62in UNIX timestamp format (timezone independent - UTC) under the key `iat` (issued at).
63This token will be valid during **9 minutes**.
64
65```json
66{
67 "iat": 1468663519
68}
69```
70
71See [RFC reference](https://tools.ietf.org/html/rfc7519#section-4.1.6).
72
73 12
74#### Signature 13The host where the API client is invoked should also be synchronized with NTP, see _payload/token expiration_
75
76The signature authenticate the token validity. It contains the base64 of the header and the body, separated by a dot `.`, hashed in SHA512 with the API secret available in Shaarli administration page.
77
78Signature example with PHP:
79
80```php
81$content = base64_encode($header) . '.' . base64_encode($payload);
82$signature = hash_hmac('sha512', $content, $secret);
83```
84 14
85 15
86## Clients and examples 16## Clients and examples
87### Android, Java, Kotlin
88
89- [Android client example with Kotlin](https://gitlab.com/snippets/1665808)
90 by [Braincoke](https://github.com/Braincoke)
91
92### Javascript, NodeJS
93 17
94- [shaarli-client](https://www.npmjs.com/package/shaarli-client) 18- **[python-shaarli-client](https://github.com/shaarli/python-shaarli-client)** - the reference API client ([Documentation](http://python-shaarli-client.readthedocs.io/en/latest/))
95 ([source code](https://github.com/laBecasse/shaarli-client)) 19- [shaarli-client](https://www.npmjs.com/package/shaarli-client) - NodeJs client ([source code](https://github.com/laBecasse/shaarli-client)) by [laBecasse](https://github.com/laBecasse)
96 by [laBecasse](https://github.com/laBecasse) 20- [Android client example with Kotlin](https://gitlab.com/snippets/1665808) by [Braincoke](https://github.com/Braincoke)
97 21
98### PHP
99 22
100This example uses the [PHP cURL](http://php.net/manual/en/book.curl.php) library. 23This example uses the [PHP cURL](http://php.net/manual/en/book.curl.php) library.
101 24
@@ -145,13 +68,57 @@ function getInfo($baseUrl, $secret) {
145var_dump(getInfo($baseUrl, $secret)); 68var_dump(getInfo($baseUrl, $secret));
146``` 69```
147 70
71## Implementation
72
73### Authentication
74
75- All requests to Shaarli's API must include a **JWT token** to verify their authenticity.
76- This token must be included as an HTTP header called `Authentication: Bearer <jwt token>`.
77- JWT tokens are composed by three parts, separated by a dot `.` and encoded in base64:
78
79```
80[header].[payload].[signature]
81```
82
83##### Header
84
85Shaarli only allow one hash algorithm, so the header will always be the same:
86
87```json
88{
89 "typ": "JWT",
90 "alg": "HS512"
91}
92```
93
94Encoded in base64, it gives:
148 95
149### Python 96```
97ewogICAgICAgICJ0eXAiOiAiSldUIiwKICAgICAgICAiYWxnIjogIkhTNTEyIgogICAgfQ==
98```
99
100##### Payload
101
102Token expiration: To avoid infinite token validity, JWT tokens must include their creation date in UNIX timestamp format (timezone independent - UTC) under the key `iat` (issued at) field ([1](https://tools.ietf.org/html/rfc7519#section-4.1.6)). This token will be valid during **9 minutes**.
103
104```json
105{
106 "iat": 1468663519
107}
108```
109
110##### Signature
111
112The signature authenticates the token validity. It contains the base64 of the header and the body, separated by a dot `.`, hashed in SHA512 with the API secret available in Shaarli administration page.
113
114Example signature with PHP:
115
116```php
117$content = base64_encode($header) . '.' . base64_encode($payload);
118$signature = hash_hmac('sha512', $content, $secret);
119```
150 120
151See the reference API client:
152 121
153- [Documentation](http://python-shaarli-client.readthedocs.io/en/latest/) on ReadTheDocs
154- [python-shaarli-client](https://github.com/shaarli/python-shaarli-client) on Github
155 122
156## Troubleshooting 123## Troubleshooting
157 124
@@ -171,3 +138,13 @@ to get the actual error message in the HTTP response body with:
171 } 138 }
172} 139}
173``` 140```
141
142## References
143
144- [jwt.io](https://jwt.io) (including a list of client per language).
145- [RFC - JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519)
146- [JSON Web Tokens (JWT) vs Sessions](https://float-middle.com/json-web-tokens-jwt-vs-sessions/), [HackerNews thread](https://news.ycombinator.com/item?id=11929267)
147
148
149
150
diff --git a/doc/md/RSS-feeds.md b/doc/md/RSS-feeds.md
deleted file mode 100644
index ecbff09a..00000000
--- a/doc/md/RSS-feeds.md
+++ /dev/null
@@ -1,28 +0,0 @@
1### Feeds options
2
3Feeds are available in ATOM with `/feed/atom` and RSS with `/feed/rss`.
4
5Options:
6
7- You can use `permalinks` in the feed URL to get permalink to Shaares instead of direct link to shaared URL.
8 - E.G. `https://my.shaarli.domain/feed/atom?permalinks`.
9- You can use `nb` parameter in the feed URL to specify the number of Shaares you want in a feed (default if not specified: `50`). The keyword `all` is available if you want everything.
10 - `https://my.shaarli.domain/feed/atom?permalinks&nb=42`
11 - `https://my.shaarli.domain/feed/atom?permalinks&nb=all`
12
13### RSS Feeds or Picture Wall for a specific search/tag
14
15It is possible to filter RSS/ATOM feeds and Picture Wall on a Shaarli to **only display results of a specific search, or for a specific tag**.
16
17For example, if you want to subscribe only to links tagged `photography`:
18
19- Go to the desired Shaarli instance.
20- Search for the `photography` tag in the _Filter by tag_ box. Links tagged `photography` are displayed.
21- Click on the `RSS Feed` button.
22- You are presented with an RSS feed showing only these links. Subscribe to it to receive only updates with this tag.
23- The same method **also works for a full-text search** (_Search_ box) **and for the Picture Wall** (want to only see pictures about `nature`?)
24- You can also build the URLs manually:
25 - `https://my.shaarli.domain/?do=rss&searchtags=nature`
26 - `https://my.shaarli.domain/links/picture-wall?searchterm=poney`
27
28![](images/rss-filter-1.png) ![](images/rss-filter-2.png)
diff --git a/doc/md/Release-Shaarli.md b/doc/md/Release-Shaarli.md
deleted file mode 100644
index e22eabc9..00000000
--- a/doc/md/Release-Shaarli.md
+++ /dev/null
@@ -1,161 +0,0 @@
1See [Git - Maintaining a project - Tagging your
2releases](http://git-scm.com/book/en/v2/Distributed-Git-Maintaining-a-Project#Tagging-Your-Releases).
3
4## Prerequisites
5This guide assumes that you have:
6
7- a GPG key matching your GitHub authentication credentials
8 - i.e., the email address identified by the GPG key is the same as the one in your `~/.gitconfig`
9- a GitHub fork of Shaarli
10- a local clone of your Shaarli fork, with the following remotes:
11 - `origin` pointing to your GitHub fork
12 - `upstream` pointing to the main Shaarli repository
13- maintainer permissions on the main Shaarli repository, to:
14 - push the signed tag
15 - create a new release
16- [Composer](https://getcomposer.org/) needs to be installed
17- The [venv](https://docs.python.org/3/library/venv.html) Python 3 module needs to be installed for HTML documentation generation.
18
19## GitHub release draft and `CHANGELOG.md`
20See http://keepachangelog.com/en/0.3.0/ for changelog formatting.
21
22### GitHub release draft
23GitHub allows drafting the release note for the upcoming release, from the [Releases](https://github.com/shaarli/Shaarli/releases) page. This way, the release note can be drafted while contributions are merged to `master`.
24
25### `CHANGELOG.md`
26This file should contain the same information as the release note draft for the upcoming version.
27
28Update it to:
29
30- add new entries (additions, fixes, etc.)
31- mark the current version as released by setting its date and link
32- add a new section for the future unreleased version
33
34```bash
35$ cd /path/to/shaarli
36
37$ nano CHANGELOG.md
38
39[...]
40## vA.B.C - UNRELEASED
41TBA
42
43## [vX.Y.Z](https://github.com/shaarli/Shaarli/releases/tag/vX.Y.Z) - YYYY-MM-DD
44[...]
45```
46
47
48## Increment the version code, update docs, create and push a signed tag
49### Update the list of Git contributors
50```bash
51$ make authors
52$ git commit -s -m "Update AUTHORS"
53```
54
55### Create and merge a Pull Request
56This one is pretty straightforward ;-)
57
58### Bump Shaarli version to v0.x branch
59
60```bash
61$ git checkout master
62$ git fetch upstream
63$ git pull upstream master
64
65# IF the branch doesn't exists
66$ git checkout -b v0.5
67# OR if the branch already exists
68$ git checkout v0.5
69$ git rebase upstream/master
70
71# Bump shaarli version from dev to 0.5.0, **without the `v`**
72$ vim shaarli_version.php
73$ git add shaarli_version
74$ git commit -s -m "Bump Shaarli version to v0.5.0"
75$ git push upstream v0.5
76```
77
78### Create and push a signed tag
79```bash
80# update your local copy
81$ git checkout v0.5
82$ git fetch upstream
83$ git pull upstream v0.5
84
85# create a signed tag
86$ git tag -s -m "Release v0.5.0" v0.5.0
87
88# push it to "upstream"
89$ git push --tags upstream
90```
91
92### Verify a signed tag
93[`v0.5.0`](https://github.com/shaarli/Shaarli/releases/tag/v0.5.0) is the first GPG-signed tag pushed on the Community Shaarli.
94
95Let's have a look at its signature!
96
97```bash
98$ cd /path/to/shaarli
99$ git fetch upstream
100
101# get the SHA1 reference of the tag
102$ git show-ref tags/v0.5.0
103f7762cf803f03f5caf4b8078359a63783d0090c1 refs/tags/v0.5.0
104
105# verify the tag signature information
106$ git verify-tag f7762cf803f03f5caf4b8078359a63783d0090c1
107gpg: Signature made Thu 30 Jul 2015 11:46:34 CEST using RSA key ID 4100DF6F
108gpg: Good signature from "VirtualTam <virtualtam@flibidi.net>" [ultimate]
109```
110
111## Publish the GitHub release
112### Update release badges
113Update `README.md` so version badges display and point to the newly released Shaarli version(s), in the `master` branch.
114
115### Create a GitHub release from a Git tag
116From the previously drafted release:
117
118- edit the release notes (if needed)
119- specify the appropriate Git tag
120- publish the release
121- profit!
122
123### Generate and upload all-in-one release archives
124Users with a shared hosting may have:
125
126- no SSH access
127- no possibility to install PHP packages or server extensions
128- no possibility to run scripts
129
130To ease Shaarli installations, it is possible to generate and upload additional release archives,
131that will contain Shaarli code plus all required third-party libraries.
132
133**From the `v0.5` branch:**
134
135```bash
136$ make release_archive
137```
138
139This will create the following archives:
140
141- `shaarli-vX.Y.Z-full.tar`
142- `shaarli-vX.Y.Z-full.zip`
143
144The archives need to be manually uploaded on the previously created GitHub release.
145
146### Update `stable` and `latest` branches
147
148```
149$ git checkout latest
150# latest release
151$ git merge v0.5.0
152# fix eventual conflicts
153$ make test
154$ git push upstream latest
155$ git checkout stable
156# latest previous major
157$ git merge v0.4.5
158# fix eventual conflicts
159$ make test
160$ git push upstream stable
161```
diff --git a/doc/md/Reverse-proxy.md b/doc/md/Reverse-proxy.md
new file mode 100644
index 00000000..b7e347d5
--- /dev/null
+++ b/doc/md/Reverse-proxy.md
@@ -0,0 +1,141 @@
1# Reverse proxy
2
3If Shaarli is hosted on a server behind a [reverse proxy](https://en.wikipedia.org/wiki/Reverse_proxy) (i.e. there is a proxy server between clients and the web server hosting Shaarli), configure it accordingly. See [Reverse proxy](Reverse-proxy.md) configuration. In this example:
4
5- The Shaarli application server exposes port `10080` to the proxy (for example docker container started with `--publish 127.0.0.1:10080:80`).
6- The Shaarli application server runs at `127.0.0.1` (container). Replace with the server's IP address if running on a different machine.
7- Shaarli's Fully Qualified Domain Name (FQDN) is `shaarli.mydomain.org`.
8- No HTTPS is setup on the application server, SSL termination is done at the reverse proxy.
9
10In your [Shaarli configuration](Shaarli-configuration) `data/config.json.php`, add the public IP of your proxy under `security.trusted_proxies`.
11
12See also [proxy-related](https://github.com/shaarli/Shaarli/issues?utf8=%E2%9C%93&q=label%3Aproxy+) issues.
13
14
15## Apache
16
17```apache
18<VirtualHost *:80>
19 ServerName shaarli.mydomain.org
20
21 # For SSL/TLS certificates acquired with certbot or self-signed certificates
22 # Redirect HTTP requests to HTTPS, except Let's Encrypt ACME challenge requests
23 RewriteEngine on
24 RewriteRule ^.well-known/acme-challenge/ - [L]
25 RewriteCond %{HTTP_HOST} =shaarli.mydomain.org
26 RewriteRule ^ https://shaarli.mydomain.org%{REQUEST_URI} [END,NE,R=permanent]
27</VirtualHost>
28
29# SSL/TLS configuration for Let's Encrypt certificates managed with mod_md
30#MDomain shaarli.mydomain.org
31#MDCertificateAgreement accepted
32#MDContactEmail admin@shaarli.mydomain.org
33#MDPrivateKeys RSA 4096
34
35<VirtualHost *:443>
36 ServerName shaarli.mydomain.org
37
38 # SSL/TLS configuration for Let's Encrypt certificates acquired with certbot standalone
39 SSLEngine on
40 SSLCertificateFile /etc/letsencrypt/live/shaarli.mydomain.org/fullchain.pem
41 SSLCertificateKeyFile /etc/letsencrypt/live/shaarli.mydomain.org/privkey.pem
42 # Let's Encrypt settings from https://github.com/certbot/certbot/blob/master/certbot-apache/certbot_apache/_internal/tls_configs/current-options-ssl-apache.conf
43 SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
44 SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
45 SSLHonorCipherOrder off
46 SSLSessionTickets off
47 SSLOptions +StrictRequire
48
49 # SSL/TLS configuration for self-signed certificates
50 #SSLEngine on
51 #SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
52 #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
53
54 # let the proxied shaarli server/container know HTTPS URLs should be served
55 RequestHeader set X-Forwarded-Proto "https"
56
57 # send the original SERVER_NAME to the proxied host
58 ProxyPreserveHost On
59
60 # pass requests to the proxied host
61 # sets X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Server headers
62 ProxyPass / http://127.0.0.1:10080/
63 ProxyPassReverse / http://127.0.0.1:10080/
64</VirtualHost>
65```
66
67
68## HAProxy
69
70
71```conf
72global
73 [...]
74
75defaults
76 [...]
77
78frontend http-in
79 bind :80
80 redirect scheme https code 301 if !{ ssl_fc }
81 bind :443 ssl crt /path/to/cert.pem
82 default_backend shaarli
83
84backend shaarli
85 mode http
86 option http-server-close
87 option forwardfor
88 reqadd X-Forwarded-Proto: https
89 server shaarli1 127.0.0.1:10080
90```
91
92- [HAProxy documentation](https://cbonte.github.io/haproxy-dconv/)
93
94## Nginx
95
96
97```nginx
98http {
99 [...]
100
101 index index.html index.php;
102
103 root /home/john/web;
104 access_log /var/log/nginx/access.log combined;
105 error_log /var/log/nginx/error.log;
106
107 server {
108 listen 80;
109 server_name shaarli.mydomain.org;
110 # redirect HTTP to HTTPS
111 return 301 https://shaarli.mydomain.org$request_uri;
112 }
113
114 server {
115 listen 443 ssl http2;
116 server_name shaarli.mydomain.org;
117
118 ssl_certificate /path/to/certificate
119 ssl_certificate_key /path/to/private/key
120
121 location / {
122 proxy_set_header X-Real-IP $remote_addr;
123 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
124 proxy_set_header X-Forwarded-Proto $scheme;
125 proxy_set_header X-Forwarded-Host $host;
126
127 # pass requests to the proxied host
128 proxy_pass http://localhost:10080/;
129 proxy_set_header Host $host;
130 proxy_connect_timeout 30s;
131 proxy_read_timeout 120s;
132 }
133 }
134}
135```
136
137## References
138
139- [`X-Forwarded-Proto`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto)
140- [`X-Forwarded-Host`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host)
141- [`X-Forwarded-For`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)
diff --git a/doc/md/Security.md b/doc/md/Security.md
deleted file mode 100644
index 65db4225..00000000
--- a/doc/md/Security.md
+++ /dev/null
@@ -1,25 +0,0 @@
1## Client browser
2- 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
3
4## Server and sessions
5- Directories are protected using `.htaccess` files
6- Forms are protected against XSRF (Cross-site requests forgery):
7 - Forms which act on data (save,delete…) contain a token generated by the server.
8 - Any posted form which does not contain a valid token is rejected.
9 - Any token can only be used once.
10 - Tokens are attached to the session and cannot be reused in another session.
11- Sessions automatically expire after 60 minutes.
12- Sessions are protected against hijacking: the session ID cannot be used from a different IP address.
13
14## Shaarli datastore and configuration
15- The password is salted, hashed and stored in the data subdirectory, in a PHP file, and protected by htaccess. Even if the webserver does not support htaccess, the hash is not readable by URL. Even if the .php file is stolen, the password cannot deduced from the hash. The salt prevents rainbow-tables attacks.
16- Links are stored as an associative array which is serialized, compressed (with deflate), base64-encoded and saved as a comment in a `.php` file.
17- Even if the server does not support `.htaccess` files, the data file will still not be readable by URL.
18- The database looks like this:
19
20```php
21<?php /* zP1ZjxxJtiYIvvevEPJ2lDOaLrZv7o...
22...ka7gaco/Z+TFXM2i7BlfMf8qxpaSSYfKlvqv/x8= */ ?>
23```
24
25- Small hashes are used to make a link to an entry in Shaarli. They are unique. In fact, the date of the items (eg. `20110923_150523`) is hashed with CRC32, then converted to base64 and some characters are replaced. They are always 6 characters longs and use only `A-Z a-z 0-9 - _` and `@`.
diff --git a/doc/md/Server-configuration.md b/doc/md/Server-configuration.md
index f9ea2ed2..297d7c29 100644
--- a/doc/md/Server-configuration.md
+++ b/doc/md/Server-configuration.md
@@ -1,20 +1,46 @@
1# Server configuration
1 2
2- [Prerequisites](#prerequisistes) 3## Requirements
3- [Apache](#apache)
4- [Nginx](#nginx)
5- [Proxies](#proxies)
6- [See also](#see-also)
7 4
8## Prerequisites 5### Operating system and web server
9### Shaarli
10 6
11- A web server and PHP interpreter module/service have been installed. 7Shaarli can be hosted on dedicated/virtual servers, or shared hosting.
12- You have write access to the Shaarli installation directory. 8
13- The correct read/write permissions have been granted to the web server user and group. 9You need write access to the Shaarli installation directory - you should have received instructions from your hosting provider on how to connect to the server using SSH (or FTP for shared hosts).
14- Your PHP interpreter is compatible with supported PHP versions: 10
11Examples in this documentation are given for [Debian](https://www.debian.org/), a GNU/Linux distribution widely used in server environments. Please adapt them to your specific Linux distribution.
12
13A $5/month VPS (1 CPU, 1 GiB RAM and 25 GiB SSD) will run any Shaarli installation without problems. Some hosting providers: [DigitalOcean](https://www.digitalocean.com/) ([1](https://www.digitalocean.com/docs/droplets/overview/), [2](https://www.digitalocean.com/pricing/), [3](https://www.digitalocean.com/docs/droplets/how-to/create/), [4](https://www.digitalocean.com/docs/droplets/how-to/add-ssh-keys/), [5](https://www.digitalocean.com/community/tutorials/initial-server-setup-with-debian-8), [6](https://www.digitalocean.com/community/tutorials/an-introduction-to-securing-your-linux-vps)), [Gandi](https://www.gandi.net/en), [OVH](https://www.ovh.co.uk/), [RackSpace](https://www.rackspace.com/), etc.
14
15
16### Network and domain name
17
18Try to host the server in a region that is geographically close to your users.
19
20A **domain name** ([DNS record](https://opensource.com/article/17/4/introduction-domain-name-system-dns)) pointing to the server's public IP address is required to obtain a SSL/TLS certificate and setup HTTPS to secure client traffic to your Shaarli instance.
21
22You can obtain a domain name from a [registrar](https://en.wikipedia.org/wiki/Domain_name_registrar) ([1](https://www.ovh.co.uk/domains), [2](https://www.gandi.net/en/domain)), or from free subdomain providers ([1](https://freedns.afraid.org/)). If you don't have a domain name, please set up a private domain name ([FQDN](ttps://en.wikipedia.org/wiki/Fully_qualified_domain_name)) in your clients' [hosts files](https://en.wikipedia.org/wiki/Hosts_(file)) to access the server (direct access by IP address can result in unexpected behavior).
23
24Setup a **firewall** (using `iptables`, [ufw](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-debian-10), [fireHOL](https://firehol.org/) or any frontend of your choice) to deny all incoming traffic except `tcp/80` and `tcp/443`, which are needed to access the web server (and any other posrts you might need, like SSH). If the server is in a private network behind a NAT, ensure these **ports are forwarded** to the server.
25
26Shaarli makes outbound HTTP/HTTPS connections to websites you bookmark to fetch page information (title, thumbnails), the server must then have access to the Internet as well, and a working DNS resolver.
27
28
29### Screencast
30
31Here is a screencast of the installation procedure
32
33[![asciicast](https://asciinema.org/a/z3RXxcJIRgWk0jM2ws6EnUFgO.svg)](https://asciinema.org/a/z3RXxcJIRgWk0jM2ws6EnUFgO)
34
35--------------------------------------------------------------------------------
36
37### PHP
38
39Supported PHP versions:
15 40
16Version | Status | Shaarli compatibility 41Version | Status | Shaarli compatibility
17:---:|:---:|:---: 42:---:|:---:|:---:
437.3 | Supported | Yes
187.2 | Supported | Yes 447.2 | Supported | Yes
197.1 | Supported | Yes 457.1 | Supported | Yes
207.0 | EOL: 2018-12-03 | Yes (up to Shaarli 0.10.x) 467.0 | EOL: 2018-12-03 | Yes (up to Shaarli 0.10.x)
@@ -23,420 +49,398 @@ Version | Status | Shaarli compatibility
235.4 | EOL: 2015-09-14 | Yes (up to Shaarli 0.8.x) 495.4 | EOL: 2015-09-14 | Yes (up to Shaarli 0.8.x)
245.3 | EOL: 2014-08-14 | Yes (up to Shaarli 0.8.x) 505.3 | EOL: 2014-08-14 | Yes (up to Shaarli 0.8.x)
25 51
26- The following PHP extensions are installed on the server: 52Required PHP extensions:
27 53
28Extension | Required? | Usage 54Extension | Required? | Usage
29---|:---:|--- 55---|:---:|---
30[`openssl`](http://php.net/manual/en/book.openssl.php) | All | OpenSSL, HTTPS 56[`openssl`](http://php.net/manual/en/book.openssl.php) | requires | OpenSSL, HTTPS
31[`php-json`](http://php.net/manual/en/book.json.php) | required | configuration parsing 57[`php-json`](http://php.net/manual/en/book.json.php) | required | configuration parsing
58[`php-simplexml`](https://www.php.net/manual/en/book.simplexml.php) | required | REST API (Slim framework)
32[`php-mbstring`](http://php.net/manual/en/book.mbstring.php) | CentOS, Fedora, RHEL, Windows, some hosting providers | multibyte (Unicode) string support 59[`php-mbstring`](http://php.net/manual/en/book.mbstring.php) | CentOS, Fedora, RHEL, Windows, some hosting providers | multibyte (Unicode) string support
33[`php-gd`](http://php.net/manual/en/book.image.php) | optional | required to use thumbnails 60[`php-gd`](http://php.net/manual/en/book.image.php) | optional | required to use thumbnails
34[`php-intl`](http://php.net/manual/en/book.intl.php) | optional | localized text sorting (e.g. `e->è->f`) 61[`php-intl`](http://php.net/manual/en/book.intl.php) | optional | localized text sorting (e.g. `e->è->f`)
35[`php-curl`](http://php.net/manual/en/book.curl.php) | optional | using cURL for fetching webpages and thumbnails in a more robust way 62[`php-curl`](http://php.net/manual/en/book.curl.php) | optional | using cURL for fetching webpages and thumbnails in a more robust way
36[`php-gettext`](http://php.net/manual/en/book.gettext.php) | optional | Use the translation system in gettext mode (faster) 63[`php-gettext`](http://php.net/manual/en/book.gettext.php) | optional | Use the translation system in gettext mode (faster)
37--------------------------------------------------------------------------------
38
39### SSL/TLS configuration
40 64
41To setup HTTPS / SSL on your webserver (recommended), you must generate a public/private **key pair** and a **certificate**, and install, configure and activate the appropriate **webserver SSL extension**. 65Some [plugins](Plugins.md) may require additional configuration.
42 66
43#### Let's Encrypt 67- [PHP: Supported versions](http://php.net/supported-versions.php)
68- [PHP: Unsupported versions (EOL/End-of-life)](http://php.net/eol.php)
69- [PHP 7 Changelog](http://php.net/ChangeLog-7.php)
70- [PHP 5 Changelog](http://php.net/ChangeLog-5.php)
71- [PHP: Bugs](https://bugs.php.net/)
44 72
45[Let's Encrypt](https://en.wikipedia.org/wiki/Let%27s_Encrypt) is a certificate authority that provides free TLS/X.509 certificates via an automated process.
46 73
47 * Install `certbot` using the appropriate method described on https://certbot.eff.org/. 74## SSL/TLS (HTTPS)
48
49Location of the `certbot` program and template configuration files may vary depending on which installation method was used. Change the file paths below accordingly. Here is an easy way to create a signed certificate using `certbot`, it assumes `certbot` was installed through APT on a Debian-based distribution:
50 75
51 * Stop the apache2/nginx service. 76We recommend setting up [HTTPS](https://en.wikipedia.org/wiki/HTTPS) (SSL/[TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security)) on your webserver for secure communication between clients and the server.
52 * Run `certbot --agree-tos --standalone --preferred-challenges tls-sni --email "youremail@example.com" --domain yourdomain.example.com`
53 * For the Apache webserver, copy `/usr/lib/python2.7/dist-packages/certbot_apache/options-ssl-apache.conf` to `/etc/letsencrypt/options-ssl-apache.conf` (paths may vary depending on installation method)
54 * For Nginx: TODO
55 * Setup your webserver as described below
56 * Restart the apache2/nginx service.
57 77
58#### Self-signed certificates 78### Let's Encrypt
59 79
60If you don't want to request a certificate from Let's Encrypt, or are unable to (for example, webserver on a LAN, or domain name not registered in the public DNS system), you can generate a self-signed certificate. This certificate will trigger security warnings in web browsers, unless you add it to the browser's SSL store manually. 80For public-facing web servers this can be done using free SSL/TLS certificates from [Let's Encrypt](https://en.wikipedia.org/wiki/Let's_Encrypt), a non-profit certificate authority provididing free certificates.
61 81
62* Apache: run `make-ssl-cert generate-default-snakeoil --force-overwrite` 82 - [How to secure Apache with Let's Encrypt](https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-debian-10)
63* Nginx: TODO 83 - [How to secure Nginx with Let's Encrypt](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-debian-10)
84 - [How To Use Certbot Standalone Mode to Retrieve Let's Encrypt SSL Certificates](https://www.digitalocean.com/community/tutorials/how-to-use-certbot-standalone-mode-to-retrieve-let-s-encrypt-ssl-certificates-on-debian-10).
64 85
65-------------------------------------------------------------------------------- 86In short:
66 87
67## Apache 88```bash
89# install certbot
90sudo apt install certbot
68 91
69Here is a basic configuration example for the Apache web server with `mod_php`. 92# stop your webserver if you already have one running
93# certbot in standalone mode needs to bind to port 80 (only needed on initial generation)
94sudo systemctl stop apache2
95sudo systemctl stop nginx
70 96
71In `/etc/apache2/sites-available/shaarli.conf`: 97# generate initial certificates
98# Let's Encrypt ACME servers must be able to access your server! port forwarding and firewall must be properly configured
99sudo certbot certonly --standalone --noninteractive --agree-tos --email "admin@shaarli.mydomain.org" -d shaarli.mydomain.org
100# this will generate a private key and certificate at /etc/letsencrypt/live/shaarli.mydomain.org/{privkey,fullchain}.pem
72 101
73```apache 102# restart the web server
74<VirtualHost *:443> 103sudo systemctl start apache2
75 ServerName shaarli.my-domain.org 104sudo systemctl start nginx
76 DocumentRoot /absolute/path/to/shaarli/ 105```
77 106
78 # Logging 107On apache `2.4.43+`, you can also delegate LE certificate management to [mod_md](https://httpd.apache.org/docs/2.4/mod/mod_md.html) [[1](https://www.cyberciti.biz/faq/how-to-secure-apache-with-mod_md-lets-encrypt-on-ubuntu-20-04-lts/)] in which case you don't need certbot and manual SSL configuration in virtualhosts.
79 # Possible values include: debug, info, notice, warn, error, crit, alert, emerg.
80 LogLevel warn
81 ErrorLog /var/log/apache2/shaarli-error.log
82 CustomLog /var/log/apache2/shaarli-access.log combined
83 108
84 # Let's Encrypt SSL configuration (recommended) 109### Self-signed
85 SSLEngine on
86 SSLCertificateFile /etc/letsencrypt/live/yourdomain.example.com/fullchain.pem
87 SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.example.com/privkey.pem
88 Include /etc/letsencrypt/options-ssl-apache.conf
89 110
90 # Self-signed SSL cert configuration 111If you don't want to rely on a certificate authority, or the server can only be accessed from your own network, you can also generate self-signed certificates. Not that this will generate security warnings in web browsers/clients trying to access Shaarli:
91 #SSLEngine on
92 #SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
93 #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
94 112
95 # Optional, log PHP errors, useful for debugging 113- [How To Create a Self-Signed SSL Certificate for Apache](https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-apache-on-debian-10)
96 #php_flag log_errors on 114- [How To Create a Self-Signed SSL Certificate for Nginx](https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-nginx-on-debian-10)
97 #php_flag display_errors on 115- [How to Create Self-Signed SSL Certificates with OpenSSL](http://www.xenocafe.com/tutorials/linux/centos/openssl/self_signed_certificates/index.php)
98 #php_value error_reporting 2147483647 116- [How do I create my own Certificate Authority?](https://workaround.org/certificate-authority)
99 #php_value error_log /var/log/apache2/shaarli-php-error.log
100 117
101 <Directory /absolute/path/to/shaarli/> 118--------------------------------------------------------------------------------
102 #Required for .htaccess support
103 AllowOverride All
104 Order allow,deny
105 Allow from all
106 119
107 Options Indexes FollowSymLinks MultiViews #TODO is Indexes/Multiviews required? 120## Examples
108 121
109 # Optional - required for playvideos plugin 122The following examples assume a Debian-based operating system is installed. On other distributions you may have to adapt details such as package installation procedures, configuration file locations, and webserver username/group (`www-data` or `httpd` are common values). In these examples we assume the document root for your web server/virtualhost is at `/var/www/shaarli.mydomain.org/`:
110 #Header set Content-Security-Policy "script-src 'self' 'unsafe-inline' https://www.youtube.com https://s.ytimg.com 'unsafe-eval'"
111 </Directory>
112 123
113</VirtualHost> 124```bash
125# create the document root (replace with your own domain name)
126sudo mkdir -p /var/www/shaarli.mydomain.org/
114``` 127```
115 128
116Enable this configuration with `sudo a2ensite shaarli` 129You can install Shaarli at the root of your virtualhost, or in a subdirectory as well. See [Directory structure](Directory-structure)
117 130
118_Note: If you use Apache 2.2 or lower, you need [mod_version](https://httpd.apache.org/docs/current/mod/mod_version.html) to be installed and enabled._
119 131
120_Note: Apache module `mod_rewrite` must be enabled to use the REST API._ 132### Apache
121 133
134```bash
135# Install apache + mod_php and PHP modules
136sudo apt update
137sudo apt install apache2 libapache2-mod-php php-json php-mbstring php-gd php-intl php-curl php-gettext
122 138
123## Nginx 139# Edit the virtualhost configuration file with your favorite editor (replace the example domain name)
140sudo nano /etc/apache2/sites-available/shaarli.mydomain.org.conf
141```
124 142
125Here is a basic configuration example for the Nginx web server, using the [php-fpm](http://php-fpm.org) PHP FastCGI Process Manager, and Nginx's [FastCGI](https://en.wikipedia.org/wiki/FastCGI) module. 143```apache
144<VirtualHost *:80>
145 ServerName shaarli.mydomain.org
146 DocumentRoot /var/www/shaarli.mydomain.org/
147
148 # For SSL/TLS certificates acquired with certbot or self-signed certificates
149 # Redirect HTTP requests to HTTPS, except Let's Encrypt ACME challenge requests
150 RewriteEngine on
151 RewriteRule ^.well-known/acme-challenge/ - [L]
152 RewriteCond %{HTTP_HOST} =shaarli.mydomain.org
153 RewriteRule ^ https://shaarli.mydomain.org%{REQUEST_URI} [END,NE,R=permanent]
154</VirtualHost>
126 155
127<!--- TODO refactor everything below this point ---> 156# SSL/TLS configuration for Let's Encrypt certificates managed with mod_md
157#MDomain shaarli.mydomain.org
158#MDCertificateAgreement accepted
159#MDContactEmail admin@shaarli.mydomain.org
160#MDPrivateKeys RSA 4096
161
162<VirtualHost *:443>
163 ServerName shaarli.mydomain.org
164 DocumentRoot /var/www/shaarli.mydomain.org/
128 165
129### Common setup 166 # SSL/TLS configuration for Let's Encrypt certificates acquired with certbot standalone
130Once Nginx and PHP-FPM are installed, we need to ensure: 167 SSLEngine on
168 SSLCertificateFile /etc/letsencrypt/live/shaarli.mydomain.org/fullchain.pem
169 SSLCertificateKeyFile /etc/letsencrypt/live/shaarli.mydomain.org/privkey.pem
170 # Let's Encrypt settings from https://github.com/certbot/certbot/blob/master/certbot-apache/certbot_apache/_internal/tls_configs/current-options-ssl-apache.conf
171 SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
172 SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
173 SSLHonorCipherOrder off
174 SSLSessionTickets off
175 SSLOptions +StrictRequire
176
177 # SSL/TLS configuration for self-signed certificates
178 #SSLEngine on
179 #SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
180 #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
131 181
132- Nginx and PHP-FPM are running using the _same user and group_ 182 # Optional, log PHP errors, useful for debugging
133- both these user and group have 183 #php_flag log_errors on
134 - `read` permissions for Shaarli resources 184 #php_flag display_errors on
135 - `execute` permissions for Shaarli directories _AND_ their parent directories 185 #php_value error_reporting 2147483647
186 #php_value error_log /var/log/apache2/shaarli-php-error.log
136 187
137On a production server: 188 <Directory /var/www/shaarli.mydomain.org/>
189 # Required for .htaccess support
190 AllowOverride All
191 Require all granted
192 </Directory>
138 193
139- `user:group` will likely be `http:http`, `www:www` or `www-data:www-data` 194 <LocationMatch "/\.">
140- files will be located under `/var/www`, `/var/http` or `/usr/share/nginx` 195 # Prevent accessing dotfiles
196 RedirectMatch 404 ".*"
197 </LocationMatch>
141 198
142On a development server: 199 <LocationMatch "\.(?:ico|css|js|gif|jpe?g|png)$">
200 # allow client-side caching of static files
201 Header set Cache-Control "max-age=2628000, public, must-revalidate, proxy-revalidate"
202 </LocationMatch>
143 203
144- files may be located in a user's home directory 204 # serve the Shaarli favicon from its custom location
145- in this case, make sure both Nginx and PHP-FPM are running as the local user/group! 205 Alias favicon.ico /var/www/shaarli.mydomain.org/images/favicon.ico
146 206
147For all following configuration examples, this user/group pair will be used: 207</VirtualHost>
208```
148 209
149- `user:group = john:users`, 210```bash
211# Enable the virtualhost
212sudo a2ensite shaarli.mydomain.org
150 213
151which corresponds to the following service configuration: 214# mod_ssl must be enabled to use TLS/SSL certificates
215# https://httpd.apache.org/docs/current/mod/mod_ssl.html
216sudo a2enmod ssl
152 217
153```ini 218# mod_rewrite must be enabled to use the REST API
154; /etc/php/php-fpm.conf 219# https://httpd.apache.org/docs/current/mod/mod_rewrite.html
155user = john 220sudo a2enmod rewrite
156group = users
157 221
158[...] 222# mod_headers must be enabled to set custom headers from the server config
159listen.owner = john 223sudo a2enmod headers
160listen.group = users
161```
162 224
163```nginx 225# mod_version must only be enabled if you use Apache 2.2 or lower
164# /etc/nginx/nginx.conf 226# https://httpd.apache.org/docs/current/mod/mod_version.html
165user john users; 227# sudo a2enmod version
166 228
167http { 229# restart the apache service
168 [...] 230sudo systemctl restart apache2
169}
170``` 231```
171 232
172### (Optional) Increase the maximum file upload size 233- [How to install the Apache web server](https://www.digitalocean.com/community/tutorials/how-to-install-the-apache-web-server-on-debian-10)
173Some bookmark dumps generated by web browsers can be _huge_ due to the presence of Base64-encoded images and favicons, as well as extra verbosity when nesting links in (sub-)folders. 234- [Apache/PHP - error log per VirtualHost - StackOverflow](http://stackoverflow.com/q/176)
235- [Apache - PHP: php_value vs php_admin_value and the use of php_flag explained](https://ma.ttias.be/php-php_value-vs-php_admin_value-and-the-use-of-php_flag-explained/)
236- [Server-side TLS (Apache) - Mozilla](https://wiki.mozilla.org/Security/Server_Side_TLS#Apache)
237- [Apache 2.4 documentation](https://httpd.apache.org/docs/2.4/)
238- [Apache mod_proxy](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html)
239- [Apache Reverse Proxy Request Headers](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#x-headers)
174 240
175To increase upload size, you will need to modify both nginx and PHP configuration:
176 241
177```nginx 242### Nginx
178# /etc/nginx/nginx.conf
179 243
180http { 244This examples uses nginx and the [PHP-FPM](https://www.digitalocean.com/community/tutorials/how-to-install-linux-nginx-mariadb-php-lemp-stack-on-debian-10#step-3-%E2%80%94-installing-php-for-processing) PHP interpreter. Nginx and PHP-FPM must be running using the same user and group, here we assume the user/group to be `www-data:www-data`.
181 [...]
182 245
183 client_max_body_size 10m;
184 246
185 [...] 247```bash
186} 248# install nginx and php-fpm
187``` 249sudo apt update
188 250sudo apt install nginx php-fpm
189```ini
190# /etc/php/<PHP_VERSION>/fpm/php.ini
191 251
192[...] 252# Edit the virtualhost configuration file with your favorite editor
193post_max_size = 10M 253sudo nano /etc/nginx/sites-available/shaarli.mydomain.org
194[...]
195upload_max_filesize = 10M
196``` 254```
197 255
198### Minimal
199_WARNING: Use for development only!_
200
201```nginx 256```nginx
202user john users; 257server {
203worker_processes 1; 258 listen 80;
204events { 259 server_name shaarli.mydomain.org;
205 worker_connections 1024; 260
261 # redirect all plain HTTP requests to HTTPS
262 return 301 https://shaarli.mydomain.org$request_uri;
206} 263}
207 264
208http { 265server {
209 include mime.types; 266 # ipv4 listening port/protocol
210 default_type application/octet-stream; 267 listen 443 ssl http2;
211 keepalive_timeout 20; 268 # ipv6 listening port/protocol
212 269 listen [::]:443 ssl http2;
213 index index.html index.php; 270 server_name shaarli.mydomain.org;
214 271 root /var/www/shaarli.mydomain.org;
215 server { 272
216 listen 80; 273 # log file locations
217 server_name localhost; 274 # combined log format prepends the virtualhost/domain name to log entries
218 root /home/john/web; 275 access_log /var/log/nginx/access.log combined;
219 276 error_log /var/log/nginx/error.log;
220 access_log /var/log/nginx/access.log; 277
221 error_log /var/log/nginx/error.log; 278 # paths to private key and certificates for SSL/TLS
222 279 ssl_certificate /etc/ssl/shaarli.mydomain.org.crt;
223 location /shaarli/ { 280 ssl_certificate_key /etc/ssl/private/shaarli.mydomain.org.key;
224 try_files $uri /shaarli/index.php$is_args$args; 281
225 access_log /var/log/nginx/shaarli.access.log; 282 # Let's Encrypt SSL settings from https://github.com/certbot/certbot/blob/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf
226 error_log /var/log/nginx/shaarli.error.log; 283 ssl_session_cache shared:le_nginx_SSL:10m;
227 } 284 ssl_session_timeout 1440m;
228 285 ssl_session_tickets off;
229 location ~ (index)\.php$ { 286 ssl_protocols TLSv1.2 TLSv1.3;
230 try_files $uri =404; 287 ssl_prefer_server_ciphers off;
231 fastcgi_split_path_info ^(.+\.php)(/.+)$; 288 ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
232 fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; 289
233 fastcgi_index index.php; 290 # increase the maximum file upload size if needed: by default nginx limits file upload to 1MB (413 Entity Too Large error)
234 include fastcgi.conf; 291 client_max_body_size 100m;
235 } 292
293 # relative path to shaarli from the root of the webserver
294 location / {
295 # default index file when no file URI is requested
296 index index.php;
297 try_files $uri /index.php$is_args$args;
236 } 298 }
237}
238```
239 299
240### Modular 300 location ~ (index)\.php$ {
241The previous setup is sufficient for development purposes, but has several major caveats: 301 try_files $uri =404;
302 # slim API - split URL path into (script_filename, path_info)
303 fastcgi_split_path_info ^(.+\.php)(/.+)$;
304 # pass PHP requests to PHP-FPM
305 fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
306 fastcgi_index index.php;
307 include fastcgi.conf;
308 }
242 309
243- every content that does not match the PHP rule will be sent to client browsers: 310 location ~ \.php$ {
244 - dotfiles - in our case, `.htaccess` 311 # deny access to all other PHP scripts
245 - temporary files, e.g. Vim or Emacs files: `index.php~` 312 # disable this if you host other PHP applications on the same virtualhost
246- asset / static resource caching is not optimized 313 deny all;
247- if serving several PHP sites, there will be a lot of duplication: `location /shaarli/`, `location /mysite/`, etc. 314 }
248 315
249To solve this, we will split Nginx configuration in several parts, that will be included when needed: 316 location ~ /\. {
317 # deny access to dotfiles
318 deny all;
319 }
250 320
251```nginx 321 location ~ ~$ {
252# /etc/nginx/deny.conf 322 # deny access to temp editor files, e.g. "script.php~"
253location ~ /\. { 323 deny all;
254 # deny access to dotfiles 324 }
255 access_log off;
256 log_not_found off;
257 deny all;
258}
259 325
260location ~ ~$ { 326 location = /favicon.ico {
261 # deny access to temp editor files, e.g. "script.php~" 327 # serve the Shaarli favicon from its custom location
262 access_log off; 328 alias /var/www/shaarli/images/favicon.ico;
263 log_not_found off; 329 }
264 deny all;
265}
266```
267 330
268```nginx 331 # allow client-side caching of static files
269# /etc/nginx/php.conf 332 location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
270location ~ (index)\.php$ { 333 expires max;
271 # Slim - split URL path into (script_filename, path_info) 334 add_header Cache-Control "public, must-revalidate, proxy-revalidate";
272 try_files $uri =404; 335 # HTTP 1.0 compatibility
273 fastcgi_split_path_info ^(.+\.php)(/.+)$; 336 add_header Pragma public;
274 337 }
275 # filter and proxy PHP requests to PHP-FPM
276 fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
277 fastcgi_index index.php;
278 include fastcgi.conf;
279}
280 338
281location ~ \.php$ {
282 # deny access to all other PHP scripts
283 deny all;
284} 339}
285``` 340```
286 341
287```nginx 342```bash
288# /etc/nginx/static_assets.conf 343# enable the configuration/virtualhost
289location ~* \.(?:ico|css|js|gif|jpe?g|png)$ { 344sudo ln -s /etc/nginx/sites-available/shaarli.mydomain.org /etc/nginx/sites-enabled/shaarli.mydomain.org
290 expires max; 345# reload nginx configuration
291 add_header Pragma public; 346sudo systemctl reload nginx
292 add_header Cache-Control "public, must-revalidate, proxy-revalidate";
293}
294``` 347```
295 348
296```nginx 349- [How to install the Nginx web server](https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-debian-10)
297# /etc/nginx/nginx.conf 350- [Nginx Beginner's guide](http://nginx.org/en/docs/beginners_guide.html)
298[...] 351- [Nginx documentation](https://nginx.org/en/docs/)
299 352- [Nginx ngx_http_fastcgi_module](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html)
300http { 353- [Nginx Pitfalls](http://wiki.nginx.org/Pitfalls)
301 [...] 354- [Nginx PHP configuration examples - Karl Blessing](http://kbeezie.com/nginx-configuration-examples/)
302 355- [Server-side TLS (Nginx) - Mozilla](https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx)
303 root /home/john/web;
304 access_log /var/log/nginx/access.log;
305 error_log /var/log/nginx/error.log;
306 356
307 server {
308 # virtual host for a first domain
309 listen 80;
310 server_name my.first.domain.org;
311 357
312 location /shaarli/ {
313 # Slim - rewrite URLs
314 try_files $uri /shaarli/index.php$is_args$args;
315 358
316 access_log /var/log/nginx/shaarli.access.log; 359## Reverse proxies
317 error_log /var/log/nginx/shaarli.error.log;
318 }
319 360
320 location = /shaarli/favicon.ico { 361If Shaarli is hosted on a server behind a [reverse proxy](https://en.wikipedia.org/wiki/Reverse_proxy) (i.e. there is a proxy server between clients and the web server hosting Shaarli), configure it accordingly. See [Reverse proxy](Reverse-proxy.md) configuration.
321 # serve the Shaarli favicon from its custom location
322 alias /var/www/shaarli/images/favicon.ico;
323 }
324 362
325 include deny.conf;
326 include static_assets.conf;
327 include php.conf;
328 }
329 363
330 server {
331 # virtual host for a second domain
332 listen 80;
333 server_name second.domain.com;
334 364
335 location /minigal/ { 365## Allow import of large browser bookmarks export
336 access_log /var/log/nginx/minigal.access.log;
337 error_log /var/log/nginx/minigal.error.log;
338 }
339 366
340 include deny.conf; 367Web browser bookmark exports can be large due to the presence of base64-encoded images and favicons/long subfolder names. Edit the PHP configuration file.
341 include static_assets.conf;
342 include php.conf;
343 }
344}
345```
346 368
347### Redirect HTTP to HTTPS 369- Apache: `/etc/php/<PHP_VERSION>/apache2/php.ini`
348Assuming you have generated a (self-signed) key and certificate, and they are 370- Nginx + PHP-FPM: `/etc/php/<PHP_VERSION>/fpm/php.ini` (in addition to `client_max_body_size` in the [Nginx configuration](#nginx))
349located under `/home/john/ssl/localhost.{key,crt}`, it is pretty straightforward
350to set an HTTP (:80) to HTTPS (:443) redirection to force SSL/TLS usage.
351 371
352```nginx 372```ini
353# /etc/nginx/nginx.conf
354[...] 373[...]
374# (optional) increase the maximum file upload size:
375post_max_size = 100M
376[...]
377# (optional) increase the maximum file upload size:
378upload_max_filesize = 100M
379```
355 380
356http { 381To verify PHP settings currently set on the server, create a `phpinfo.php` in your webserver's document root
357 [...]
358
359 index index.html index.php;
360
361 root /home/john/web;
362 access_log /var/log/nginx/access.log;
363 error_log /var/log/nginx/error.log;
364
365 server {
366 listen 80;
367 server_name localhost;
368 382
369 return 301 https://localhost$request_uri; 383```bash
370 } 384# example
385echo '<?php phpinfo(); ?>' | sudo tee /var/www/shaarli.mydomain.org/phpinfo.php
386#give read-only access to this file to the webserver user
387sudo chown www-data:root /var/www/shaarli.mydomain.org/phpinfo.php
388sudo chmod 0400 /var/www/shaarli.mydomain.org/phpinfo.php
389```
371 390
372 server { 391Access the file from a web browser (eg. <https://shaarli.mydomain.org/phpinfo.php> and look at the _Loaded Configuration File_ and _Scan this dir for additional .ini files_ entries
373 listen 443 ssl;
374 server_name localhost;
375 392
376 ssl_certificate /home/john/ssl/localhost.crt; 393It is recommended to remove the `phpinfo.php` when no longer needed as it publicly discloses details about your webserver configuration.
377 ssl_certificate_key /home/john/ssl/localhost.key;
378 394
379 location /shaarli/ {
380 # Slim - rewrite URLs
381 try_files $uri /index.php$is_args$args;
382 395
383 access_log /var/log/nginx/shaarli.access.log; 396## Robots and crawlers
384 error_log /var/log/nginx/shaarli.error.log;
385 }
386 397
387 location = /shaarli/favicon.ico { 398To opt-out of indexing your Shaarli instance by search engines, create a `robots.txt` file at the root of your virtualhost:
388 # serve the Shaarli favicon from its custom location
389 alias /var/www/shaarli/images/favicon.ico;
390 }
391 399
392 include deny.conf; 400```
393 include static_assets.conf; 401User-agent: *
394 include php.conf; 402Disallow: /
395 }
396}
397``` 403```
398 404
399## Proxies 405By default Shaarli already disallows indexing of your local copy of the documentation by default, using `<meta name="robots">` HTML tags. Your Shaarli instance may still be indexed by various robots on the public Internet, that do not respect this header or the robots standard.
400
401If Shaarli is served behind a proxy (i.e. there is a proxy server between clients and the web server hosting Shaarli), please refer to the proxy server documentation for proper configuration. In particular, you have to ensure that the following server variables are properly set:
402 406
403- `X-Forwarded-Proto` 407- [Robots exclusion standard](https://en.wikipedia.org/wiki/Robots_exclusion_standard)
404- `X-Forwarded-Host` 408- [Introduction to robots.txt](https://support.google.com/webmasters/answer/6062608?hl=en)
405- `X-Forwarded-For` 409- [Robots meta tag, data-nosnippet, and X-Robots-Tag specifications](https://developers.google.com/search/reference/robots_meta_tag)
410- [About robots.txt](http://www.robotstxt.org)
411- [About the robots META tag](https://www.robotstxt.org/meta.html)
406 412
407In you [Shaarli configuration](Shaarli-configuration) `data/config.json.php`, add the public IP of your proxy under `security.trusted_proxies`.
408 413
409See also [proxy-related](https://github.com/shaarli/Shaarli/issues?utf8=%E2%9C%93&q=label%3Aproxy+) issues. 414## Fail2ban
410 415
411## Robots and crawlers 416[fail2ban](http://www.fail2ban.org/wiki/index.php/Main_Page) is an intrusion prevention framework that reads server (Apache, SSH, etc.) and uses `iptables` profiles to block brute-force attempts. You need to create a filter to detect shaarli login failures in logs, and a jail configuation to configure the behavior when failed login attempts are detected:
412 417
413Shaarli disallows indexing and crawling of your local documentation pages by search engines, using `<meta name="robots">` HTML tags. 418```ini
414Your Shaarli instance and other pages you host may still be indexed by various robots on the public Internet. 419# /etc/fail2ban/filter.d/shaarli-auth.conf
415You may want to setup a robots.txt file or other crawler control mechanism on your server. 420[INCLUDES]
416See [[1]](https://en.wikipedia.org/wiki/Robots_exclusion_standard), [[2]](https://support.google.com/webmasters/answer/6062608?hl=en) and [[3]](https://developers.google.com/search/reference/robots_meta_tag) 421before = common.conf
422[Definition]
423failregex = \s-\s<HOST>\s-\sLogin failed for user.*$
424ignoreregex =
425```
417 426
418## See also 427```ini
428# /etc/fail2ban/jail.local
429[shaarli-auth]
430enabled = true
431port = https,http
432filter = shaarli-auth
433logpath = /var/www/shaarli.mydomain.org/data/log.txt
434# allow 3 login attempts per IP address
435# (over a period specified by findtime = in /etc/fail2ban/jail.conf)
436maxretry = 3
437# permanently ban the IP address after reaching the limit
438bantime = -1
439```
419 440
420 * [Server security](Server-security.md) 441Then restart the service: `sudo systemctl restart fail2ban`
421 442
422#### Webservers
423 443
424- [Apache/PHP - error log per VirtualHost](http://stackoverflow.com/q/176) (StackOverflow) 444## What next?
425- [Apache - PHP: php_value vs php_admin_value and the use of php_flag explained](https://ma.ttias.be/php-php_value-vs-php_admin_value-and-the-use-of-php_flag-explained/)
426- [Server-side TLS (Apache)](https://wiki.mozilla.org/Security/Server_Side_TLS#Apache) (Mozilla)
427- [Nginx Beginner's guide](http://nginx.org/en/docs/beginners_guide.html)
428- [Nginx ngx_http_fastcgi_module](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html)
429- [Nginx Pitfalls](http://wiki.nginx.org/Pitfalls)
430- [Nginx PHP configuration examples](http://kbeezie.com/nginx-configuration-examples/) (Karl Blessing)
431- [Server-side TLS (Nginx)](https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx) (Mozilla)
432- [How to Create Self-Signed SSL Certificates with OpenSSL](http://www.xenocafe.com/tutorials/linux/centos/openssl/self_signed_certificates/index.php)
433- [How do I create my own Certificate Authority?](https://workaround.org/certificate-authority)
434
435#### PHP
436 445
437- [Travis configuration](https://github.com/shaarli/Shaarli/blob/master/.travis.yml) 446[Shaarli installation](Installation.md)
438- [PHP: Supported versions](http://php.net/supported-versions.php)
439- [PHP: Unsupported versions](http://php.net/eol.php) _(EOL - End Of Life)_
440- [PHP 7 Changelog](http://php.net/ChangeLog-7.php)
441- [PHP 5 Changelog](http://php.net/ChangeLog-5.php)
442- [PHP: Bugs](https://bugs.php.net/)
diff --git a/doc/md/Server-security.md b/doc/md/Server-security.md
deleted file mode 100644
index ea1b637d..00000000
--- a/doc/md/Server-security.md
+++ /dev/null
@@ -1,76 +0,0 @@
1## php.ini
2PHP settings are defined in:
3
4- a main configuration file, usually found under `/etc/php/$php_version/php.ini`; some distributions provide different configuration environments, e.g.
5 - `/etc/php/$php_version/cli/php.ini` - used when running console scripts
6 - `/etc/php/$php_version/apache2/php.ini` - used when a client requests PHP resources from Apache
7 - `/etc/php/$php_version/php-fpm.conf` - used when PHP requests are proxied to PHP-FPM
8- additional configuration files/entries, depending on the installed/enabled extensions:
9 - `/etc/php/conf.d/xdebug.ini`
10
11### Locate .ini files
12#### Console environment
13```bash
14$ php --ini
15Configuration File (php.ini) Path: /etc/php
16Loaded Configuration File: /etc/php/php.ini
17Scan for additional .ini files in: /etc/php/conf.d
18Additional .ini files parsed: /etc/php/conf.d/xdebug.ini
19```
20
21#### Server environment
22- create a `phpinfo.php` script located in a path supported by the web server, e.g.
23 - Apache (with user dirs enabled): `/home/myself/public_html/phpinfo.php`
24 - `/var/www/test/phpinfo.php`
25- make sure the script is readable by the web server user/group (usually, `www`, `www-data` or `httpd`)
26- access the script from a web browser
27- look at the _Loaded Configuration File_ and _Scan this dir for additional .ini files_ entries
28```php
29<?php phpinfo(); ?>
30```
31
32## fail2ban
33`fail2ban` is an intrusion prevention framework that reads server (Apache, SSH, etc.) and uses `iptables` profiles to block brute-force attempts:
34
35- [Official website](http://www.fail2ban.org/wiki/index.php/Main_Page)
36- [Source code](https://github.com/fail2ban/fail2ban)
37
38### Read Shaarli logs to ban IPs
39Example configuration:
40- allow 3 login attempts per IP address
41- after 3 failures, permanently ban the corresponding IP adddress
42
43`/etc/fail2ban/jail.local`
44```ini
45[shaarli-auth]
46enabled = true
47port = https,http
48filter = shaarli-auth
49logpath = /var/www/path/to/shaarli/data/log.txt
50maxretry = 3
51bantime = -1
52```
53
54`/etc/fail2ban/filter.d/shaarli-auth.conf`
55```ini
56[INCLUDES]
57before = common.conf
58[Definition]
59failregex = \s-\s<HOST>\s-\sLogin failed for user.*$
60ignoreregex =
61```
62
63## Robots - Restricting search engines and web crawler traffic
64
65Creating a `robots.txt` with the following contents at the root of your Shaarli installation will prevent _honest_ web crawlers from indexing each and every link and Daily page from a Shaarli instance, thus getting rid of a certain amount of unsollicited network traffic.
66
67```
68User-agent: *
69Disallow: /
70```
71
72See:
73
74- http://www.robotstxt.org
75- http://www.robotstxt.org/robotstxt.html
76- http://www.robotstxt.org/meta.html
diff --git a/doc/md/Shaarli-configuration.md b/doc/md/Shaarli-configuration.md
index 2462e20e..14eec7b2 100644
--- a/doc/md/Shaarli-configuration.md
+++ b/doc/md/Shaarli-configuration.md
@@ -1,126 +1,19 @@
1## Foreword 1# Shaarli configuration
2
3**Do not edit configuration options in index.php! Your changes would be lost.**
4 2
5Once your Shaarli instance is installed, the file `data/config.json.php` is generated: 3Once your Shaarli instance is installed, the file `data/config.json.php` is generated:
6* it contains all settings in JSON format, and can be edited to customize values
7* it defines which [plugins](Plugin-System) are enabled
8* its values override those defined in `index.php`
9* it is wrap in a PHP comment to prevent anyone accessing it, regardless of server configuration
10
11## File and directory permissions
12
13The server process running Shaarli must have:
14
15- `read` access to the following resources:
16 - PHP scripts: `index.php`, `application/*.php`, `plugins/*.php`
17 - 3rd party PHP and Javascript libraries: `inc/*.php`, `inc/*.js`
18 - static assets:
19 - CSS stylesheets: `inc/*.css`
20 - `images/*`
21 - RainTPL templates: `tpl/*.html`
22- `read`, `write` and `execution` access to the following directories:
23 - `cache` - thumbnail cache
24 - `data` - link data store, configuration options
25 - `pagecache` - Atom/RSS feed cache
26 - `tmp` - RainTPL page cache
27
28On a Linux distribution:
29
30- the web server user will likely be `www` or `http` (for Apache2)
31- it will be a member of a group of the same name: `www:www`, `http:http`
32- to give it access to Shaarli, either:
33 - unzip Shaarli in the default web server location (usually `/var/www/`) and set the web server user as the owner
34 - put users in the same group as the web server, and set the appropriate access rights
35- if you have a domain / subdomain to serve Shaarli, [configure the server](Server-configuration) accordingly
36
37## Configuration
38
39In `data/config.json.php`.
40
41See also [Plugin System](Plugin-System).
42
43### Credentials
44
45_These settings should not be edited_
46
47- **login**: Login username.
48- **hash**: Generated password hash.
49- **salt**: Password salt.
50
51### General
52 4
53- **title**: Shaarli's instance title. 5- it contains all settings in JSON format, and can be edited to customize values
54- **header_link**: Link to the homepage. 6- it defines which [plugins](Plugins.md) are enabled
55- **links_per_page**: Number of shaares displayed per page. 7- its values override those defined in `index.php`
56- **timezone**: See [the list of supported timezones](http://php.net/manual/en/timezones.php). 8- it is wrapped in a PHP comment so that its contents are never served by the web server, regardless of configuration
57- **enabled_plugins**: List of enabled plugins.
58- **default_note_title**: Default title of a new note.
59- **retrieve_description** (boolean): If set to true, for every new links Shaarli will try
60to retrieve the description and keywords from the HTML meta tags.
61
62### Security
63
64- **session_protection_disabled**: Disable session cookie hijacking protection (not recommended).
65 It might be useful if your IP adress often changes.
66- **ban_after**: Failed login attempts before being IP banned.
67- **ban_duration**: IP ban duration in seconds.
68- **open_shaarli**: Anyone can add a new link while logged out if enabled.
69- **trusted_proxies**: List of trusted IP which won't be banned after failed login attemps. Useful if Shaarli is behind a reverse proxy.
70- **allowed_protocols**: List of allowed protocols in shaare URLs or markdown-rendered descriptions. Useful if you want to store `javascript:` links (bookmarklets) in Shaarli (default: `["ftp", "ftps", "magnet"]`).
71
72### Resources
73 9
74- **data_dir**: Data directory. 10**Do not edit configuration options in index.php! Your changes would be lost.**
75- **datastore**: Shaarli's links database file path.
76- **history**: Shaarli's operation history file path.
77- **updates**: File path for the ran updates file.
78- **log**: Log file path.
79- **update_check**: Last update check file path.
80- **raintpl_tpl**: Templates directory.
81- **raintpl_tmp**: Template engine cache directory.
82- **thumbnails_cache**: Thumbnails cache directory.
83- **page_cache**: Shaarli's internal cache directory.
84- **ban_file**: Banned IP file path.
85
86### Translation
87
88- **language**: translation language (also see [Translations](Translations))
89 - **auto** (default): The translation language is chosen from the browser locale.
90 It means that the language can be different for 2 different visitors depending on their locale.
91 - **en**: Use the English translation.
92 - **fr**: Use the French translation.
93- **mode**:
94 - **auto** or **php** (default): Use the PHP implementation of gettext (slower)
95 - **gettext**: Use PHP builtin gettext extension
96 (faster, but requires `php-gettext` to be installed and to reload the web server on update)
97- **extension**: Translation extensions for custom themes or plugins.
98Must be an associative array: `translation domain => translation path`.
99
100### Updates
101
102- **check_updates**: Enable or disable update check to the git repository.
103- **check_updates_branch**: Git branch used to check updates (e.g. `stable` or `master`).
104- **check_updates_interval**: Look for new version every N seconds (default: every day).
105
106### Privacy
107
108- **default_private_links**: Check the private checkbox by default for every new link.
109- **hide_public_links**: All links are hidden while logged out.
110- **force_login**: if **hide_public_links** and this are set to `true`, all anonymous users are redirected to the login page.
111- **hide_timestamps**: Timestamps are hidden.
112- **remember_user_default**: Default state of the login page's *remember me* checkbox
113 - `true`: checked by default, `false`: unchecked by default
114 11
115### Feed 12## Tools menu
116 13
117- **rss_permalinks**: Enable this to redirect RSS links to Shaarli's permalinks instead of shaared URL. 14Some settings can be configured directly from a web browser by accesing the `Tools` menu. Values are read/written to/from the configuration file.
118- **show_atom**: Display ATOM feed button.
119 15
120### Thumbnail 16![](https://i.imgur.com/boaaibC.png)
121
122- **enable_thumbnails**: Enable or disable thumbnail display.
123- **enable_localcache**: Enable or disable local cache.
124 17
125### LDAP 18### LDAP
126 19
@@ -182,6 +75,9 @@ Must be an associative array: `translation domain => translation path`.
182 "title": "My Shaarli", 75 "title": "My Shaarli",
183 "header_link": "?" 76 "header_link": "?"
184 }, 77 },
78 "dev": {
79 "debug": false,
80 }
185 "extras": { 81 "extras": {
186 "show_atom": false, 82 "show_atom": false,
187 "hide_public_links": false, 83 "hide_public_links": false,
@@ -236,9 +132,89 @@ Must be an associative array: `translation domain => translation path`.
236} ?> 132} ?>
237``` 133```
238 134
239## Additional configuration 135## Settings
136
137### Credentials
138
139_These settings should not be edited_
140
141- **login**: Login username.
142- **hash**: Generated password hash.
143- **salt**: Password salt.
144
145### General
146
147- **title**: Shaarli's instance title.
148- **header_link**: Link to the homepage.
149- **links_per_page**: Number of Shaares displayed per page.
150- **timezone**: See [the list of supported timezones](http://php.net/manual/en/timezones.php).
151- **enabled_plugins**: List of enabled plugins.
152- **default_note_title**: Default title of a new note.
153- **retrieve_description** (boolean): If set to true, for every new Shaare Shaarli will try to retrieve the description and keywords from the HTML meta tags.
154
155### Security
156
157- **session_protection_disabled**: Disable session cookie hijacking protection (not recommended).
158 It might be useful if your IP adress often changes.
159- **ban_after**: Failed login attempts before being IP banned.
160- **ban_duration**: IP ban duration in seconds.
161- **open_shaarli**: Anyone can add a new Shaare while logged out if enabled.
162- **trusted_proxies**: List of trusted IP which won't be banned after failed login attemps. Useful if Shaarli is behind a reverse proxy.
163- **allowed_protocols**: List of allowed protocols in shaare URLs or markdown-rendered descriptions. Useful if you want to store `javascript:` links (bookmarklets) in Shaarli (default: `["ftp", "ftps", "magnet"]`).
164
165### Resources
166
167- **data_dir**: Data directory.
168- **datastore**: Shaarli's Shaares database file path.
169- **history**: Shaarli's operation history file path.
170- **updates**: File path for the ran updates file.
171- **log**: Log file path.
172- **update_check**: Last update check file path.
173- **raintpl_tpl**: Templates directory.
174- **raintpl_tmp**: Template engine cache directory.
175- **thumbnails_cache**: Thumbnails cache directory.
176- **page_cache**: Shaarli's internal cache directory.
177- **ban_file**: Banned IP file path.
178
179### Translation
180
181- **language**: translation language (also see [Translations](Translations))
182 - **auto** (default): The translation language is chosen from the browser locale.
183 It means that the language can be different for 2 different visitors depending on their locale.
184 - **en**: Use the English translation.
185 - **fr**: Use the French translation.
186- **mode**:
187 - **auto** or **php** (default): Use the PHP implementation of gettext (slower)
188 - **gettext**: Use PHP builtin gettext extension
189 (faster, but requires `php-gettext` to be installed and to reload the web server on update)
190- **extension**: Translation extensions for custom themes or plugins.
191Must be an associative array: `translation domain => translation path`.
192
193### Updates
194
195- **check_updates**: Enable or disable update check to the git repository.
196- **check_updates_branch**: Git branch used to check updates (e.g. `stable` or `master`).
197- **check_updates_interval**: Look for new version every N seconds (default: every day).
198
199### Privacy
200
201- **default_private_links**: Check the private checkbox by default for every new Shaare.
202- **hide_public_links**: All Shaares are hidden while logged out.
203- **force_login**: if **hide_public_links** and this are set to `true`, all anonymous users are redirected to the login page.
204- **hide_timestamps**: Timestamps are hidden.
205- **remember_user_default**: Default state of the login page's *remember me* checkbox
206 - `true`: checked by default, `false`: unchecked by default
207
208### Feed
209
210- **rss_permalinks**: Enable this to redirect RSS links to Shaarli's permalinks instead of shaared URL.
211- **show_atom**: Display ATOM feed button.
212
213### Thumbnail
214
215- **enable_thumbnails**: Enable or disable thumbnail display.
216- **enable_localcache**: Enable or disable local cache.
240 217
241The `playvideos` plugin may require that you adapt your server's 218## Plugins configuration
242[Content Security Policy](https://github.com/shaarli/Shaarli/blob/master/plugins/playvideos/README.md#troubleshooting)
243configuration to work properly.
244 219
220See [Plugins](Plugins.md) \ No newline at end of file
diff --git a/doc/md/Sharing-content.md b/doc/md/Sharing-content.md
deleted file mode 100644
index 9a16fc62..00000000
--- a/doc/md/Sharing-content.md
+++ /dev/null
@@ -1,71 +0,0 @@
1Content posted to Shaarli is separated in items called _Shaares_. For each Shaare,
2you can customize the following aspects:
3
4 * URL to link to
5 * Title
6 * Free-text description
7 * Tags
8 * Public/private status
9
10--------------------------------------------------------------------------------
11
12## Adding new Shaares
13
14While logged in to your Shaarli, you can add new Shaares in several ways:
15
16 * [+Shaare button](#shaare-button)
17 * [Bookmarklet](#bookmarklet)
18 * Third-party [apps and browser addons](Community-&-Related-software.md#mobile-apps)
19 * [REST API](https://shaarli.github.io/api-documentation/)
20
21### +Shaare button
22
23 * While logged in to your Shaarli, click the **`+Shaare`** button located in the toolbar.
24 * Enter the URL of a link you want to share.
25 * Click `Add link`
26 * The `New Shaare` dialog appears, allowing you to fill in the details of your Shaare.
27 * The Description, Title, and Tags will help you find your Shaare later using tags or full-text search.
28 * You can also check the “Private” box so that the link is saved but only visible to you (the logged-in user).
29 * Click `Save`.
30
31<!-- TODO Add screenshot of add/edit link dialog -->
32
33### Bookmarklet
34
35The _Bookmarklet_ \[[1](https://en.wikipedia.org/wiki/Bookmarklet)\] is a special
36browser bookmark you can use to add new content to your Shaarli. This bookmarklet is
37compatible with Firefox, Opera, Chrome and Safari. To set it up:
38
39 * Access the `Tools` page from the button in the toolbar.
40 * Drag the **`✚Shaare link` button** to your browser's bookmarks bar.
41
42Once this is done, you can shaare any URL you are visiting simply by clicking the
43bookmarklet in your browser! The same `New Shaare` dialog as above is displayed.
44
45| Note | Websites which enforce Content Security Policy (CSP), such as github.com, disallow usage of bookmarklets. Unfortunately, there is nothing Shaarli can do about it. \[[1](https://github.com/shaarli/Shaarli/issues/196)]\ \[[2](https://bugzilla.mozilla.org/show_bug.cgi?id=866522)]\ \[[3](https://code.google.com/p/chromium/issues/detail?id=233903)]\ |
46|---------|---------|
47
48| Note | Under Opera, you can't drag'n drop the button: You have to right-click on it and add a bookmark to your personal toolbar. |
49|---------|---------|
50
51![](images/bookmarklet.png)
52
53
54--------------------------------------------------------------------------------
55
56## Editing Shaares
57
58Any Shaare can edited by clicking its ![](images/edit_icon.png) `Edit` button.
59
60Editing a Shaare will not change it's permalink, each permalink always points to the
61latest revision of a Shaare.
62
63--------------------------------------------------------------------------------
64
65## Using shaarli as a blog, notepad, pastebin...
66
67While adding or editing a link, leave the URL field blank to create a text-only
68("note") post. This allows you to post any kind of text content, such as blog
69articles, private or public notes, snippets... There is no character limit! You can
70access your Shaare from its permalink.
71
diff --git a/doc/md/Static-analysis.md b/doc/md/Static-analysis.md
deleted file mode 100644
index 29d98362..00000000
--- a/doc/md/Static-analysis.md
+++ /dev/null
@@ -1,13 +0,0 @@
1## WIP
2This topic is currently being discussed here:
3
4- [Fix coding style (static analysis)](https://github.com/shaarli/Shaarli/issues/95) (#95)
5- [Continuous Integration tools & features](https://github.com/shaarli/Shaarli/issues/130) (#130)
6
7### Usage
8Static analysis tools can be installed with Composer, and used through Shaarli's [Makefile](https://github.com/shaarli/Shaarli/blob/master/Makefile).
9
10For an overview of the available features, see:
11
12- [Code quality: Makefile to run static code checkers](https://github.com/shaarli/Shaarli/pull/124) (#124)
13- [Run PHPCS against different coding standards](https://github.com/shaarli/Shaarli/pull/276) (#276)
diff --git a/doc/md/Troubleshooting.md b/doc/md/Troubleshooting.md
index 01fd9840..e1ed5e00 100644
--- a/doc/md/Troubleshooting.md
+++ b/doc/md/Troubleshooting.md
@@ -1,5 +1,8 @@
1# Troubleshooting 1# Troubleshooting
2 2
3First of all, ensure that both the [web server](Server-configuration.md) and [Shaarli](Shaarli-configuration.md) are correctly configured.
4
5
3## Login 6## Login
4 7
5### I forgot my password! 8### I forgot my password!
@@ -8,38 +11,48 @@ Delete the file `data/config.json.php` and display the page again. You will be a
8 11
9### I'm locked out - Login bruteforce protection 12### I'm locked out - Login bruteforce protection
10 13
11Login form is protected against brute force attacks: 4 failed logins will ban the IP address from login for 30 minutes. Banned IPs can still browse links. 14Login form is protected against brute force attacks: 4 failed logins will ban the IP address from login for 30 minutes. Banned IPs can still browse Shaares.
12 15
13- To remove the current IP bans, delete the file `data/ipbans.php` 16- To remove the current IP bans, delete the file `data/ipbans.php`
14- To list all login attempts, see `data/log.txt` (succesful/failed logins, bans/lifted bans) 17- To list all login attempts, see `data/log.txt` (succesful/failed logins, bans/lifted bans)
15 18
19--------------------------------------
20
16## Browser issues 21## Browser issues
17 22
18### Redirection issues (HTTP Referer) 23### Redirection issues (HTTP Referer)
19 24
20Depending on its configuration and installed plugins, the browser may remove or alter (spoof) [HTTP referers](https://en.wikipedia.org/wiki/HTTP_referer), thus preventing Shaarli from properly redirecting between pages. Referer settings are available by browsing `about:config` and are documented [here](https://wiki.mozilla.org/Security/Referrer). `network.http.referer.spoofSource = true` in particular is known to break some functionality in Shaarli. 25Shaarli relies on `HTTP_REFERER` for some functions (like redirects and clicking on tags). If you have disabled or altered/spoofed [HTTP referers](https://en.wikipedia.org/wiki/HTTP_referer) in your browser, some features of Shaarli may not work as expected (depending on configuration and installed plugins), notably redirections between pages.
26
27Firefox Referer settings are available by browsing `about:config` and are documented [here](https://wiki.mozilla.org/Security/Referrer). `network.http.referer.spoofSource = true` in particular is known to break some functionality in Shaarli.
28
21 29
22### Firefox, localhost and redirections 30### Firefox, localhost and redirections
23 31
24`localhost` is not a proper Fully Qualified Domain Name (FQDN); if Firefox has been set up to spoof referers, or only accept requests from the same base domain/host, 32`localhost` is not a proper Fully Qualified Domain Name (FQDN); if Firefox has been set up to spoof referers, or only accept requests from the same base domain/host,
25Shaarli redirections will not work properly. To solve this, assign a local domain to your host, e.g. `localhost.lan` in your [hosts file](https://en.wikipedia.org/wiki/Hosts_(file)) and browse Shaarli at http://localhost.lan/. 33Shaarli redirections will not work properly. To solve this, assign a local domain to your host, e.g. `localhost.lan` in your [hosts file](https://en.wikipedia.org/wiki/Hosts_(file)) and browse Shaarli at http://localhost.lan/.
26 34
35-----------------------------------------
36
27## Hosting problems 37## Hosting problems
28 38
29### Old PHP versions 39### Old PHP versions
30 40
31On **free.fr**: free.fr now supports php 5.6.x([link](http://les.pages.perso.chez.free.fr/migrations/php5v6.io)) 41- On hosts (such as **free.fr**) which only support PHP 5.6, Shaarli [v0.10.4](https://github.com/shaarli/Shaarli/releases/tag/v0.10.4) is the maximum supported version. At the root of your webspace create a `sessions` directory and a `.htaccess` file containing:
32and so support now the tag autocompletion but you have to do the following.
33
34At the root of your webspace create a `sessions` directory and a `.htaccess` file containing:
35 42
36```xml 43```xml
37<IfDefine Free> 44<IfDefine Free>
38php56 1 45php56 1
39</IfDefine> 46</IfDefine>
47<Files ".ht*">
48Order allow,deny
49Deny from all
50Satisfy all
51</Files>
52Options -Indexes
40``` 53```
41 54
42- If you have an error such as: `Parse error: syntax error, unexpected '=', expecting '(' in /links/index.php on line xxx`, it means that your host is using php4, not php5. Shaarli requires php 5.1. Try changing the file extension to `.php5` 55- If you have an error such as: `Parse error: syntax error, unexpected '=', expecting '(' in /links/index.php on line xxx`, it means that your host is using PHP 4, not PHP 5. Shaarli requires PHP 5.1. Try changing the file extension to `.php5`
43- On **1and1** : If you add the link from the page (and not from the bookmarklet), Shaarli will no be able to get the title of the page. You will have to enter it manually. (Because they have disabled the ability to download a file through HTTP). 56- On **1and1** : If you add the link from the page (and not from the bookmarklet), Shaarli will no be able to get the title of the page. You will have to enter it manually. (Because they have disabled the ability to download a file through HTTP).
44- If you have the error `Warning: file_get_contents() [function.file-get-contents]: URL file-access is disabled in the server configuration in /…/index.php on line xxx`, it means that your host has disabled the ability to fetch a file by HTTP in the php config (Typically in 1and1 hosting). Bad host. Change host. Or comment the following lines: 57- If you have the error `Warning: file_get_contents() [function.file-get-contents]: URL file-access is disabled in the server configuration in /…/index.php on line xxx`, it means that your host has disabled the ability to fetch a file by HTTP in the php config (Typically in 1and1 hosting). Bad host. Change host. Or comment the following lines:
45 58
@@ -49,9 +62,11 @@ php56 1
49//if (strpos($status,'200 OK')) $title=html_extract_title($data); 62//if (strpos($status,'200 OK')) $title=html_extract_title($data);
50``` 63```
51 64
52- On hosts which forbid outgoing HTTP requests (such as free.fr), some thumbnails will not work. 65- On hosts (such as **free.fr**) which forbid outgoing HTTP requests, some thumbnails will not work.
66- On hosts (such as **free.fr**) which limit the number of FTP connections, setup your FTP client accordingly (else some files may be missing after upload).
53- On **lost-oasis**, RSS doesn't work correctly, because of this message at the begining of the RSS/ATOM feed : `<? // tout ce qui est charge ici (generalement des includes et require) est charge en permanence. ?>`. To fix this, remove this message from `php-include/prepend.php` 67- On **lost-oasis**, RSS doesn't work correctly, because of this message at the begining of the RSS/ATOM feed : `<? // tout ce qui est charge ici (generalement des includes et require) est charge en permanence. ?>`. To fix this, remove this message from `php-include/prepend.php`
54 68
69
55### Dates are not properly formatted 70### Dates are not properly formatted
56 71
57Shaarli tries to sniff the language of the browser (using `HTTP_ACCEPT_LANGUAGE` headers) 72Shaarli tries to sniff the language of the browser (using `HTTP_ACCEPT_LANGUAGE` headers)
@@ -71,11 +86,118 @@ This can be caused by several things:
71- You may be using OperaTurbo or OperaMini, which use their own proxies which may change from time to time. 86- You may be using OperaTurbo or OperaMini, which use their own proxies which may change from time to time.
72- If you have another application on the same webserver where Shaarli is installed, these application may forcefully expire php sessions. 87- If you have another application on the same webserver where Shaarli is installed, these application may forcefully expire php sessions.
73 88
89
74### Old apache versions, Internal Server Error 90### Old apache versions, Internal Server Error
75 91
76If you hosting provider only provides apache 2.2 and no support for `mod_version`, `.htaccess` files may cause 500 errors (Internal Server Error). See [this workaround](https://github.com/shaarli/Shaarli/issues/1196#issuecomment-412271085). 92If you hosting provider only provides apache 2.2 and no support for `mod_version`, `.htaccess` files may cause 500 errors (Internal Server Error). See [this workaround](https://github.com/shaarli/Shaarli/issues/1196#issuecomment-412271085).
77 93
78## Sessions do not seem to work correctly on your server 94
95### Sessions do not seem to work correctly on your server
79 96
80Follow the instructions in the error message. Make sure you are accessing shaarli via a direct IP address or a proper hostname. If you have **no dots** in the hostname (e.g. `localhost` or `http://my-webserver/shaarli/`), some browsers will not store cookies at all (this respects the [HTTP cookie specification](http://curl.haxx.se/rfc/cookie_spec.html)). 97Follow the instructions in the error message. Make sure you are accessing shaarli via a direct IP address or a proper hostname. If you have **no dots** in the hostname (e.g. `localhost` or `http://my-webserver/shaarli/`), some browsers will not store cookies at all (this respects the [HTTP cookie specification](http://curl.haxx.se/rfc/cookie_spec.html)).
81 98
99----------------------------------------------------------
100
101## Upgrades
102
103### You must specify an integer as a key
104
105In `v0.8.1` we changed how Shaare keys are handled (from timestamps to incremental integers). Take a look at `data/updates.txt` content.
106
107
108### `updates.txt` contains `updateMethodDatastoreIds`
109
110Try to delete it and refresh your page while being logged in.
111
112### `updates.txt` doesn't exist or doesn't contain `updateMethodDatastoreIds`
113
1141. Create `data/updates.txt` if it doesn't exist
1152. Paste this string in the update file `;updateMethodRenameDashTags;`
1163. Login to Shaarli
1174. Delete the update file
1185. Refresh
119
120
121
122--------------------------------------------------------
123
124## Import/export
125
126### Importing shaarli data to Firefox
127
128- In Firefox, open the bookmark manager (`Bookmarks menu > Show all bookmarks` or `Ctrl+Shift+B`), select `Import and Backup > Import bookmarks in HTML format`
129- Make sure the `Prepend note permalinks with this Shaarli instance's URL` box is checked when exporting, so that text-only/notes Shaares still point to the Shaarli instance you exported them from.
130- Depending on the number of bookmarks, the import can take some time.
131
132You may be interested in these Firefox addons to manage bookmarks imported from Shaarli
133
134- [Bookmark Deduplicator](https://addons.mozilla.org/en-US/firefox/addon/bookmark-deduplicator/) - provides an easy way to deduplicate your bookmarks
135- [TagSieve](https://addons.mozilla.org/en-US/firefox/addon/tagsieve/) - browse your bookmarks by their tags
136
137### Diigo
138
139If you export your bookmark from Diigo, make sure you use the Delicious export, not the Netscape export. (Their Netscape export is broken, and they don't seem to be interested in fixing it.)
140
141### Mister Wong
142
143See [this issue](https://github.com/sebsauvage/Shaarli/issues/146) for import tweaks.
144
145### SemanticScuttle
146
147To correctly import the tags from a [SemanticScuttle](http://semanticscuttle.sourceforge.net/) HTML export, edit the HTML file before importing and replace all occurences of `tags=` (lowercase) to `TAGS=` (uppercase).
148
149### Scuttle
150
151Shaarli cannot import data directly from [Scuttle](https://github.com/scronide/scuttle).
152
153However, you can use the third-party [scuttle-to-shaarli](https://github.com/q2apro/scuttle-to-shaarli)
154tool to export the Scuttle database to the Netscape HTML format compatible with the Shaarli importer.
155
156### Refind.com
157
158You can use the third-party tool [Derefind](https://github.com/ShawnPConroy/Derefind) to convert refind.com bookmark exports to a format that can be imported into Shaarli.
159
160
161-------------------------------------------------------
162
163## Other
164
165### The bookmarklet doesn't work
166
167Websites which enforce Content Security Policy (CSP), such as github.com, disallow usage of bookmarklets. Unfortunately, there is nothing Shaarli can do about it ([1](https://github.com/shaarli/Shaarli/issues/196), [2](https://bugzilla.mozilla.org/show_bug.cgi?id=866522), [3](https://code.google.com/p/chromium/issues/detail?id=233903).
168
169Under Opera, you can't drag'n drop the button: You have to right-click on it and add a bookmark to your personal toolbar.
170
171
172### Changing the timestamp for a shaare
173
174- Look for `<input type="hidden" name="lf_linkdate" value="{$link.linkdate}">` in `tpl/editlink.tpl` (line 14)
175- Replace `type="hidden"` with `type="text"` from this line
176- A new date/time field becomes available in the edit/new Shaare dialog.
177- You can set the timestamp manually by entering it in the format `YYYMMDD_HHMMS`.
178
179### Clearing Shaarli caches
180
181For debugging purposes:
182
183```bash
184# clear raintpl cache and temporary files
185find /var/www/links/cache/ /var/www/links/pagecache/ /var/www/links/tmp/ -type f -exec rm -v '{}' \;
186# if you have a php accelerator such as php-apcu, restart the webserver
187sudo systemctl restart apache2
188```
189
190-------------------------------------------------------
191
192## Support
193
194If the solutions above did not help, please:
195
196- Come and ask question on the [Gitter chat](https://gitter.im/shaarli/Shaarli) (also reachable via [IRC](https://irc.gitter.im/))
197- Search for [issues](https://github.com/shaarli/Shaarli/issues) and [Pull Requests](https://github.com/shaarli/Shaarli/pulls)
198 - if you find one that is related to the issue, feel free to comment and provide additional details (host/Shaarli setup...)
199 - check issues labeled [`feature`](https://github.com/shaarli/Shaarli/labels/feature), [`enhancement`](https://github.com/shaarli/Shaarli/labels/enhancement), and [`plugin`](https://github.com/shaarli/Shaarli/labels/plugin) if you would like a feature added to Shaarli.
200 - else, [open a new issue](https://github.com/shaarli/Shaarli/issues/new), and provide information about the problem:
201 - _what happens?_ - display glitches, invalid data, security flaws...
202 - _what is your configuration?_ - OS, server version, activated extensions, web browser...
203 - _is it reproducible?_ \ No newline at end of file
diff --git a/doc/md/Unit-tests.md b/doc/md/Unit-tests.md
deleted file mode 100644
index a9544656..00000000
--- a/doc/md/Unit-tests.md
+++ /dev/null
@@ -1,119 +0,0 @@
1The testing framework used is [PHPUnit](https://phpunit.de/); it can be installed with [Composer](https://getcomposer.org/), which is a dependency management tool.
2
3## Setup a testing environment
4
5### Install composer
6
7You can either use:
8
9- a system-wide version, e.g. installed through your distro's package manager (eg. `sudo apt install composer`)
10- a local version, downloadable [here](https://getcomposer.org/download/). To update a local composer installation, run `php composer.phar self-update`
11
12
13### Install Shaarli development dependencies
14
15```bash
16$ cd /path/to/shaarli
17$ composer install
18```
19
20### Install Xdebug
21
22Xdebug must be installed and enable for PHPUnit to generate coverage reports. See http://xdebug.org/docs/install.
23
24```bash
25# for Debian-based distributions
26$ aptitude install php-xdebug
27
28# for ArchLinux:
29$ pacman -S xdebug
30```
31
32Then add the following line to `/etc/php/<PHP_VERSION>/cli/php.ini`:
33
34```ini
35zend_extension=xdebug.so
36```
37
38## Run unit tests
39
40Run `make test` and ensure tests return `OK`. If tests return failures, refer to PHPUnit messages and fix your code/tests accordingly.
41
42By default, PHPUnit will run all suitable tests found under the `tests` directory. Each test has 3 possible outcomes:
43
44- `.` - success
45- `F` - failure: the test was run but its results are invalid
46 - the code does not behave as expected
47 - dependencies to external elements: globals, session, cache...
48- `E` - error: something went wrong and the tested code has crashed
49 - typos in the code, or in the test code
50 - dependencies to missing external elements
51
52If Xdebug has been installed and activated, two coverage reports will be generated:
53
54- a summary in the console
55- a detailed HTML report with metrics for tested code
56 - to open it in a web browser: `firefox coverage/index.html &`
57
58### Executing specific tests
59
60Add a [`@group`](https://phpunit.de/manual/current/en/appendixes.annotations.html#appendixes.annotations.group) annotation in a test class or method comment:
61
62```php
63/**
64 * Netscape bookmark import
65 * @group WIP
66 */
67class BookmarkImportTest extends PHPUnit_Framework_TestCase
68{
69 [...]
70}
71```
72
73To run all tests annotated with `@group WIP`:
74```bash
75$ vendor/bin/phpunit --group WIP tests/
76```
77
78### Running tests inside Docker containers
79
80Test Dockerfiles are located under `tests/docker/<distribution>/Dockerfile`,
81and can be used to build Docker images to run Shaarli test suites under common
82Linux environments.
83
84Dockerfiles are provided for the following environments:
85
86- `alpine36` - [Alpine 3.6](https://www.alpinelinux.org/downloads/)
87- `debian8` - [Debian 8 Jessie](https://www.debian.org/DebianJessie) (oldstable)
88- `debian9` - [Debian 9 Stretch](https://wiki.debian.org/DebianStretch) (stable)
89- `ubuntu16` - [Ubuntu 16.04 Xenial Xerus](http://releases.ubuntu.com/16.04/) (LTS)
90
91What's behind the curtains:
92
93- each image provides:
94 - a base Linux OS
95 - Shaarli PHP dependencies (OS packages)
96 - test PHP dependencies (OS packages)
97 - Composer
98- the local workspace is mapped to the container's `/shaarli/` directory,
99- the files are rsync'd so tests are run using a standard Linux user account
100 (running tests as `root` would bypass permission checks and may hide issues)
101- the tests are run inside the container.
102
103To run tests inside a Docker container:
104
105```bash
106# build the Debian 9 Docker image for unit tests
107$ cd /path/to/shaarli
108$ cd tests/docker/debian9
109$ docker build -t shaarli-test:debian9 .
110
111# install/update 3rd-party test dependencies
112$ composer install --prefer-dist
113
114# run tests using the freshly built image
115$ docker run -v $PWD:/shaarli shaarli-test:debian9 docker_test
116
117# run the full test campaign
118$ docker run -v $PWD:/shaarli shaarli-test:debian9 docker_all_tests
119```
diff --git a/doc/md/Upgrade-and-migration.md b/doc/md/Upgrade-and-migration.md
index d5682a34..bfef3e8c 100644
--- a/doc/md/Upgrade-and-migration.md
+++ b/doc/md/Upgrade-and-migration.md
@@ -1,96 +1,83 @@
1## Preparation 1# Upgrade and migration
2 2
3### Note your current version 3## Note your current version
4 4
5If anything goes wrong, it's important for us to know which version you're upgrading from. 5If anything goes wrong, it's important for us to know which version you're upgrading from.
6The current version is present in the `shaarli_version.php` file. 6The current version is present in the `shaarli_version.php` file.
7 7
8### Backup your data
9 8
10Shaarli stores all user data under the `data` directory: 9## Backup your data
11 10
12- `data/config.json.php` (or `data/config.php` for older Shaarli versions) - main configuration file 11Shaarli stores all user data and [configuration](Shaarli-configuration.md) under the `data` directory. [Backup](Backup-and-restore.md) this repository _before_ upgrading Shaarli. You will need to restore it after the following upgrade steps.
13- `data/datastore.php` - bookmarked links
14- `data/ipbans.php` - banned IP addresses
15- `data/updates.txt` - contains all automatic update to the configuration and datastore files already run
16 12
17See [Shaarli configuration](Shaarli-configuration) for more information about Shaarli resources. 13```bash
18 14sudo cp -r /var/www/shaarli.mydomain.org/data ~/shaarli-data-backup
19It is recommended to backup this repository _before_ starting updating/upgrading Shaarli: 15```
20
21- users with SSH access: copy or archive the directory to a temporary location
22- users with FTP access: download a local copy of your Shaarli installation using your favourite client
23 16
24### Migrating data from a previous installation 17## Upgrading from ZIP archives
25 18
26As all user data is kept under `data`, this is the only directory you need to worry about when migrating to a new installation, which corresponds to the following steps: 19If you installed Shaarli from a [release ZIP archive](Installation.md#from-release-zip):
27 20
28- backup the `data` directory 21```bash
29- install or update Shaarli: 22# Download the archive to the server, and extract it
30 - fresh installation - see [Download and Installation](Download-and-Installation) 23cd ~
31 - update - see the following sections 24wget https://github.com/shaarli/Shaarli/releases/download/v0.X.Y/shaarli-v0.X.Y-full.zip
32- check or restore the `data` directory 25unzip shaarli-v0.X.Y-full.zip
33 26
34## Recommended : Upgrading from release archives 27# overwrite your Shaarli installation with the new release **All data will be lost, see _Backup your data_ above.**
28sudo rsync -avP --delete Shaarli/ /var/www/shaarli.mydomain.org/
35 29
36All tagged revisions can be downloaded as tarballs or ZIP archives from the [releases](https://github.com/shaarli/Shaarli/releases) page. 30# restore file permissions as described on the installation page
31sudo chown -R root:www-data /var/www/shaarli.mydomain.org
32sudo chmod -R g+rX /var/www/shaarli.mydomain.org
33sudo chmod -R g+rwX /var/www/shaarli.mydomain.org/{cache/,data/,pagecache/,tmp/}
37 34
38We recommend that you use the latest release tarball with the `-full` suffix. It contains the dependencies, please read [Download and Installation](Download-and-Installation) for `git` complete instructions. 35# restore backups of the data directory
36sudo cp -r ~/shaarli-data-backup/* /var/www/shaarli.mydomain.org/data/
39 37
40Once downloaded, extract the archive locally and update your remote installation (e.g. via FTP) -be sure you keep the content of the `data` directory! 38# If you use gettext mode for translations (not the default), reload your web server.
39sudo systemctl restart apache2
40sudo systemctl restart nginx
41```
41 42
42If you use translations in gettext mode - meaning you manually changed the default mode -, 43If you don't have shell access (eg. on shared hosting), backup the shaarli data directory, download the ZIP archive locally, extract it, upload it to the server using file transfer, and restore the data directory backup.
43reload your web server.
44 44
45After upgrading, access your fresh Shaarli installation from a web browser; the configuration and data store will then be automatically updated, and new settings added to `data/config.json.php` (see [Shaarli configuration](Shaarli configuration) for more details). 45Access your fresh Shaarli installation from a web browser; the configuration and data store will then be automatically updated, and new settings added to `data/config.json.php` (see [Shaarli configuration](Shaarli-configuration.md) for more details).
46 46
47## Upgrading with Git
48 47
49### Updating a community Shaarli 48## Upgrading from Git
50 49
51If you have installed Shaarli from the [community Git repository](Download#clone-with-git-recommended), simply [pull new changes](https://www.git-scm.com/docs/git-pull) from your local clone: 50If you have installed Shaarli [from sources](Installation.md#from-sources):
52 51
53```bash 52```bash
54$ cd /path/to/shaarli 53# pull new changes from your local clone
55$ git pull 54cd /var/www/shaarli.mydomain.org/
56 55sudo git pull
57From github.com:shaarli/Shaarli
58 * branch master -> FETCH_HEAD
59Updating ebd67c6..521f0e6
60Fast-forward
61 application/Url.php | 1 +
62 shaarli_version.php | 2 +-
63 tests/Url/UrlTest.php | 1 +
64 3 files changed, 3 insertions(+), 1 deletion(-)
65```
66 56
67Shaarli >= `v0.8.x`: install/update third-party PHP dependencies using [Composer](https://getcomposer.org/): 57# update PHP dependencies (Shaarli >= v0.8)
58sudo composer install --no-dev
68 59
69```bash 60# update translations (Shaarli >= v0.9.2)
70$ composer install --no-dev 61sudo make translate
71 62
72Loading composer repositories with package information 63# If you use translations in gettext mode (not the default), reload your web server.
73Updating dependencies 64sudo systemctl reload apache
74 - Installing shaarli/netscape-bookmark-parser (v1.0.1) 65sudo systemctl reload nginx
75 Downloading: 100%
76```
77 66
78Shaarli >= `v0.9.2` supports translations: 67# update front-end dependencies (Shaarli >= v0.10.0)
68sudo make build_frontend
79 69
80```bash 70# restore file permissions as described on the installation page
81$ make translate 71sudo chown -R root:www-data /var/www/shaarli.mydomain.org
82``` 72sudo chmod -R g+rX /var/www/shaarli.mydomain.org
73sudo chmod -R g+rwX /var/www/shaarli.mydomain.org/{cache/,data/,pagecache/,tmp/}
74```
83 75
84If you use translations in gettext mode, reload your web server. 76Access your fresh Shaarli installation from a web browser; the configuration and data store will then be automatically updated, and new settings added to `data/config.json.php` (see [Shaarli configuration](Shaarli-configuration.md) for more details).
85 77
86Shaarli >= `v0.10.0` manages its front-end dependencies with nodejs. You need to install 78---------------------------------------------------------------
87[yarn](https://yarnpkg.com/lang/en/docs/install/):
88 79
89```bash 80## Migrating and upgrading from Sebsauvage's repository
90$ make build_frontend
91```
92
93### Migrating and upgrading from Sebsauvage's repository
94 81
95If you have installed Shaarli from [Sebsauvage's original Git repository](https://github.com/sebsauvage/Shaarli), you can use [Git remotes](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes) to update your working copy. 82If you have installed Shaarli from [Sebsauvage's original Git repository](https://github.com/sebsauvage/Shaarli), you can use [Git remotes](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes) to update your working copy.
96 83
@@ -104,7 +91,7 @@ The following guide assumes that:
104 - no versioned file has been locally modified 91 - no versioned file has been locally modified
105 - no untracked files are present 92 - no untracked files are present
106 93
107#### Step 0: show repository information 94### Step 0: show repository information
108 95
109```bash 96```bash
110$ cd /path/to/shaarli 97$ cd /path/to/shaarli
@@ -122,7 +109,7 @@ Your branch is up-to-date with 'origin/master'.
122nothing to commit, working directory clean 109nothing to commit, working directory clean
123``` 110```
124 111
125#### Step 1: update Git remotes 112### Step 1: update Git remotes
126 113
127``` 114```
128$ git remote rename origin sebsauvage 115$ git remote rename origin sebsauvage
@@ -146,7 +133,7 @@ From https://github.com/shaarli/Shaarli
146 * [new tag] v0.7.0 -> v0.7.0 133 * [new tag] v0.7.0 -> v0.7.0
147``` 134```
148 135
149#### Step 2: use the stable community branch 136### Step 2: use the stable community branch
150 137
151```bash 138```bash
152$ git checkout origin/stable -b stable 139$ git checkout origin/stable -b stable
@@ -177,8 +164,7 @@ $ make translate
177 164
178If you use translations in gettext mode, reload your web server. 165If you use translations in gettext mode, reload your web server.
179 166
180Shaarli >= `v0.10.0` manages its front-end dependencies with nodejs. You need to install 167Shaarli >= `v0.10.0` manages its front-end dependencies with nodejs. You need to install [yarn](https://yarnpkg.com/lang/en/docs/install/):
181[yarn](https://yarnpkg.com/lang/en/docs/install/):
182 168
183```bash 169```bash
184$ make build_frontend 170$ make build_frontend
@@ -204,30 +190,14 @@ Writing objects: 100% (3317/3317), done.
204Total 3317 (delta 2050), reused 3301 (delta 2034)to 190Total 3317 (delta 2050), reused 3301 (delta 2034)to
205``` 191```
206 192
207#### Step 3: configuration 193### Step 3: configuration
208 194
209After migrating, access your fresh Shaarli installation from a web browser; the 195After migrating, access your fresh Shaarli installation from a web browser; the
210configuration will then be automatically updated, and new settings added to 196configuration will then be automatically updated, and new settings added to
211`data/config.json.php` (see [Shaarli configuration](Shaarli-configuration) for more 197`data/config.json.php` (see [Shaarli configuration](Shaarli-configuration.md) for more
212details). 198details).
213 199
214## Troubleshooting 200## Troubleshooting
215 201
216If the solutions provided here don't work, please open an issue specifying which version you're upgrading from and to. 202If the solutions provided here don't work, see [Troubleshooting](Troubleshooting.md) and/or open an issue specifying which version you're upgrading from and to.
217
218### You must specify an integer as a key
219
220In `v0.8.1` we changed how link keys are handled (from timestamps to incremental integers).
221Take a look at `data/updates.txt` content.
222
223#### `updates.txt` contains `updateMethodDatastoreIds`
224
225Try to delete it and refresh your page while being logged in.
226
227#### `updates.txt` doesn't exist or doesn't contain `updateMethodDatastoreIds`
228 203
2291. Create `data/updates.txt` if it doesn't exist
2302. Paste this string in the update file `;updateMethodRenameDashTags;`
2313. Login to Shaarli
2324. Delete the update file
2335. Refresh
diff --git a/doc/md/Usage.md b/doc/md/Usage.md
new file mode 100644
index 00000000..6dadde0a
--- /dev/null
+++ b/doc/md/Usage.md
@@ -0,0 +1,111 @@
1## Features
2
3For any item posted to Shaarli (called a _Shaare_), you can customize the following aspects:
4
5- URL to link to
6- Title
7- Free-text description
8- Tags
9- Public/private status
10
11
12### Adding/editing Shaares
13
14While logged in to your Shaarli, you can add, edit or delete Shaares:
15
16- Using the **+Shaare** button: enter the URL you want to share, click `Add link`, fill in the details of your Shaare, and `Save`
17- Using the [Bookmarklet](https://en.wikipedia.org/wiki/Bookmarklet): drag the `✚Shaare link` button from the `Tools` page to your browser's bookmarks bar, click it to share the current page.
18- Using [apps and browser addons](Community-and-related-software.md#mobile-apps)
19- Using the [REST API](https://shaarli.github.io/api-documentation/)
20- Any Shaare can edited by clicking its ![](images/edit_icon.png) `Edit` button.
21
22
23### Tags
24
25Tags can be be used to organize and categorize your Shaares:
26
27- You can rename, merge and delete tags from the _Tools_ menu or the [tag cloud/list](#tag-cloud)
28- Tags are auto-completed (from the list of existing tags) in all dialogs
29- Tags can be combined with text in [search](#search) queries
30
31
32### Public/private Shaares
33
34Additional filter buttons can be found at the top left of the Shaare list **only when logged in**:
35
36- **Only show private Shaares:** Private shares can be searched by clicking the `only show private links` toggle button top left of the Shaares list (only when logged in)
37
38
39### Permalinks
40
41Permalinks are fixed, short links attached to each Shaare. Editing a Shaare will not change it's permalink, each permalink always points to the latest revision of a Shaare.
42
43
44### Text-only (note) Shaares
45
46Shaarli can be used as a minimal blog, notepad, pastebin...: While adding or editing a Shaare, leave the URL field blank to create a text-only ("note") post. This allows you to post any kind of text content, such as blog articles, private or public notes, snippets... There is no character limit! You can access your post from its permalink.
47
48
49### Search
50
51- **Plain text search:** Use `Search text` to search in all fields of all Shaares (Title, URL, Description...). Use double-quotes (example `"exact search"`) to search for the exact expression.
52- **Tags search:** `Filter by tags` allow only displaying Shaares tagged with one or multiple tags (use space to separate tags).
53- **Hidden tags:** tags starting with a dot `.` (example `.secret`) are private. They can only be seen and searched when logged in.
54- **Exclude text/tags:** Use the `-` operator before a word or tag to exclude Shaares matching this word from search results (`NOT` operator).
55- **Untagged links:** Shaares without tags can be searched by clicking the `untagged` toggle button top left of the Shaares list (only when logged in).
56
57Both exclude patterns and exact searches can be combined with normal searches (example `"exact search" term otherterm -notthis "very exact" stuff -notagain`). Only AND (and NOT) search is currrently supported.
58
59Active search terms are displayed on top of the link list. To remove terms/tags from the curent search, click the `x` next to any of them, or simply clear text/tag search fields.
60
61
62### Tag cloud
63
64The `Tag cloud` page diplays a "cloud" or list view of all tags in your Shaarli (most frequently used tags are displayed with a bigger font size)
65
66
67- **Tags list:** click on `Most used` or `Alphabetical` to display tags as a list. You can also edit/delete tags for this page.
68- Click on any tag to search all Shaares matching this tag.
69- **Filtering the tag cloud/list:** Click on the counter next to a tag to show other tags of Shaares with this tag. Repeat this any number of times to further filter the tag cloud. Click `List all links with those tags` to display Shaares matching your current tag filter set.
70
71
72
73### RSS feeds
74
75RSS/ATOM feeds feeds are available (in ATOM with `/feed/atom` and RSS with `/feed/rss`)
76
77- **Filtering RSS feeds:** RSS feeds and picture wall can also be restricted to only return items matching a text/tag search. For example, search for `photography` (text or tags) in Shaarli, then click the `RSS Feed` button. A feed with only matching results is displayed.
78- Add the `&nb` parameter in feed URLs to specify the number of Shaares you want in a feed (default if not specified: `50`). The keyword `all` is available if you want everything.
79- Add the `&permalinks` parameter in feed URLs to point permalinks to the corresponding shaarly entry/link instead of the direct, Shaare URL attribute
80
81![](images/rss-filter-1.png) ![](images/rss-filter-2.png)
82
83```bash
84# examples
85https://shaarli.mydomain.org/feed/atom?permalinks
86https://shaarli.mydomain.org/feed/atom?permalinks&nb=42
87https://shaarli.mydomain.org/feed/atom?permalinks&nb=all
88https://shaarli.mydomain.org/feed/rss?searchtags=nature
89https://shaarli.mydomain.org/links/picture-wall?searchterm=poney
90```
91
92
93### Picture wall
94
95- The picture wall can be filtered by text or tags search in the same way as [RSS feeds](#rss-feeds)
96
97
98### Import/export
99
100To **export Shaares as a HTML file**, under _Tools > Export_, choose:
101
102- `Export all` to export both public and private Shaares
103- `Export public` to export public Shaares only
104- `Export private` to export private Shaares only
105
106Restore by using the `Import` feature.
107
108- These exports contain the full data (URL, title, tags, date, description, public/private status of your Shaares)
109- They can also be imported to your web browser bookmarks.
110
111To **import a HTML bookmarks file** exported from your browser, just use the `Import` feature. For each "folder" in the bookmarks you imported, a new tag will be created (for example a bookmark in `Movies > Sci-fi` folder will be tagged `Movies` `Sci-fi`).
diff --git a/doc/md/dev/Development.md b/doc/md/dev/Development.md
new file mode 100644
index 00000000..5c085e03
--- /dev/null
+++ b/doc/md/dev/Development.md
@@ -0,0 +1,179 @@
1# Development
2
3Please read [Contributing to Shaarli](https://github.com/shaarli/Shaarli/tree/master/CONTRIBUTING.md)
4
5## Guidelines
6
7
8- [Unit tests](Unit-tests)
9- Javascript linting - Shaarli uses [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript).
10Run `make eslint` to check JS style.
11- [GnuPG signature](GnuPG-signature) for tags/releases
12
13
14## Third-party libraries
15
16CSS:
17
18- Yahoo UI [CSS Reset](http://yuilibrary.com/yui/docs/cssreset/) - standardize cross-browser rendering
19
20Javascript:
21
22- [Awesomeplete](https://leaverou.github.io/awesomplete/) ([GitHub](https://github.com/LeaVerou/awesomplete)) - autocompletion in input forms
23- [bLazy](http://dinbror.dk/blazy/) ([GitHub](https://github.com/dinbror/blazy)) - lazy loading for thumbnails
24- [qr.js](http://neocotic.com/qr.js/) ([GitHub](https://github.com/neocotic/qr.js)) - QR code generation
25
26PHP (managed through [`composer.json`](https://github.com/shaarli/Shaarli/blob/master/composer.json)):
27
28- [RainTPL](https://github.com/rainphp/raintpl) - HTML templating for PHP
29- [`shaarli/netscape-bookmark-parser`](https://packagist.org/packages/shaarli/netscape-bookmark-parser) - Import bookmarks from Netscape files
30- [`erusev/parsedown`](https://packagist.org/packages/erusev/parsedown) - Parse MarkDown syntax for the MarkDown plugin
31- [`slim/slim`](https://packagist.org/packages/slim/slim) - Handle routes and middleware for the REST API
32- [`ArthurHoaro/web-thumbnailer`](https://github.com/ArthurHoaro/web-thumbnailer) - PHP library which will retrieve a thumbnail for any given URL
33- [`pubsubhubbub/publisher`](https://github.com/pubsubhubbub/php-publisher) - A PubSubHubbub publisher module for PHP.
34- [`gettext/gettext`](https://github.com/php-gettext/Gettext) - PHP library to collect and manipulate gettext (.po, .mo, .php, .json, etc)
35
36
37## Security
38
39- The password is salted, hashed and stored in the data subdirectory, in a PHP file, and protected by htaccess. Even if the webserver does not support htaccess, the hash is not readable by URL. Even if the .php file is stolen, the password cannot deduced from the hash. The salt prevents rainbow-tables attacks.
40- Directories are protected using `.htaccess` files
41- Forms are protected against [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery):
42 - Forms which act on data (save,delete…) contain a token generated by the server.
43 - Any posted form which does not contain a valid token is rejected.
44 - Any token can only be used once.
45 - Tokens are attached to the session and cannot be reused in another session.
46- Sessions automatically expire after 60 minutes.
47- Sessions are protected against hijacking: the session ID cannot be used from a different IP address.
48- Links are stored as an associative array which is serialized, compressed (with deflate), base64-encoded and saved as a comment in a `.php` file - even if the server does not support `.htaccess` files, the data file will still not be readable by URL.
49- Bruteforce protection: Successful and failed login attempts are logged - IP bans are enforced after a configurable amount of failures. Logs can also be used consumed by [fail2ban](../Server-configuration.md#fail2ban)
50- A pop-up notification is shown when a new release is available.
51
52## Link structure
53
54Every link available through the `LinkDB` object is represented as an array
55containing the following fields:
56
57 * `id` (integer): Unique identifier.
58 * `title` (string): Title of the link.
59 * `url` (string): URL of the link. Used for displayable links (without redirector, url encoding, etc.).
60 Can be absolute or relative for Notes.
61 * `real_url` (string): Real destination URL, can be redirected, encoded, etc.
62 * `shorturl` (string): Permalink small hash.
63 * `description` (string): Link text description.
64 * `private` (boolean): whether the link is private or not.
65 * `tags` (string): all link tags separated by a single space
66 * `thumbnail` (string|boolean): relative path of the thumbnail cache file, or false if there isn't any.
67 * `created` (DateTime): link creation date time.
68 * `updated` (DateTime): last modification date time.
69
70Small hashes are used to make a link to an entry in Shaarli. They are unique: the date of the item (eg. `20110923_150523`) is hashed with CRC32, then converted to base64 and some characters are replaced. They are always 6 characters longs and use only `A-Z a-z 0-9 - _` and `@`.
71
72
73## Directory structure
74
75Here is the directory structure of Shaarli and the purpose of the different files:
76
77```bash
78 index.php # Main program
79 application/ # Shaarli classes
80 ├── LinkDB.php
81
82 ...
83
84 └── Utils.php
85 tests/ # Shaarli unitary & functional tests
86 ├── LinkDBTest.php
87
88 ...
89
90 ├── utils # utilities to ease testing
91 │ └── ReferenceLinkDB.php
92 └── UtilsTest.php
93 assets/
94 ├── common/ # Assets shared by multiple themes
95 ├── ...
96 ├── default/ # Assets for the default template, before compilation
97 ├── fonts/ # Font files
98 ├── img/ # Images used by the default theme
99 ├── js/ # JavaScript files in ES6 syntax
100 ├── scss/ # SASS files
101 └── vintage/ # Assets for the vintage template, before compilation
102 └── ...
103 COPYING # Shaarli license
104 inc/ # static assets and 3rd party libraries
105 └── rain.tpl.class.php # RainTPL templating library
106 images/ # Images and icons used in Shaarli
107 data/ # data storage: bookmark database, configuration, logs, banlist...
108 ├── config.json.php # Shaarli configuration (login, password, timezone, title...)
109 ├── datastore.php # Your link database (compressed).
110 ├── ipban.php # IP address ban system data
111 ├── lastupdatecheck.txt # Update check timestamp file
112 └── log.txt # login/IPban log.
113 tpl/ # RainTPL templates for Shaarli. They are used to build the pages.
114 ├── default/ # Default Shaarli theme
115 ├── fonts/ # Font files
116 ├── img/ # Images
117 ├── js/ # JavaScript files compiled by Babel and compatible with all browsers
118 ├── css/ # CSS files compiled with SASS
119 └── vintage/ # Legacy Shaarli theme
120 └── ...
121 cache/ # thumbnails cache
122 # This directory is automatically created. You can erase it anytime you want.
123 tmp/ # Temporary directory for compiled RainTPL templates.
124 # This directory is automatically created. You can erase it anytime you want.
125 vendor/ # Third-party dependencies. This directory is created by Composer
126```
127
128Shaarli needs read access to:
129
130- the root index.php file
131- the `application/`, `plugins/` and `inc/` directories (recursively)
132
133Shaarli needs read/write access to the `cache/`, `data/`, `pagecache/`, and `tmp/` directories
134
135
136## Automation
137
138A [`Makefile`](https://github.com/shaarli/Shaarli/blob/master/Makefile) is available to perform project-related operations:
139
140- [Static analysis](#Static-analysis) - check that the code is compliant to PHP conventions
141- [Unit tests](#Unit-tests) - ensure there are no regressions introduced by new commits
142- Documentation - generate a local HTML copy of the markdown documentation
143
144### Continuous Integration
145
146[Travis CI](http://docs.travis-ci.com/) is a Continuous Integration build server, that runs a build:
147
148- each time a commit is merged to the mainline (`master` branch)
149- each time a Pull Request is submitted or updated
150
151After all jobs have finished, Travis returns the results to GitHub:
152
153- a status icon represents the result for the `master` branch: [![](https://api.travis-ci.org/shaarli/Shaarli.svg)](https://travis-ci.org/shaarli/Shaarli)
154- Pull Requests are updated with the Travis build result.
155
156See [`.travis.yml`](https://github.com/shaarli/Shaarli/blob/master/.travis.yml).
157
158
159### Documentation
160
161[mkdocs](https://www.mkdocs.org/) is used to convert markdown documentation to HTML pages. The [public documentation](https://shaarli.readthedocs.io/en/master/) website is rendered and hosted by [readthedocs.org](https://readthedocs.org/). A copy of the documentation is also included in prebuilt [release archives](https://github.com/shaarli/Shaarli/releases) (`doc/html/` path in your Shaarli installation). To generate the HTML documentation locally, install a recent version of Python `setuptools` and run `make doc`.
162
163
164## Static analysis
165
166Patches should try to stick to the [PHP Standard Recommendations](http://www.php-fig.org/psr/) (PSR), especially:
167
168- [PSR-1](http://www.php-fig.org/psr/psr-1/) - Basic Coding Standard
169- [PSR-2](http://www.php-fig.org/psr/psr-2/) - Coding Style Guide
170
171
172**Work in progress:** Static analysis is currently being discussed here: in [#95 - Fix coding style (static analysis)](https://github.com/shaarli/Shaarli/issues/95), [#130 - Continuous Integration tools & features](https://github.com/shaarli/Shaarli/issues/130)
173
174Static analysis tools can be installed with Composer, and used through Shaarli's [Makefile](https://github.com/shaarli/Shaarli/blob/master/Makefile).
175
176For an overview of the available features, see:
177
178- [Code quality: Makefile to run static code checkers](https://github.com/shaarli/Shaarli/pull/124) (#124)
179- [Run PHPCS against different coding standards](https://github.com/shaarli/Shaarli/pull/276) (#276)
diff --git a/doc/md/GnuPG-signature.md b/doc/md/dev/GnuPG-signature.md
index d1fc10a5..25578001 100644
--- a/doc/md/GnuPG-signature.md
+++ b/doc/md/dev/GnuPG-signature.md
@@ -1,24 +1,16 @@
1## Introduction 1## Introduction
2### PGP and GPG 2### PGP and GPG
3[Gnu Privacy Guard](https://gnupg.org/) (GnuPG) is an Open Source implementation of the 3[Gnu Privacy Guard](https://gnupg.org/) (GnuPG) is an Open Source implementation of the [Pretty Good Privacy](https://en.wikipedia.org/wiki/Pretty_Good_Privacy#OpenPGP) (OpenPGP) specification. Its main purposes are digital authentication, signature and encryption. It is often used by the [FLOSS](https://en.wikipedia.org/wiki/Free_and_open-source_software) community to verify:
4[Pretty Good Privacy](https://en.wikipedia.org/wiki/Pretty_Good_Privacy#OpenPGP)
5(OpenPGP) specification. Its main purposes are digital authentication, signature and encryption.
6 4
7It is often used by the [FLOSS](https://en.wikipedia.org/wiki/Free_and_open-source_software) community to verify: 5- Linux package signatures: Debian [SecureApt](https://wiki.debian.org/SecureApt), ArchLinux [Master Keys](https://www.archlinux.org/master-keys/)
6- [Version control](https://en.wikipedia.org/wiki/Revision_control) releases & maintainer identity
8 7
9- Linux package signatures: Debian [SecureApt](https://wiki.debian.org/SecureApt), ArchLinux [Master 8> You MUST understand that presence of data in the keyserver (pools) in no way connotes trust. Anyone can generate a key, with any name or email address, and upload it. All security and trust comes from evaluating security at the “object level”, via PGP [Web of trust](https://en.wikipedia.org/wiki/Web_of_trust) signatures. This keyserver makes it possible to retrieve keys, looking them up via various indices, but the collection of keys in this public pool is KNOWN to contain malicious and fraudulent keys. It is the common expectation of server operators that users understand this and use software which, like all known common OpenPGP implementations, evaluates trust accordingly. This expectation is so common that it is not normally explicitly stated.
10Keys](https://www.archlinux.org/master-keys/)
11- [SCM](https://en.wikipedia.org/wiki/Revision_control) releases & maintainer identity
12 9
13### Trust 10-- Phil Pennock (author of the [SKS](https://bitbucket.org/skskeyserver/sks-keyserver/wiki/Home) key server - http://sks.spodhuis.org/)
14To quote Phil Pennock (the author of the [SKS](https://bitbucket.org/skskeyserver/sks-keyserver/wiki/Home) key server - http://sks.spodhuis.org/):
15 11
16> You MUST understand that presence of data in the keyserver (pools) in no way connotes trust. Anyone can generate a key, with any name or email address, and upload it. All security and trust comes from evaluating security at the “object level”, via PGP Web-Of-Trust signatures. This keyserver makes it possible to retrieve keys, looking them up via various indices, but the collection of keys in this public pool is KNOWN to contain malicious and fraudulent keys. It is the common expectation of server operators that users understand this and use software which, like all known common OpenPGP implementations, evaluates trust accordingly. This expectation is so common that it is not normally explicitly stated. 12Trust can be gained by having your key signed by other people (and signing their key back, too :) ), for instance during [key signing parties](https://en.wikipedia.org/wiki/Key_signing_party): [Keysigning party HOWTO](http://www.cryptnet.net/fdp/crypto/keysigning_party/en/keysigning_party.html),
17 13
18Trust can be gained by having your key signed by other people (and signing their key back, too :) ), for instance during [key signing parties](https://en.wikipedia.org/wiki/Key_signing_party), see:
19
20- [The Keysigning party HOWTO](http://www.cryptnet.net/fdp/crypto/keysigning_party/en/keysigning_party.html)
21- [Web of trust](https://en.wikipedia.org/wiki/Web_of_trust)
22 14
23## Generate a GPG key 15## Generate a GPG key
24- [Generating a GPG key for Git tagging](http://stackoverflow.com/a/16725717) (StackOverflow) 16- [Generating a GPG key for Git tagging](http://stackoverflow.com/a/16725717) (StackOverflow)
diff --git a/doc/md/Plugin-System.md b/doc/md/dev/Plugin-system.md
index 87a2638d..a87bd0cf 100644
--- a/doc/md/Plugin-System.md
+++ b/doc/md/dev/Plugin-system.md
@@ -1,19 +1,16 @@
1[**I am a developer: ** Developer API](#developer-api) 1# Plugin system
2
3[**I am a template designer: ** Guide for template designers](#guide-for-template-designer)
4
5---
6 2
7## Developer API 3## Developer API
8 4
9### What can I do with plugins? 5### What can I do with plugins?
10 6
11The plugin system let you: 7The plugin system lets you:
12 8
13- insert content into specific places across templates. 9- insert content into specific places across templates.
14- alter data before templates rendering. 10- alter data before templates rendering.
15- alter data before saving new links. 11- alter data before saving new links.
16 12
13
17### How can I create a plugin for Shaarli? 14### How can I create a plugin for Shaarli?
18 15
19First, chose a plugin name, such as `demo_plugin`. 16First, chose a plugin name, such as `demo_plugin`.
@@ -30,6 +27,7 @@ You should have the following tree view:
30| |---| demo_plugin.php 27| |---| demo_plugin.php
31``` 28```
32 29
30
33### Plugin initialization 31### Plugin initialization
34 32
35At the beginning of Shaarli execution, all enabled plugins are loaded. At this point, the plugin system looks for an `init()` function in the <plugin_name>.php to execute and run it if it exists. This function must be named this way, and takes the `ConfigManager` as parameter. 33At the beginning of Shaarli execution, all enabled plugins are loaded. At this point, the plugin system looks for an `init()` function in the <plugin_name>.php to execute and run it if it exists. This function must be named this way, and takes the `ConfigManager` as parameter.
@@ -63,6 +61,7 @@ For example, if my plugin want to add data to the header, this function is neede
63 61
64If this function is declared, and the plugin enabled, it will be called every time Shaarli is rendering the header. 62If this function is declared, and the plugin enabled, it will be called every time Shaarli is rendering the header.
65 63
64
66### Plugin's data 65### Plugin's data
67 66
68#### Parameters 67#### Parameters
@@ -109,6 +108,7 @@ array_push($data['top_placeholder'], 'My', 'content');
109return $data; 108return $data;
110``` 109```
111 110
111
112#### Data manipulation 112#### Data manipulation
113 113
114When a page is displayed, every variable send to the template engine is passed to plugins before that in `$data`. 114When a page is displayed, every variable send to the template engine is passed to plugins before that in `$data`.
@@ -139,12 +139,14 @@ Each file contain two keys:
139 139
140> Note: In PHP, `parse_ini_file()` seems to want strings to be between by quotes `"` in the ini file. 140> Note: In PHP, `parse_ini_file()` seems to want strings to be between by quotes `"` in the ini file.
141 141
142
142### It's not working! 143### It's not working!
143 144
144Use `demo_plugin` as a functional example. It covers most of the plugin system features. 145Use `demo_plugin` as a functional example. It covers most of the plugin system features.
145 146
146If it's still not working, please [open an issue](https://github.com/shaarli/Shaarli/issues/new). 147If it's still not working, please [open an issue](https://github.com/shaarli/Shaarli/issues/new).
147 148
149
148### Hooks 150### Hooks
149 151
150| Hooks | Description | 152| Hooks | Description |
@@ -165,12 +167,10 @@ If it's still not working, please [open an issue](https://github.com/shaarli/Sha
165| [save_plugin_parameters](#save_plugin_parameters) | Allow to manipulate plugin parameters before they're saved. | 167| [save_plugin_parameters](#save_plugin_parameters) | Allow to manipulate plugin parameters before they're saved. |
166 168
167 169
168
169#### render_header 170#### render_header
170 171
171Triggered on every page. 172Triggered on every page - allows plugins to add content in page headers.
172 173
173Allow plugin to add content in page headers.
174 174
175##### Data 175##### Data
176 176
@@ -194,13 +194,12 @@ List of placeholders:
194 194
195![fields_toolbar_example](http://i.imgur.com/3GMifI2.png) 195![fields_toolbar_example](http://i.imgur.com/3GMifI2.png)
196 196
197#### render_includes
198 197
199Triggered on every page. 198#### render_includes
200 199
201Allow plugin to include their own CSS files. 200Triggered on every page - allows plugins to include their own CSS files.
202 201
203##### Data 202##### data
204 203
205`$data` is an array containing: 204`$data` is an array containing:
206 205
@@ -216,13 +215,14 @@ List of placeholders:
216 215
217> Note: only add the path of the CSS file. E.g: `plugins/demo_plugin/custom_demo.css`. 216> Note: only add the path of the CSS file. E.g: `plugins/demo_plugin/custom_demo.css`.
218 217
218
219#### render_footer 219#### render_footer
220 220
221Triggered on every page. 221Triggered on every page.
222 222
223Allow plugin to add content in page footer and include their own JS files. 223Allow plugin to add content in page footer and include their own JS files.
224 224
225##### Data 225##### data
226 226
227`$data` is an array containing: 227`$data` is an array containing:
228 228
@@ -243,20 +243,21 @@ List of placeholders:
243 243
244> Note: only add the path of the JS file. E.g: `plugins/demo_plugin/custom_demo.js`. 244> Note: only add the path of the JS file. E.g: `plugins/demo_plugin/custom_demo.js`.
245 245
246
246#### render_linklist 247#### render_linklist
247 248
248Triggered when `linklist` is displayed (list of links, permalink, search, tag filtered, etc.). 249Triggered when `linklist` is displayed (list of links, permalink, search, tag filtered, etc.).
249 250
250It allows to add content at the begining and end of the page, after every link displayed and to alter link data. 251It allows to add content at the begining and end of the page, after every link displayed and to alter link data.
251 252
252##### Data 253##### data
253 254
254`$data` is an array containing: 255`$data` is an array containing:
255 256
256 - All templates data, including links. 257 - All templates data, including links.
257 - [Special data](#special-data) 258 - [Special data](#special-data)
258 259
259##### Template placeholders 260##### template placeholders
260 261
261Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array. 262Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
262 263
@@ -278,20 +279,21 @@ List of placeholders:
278 279
279![plugin_end_zone_example](http://i.imgur.com/6IoRuop.png) 280![plugin_end_zone_example](http://i.imgur.com/6IoRuop.png)
280 281
282
281#### render_editlink 283#### render_editlink
282 284
283Triggered when the link edition form is displayed. 285Triggered when the link edition form is displayed.
284 286
285Allow to add fields in the form, or display elements. 287Allow to add fields in the form, or display elements.
286 288
287##### Data 289##### data
288 290
289`$data` is an array containing: 291`$data` is an array containing:
290 292
291 - All templates data. 293 - All templates data.
292 - [Special data](#special-data) 294 - [Special data](#special-data)
293 295
294##### Template placeholders 296##### template placeholders
295 297
296Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array. 298Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
297 299
@@ -301,20 +303,21 @@ List of placeholders:
301 303
302![edit_link_plugin_example](http://i.imgur.com/5u17Ens.png) 304![edit_link_plugin_example](http://i.imgur.com/5u17Ens.png)
303 305
306
304#### render_tools 307#### render_tools
305 308
306Triggered when the "tools" page is displayed. 309Triggered when the "tools" page is displayed.
307 310
308Allow to add content at the end of the page. 311Allow to add content at the end of the page.
309 312
310##### Data 313##### data
311 314
312`$data` is an array containing: 315`$data` is an array containing:
313 316
314 - All templates data. 317 - All templates data.
315 - [Special data](#special-data) 318 - [Special data](#special-data)
316 319
317##### Template placeholders 320##### template placeholders
318 321
319Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array. 322Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
320 323
@@ -324,20 +327,21 @@ List of placeholders:
324 327
325![tools_plugin_example](http://i.imgur.com/Bqhu9oQ.png) 328![tools_plugin_example](http://i.imgur.com/Bqhu9oQ.png)
326 329
330
327#### render_picwall 331#### render_picwall
328 332
329Triggered when picwall is displayed. 333Triggered when picwall is displayed.
330 334
331Allow to add content at the top and bottom of the page. 335Allow to add content at the top and bottom of the page.
332 336
333##### Data 337##### data
334 338
335`$data` is an array containing: 339`$data` is an array containing:
336 340
337 - All templates data. 341 - All templates data.
338 - [Special data](#special-data) 342 - [Special data](#special-data)
339 343
340##### Template placeholders 344##### template placeholders
341 345
342Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array. 346Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
343 347
@@ -348,13 +352,14 @@ List of placeholders:
348 352
349![plugin_start_end_zone_example](http://i.imgur.com/tVTQFER.png) 353![plugin_start_end_zone_example](http://i.imgur.com/tVTQFER.png)
350 354
355
351#### render_tagcloud 356#### render_tagcloud
352 357
353Triggered when tagcloud is displayed. 358Triggered when tagcloud is displayed.
354 359
355Allow to add content at the top and bottom of the page. 360Allow to add content at the top and bottom of the page.
356 361
357##### Data 362##### data
358 363
359`$data` is an array containing: 364`$data` is an array containing:
360 365
@@ -379,11 +384,9 @@ For each tag, the following placeholder can be used:
379 384
380#### render_taglist 385#### render_taglist
381 386
382Triggered when taglist is displayed. 387Triggered when taglist is displayed - allows to add content at the top and bottom of the page.
383
384Allow to add content at the top and bottom of the page.
385 388
386##### Data 389##### data
387 390
388`$data` is an array containing: 391`$data` is an array containing:
389 392
@@ -409,7 +412,8 @@ Triggered when tagcloud is displayed.
409 412
410Allow to add content at the top and bottom of the page, the bottom of each link and to alter data. 413Allow to add content at the top and bottom of the page, the bottom of each link and to alter data.
411 414
412##### Data 415
416##### data
413 417
414`$data` is an array containing: 418`$data` is an array containing:
415 419
@@ -429,13 +433,14 @@ List of placeholders:
429- `plugin_start_zone`: before displaying the template content. 433- `plugin_start_zone`: before displaying the template content.
430- `plugin_end_zone`: after displaying the template content. 434- `plugin_end_zone`: after displaying the template content.
431 435
436
432#### render_feed 437#### render_feed
433 438
434Triggered when the ATOM or RSS feed is displayed. 439Triggered when the ATOM or RSS feed is displayed.
435 440
436Allow to add tags in the feed, either in the header or for each items. Items (links) can also be altered before being rendered. 441Allow to add tags in the feed, either in the header or for each items. Items (links) can also be altered before being rendered.
437 442
438##### Data 443##### data
439 444
440`$data` is an array containing: 445`$data` is an array containing:
441 446
@@ -454,13 +459,14 @@ For each links:
454 459
455- `feed_plugins`: additional tag for every link entry. 460- `feed_plugins`: additional tag for every link entry.
456 461
462
457#### save_link 463#### save_link
458 464
459Triggered when a link is save (new link or edit). 465Triggered when a link is save (new link or edit).
460 466
461Allow to alter the link being saved in the datastore. 467Allow to alter the link being saved in the datastore.
462 468
463##### Data 469##### data
464 470
465`$data` is an array containing the link being saved: 471`$data` is an array containing the link being saved:
466 472
@@ -483,7 +489,7 @@ Triggered when a link is deleted.
483 489
484Allow to execute any action before the link is actually removed from the datastore 490Allow to execute any action before the link is actually removed from the datastore
485 491
486##### Data 492##### data
487 493
488`$data` is an array containing the link being deleted: 494`$data` is an array containing the link being deleted:
489 495
@@ -506,7 +512,7 @@ Triggered when the plugin parameters are saved from the plugin administration pa
506Plugins can perform an action every times their settings are updated. 512Plugins can perform an action every times their settings are updated.
507For example it is used to update the CSS file of the `default_colors` plugins. 513For example it is used to update the CSS file of the `default_colors` plugins.
508 514
509##### Data 515##### data
510 516
511`$data` input contains the `$_POST` array. 517`$data` input contains the `$_POST` array.
512 518
@@ -515,7 +521,7 @@ the array will contain an entry with `MYPLUGIN_PARAMETER` as a key.
515 521
516Also [special data](#special-data). 522Also [special data](#special-data).
517 523
518## Guide for template designer 524## Guide for template designers
519 525
520### Plugin administration 526### Plugin administration
521 527
diff --git a/doc/md/dev/Release-Shaarli.md b/doc/md/dev/Release-Shaarli.md
new file mode 100644
index 00000000..2c772406
--- /dev/null
+++ b/doc/md/dev/Release-Shaarli.md
@@ -0,0 +1,145 @@
1# Release Shaarli
2
3## Requirements
4
5This guide assumes that you have:
6
7- a GPG key matching your GitHub authentication credentials/email (the email address identified by the GPG key is the same as the one in your `~/.gitconfig`)
8- a GitHub fork of Shaarli
9- a local clone of your Shaarli fork, with the following remotes:
10 - `origin` pointing to your GitHub fork
11 - `upstream` pointing to the main Shaarli repository
12- maintainer permissions on the main Shaarli repository, to:
13 - push the signed tag
14 - create a new release
15- [Composer](https://getcomposer.org/) needs to be installed
16- The [venv](https://docs.python.org/3/library/venv.html) Python 3 module needs to be installed for HTML documentation generation.
17
18## Release notes and `CHANGELOG.md`
19
20GitHub allows drafting the release notes for the upcoming release, from the [Releases](https://github.com/shaarli/Shaarli/releases) page. This way, the release note can be drafted while contributions are merged to `master`. See http://keepachangelog.com/en/0.3.0/ for changelog formatting.
21
22`CHANGELOG.md` should contain the same information as the release note draft for the upcoming version. Update it to:
23
24- add new entries (additions, fixes, etc.)
25- mark the current version as released by setting its date and link
26- add a new section for the future unreleased version
27
28```bash
29## [v0.x.y](https://github.com/shaarli/Shaarli/releases/tag/v0.x.y) - UNRELEASES
30
31### Added
32
33### Changed
34
35### Fixed
36
37### Removed
38
39### Deprecated
40
41### Security
42
43```
44
45
46## Update the list of Git contributors
47
48```bash
49$ make authors
50$ git commit -s -m "Update AUTHORS"
51```
52
53## Create and merge a Pull Request
54
55Create a Pull Request to marge changes from your remote, into `master` in the community Shaarli repository, and have it merged.
56
57
58## Create the release branch and update shaarli_version.php
59
60```bash
61# fetch latest changes from master to your local copy
62git checkout master
63git pull upstream master
64
65# If releasing a new minor version, create a release branch
66$ git checkout -b v0.x
67
68# Bump shaarli_version.php from dev to 0.x.0, **without the v**
69$ vim shaarli_version.php
70$ git add shaarli_version
71$ git commit -s -m "Bump Shaarli version to v0.x.0"
72$ git push upstream v0.x
73```
74
75## Create and push a signed tag
76
77Git [tags](http://git-scm.com/book/en/v2/Distributed-Git-Maintaining-a-Project#Tagging-Your-Releases) are used to identify specific revisions with a unique version number that follows [semantic versioning](https://semver.org/)
78
79```bash
80# update your local copy
81git checkout v0.5
82git pull upstream v0.5
83
84# create a signed tag
85git tag -s -m "Release v0.5.0" v0.5.0
86
87# push the tag to upstream
88git push --tags upstream
89```
90
91Here is how to verify a signed tag. [`v0.5.0`](https://github.com/shaarli/Shaarli/releases/tag/v0.5.0) is the first GPG-signed tag pushed on the Community Shaarli. Let's have a look at its signature!
92
93```bash
94# update the list of available tags
95git fetch upstream
96
97# get the SHA1 reference of the tag
98git show-ref tags/v0.5.0
99# gives: f7762cf803f03f5caf4b8078359a63783d0090c1 refs/tags/v0.5.0
100
101# verify the tag signature information
102git verify-tag f7762cf803f03f5caf4b8078359a63783d0090c1
103# gpg: Signature made Thu 30 Jul 2015 11:46:34 CEST using RSA key ID 4100DF6F
104# gpg: Good signature from "VirtualTam <virtualtam@flibidi.net>" [ultimate]
105```
106
107## Publish the GitHub release
108
109- In the `master` banch, update version badges in `README.md` to point to the newly released Shaarli version
110- Update the previously drafted [release](https://github.com/shaarli/Shaarli/releases) (notes, tag) and publish it
111- Profit!
112
113
114## Generate full release zip archives
115
116Release archives will contain Shaarli code plus all required third-party libraries. They are useful for users who:
117
118- have no SSH access, no possibility to install PHP packages/server extensions, no possibility to run scripts (shared hosting)
119- do not want to install build/dev dependencies on their server
120
121 `git checkout` the appropriate branch, then:
122
123```bash
124# checkout the appropriate branch
125git checkout 0.x.y
126# generate zip archives
127make release_archive
128```
129
130This will create `shaarli-v0.x.y-full.tar`, `shaarli-v0.x.y-full.zip`. These archives need to be manually uploaded on the previously created GitHub [release](https://github.com/shaarli/Shaarli/releases).
131
132
133### Update the `latest` branch
134
135```bash
136# checkout the 'latest' branch
137git checkout latest
138# merge changes from your newly published release branch
139git merge v0.x.y
140# fix eventual conflicts with git mergetool...
141# run tests
142make test
143# push the latest branch
144git push upstream latest
145```
diff --git a/doc/md/Theming.md b/doc/md/dev/Theming.md
index eb84e11c..1ad30465 100644
--- a/doc/md/Theming.md
+++ b/doc/md/dev/Theming.md
@@ -1,3 +1,5 @@
1# Theming
2
1## Foreword 3## Foreword
2 4
3There are two ways of customizing how Shaarli looks: 5There are two ways of customizing how Shaarli looks:
@@ -43,6 +45,7 @@ Installation:
43- [kalvn/shaarli-blocks](https://github.com/kalvn/shaarli-blocks) - A template/theme for Shaarli 45- [kalvn/shaarli-blocks](https://github.com/kalvn/shaarli-blocks) - A template/theme for Shaarli
44- [kalvn/Shaarli-Material](https://github.com/kalvn/Shaarli-Material) - A theme (template) based on Google's Material Design for Shaarli, the superfast delicious clone 46- [kalvn/Shaarli-Material](https://github.com/kalvn/Shaarli-Material) - A theme (template) based on Google's Material Design for Shaarli, the superfast delicious clone
45- [ManufacturaInd/shaarli-2004licious-theme](https://github.com/ManufacturaInd/shaarli-2004licious-theme) - A template/theme as a humble homage to the early looks of the del.icio.us site 47- [ManufacturaInd/shaarli-2004licious-theme](https://github.com/ManufacturaInd/shaarli-2004licious-theme) - A template/theme as a humble homage to the early looks of the del.icio.us site
48- [xfnw/shaarli-default-dark](https://github.com/xfnw/shaarli-default-dark) - The default theme but nice and dark for your eyeballs
46 49
47### Shaarli forks 50### Shaarli forks
48 51
diff --git a/doc/md/Translations.md b/doc/md/dev/Translations.md
index c23ec962..8f3b8f10 100644
--- a/doc/md/Translations.md
+++ b/doc/md/dev/Translations.md
@@ -7,87 +7,80 @@ Note that only the `default` theme supports translations.
7 7
8### Contributing 8### Contributing
9 9
10We encourage the community to contribute to Shaarli's translation either by improving existing 10We encourage the community to contribute to Shaarli translations, either by improving existing translations or submitting a new language.
11translations or submitting a new language.
12 11
13Contributing to the translation does not require development skill. 12Contributing to the translation does not require software development knowledge.
14 13
15Please submit a pull request with the `.po` file updated/created. Note that the compiled file (`.mo`) 14Please submit a pull request with the `.po` file updated/created. Note that the compiled file (`.mo`) is not stored on the repository, and is generated during the release process.
16is not stored on the repository, and is generated during the release process.
17 15
18### How to
19
20First, install [Poedit](https://poedit.net/) tool.
21
22Poedit will extract strings to translate from the PHP source code.
23 16
24**Important**: due to the usage of a template engine, it's important to generate PHP cache files to extract 17### How to
25every translatable string.
26 18
27You can either use [this script](https://gist.github.com/ArthurHoaro/5d0323f758ab2401ef444a53f54e9a07) (recommended) 19Install [Poedit](https://poedit.net/) (used to extract strings to translate from the PHP source code, and generate `.po` files).
28or visit every template page in your browser to generate cache files, while logged in.
29 20
30Here is a list : 21Due to the usage of a template engine, it's important to generate PHP cache files to extract every translatable string. You can either use [this script](https://gist.github.com/ArthurHoaro/5d0323f758ab2401ef444a53f54e9a07) (recommended) or visit every template page in your browser to generate cache files, while logged in. Here is a list :
31 22
32``` 23```
33http://<replace_domain>/ 24http://<replace_domain>/
25http://<replace_domain>/login
26http://<replace_domain>/daily
27http://<replace_domain>/tags/cloud
28http://<replace_domain>/tags/list
29http://<replace_domain>/picture-wall
34http://<replace_domain>/?nonope 30http://<replace_domain>/?nonope
35http://<replace_domain>/admin/add-shaare 31http://<replace_domain>/admin/add-shaare
36http://<replace_domain>/admin/password 32http://<replace_domain>/admin/password
37http://<replace_domain>/admin/tags 33http://<replace_domain>/admin/tags
38http://<replace_domain>/admin/configure 34http://<replace_domain>/admin/configure
39http://<replace_domain>/admin/tools 35http://<replace_domain>/admin/tools
40http://<replace_domain>/daily
41http://<replace_domain>/admin/shaare 36http://<replace_domain>/admin/shaare
42http://<replace_domain>/admin/export 37http://<replace_domain>/admin/export
43http://<replace_domain>/admin/import 38http://<replace_domain>/admin/import
44http://<replace_domain>/login
45http://<replace_domain>/picture-wall
46http://<replace_domain>/admin/plugins 39http://<replace_domain>/admin/plugins
47http://<replace_domain>/tags/cloud
48http://<replace_domain>/tags/list
49``` 40```
50 41
51#### Improve existing translation
52
53In Poedit, click on "Edit a Translation", and from Shaarli's directory open
54`inc/languages/<lang>/LC_MESSAGES/shaarli.po`.
55 42
56The existing list of translatable strings should have been loaded, then click on the "Update" button. 43#### Improve existing translations
57 44
58You can start editing the translation. 45- In Poedit, click on "Edit a Translation
46- Open `inc/languages/<lang>/LC_MESSAGES/shaarli.po` under Shaarli's directory
47- The existing list of translatable strings should load
48- Click on the "Update" button.
49- Start editing translations.
59 50
60![poedit-screenshot](images/poedit-1.jpg) 51![poedit-screenshot](images/poedit-1.jpg)
61 52
62Save when you're done, then you can submit a pull request containing the updated `shaarli.po`. 53Save when you're done, then you can submit a pull request containing the updated `shaarli.po`.
63 54
64#### Add a new language
65
66Open Poedit and select "Create New Translation", then from Shaarli's directory open
67`inc/languages/<lang>/LC_MESSAGES/shaarli.po`.
68
69Then select the language you want to create.
70 55
71Click on `File > Save as...`, and save your file in `<shaarli directory>/inc/language/<new language>/LC_MESSAGES/shaarli.po`. 56#### Add a new language
72`<new language>` here should be the language code respecting the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-2)
73format in lowercase (e.g. `de` for German).
74 57
75Then click on the "Update" button, and you can start to translate every available string. 58- In Poedit select "Create New Translation"
59- Open `inc/languages/<lang>/LC_MESSAGES/shaarli.po` under Shaarli's directory
60- Select the language you want to create.
61- Click on `File > Save as...`, save your file in `<shaarli directory>/inc/language/<new language>/LC_MESSAGES/shaarli.po` (`<new language>` here should be the language code respecting the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-2) format in lowercase - e.g. `de` for German)
62- Click on the "Update" button
63- Start editing translations.
76 64
77Save when you're done, then you can submit a pull request containing the new `shaarli.po`. 65Save when you're done, then you can submit a pull request containing the new `shaarli.po`.
78 66
67
79### Theme translations 68### Theme translations
80 69
81Theme translation extensions are loaded automatically if they're present. 70[Theme](Theming) translation extensions are loaded automatically if they're present.
82 71
83As a theme developer, all you have to do is to add the `.po` and `.mo` compiled file like this: 72As a theme developer, all you have to do is to add the `.po` and `.mo` compiled file like this:
84 73
85 tpl/<theme name>/language/<lang>/LC_MESSAGES/<theme name>.po 74```
86 tpl/<theme name>/language/<lang>/LC_MESSAGES/<theme name>.mo 75tpl/<theme name>/language/<lang>/LC_MESSAGES/<theme name>.po
76tpl/<theme name>/language/<lang>/LC_MESSAGES/<theme name>.mo
77```
87 78
88Where `<lang>` is the ISO 3166-1 alpha-2 language code. 79Where `<lang>` is the ISO 3166-1 alpha-2 language code.
80
89Read the following section "Extend Shaarli's translation" to learn how to generate those files. 81Read the following section "Extend Shaarli's translation" to learn how to generate those files.
90 82
83
91### Extend Shaarli's translation 84### Extend Shaarli's translation
92 85
93If you're writing a custom theme, or a non official plugin, you might want to use the translation system, 86If you're writing a custom theme, or a non official plugin, you might want to use the translation system,
diff --git a/doc/md/dev/Unit-tests.md b/doc/md/dev/Unit-tests.md
new file mode 100644
index 00000000..25af82d7
--- /dev/null
+++ b/doc/md/dev/Unit-tests.md
@@ -0,0 +1,138 @@
1# Unit tests
2
3Shaarli uses the [PHPUnit](https://phpunit.de/) test framework; it can be installed with [Composer](https://getcomposer.org/), which is a dependency management tool.
4
5## Install composer
6
7You can either use:
8
9- a system-wide version, e.g. installed through your distro's package manager
10- a local version, downloadable [here](https://getcomposer.org/download/).
11
12```bash
13# system-wide version
14$ composer install
15$ composer update
16
17# local version
18$ php composer.phar self-update
19$ php composer.phar install
20$ php composer.phar update
21```
22
23## Install Shaarli dev dependencies
24
25```bash
26$ cd /path/to/shaarli
27$ composer update
28```
29
30## Install and enable Xdebug to generate PHPUnit coverage reports
31
32
33[Xdebug](http://xdebug.org/docs/install) is a PHP extension which provides debugging and profiling capabilities. Install Xdebug:
34
35```bash
36# for Debian-based distros:
37sudo aptitude install php5-xdebug
38
39# for ArchLinux:
40pacman -S xdebug
41
42# then add the following line to /etc/php/php.ini
43zend_extension=xdebug.so
44```
45
46## Run unit tests
47
48Ensure tests pass successuflly:
49
50```bash
51make test
52# ...
53# OK (36 tests, 65 assertions)
54```
55
56In case of failure the test suite will point you to actual errors and output a summary:
57
58```bash
59make test
60# ...
61# FAILURES!
62# Tests: 36, Assertions: 63, Errors: 1, Failures: 2.
63```
64
65By default, PHPUnit will run all suitable tests found under the `tests` directory. Each test has 3 possible outcomes:
66
67- `.` - success
68- `F` - failure: the test was run but its results are invalid
69 - the code does not behave as expected
70 - dependencies to external elements: globals, session, cache...
71- `E` - error: something went wrong and the tested code has crashed
72 - typos in the code, or in the test code
73 - dependencies to missing external elements
74
75If Xdebug has been installed and activated, two coverage reports will be generated:
76
77- a summary in the console
78- a detailed HTML report with metrics for tested code
79 - to open it in a web browser: `firefox coverage/index.html &`
80
81
82### Executing specific tests
83
84Add a [`@group`](https://phpunit.de/manual/current/en/appendixes.annotations.html#appendixes.annotations.group) annotation in a test class or method comment:
85
86```php
87/**
88 * Netscape bookmark import
89 * @group WIP
90 */
91class BookmarkImportTest extends PHPUnit_Framework_TestCase
92{
93 [...]
94}
95```
96
97To run all tests annotated with `@group WIP`:
98```bash
99$ vendor/bin/phpunit --group WIP tests/
100```
101
102## Running tests inside Docker containers
103
104Unit tests can be run inside [Docker](../Docker.md) containers.
105
106Test Dockerfiles are located under `tests/docker/<distribution>/Dockerfile`, and can be used to build Docker images to run Shaarli test suites under commonLinux environments. Dockerfiles are provided for the following environments:
107
108- [`alpine36`](https://github.com/shaarli/Shaarli/blob/master/tests/docker/alpine36/Dockerfile) - [Alpine Linux 3.6](https://www.alpinelinux.org/downloads/)
109- [`debian8`](https://github.com/shaarli/Shaarli/blob/master/tests/docker/debian8/Dockerfile) - [Debian 8 Jessie](https://www.debian.org/DebianJessie) (oldoldstable)
110- [`debian9`](https://github.com/shaarli/Shaarli/blob/master/tests/docker/debian9/Dockerfile) - [Debian 9 Stretch](https://wiki.debian.org/DebianStretch) (oldstable)
111- [`ubuntu16`](https://github.com/shaarli/Shaarli/blob/master/tests/docker/ubuntu16/Dockerfile) - [Ubuntu 16.04 Xenial Xerus](http://releases.ubuntu.com/16.04/) (old LTS)
112
113Each image provides:
114- a base Linux OS
115- Shaarli PHP dependencies (OS packages)
116- test PHP dependencies (OS packages)
117- Composer
118- Tests that run inside the conatiner using a standard Linux user account (running tests as `root` would bypass permission checks and may hide issues)
119
120Build a test image:
121
122```bash
123# build the Debian 9 Docker image
124cd /path/to/shaarli/tests/docker/debian9
125docker build -t shaarli-test:debian9 .
126```
127
128Run unit tests in a container:
129
130```bash
131cd /path/to/shaarli
132# install/update 3rd-party test dependencies
133composer install --prefer-dist
134# run tests using the freshly built image
135docker run -v $PWD:/shaarli shaarli-test:debian9 docker_test
136# run the full test campaign
137docker run -v $PWD:/shaarli shaarli-test:debian9 docker_all_tests
138```
diff --git a/doc/md/Versioning-and-Branches.md b/doc/md/dev/Versioning.md
index 7097ca0a..32c80a5c 100644
--- a/doc/md/Versioning-and-Branches.md
+++ b/doc/md/dev/Versioning.md
@@ -1,6 +1,7 @@
1**WORK IN PROGRESS** 1# Versioning
2
3If you're maintaining a 3rd party tool for Shaarli (theme, plugin, etc.), It's important to understand how Shaarli branches work ensure your tool stays compatible.
2 4
3It's important to understand how Shaarli branches work, especially if you're maintaining a 3rd party tools for Shaarli (theme, plugin, etc.), to be sure stay compatible.
4 5
5## `master` branch 6## `master` branch
6 7
@@ -11,39 +12,26 @@ Remarks:
11- This branch shouldn't be used for production as it isn't necessary stable. 12- This branch shouldn't be used for production as it isn't necessary stable.
12- 3rd party aren't required to be compatible with the latest changes. 13- 3rd party aren't required to be compatible with the latest changes.
13- Official plugins, themes and libraries (contained within Shaarli organization repos) must be compatible with the master branch. 14- Official plugins, themes and libraries (contained within Shaarli organization repos) must be compatible with the master branch.
14- The version in this branch is always `dev`.
15 15
16## `v0.x` branch
17 16
18This `v0.x` branch, points to the latest `v0.x.y` release. 17## `v0.x` branch
19 18
20Explanation: 19The `v0.x` branch points to the latest `v0.x.y` release.
21 20
22When a new version is released, it might contains a major bug which isn't detected right away. For example, a new PHP version is released, containing backward compatibility issue which doesn't work with Shaarli. 21If a major bug affects the original `v0.x.0` release, we may [backport](https://en.wikipedia.org/wiki/Backporting) a fix for this bug from master, to the `v0.x` branch, and create a new bugfix release (eg. `v0.x.1`) from this branch.
23 22
24In this case, the issue is fixed in the `master` branch, and the fix is backported the to the `v0.x` branch. Then a new release is made from the `v0.x` branch. 23This allows users of the original release to upgrade to the fixed version, without having to upgrade to a completely new minor/major release.
25 24
26This workflow allow us to fix any major bug detected, without having to release bleeding edge feature too soon.
27 25
28## `latest` branch 26## `latest` branch
29 27
30This branch point the latest release. It recommended to use it to get the latest tested changes. 28This branch point the latest release. It recommended to use it to get the latest tested changes.
31 29
32## `stable` branch
33
34The `stable` branch doesn't contain any major bug, and is one major digit version behind the latest release.
35
36For example, the current latest release is `v0.8.3`, the stable branch is an alias to the latest `v0.7.x` release. When the `v0.9.0` version will be released, the stable will move to the latest `v0.8.x` release.
37
38Remarks:
39
40- Shaarli release pace isn't fast, and the stable branch might be a few months behind the latest release.
41 30
42## Releases 31## Releases
43 32
44Releases are always made from the latest `v0.x` branch. 33For every release, we manually generate a .zip file which contains all Shaarli dependencies, making Shaarli's installation only one step.
45 34
46Note that for every release, we manually generate a tarball which contains all Shaarli dependencies, making Shaarli's installation only one step.
47 35
48## Advices on 3rd party git repos workflow 36## Advices on 3rd party git repos workflow
49 37
diff --git a/doc/md/images/poedit-1.jpg b/doc/md/dev/images/poedit-1.jpg
index 673ae6d6..673ae6d6 100644
--- a/doc/md/images/poedit-1.jpg
+++ b/doc/md/dev/images/poedit-1.jpg
Binary files differ
diff --git a/doc/md/docker/docker-101.md b/doc/md/docker/docker-101.md
deleted file mode 100644
index a9c00b85..00000000
--- a/doc/md/docker/docker-101.md
+++ /dev/null
@@ -1,140 +0,0 @@
1## Basics
2Install [Docker](https://www.docker.com/), by following the instructions relevant
3to your OS / distribution, and start the service.
4
5### Search an image on [DockerHub](https://hub.docker.com/)
6
7```bash
8$ docker search debian
9
10NAME DESCRIPTION STARS OFFICIAL AUTOMATED
11ubuntu Ubuntu is a Debian-based Linux operating s... 2065 [OK]
12debian Debian is a Linux distribution that's comp... 603 [OK]
13google/debian 47 [OK]
14```
15
16### Show available tags for a repository
17```bash
18$ curl https://index.docker.io/v1/repositories/debian/tags | python -m json.tool
19
20% Total % Received % Xferd Average Speed Time Time Time Current
21Dload Upload Total Spent Left Speed
22100 1283 0 1283 0 0 433 0 --:--:-- 0:00:02 --:--:-- 433
23```
24
25Sample output:
26```json
27[
28 {
29 "layer": "85a02782",
30 "name": "stretch"
31 },
32 {
33 "layer": "59abecbc",
34 "name": "testing"
35 },
36 {
37 "layer": "bf0fd686",
38 "name": "unstable"
39 },
40 {
41 "layer": "60c52dbe",
42 "name": "wheezy"
43 },
44 {
45 "layer": "c5b806fe",
46 "name": "wheezy-backports"
47 }
48]
49
50```
51
52### Pull an image from DockerHub
53```bash
54$ docker pull repository[:tag]
55
56$ docker pull debian:wheezy
57wheezy: Pulling from debian
584c8cbfd2973e: Pull complete
5960c52dbe9d91: Pull complete
60Digest: sha256:c584131da2ac1948aa3e66468a4424b6aea2f33acba7cec0b631bdb56254c4fe
61Status: Downloaded newer image for debian:wheezy
62```
63
64Docker 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.
65
66### Start a container
67A 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.
68
69The 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``.
70
71Stopped containers are not destroyed, unless you specify ``--rm``. To view all created, running and stopped containers, enter:
72```bash
73$ docker ps -a
74```
75
76Some 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.
77
78### Access a running container
79A running container is accessible using ``docker exec``, or ``docker copy``. You can use ``exec`` to start a root shell in the Shaarli container:
80```bash
81$ docker exec -ti <container-name-or-id> bash
82```
83Note 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.
84
85Access can also be through one or more network ports, or disk volumes. Both are specified on and fixed on ``docker create`` or ``run``.
86
87You can view the console output of the main container process too:
88```bash
89$ docker logs -f <container-name-or-id>
90```
91
92### Docker disk use
93Trying out different images can fill some gigabytes of disk quickly. Besides images, the docker volumes usually take up most disk space.
94
95If 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:
96
97```bash
98$ docker rmi -f $(docker images -aq) # remove or mark all images for disposal
99$ docker volume rm $(docker volume ls -q) # remove all volumes
100```
101
102### Systemd config
103Systemd 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.
104
105```bash
106systemctl enable /etc/systemd/system/docker.shaarli.service
107systemctl start docker.shaarli
108systemctl status docker.*
109journalctl -f # inspect system log if needed
110```
111
112You will need sudo or a root terminal to perform some or all of the steps above. Here are the contents for the service file:
113```
114[Unit]
115Description=Shaarli Bookmark Manager Container
116After=docker.service
117Requires=docker.service
118
119
120[Service]
121Restart=always
122
123# Put any environment you want in an included file, like $host- or $domainname in this example
124EnvironmentFile=/etc/sysconfig/box-environment
125
126# It's just an example..
127ExecStart=/usr/bin/docker run \
128 -p 28010:80 \
129 --name ${hostname}-shaarli \
130 --hostname shaarli.${domainname} \
131 -v /srv/docker-volumes-local/shaarli-data:/var/www/shaarli/data:rw \
132 -v /etc/localtime:/etc/localtime:ro \
133 shaarli/shaarli:latest
134
135ExecStop=/usr/bin/docker rm -f ${hostname}-shaarli
136
137
138[Install]
139WantedBy=multi-user.target
140```
diff --git a/doc/md/docker/resources.md b/doc/md/docker/resources.md
deleted file mode 100644
index 082d4a46..00000000
--- a/doc/md/docker/resources.md
+++ /dev/null
@@ -1,19 +0,0 @@
1### Docker
2
3- [Interactive Docker training portal](https://www.katacoda.com/courses/docker/) on [Katakoda](https://www.katacoda.com/)
4- [Where are Docker images stored?](http://blog.thoward37.me/articles/where-are-docker-images-stored/)
5- [Dockerfile reference](https://docs.docker.com/reference/builder/)
6- [Dockerfile best practices](https://docs.docker.com/articles/dockerfile_best-practices/)
7- [Volumes](https://docs.docker.com/userguide/dockervolumes/)
8
9### DockerHub
10
11- [Repositories](https://docs.docker.com/userguide/dockerrepos/)
12- [Teams and organizations](https://docs.docker.com/docker-hub/orgs/)
13- [GitHub automated build](https://docs.docker.com/docker-hub/github/)
14
15### Service management
16
17- [Using supervisord](https://docs.docker.com/articles/using_supervisord/)
18- [Nginx in the foreground](http://nginx.org/en/docs/ngx_core_module.html#daemon)
19- [supervisord](http://supervisord.org/)
diff --git a/doc/md/docker/reverse-proxy-configuration.md b/doc/md/docker/reverse-proxy-configuration.md
deleted file mode 100644
index e53c9422..00000000
--- a/doc/md/docker/reverse-proxy-configuration.md
+++ /dev/null
@@ -1,123 +0,0 @@
1## Foreword
2
3This guide assumes that:
4
5- Shaarli runs in a Docker container
6- The host's `10080` port is mapped to the container's `80` port
7- Shaarli's Fully Qualified Domain Name (FQDN) is `shaarli.domain.tld`
8- HTTP traffic is redirected to HTTPS
9
10## Apache
11
12- [Apache 2.4 documentation](https://httpd.apache.org/docs/2.4/)
13 - [mod_proxy](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html)
14 - [Reverse Proxy Request Headers](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#x-headers)
15
16The following HTTP headers are set when the `ProxyPass` directive is set:
17
18- `X-Forwarded-For`
19- `X-Forwarded-Host`
20- `X-Forwarded-Server`
21
22The original `SERVER_NAME` can be sent to the proxied host by setting the [`ProxyPreserveHost`](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#ProxyPreserveHost) directive to `On`.
23
24```apache
25<VirtualHost *:80>
26 ServerName shaarli.domain.tld
27 Redirect permanent / https://shaarli.domain.tld
28</VirtualHost>
29
30<VirtualHost *:443>
31 ServerName shaarli.domain.tld
32
33 SSLEngine on
34 SSLCertificateFile /path/to/cert
35 SSLCertificateKeyFile /path/to/certkey
36
37 LogLevel warn
38 ErrorLog /var/log/apache2/shaarli-error.log
39 CustomLog /var/log/apache2/shaarli-access.log combined
40
41 RequestHeader set X-Forwarded-Proto "https"
42 ProxyPreserveHost On
43
44 ProxyPass / http://127.0.0.1:10080/
45 ProxyPassReverse / http://127.0.0.1:10080/
46</VirtualHost>
47```
48
49
50## HAProxy
51
52- [HAProxy documentation](https://cbonte.github.io/haproxy-dconv/)
53
54```conf
55global
56 [...]
57
58defaults
59 [...]
60
61frontend http-in
62 bind :80
63 redirect scheme https code 301 if !{ ssl_fc }
64
65 bind :443 ssl crt /path/to/cert.pem
66
67 default_backend shaarli
68
69
70backend shaarli
71 mode http
72 option http-server-close
73 option forwardfor
74 reqadd X-Forwarded-Proto: https
75
76 server shaarli1 127.0.0.1:10080
77```
78
79
80## Nginx
81
82- [Nginx documentation](https://nginx.org/en/docs/)
83
84```nginx
85http {
86 [...]
87
88 index index.html index.php;
89
90 root /home/john/web;
91 access_log /var/log/nginx/access.log;
92 error_log /var/log/nginx/error.log;
93
94 server {
95 listen 80;
96 server_name shaarli.domain.tld;
97 return 301 https://shaarli.domain.tld$request_uri;
98 }
99
100 server {
101 listen 443 ssl http2;
102 server_name shaarli.domain.tld;
103
104 ssl_certificate /path/to/cert
105 ssl_certificate_key /path/to/certkey
106
107 location / {
108 proxy_set_header X-Real-IP $remote_addr;
109 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
110 proxy_set_header X-Forwarded-Proto $scheme;
111 proxy_set_header X-Forwarded-Host $host;
112
113 proxy_pass http://localhost:10080/;
114 proxy_set_header Host $host;
115 proxy_connect_timeout 30s;
116 proxy_read_timeout 120s;
117
118 access_log /var/log/nginx/shaarli.access.log;
119 error_log /var/log/nginx/shaarli.error.log;
120 }
121 }
122}
123```
diff --git a/doc/md/docker/shaarli-images.md b/doc/md/docker/shaarli-images.md
deleted file mode 100644
index 14971d54..00000000
--- a/doc/md/docker/shaarli-images.md
+++ /dev/null
@@ -1,118 +0,0 @@
1A brief guide on getting starting using docker is given in [Docker 101](docker-101.md).
2To learn more about user data and how to keep it across versions, please see [Upgrade and Migration](../Upgrade-and-migration.md).
3
4## Get and run a Shaarli image
5
6### DockerHub repository
7The images can be found in the [`shaarli/shaarli`](https://hub.docker.com/r/shaarli/shaarli/)
8repository.
9
10### Available image tags
11- `latest`: latest branch
12- `master`: master branch
13- `stable`: stable branch
14
15The `latest`, `master` and `stable` images rely on:
16
17- [Alpine Linux](https://www.alpinelinux.org/)
18- [PHP7-FPM](http://php-fpm.org/)
19- [Nginx](http://nginx.org/)
20
21Additional Dockerfiles are provided for the `arm32v7` platform, relying on
22[Linuxserver.io Alpine armhf
23images](https://hub.docker.com/r/lsiobase/alpine.armhf/). These images must be
24built using [`docker
25build`](https://docs.docker.com/engine/reference/commandline/build/) on an
26`arm32v7` machine or using an emulator such as
27[qemu](https://resin.io/blog/building-arm-containers-on-any-x86-machine-even-dockerhub/).
28
29### Download from Docker Hub
30```shell
31$ docker pull shaarli/shaarli
32
33latest: Pulling from shaarli/shaarli
3432716d9fcddb: Pull complete
3584899d045435: Pull complete
364b6ad7444763: Pull complete
37e0345ef7a3e0: Pull complete
385c1dd344094f: Pull complete
396422305a200b: Pull complete
407d63f861dbef: Pull complete
413eb97210645c: Pull complete
42869319d746ff: Already exists
43869319d746ff: Pulling fs layer
44902b87aaaec9: Already exists
45Digest: sha256:f836b4627b958b3f83f59c332f22f02fcd495ace3056f2be2c4912bd8704cc98
46Status: Downloaded newer image for shaarli/shaarli:latest
47```
48
49### Create and start a new container from the image
50```shell
51# map the host's :8000 port to the container's :80 port
52$ docker create -p 8000:80 shaarli/shaarli
53d40b7af693d678958adedfb88f87d6ea0237186c23de5c4102a55a8fcb499101
54
55# launch the container in the background
56$ docker start d40b7af693d678958adedfb88f87d6ea0237186c23de5c4102a55a8fcb499101
57d40b7af693d678958adedfb88f87d6ea0237186c23de5c4102a55a8fcb499101
58
59# list active containers
60$ docker ps
61CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
62d40b7af693d6 shaarli/shaarli /usr/bin/supervisor 15 seconds ago Up 4 seconds 0.0.0.0:8000->80/tcp backstabbing_galileo
63```
64
65### Stop and destroy a container
66```shell
67$ docker stop backstabbing_galileo # those docker guys are really rude to physicists!
68backstabbing_galileo
69
70# check the container is stopped
71$ docker ps
72CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
73
74# list ALL containers
75$ docker ps -a
76CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
77d40b7af693d6 shaarli/shaarli /usr/bin/supervisor 5 minutes ago Exited (0) 48 seconds ago backstabbing_galileo
78
79# destroy the container
80$ docker rm backstabbing_galileo # let's put an end to these barbarian practices
81backstabbing_galileo
82
83$ docker ps -a
84CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
85```
86
87### Automatic builds
88Docker users can start a personal instance from an
89[autobuild image](https://hub.docker.com/r/shaarli/shaarli/).
90For example to start a temporary Shaarli at ``localhost:8000``, and keep session
91data (config, storage):
92
93```shell
94MY_SHAARLI_VOLUME=$(cd /path/to/shaarli/data/ && pwd -P)
95docker run -ti --rm \
96 -p 8000:80 \
97 -v $MY_SHAARLI_VOLUME:/var/www/shaarli/data \
98 shaarli/shaarli
99```
100
101### Volumes and data persistence
102Data can be persisted by [using volumes](https://docs.docker.com/storage/volumes/).
103Volumes allow to keep your data when renewing and/or updating container images:
104
105```shell
106# Create data volumes
107$ docker volume create shaarli-data
108$ docker volume create shaarli-cache
109
110# Create and start a Shaarli container using these volumes to persist data
111$ docker create \
112 --name shaarli \
113 -v shaarli-cache:/var/www/shaarli/cache \
114 -v shaarli-data:/var/www/shaarli/data \
115 -p 8000:80 \
116 shaarli/shaarli:master
117$ docker start shaarli
118```
diff --git a/doc/md/guides/backup-restore-import-export.md b/doc/md/guides/backup-restore-import-export.md
deleted file mode 100644
index bb790074..00000000
--- a/doc/md/guides/backup-restore-import-export.md
+++ /dev/null
@@ -1,64 +0,0 @@
1## Backup and restore the datastore file
2
3Backup the file `data/datastore.php` (by FTP or SSH). Restore by putting the file back in place.
4
5Example command:
6```bash
7rsync -avzP my.server.com:/var/www/shaarli/data/datastore.php datastore-$(date +%Y-%m-%d_%H%M).php
8```
9
10## Export links as...
11
12To export links as an HTML file, under _Tools > Export_, choose:
13
14- _Export all_ to export both public and private links
15- _Export public_ to export public links only
16- _Export private_ to export private links only
17
18Restore by using the `Import` feature.
19
20- This can be done using the [shaarchiver](https://github.com/nodiscc/shaarchiver) tool.
21
22Example command:
23```bash
24./export-bookmarks.py --url=https://my.server.com/shaarli --username=myusername --password=mysupersecretpassword --download-dir=./ --type=all
25```
26
27## Import links from...
28
29### Diigo
30
31If you export your bookmark from Diigo, make sure you use the Delicious export, not the Netscape export. (Their Netscape export is broken, and they don't seem to be interested in fixing it.)
32
33### Mister Wong
34
35See [this issue](https://github.com/sebsauvage/Shaarli/issues/146) for import tweaks.
36
37### SemanticScuttle
38
39To correctly import the tags from a [SemanticScuttle](http://semanticscuttle.sourceforge.net/) HTML export, edit the HTML file before importing and replace all occurences of `tags=` (lowercase) to `TAGS=` (uppercase).
40
41### Scuttle
42
43Shaarli cannot import data directly from [Scuttle](https://github.com/scronide/scuttle).
44
45However, you can use the third-party [scuttle-to-shaarli](https://github.com/q2apro/scuttle-to-shaarli)
46tool to export the Scuttle database to the Netscape HTML format compatible with the Shaarli importer.
47
48### Refind
49
50You can use the third-party tool [Derefind](https://github.com/ShawnPConroy/Derefind) to convert refind.com bookmark exports to a format that can be imported into Shaarli.
51
52## Import Shaarli links to Firefox
53
54- Export your Shaarli links as described above.
55 - For compatibility reasons, check `Prepend note permalinks with this Shaarli instance's URL (useful to import bookmarks in a web browser)`
56- In Firefox, open the bookmark manager (not the sidebar! `Bookmarks menu > Show all bookmarks` or `Ctrl+Shift+B`)
57- Select `Import and Backup > Import bookmarks in HTML format`
58
59Your bookmarks will be imported in Firefox, ready to use, with tags and descriptions retained. "Self" (notes) shaares will still point to the Shaarli instance you exported them from, but the note text can be viewed directly in the bookmark properties inside your browser. Depending on the number of bookmarks, the import can take some time.
60
61You may be interested in these Firefox addons to manage links imported from Shaarli
62
63- [Bookmark Deduplicator](https://addons.mozilla.org/en-US/firefox/addon/bookmark-deduplicator/) - provides an easy way to deduplicate your bookmarks
64- [TagSieve](https://addons.mozilla.org/en-US/firefox/addon/tagsieve/) - browse your bookmarks by their tags
diff --git a/doc/md/guides/images/01-create-droplet-distro.jpg b/doc/md/guides/images/01-create-droplet-distro.jpg
deleted file mode 100644
index 63682ba8..00000000
--- a/doc/md/guides/images/01-create-droplet-distro.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/md/guides/images/02-create-droplet-region.jpg b/doc/md/guides/images/02-create-droplet-region.jpg
deleted file mode 100644
index 135a78be..00000000
--- a/doc/md/guides/images/02-create-droplet-region.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/md/guides/images/03-create-droplet-size.jpg b/doc/md/guides/images/03-create-droplet-size.jpg
deleted file mode 100644
index aa5b2fd2..00000000
--- a/doc/md/guides/images/03-create-droplet-size.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/md/guides/images/04-finalize.jpg b/doc/md/guides/images/04-finalize.jpg
deleted file mode 100644
index 68ec0dc5..00000000
--- a/doc/md/guides/images/04-finalize.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/md/guides/images/05-droplet.jpg b/doc/md/guides/images/05-droplet.jpg
deleted file mode 100644
index 44e93a1e..00000000
--- a/doc/md/guides/images/05-droplet.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/md/guides/images/06-domain.jpg b/doc/md/guides/images/06-domain.jpg
deleted file mode 100644
index 5827dd93..00000000
--- a/doc/md/guides/images/06-domain.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/md/guides/install-shaarli-with-debian9-and-docker.md b/doc/md/guides/install-shaarli-with-debian9-and-docker.md
deleted file mode 100644
index f1b26d47..00000000
--- a/doc/md/guides/install-shaarli-with-debian9-and-docker.md
+++ /dev/null
@@ -1,257 +0,0 @@
1_Last updated on 2018-07-01._
2
3## Goals
4- Getting a Virtual Private Server (VPS)
5- Running Shaarli:
6 - as a Docker container,
7 - using the Træfik reverse proxy,
8 - securized with TLS certificates from Let's Encrypt.
9
10
11The following components and tools will be used:
12
13- [Debian](https://www.debian.org/), a GNU/Linux distribution widely used in
14 server environments;
15- [Docker](https://docs.docker.com/engine/docker-overview/), an open platform
16 for developing, shipping, and running applications;
17- [Docker Compose](https://docs.docker.com/compose/), a tool for defining and
18 running multi-container Docker applications.
19
20
21More information can be found in the [Resources](#resources) section at the
22bottom of the guide.
23
24## Getting a Virtual Private Server
25For this guide, I went for the smallest VPS available from DigitalOcean,
26a Droplet with 1 CPU, 1 GiB RAM and 25 GiB SSD storage, which costs
27$5/month ($0.007/hour):
28
29- [Droplets Overview](https://www.digitalocean.com/docs/droplets/overview/)
30- [Pricing](https://www.digitalocean.com/pricing/)
31- [How to Create a Droplet from the DigitalOcean Control Panel](https://www.digitalocean.com/docs/droplets/how-to/create/)
32- [How to Add SSH Keys to Droplets](https://www.digitalocean.com/docs/droplets/how-to/add-ssh-keys/)
33- [Initial Server Setup with Debian 8](https://www.digitalocean.com/community/tutorials/initial-server-setup-with-debian-8) (also applies to Debian 9)
34- [An Introduction to Securing your Linux VPS](https://www.digitalocean.com/community/tutorials/an-introduction-to-securing-your-linux-vps)
35
36### Creating a Droplet
37Select `Debian 9` as the Droplet distribution:
38
39<img src="../images/01-create-droplet-distro.jpg"
40 width="500px"
41 alt="Droplet distribution" />
42
43Choose a region that is geographically close to you:
44
45<img src="../images/02-create-droplet-region.jpg"
46 width="500px"
47 alt="Droplet region" />
48
49Choose a Droplet size that corresponds to your usage and budget:
50
51<img src="../images/03-create-droplet-size.jpg"
52 width="500px"
53 alt="Droplet size" />
54
55Finalize the Droplet creation:
56
57<img src="../images/04-finalize.jpg"
58 width="500px"
59 alt="Droplet finalization" />
60
61Droplet information is displayed on the Control Panel:
62
63<img src="../images/05-droplet.jpg"
64 width="500px"
65 alt="Droplet summary" />
66
67Once your VPS has been created, you will receive an e-mail with connection
68instructions.
69
70## Obtaining a domain name
71After creating your VPS, it will be reachable using its IP address; some hosting
72providers also create a DNS record, e.g. `ns4853142.ip-01-47-127.eu`.
73
74A domain name (DNS record) is required to obtain a certificate and setup HTTPS
75(HTTP with TLS encryption).
76
77Domain names can be obtained from registrars through hosting providers such as
78[Gandi](https://www.gandi.net/en/domain).
79
80Once you have your own domain, you need to create a new DNS record that points
81to your VPS' IP address:
82
83<img src="../images/06-domain.jpg"
84 width="650px"
85 alt="Domain configuration" />
86
87## Host setup
88Now's the time to connect to your freshly created VPS!
89
90```shell
91$ ssh root@188.166.85.8
92
93Linux stretch-shaarli-02 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1+deb9u1 (2018-05-07) x86_64
94
95The programs included with the Debian GNU/Linux system are free software;
96the exact distribution terms for each program are described in the
97individual files in /usr/share/doc/*/copyright.
98
99Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
100permitted by applicable law.
101Last login: Sun Jul 1 11:20:18 2018 from <REDACTED>
102
103root@stretch-shaarli-02:~$
104```
105
106### Updating the system
107```shell
108root@stretch-shaarli-02:~$ apt update && apt upgrade -y
109```
110
111### Setting up Docker
112_The following instructions are from the
113[Get Docker CE for Debian](https://docs.docker.com/install/linux/docker-ce/debian/)
114guide._
115
116Install package dependencies:
117
118```shell
119root@stretch-shaarli-02:~$ apt install -y apt-transport-https ca-certificates curl gnupg2 software-properties-common
120```
121
122Add Docker's package repository GPG key:
123
124```shell
125root@stretch-shaarli-02:~$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
126```
127
128Add Docker's package repository:
129
130```shell
131root@stretch-shaarli-02:~$ add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian stretch stable"
132```
133
134Update package lists and install Docker:
135
136```shell
137root@stretch-shaarli-02:~$ apt update && apt install -y docker-ce
138```
139
140Verify Docker is properly configured by running the `hello-world` image:
141
142```shell
143root@stretch-shaarli-02:~$ docker run hello-world
144```
145
146### Setting up Docker Compose
147_The following instructions are from the
148[Install Docker Compose](https://docs.docker.com/compose/install/)
149guide._
150
151Download the current version from the release page:
152
153```shell
154root@stretch-shaarli-02:~$ curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
155root@stretch-shaarli-02:~$ chmod +x /usr/local/bin/docker-compose
156```
157
158## Running Shaarli
159Shaarli comes with a configuration file for Docker Compose, that will setup:
160
161- a local Docker network
162- a Docker [volume](https://docs.docker.com/storage/volumes/) to store Shaarli data
163- a Docker [volume](https://docs.docker.com/storage/volumes/) to store Træfik TLS configuration and certificates
164- a [Shaarli](https://hub.docker.com/r/shaarli/shaarli/) instance
165- a [Træfik](https://hub.docker.com/_/traefik/) instance
166
167[Træfik](https://docs.traefik.io/) is a modern HTTP reverse proxy, with native
168support for Docker and [Let's Encrypt](https://letsencrypt.org/).
169
170### Compose configuration
171Create a new directory to store the configuration:
172
173```shell
174root@stretch-shaarli-02:~$ mkdir shaarli && cd shaarli
175root@stretch-shaarli-02:~/shaarli$
176```
177
178Download the current version of Shaarli's `docker-compose.yml`:
179
180```shell
181root@stretch-shaarli-02:~/shaarli$ curl -L https://raw.githubusercontent.com/shaarli/Shaarli/master/docker-compose.yml -o docker-compose.yml
182```
183
184Create the `.env` file and fill in your VPS and domain information (replace
185`<MY_SHAARLI_DOMAIN>` and `<MY_CONTACT_EMAIL>` with your actual information):
186
187```shell
188root@stretch-shaarli-02:~/shaarli$ vim .env
189```
190
191```shell
192SHAARLI_VIRTUAL_HOST=<MY_SHAARLI_DOMAIN>
193SHAARLI_LETSENCRYPT_EMAIL=<MY_CONTACT_EMAIL>
194```
195
196### Pull the Docker images
197```shell
198root@stretch-shaarli-02:~/shaarli$ docker-compose pull
199Pulling shaarli ... done
200Pulling traefik ... done
201```
202
203### Run!
204```shell
205root@stretch-shaarli-02:~/shaarli$ docker-compose up -d
206Creating network "shaarli_http-proxy" with the default driver
207Creating volume "shaarli_traefik-acme" with default driver
208Creating volume "shaarli_shaarli-data" with default driver
209Creating shaarli_shaarli_1 ... done
210Creating shaarli_traefik_1 ... done
211```
212
213## Conclusion
214Congratulations! Your Shaarli instance should be up and running, and available
215at `https://<MY_SHAARLI_DOMAIN>`.
216
217<img src="../images/07-installation.jpg"
218 width="500px"
219 alt="Shaarli installation page" />
220
221## Resources
222### Related Shaarli documentation
223- [Docker 101](../docker/docker-101.md)
224- [Shaarli images](../docker/shaarli-images.md)
225
226### Hosting providers
227- [DigitalOcean](https://www.digitalocean.com/)
228- [Gandi](https://www.gandi.net/en)
229- [OVH](https://www.ovh.co.uk/)
230- [RackSpace](https://www.rackspace.com/)
231- etc.
232
233### Domain Names and Registrars
234- [Introduction to the Domain Name System (DNS)](https://opensource.com/article/17/4/introduction-domain-name-system-dns)
235- [ICANN](https://www.icann.org/)
236- [Domain name registrar](https://en.wikipedia.org/wiki/Domain_name_registrar)
237- [OVH Domain Registration](https://www.ovh.co.uk/domains/)
238- [Gandi Domain Registration](https://www.gandi.net/en/domain)
239
240### HTTPS and Security
241- [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security)
242- [Let's Encrypt](https://letsencrypt.org/)
243
244### Docker
245- [Docker Overview](https://docs.docker.com/engine/docker-overview/)
246- [Docker Documentation](https://docs.docker.com/)
247- [Get Docker CE for Debian](https://docs.docker.com/install/linux/docker-ce/debian/)
248- [docker logs](https://docs.docker.com/engine/reference/commandline/logs/)
249- [Volumes](https://docs.docker.com/storage/volumes/)
250- [Install Docker Compose](https://docs.docker.com/compose/install/)
251- [docker-compose logs](https://docs.docker.com/compose/reference/logs/)
252
253### Træfik
254- [Getting Started](https://docs.traefik.io/)
255- [Docker backend](https://docs.traefik.io/configuration/backends/docker/)
256- [Let's Encrypt and Docker](https://docs.traefik.io/user-guide/docker-and-lets-encrypt/)
257- [traefik](https://hub.docker.com/_/traefik/) Docker image
diff --git a/doc/md/guides/various-hacks.md b/doc/md/guides/various-hacks.md
deleted file mode 100644
index 0cef99df..00000000
--- a/doc/md/guides/various-hacks.md
+++ /dev/null
@@ -1,24 +0,0 @@
1### Decode datastore content
2
3To display the array representing the data saved in `data/datastore.php`, use the following snippet:
4
5```php
6$data = "tZNdb9MwFIb... <Commented content inside datastore.php>";
7$out = unserialize(gzinflate(base64_decode($data)));
8echo "<pre>"; // Pretty printing is love, pretty printing is life
9print_r($out);
10echo "</pre>";
11exit;
12```
13This will output the internal representation of the datastore, "unobfuscated" (if this can really be considered obfuscation).
14
15Alternatively, you can transform to JSON format (and pretty-print if you have `jq` installed):
16```
17php -r 'print(json_encode(unserialize(gzinflate(base64_decode(preg_replace("!.*/\* (.+) \*/.*!", "$1", file_get_contents("data/datastore.php")))))));' | jq .
18```
19
20### See also
21
22- [Add a new custom field to shaares (example patch)](https://gist.github.com/nodiscc/8b0194921f059d7b9ad89a581ecd482c)
23- [Copy an existing Shaarli installation over SSH, and serve it locally](https://gist.github.com/nodiscc/ed161c66e5b028b5299b0a3733d01c77)
24- [Create multiple Shaarli instances, generate an HTML index of them](https://gist.github.com/nodiscc/52e711cda3bc47717c16065231cf6b20)
diff --git a/doc/md/guides/images/07-installation.jpg b/doc/md/images/07-installation.jpg
index 42cc9f10..42cc9f10 100644
--- a/doc/md/guides/images/07-installation.jpg
+++ b/doc/md/images/07-installation.jpg
Binary files differ
diff --git a/doc/md/images/bookmarklet.png b/doc/md/images/bookmarklet.png
deleted file mode 100644
index 0262578e..00000000
--- a/doc/md/images/bookmarklet.png
+++ /dev/null
Binary files differ
diff --git a/doc/md/images/firefoxshare.png b/doc/md/images/firefoxshare.png
deleted file mode 100644
index 8f8fdba4..00000000
--- a/doc/md/images/firefoxshare.png
+++ /dev/null
Binary files differ
diff --git a/doc/md/images/install-shaarli.png b/doc/md/images/install-shaarli.png
deleted file mode 100644
index d5d5baa7..00000000
--- a/doc/md/images/install-shaarli.png
+++ /dev/null
Binary files differ
diff --git a/doc/md/index.md b/doc/md/index.md
index 1431f9e1..2c4995f8 100644
--- a/doc/md/index.md
+++ b/doc/md/index.md
@@ -2,21 +2,19 @@
2 2
3The personal, minimalist, super-fast, database free, bookmarking service. 3The personal, minimalist, super-fast, database free, bookmarking service.
4 4
5Do you want to share the links you discover? 5Do you want to share the links you discover? Shaarli is a minimalist bookmark manager and link sharing service that you can install on your own server. It is designed to be personal (single-user), fast and handy.
6Shaarli is a minimalist bookmark manager and link sharing service that you can install on your own server.
7It is designed to be personal (single-user), fast and handy.
8
9<!-- TODO screenshots -->
10 6
11Visit the pages in the sidebar to find information on how to setup, use, configure, tweak and troubleshoot Shaarli. 7Visit the pages in the sidebar to find information on how to setup, use, configure, tweak and troubleshoot Shaarli.
12 8
13
14* [GitHub project page](https://github.com/shaarli/Shaarli) 9* [GitHub project page](https://github.com/shaarli/Shaarli)
15* [Online documentation](https://shaarli.readthedocs.io/) 10* [Documentation](https://shaarli.readthedocs.io/)
16* [Latest releases](https://github.com/shaarli/Shaarli/releases)
17* [Changelog](https://github.com/shaarli/Shaarli/blob/master/CHANGELOG.md) 11* [Changelog](https://github.com/shaarli/Shaarli/blob/master/CHANGELOG.md)
18 12
19 13
14[![](https://i.imgur.com/8wEBRSG.png)](https://i.imgur.com/WWPfSj0.png) [![](https://i.imgur.com/93PpLLs.png)](https://i.imgur.com/V09kAQt.png) [![](https://i.imgur.com/rrsjWYy.png)](https://i.imgur.com/TZzGHMs.png) [![](https://i.imgur.com/8iRzHfe.png)](https://i.imgur.com/sfJJ6NT.png) [![](https://i.imgur.com/GjZGvIh.png)](https://i.imgur.com/QsedIuJ.png) [![](https://i.imgur.com/TFZ9PEq.png)](https://i.imgur.com/KdtF8Ll.png) [![](https://i.imgur.com/uICDOle.png)](https://i.imgur.com/27wYsbC.png) [![](https://i.imgur.com/tVvD3gH.png)](https://i.imgur.com/zGF4d6L.jpg)
15
16
17
20## Demo 18## Demo
21 19
22You can use this [public demo instance of Shaarli](https://demo.shaarli.org). 20You can use this [public demo instance of Shaarli](https://demo.shaarli.org).
@@ -25,101 +23,80 @@ It runs the latest development version of Shaarli and is updated/reset daily.
25Login: `demo`; Password: `demo` 23Login: `demo`; Password: `demo`
26 24
27 25
26## Getting started
27
28- [Configure your server](Server-configuration.md)
29- [Install Shaarli](Installation.md)
30- Or install Shaarli using [Docker](Docker.md)
31
32
28## Features 33## Features
29 34
30Shaarli can be used: 35Shaarli can be used:
31 36
32- to share, comment and save interesting links and news 37- to share, comment and save interesting links
33- to bookmark useful/frequent links and share them between computers 38- to bookmark useful/frequent links and share them between computers
34- as a minimal blog/microblog/writing platform 39- as a minimal blog/microblog/writing platform
35- as a read-it-later list 40- as a read-it-later/todo list
36- to draft and save articles/posts/ideas 41- as a notepad to draft and save articles/posts/ideas
37- to keep notes, documentation and code snippets 42- as a knowledge base to keep notes, documentation and code snippets
38- as a shared clipboard/notepad/pastebin between machines 43- as a shared clipboard/notepad/pastebin between computers
39- as a todo list 44- as playlist manager for online media
40- to store media playlists 45- to feed other blogs, aggregators, social networks...
41- to keep extracts/comments from webpages that may disappear.
42- to keep track of ongoing discussions
43- to feed other blogs, aggregators, social networks... using RSS feeds
44 46
45### Edit, view and search your links 47### Edit, view and search your links
46 48
47- Minimalist design 49- Editable URL, title, description, tags, private/public status for all your [Shaares](Usage.md)
48- FAST 50- [Tags](Usage.md#tags) to organize your Shaares
49- Customizable link titles and descriptions 51- [Search](Usage.md#search) in all fields
50- Tags to organize your links (features tag autocompletion, renaming, merging and deletion) 52- Unique [permalinks](Usage.md#permalinks) for easy reference
51- Search by tag or using the full-text search 53- Paginated Shaares list view (with image and video thumbnails)
52- Public and private links (visible only to logged-in users) 54- [Tag cloud/list](Usage#tag-cloud) views
53- Unique permalinks for easy reference 55- [Picture wall](Usage#picture-wall)/thumbnails view (with lazy loading)
54- Paginated link list (with image and video thumbnails) 56- [ATOM and RSS feeds](Usage.md#rss-feeds) (can also be filtered using tags or text search)
55- Tag cloud and list views 57- [Daily](Usage.md#daily): newspaper-like daily digest (and daily RSS feed)
56- Picture wall: image and video thumbnails view (with lazy loading) 58- URL cleanup: automatic removal of `?utm_source=...`, `fb=...` tracking parameters
57- ATOM and RSS feeds (can also be filtered using tags or text search) 59- Extensible through [plugins](Plugins.md)
58- Daily: newspaper-like daily digest (and daily RSS feed) 60- Easily extensible by any client using the [REST API](REST-API.md) exposed by Shaarli
59- URL cleanup: automatic removal of `?utm_source=...`, `fb=...` 61- Bookmarklet and [other tools](Community-and-related-software.md) to share links in one click
60- Extensible through [plugins](https://shaarli.readthedocs.io/en/master/Plugins/#plugin-usage) 62- Responsive/support for mobile browsers, degrades gracefully with Javascript disabled
61
62### Easy setup
63
64- Dead-simple installation: drop the files, open the page
65- Links are stored in a file (no database required, easy backup: simply copy the datastore file)
66- Import and export links as Netscape bookmarks compatible with most Web browsers
67
68### Accessibility
69
70- Bookmarklet and other tools to share links in one click
71- Support for mobile browsers
72- Degrades gracefully with Javascript disabled
73- Easy page customization through HTML/CSS/RainTPL
74
75### Security
76
77- Discreet pop-up notification when a new release is available
78- Bruteforce protection on the login form
79- Protected against [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) and session cookie hijacking
80 63
81<!-- TODO Limitations -->
82 64
83### REST API 65### Easy setup
84
85- Easily extensible by any client using the REST API exposed by Shaarli ([API documentation](http://shaarli.github.io/api-documentation/)).
86 66
67- Dead-simple [installation](Installation.md): drop the files on your server, open the page
68- Shaares are stored in a file (no database required, easy [backup](Backup-and-restore.md))
69- [Configurable](Shaarli-configuration.md) from dialog and configuration file
70- Extensible through third-party [plugins and themes](Community-and-related-software.md)
87 71
88 72
89## Screenshots 73### Fast
90 74
91[![](https://i.imgur.com/8wEBRSG.png)](https://i.imgur.com/WWPfSj0.png) [![](https://i.imgur.com/rrsjWYy.png)](https://i.imgur.com/TZzGHMs.png) [![](https://i.imgur.com/uICDOle.png)](https://i.imgur.com/27wYsbC.png) [![](https://i.imgur.com/KNvFGVB.png)](https://i.imgur.com/0f5faqw.png) [![](https://i.imgur.com/tVvD3gH.png)](https://i.imgur.com/zGF4d6L.jpg) [![](https://i.imgur.com/8iRzHfe.png)](https://i.imgur.com/sfJJ6NT.png) [![](https://i.imgur.com/GjZGvIh.png)](https://i.imgur.com/QsedIuJ.png) [![](https://i.imgur.com/TFZ9PEq.png)](https://i.imgur.com/KdtF8Ll.png) [![](https://i.imgur.com/IvlqXXK.png)](https://i.imgur.com/boaaibC.png) [![](https://i.imgur.com/nlETouG.png)](https://i.imgur.com/Ib9O7n3.png) 75- Fast! Small datastore file, write-once/read-many, served most of the time from OS disk caches (no disk I/O)
76- Stays fast with even tens of thousands shaares!
92 77
93 78
79### Self-hosted
94 80
81- Shaarli is an alternative to commercial services such as StumbleUpon, Delicio.us, Diigo...
82- The data is yours, [import and export](Usage#import-export) it to HTML bookmarksformat compatible with most web browser, and from a variety of formats
83- Shaarli does not send any telemetry/metrics/private information to developers
84- Shaarli is Free and Open-Source software, inspect and change how the program works in the [source code](https://github.com/shaarli/Shaarli)
85- Built-in [Security](dev/Development.md#security) features to help you protect your Shaarli instance
95 86
96 87
97## About 88## About
98 89
99### Shaarli community fork 90This [community fork](https://github.com/shaarli/Shaarli) of the original [Shaarli](https://github.com/sebsauvage/Shaarli/) project by [Sébastien Sauvage](http://sebsauvage.net/) (now [unmaintained](https://github.com/sebsauvage/Shaarli/issues/191)) has carried on the work to provide [many patches](https://github.com/shaarli/Shaarli/compare/sebsauvage:master...master) for [bug fixes and enhancements](https://github.com/shaarli/Shaarli/issues?q=is%3Aclosed+) in this repository, and will keep maintaining the project for the foreseeable future, while keeping Shaarli simple and efficient.
100
101This friendly fork is maintained by the Shaarli community at <https://github.com/shaarli/Shaarli>
102
103This is a community fork of the original [Shaarli](https://github.com/sebsauvage/Shaarli/) project by [Sébastien Sauvage](http://sebsauvage.net/).
104
105The original project is currently unmaintained, and the developer [has informed us](https://github.com/sebsauvage/Shaarli/issues/191) that he would have no time to work on Shaarli in the near future.
106 91
107The Shaarli community has carried on the work to provide [many 92The original Shaarli instance is still available [here](https://sebsauvage.net/links/) (+25000 shaares!)
108patches](https://github.com/shaarli/Shaarli/compare/sebsauvage:master...master) for
109[bug fixes and enhancements](https://github.com/shaarli/Shaarli/issues?q=is%3Aclosed+)
110in this repository, and will keep maintaining the project for the foreseeable
111future, while keeping Shaarli simple and efficient.
112 93
113 94
114### Contributing and getting help 95### Contributing and getting help
115 96
116Feedback is very appreciated! 97Feedback is very appreciated! Feel free to propose solutions to existing problems, help us improve the documentation and translations, and submit pull requests :-)
117 98
118- If you have any questions or ideas, please join the [chat](https://gitter.im/shaarli/Shaarli) (also reachable via [IRC](https://irc.gitter.im/)), post them in our [general discussion](https://github.com/shaarli/Shaarli/issues/308) or read the current [issues](https://github.com/shaarli/Shaarli/issues). 99See [Support](Troubleshooting.md#support) to get in touch with the Shaarli community.
119- Have a look at the open [issues](https://github.com/shaarli/Shaarli/issues) and [pull requests](https://github.com/shaarli/Shaarli/pulls)
120- If you would like a feature added to Shaarli, check the issues labeled [`feature`](https://github.com/shaarli/Shaarli/labels/feature), [`enhancement`](https://github.com/shaarli/Shaarli/labels/enhancement), and [`plugin`](https://github.com/shaarli/Shaarli/labels/plugin).
121- If you've found a bug, please create a [new issue](https://github.com/shaarli/Shaarli/issues/new).
122- Feel free to propose solutions to existing problems, help us improve the documentation and translations, and submit pull requests :-)
123 100
124 101
125### License 102### License
diff --git a/inc/languages/fr/LC_MESSAGES/shaarli.po b/inc/languages/fr/LC_MESSAGES/shaarli.po
index fbb2fe64..9a6e3958 100644
--- a/inc/languages/fr/LC_MESSAGES/shaarli.po
+++ b/inc/languages/fr/LC_MESSAGES/shaarli.po
@@ -1,8 +1,8 @@
1msgid "" 1msgid ""
2msgstr "" 2msgstr ""
3"Project-Id-Version: Shaarli\n" 3"Project-Id-Version: Shaarli\n"
4"POT-Creation-Date: 2020-08-27 12:01+0200\n" 4"POT-Creation-Date: 2020-09-10 16:06+0200\n"
5"PO-Revision-Date: 2020-08-27 12:02+0200\n" 5"PO-Revision-Date: 2020-09-10 16:07+0200\n"
6"Last-Translator: \n" 6"Last-Translator: \n"
7"Language-Team: Shaarli\n" 7"Language-Team: Shaarli\n"
8"Language: fr_FR\n" 8"Language: fr_FR\n"
@@ -60,16 +60,20 @@ msgid "Automatic"
60msgstr "Automatique" 60msgstr "Automatique"
61 61
62#: application/Languages.php:182 62#: application/Languages.php:182
63msgid "German"
64msgstr "Allemand"
65
66#: application/Languages.php:183
63msgid "English" 67msgid "English"
64msgstr "Anglais" 68msgstr "Anglais"
65 69
66#: application/Languages.php:183 70#: application/Languages.php:184
67msgid "French" 71msgid "French"
68msgstr "Français" 72msgstr "Français"
69 73
70#: application/Languages.php:184 74#: application/Languages.php:185
71msgid "German" 75msgid "Japanese"
72msgstr "Allemand" 76msgstr "Japonais"
73 77
74#: application/Thumbnailer.php:62 78#: application/Thumbnailer.php:62
75msgid "" 79msgid ""
@@ -103,36 +107,119 @@ msgstr "Mo"
103msgid "GiB" 107msgid "GiB"
104msgstr "Go" 108msgstr "Go"
105 109
106#: application/bookmark/BookmarkFileService.php:165 110#: application/bookmark/BookmarkFileService.php:174
107#: application/bookmark/BookmarkFileService.php:190 111#: application/bookmark/BookmarkFileService.php:199
108#: application/bookmark/BookmarkFileService.php:215 112#: application/bookmark/BookmarkFileService.php:224
109#: application/bookmark/BookmarkFileService.php:232 113#: application/bookmark/BookmarkFileService.php:241
110msgid "You're not authorized to alter the datastore" 114msgid "You're not authorized to alter the datastore"
111msgstr "Vous n'êtes pas autorisé à modifier les données" 115msgstr "Vous n'êtes pas autorisé à modifier les données"
112 116
113#: application/bookmark/BookmarkFileService.php:168 117#: application/bookmark/BookmarkFileService.php:177
114#: application/bookmark/BookmarkFileService.php:193 118#: application/bookmark/BookmarkFileService.php:202
115#: application/bookmark/BookmarkFileService.php:235 119#: application/bookmark/BookmarkFileService.php:244
116msgid "Provided data is invalid" 120msgid "Provided data is invalid"
117msgstr "Les informations fournies ne sont pas valides" 121msgstr "Les informations fournies ne sont pas valides"
118 122
119#: application/bookmark/BookmarkFileService.php:196 123#: application/bookmark/BookmarkFileService.php:205
120msgid "This bookmarks already exists" 124msgid "This bookmarks already exists"
121msgstr "Ce marque-page existe déjà." 125msgstr "Ce marque-page existe déjà."
122 126
123#: application/bookmark/BookmarkInitializer.php:37 127#: application/bookmark/BookmarkInitializer.php:37
124#: application/legacy/LegacyLinkDB.php:266 128msgid "(private bookmark with thumbnail demo)"
125msgid "My secret stuff... - Pastebin.com" 129msgstr "(marque page privé avec une miniature)"
126msgstr "Mes trucs secrets... - Pastebin.com"
127 130
128#: application/bookmark/BookmarkInitializer.php:39 131#: application/bookmark/BookmarkInitializer.php:40
129#: application/legacy/LegacyLinkDB.php:268 132msgid ""
130msgid "Shhhh! I'm a private link only YOU can see. You can delete me too." 133"Shaarli will automatically pick up the thumbnail for links to a variety of "
134"websites.\n"
135"\n"
136"Explore your new Shaarli instance by trying out controls and menus.\n"
137"Visit the project on [Github](https://github.com/shaarli/Shaarli) or [the "
138"documentation](https://shaarli.readthedocs.io/en/master/) to learn more "
139"about Shaarli.\n"
140"\n"
141"Now you can edit or delete the default shaares.\n"
131msgstr "" 142msgstr ""
132"Pssst ! Je suis un lien privé que VOUS êtes le seul à voir. Vous pouvez me " 143"Shaarli récupérera automatiquement la miniature associée au liens pour de "
133"supprimer aussi." 144"nombreux sites web.\n"
145"\n"
146"Explorez votre nouvelle instance de Shaarli en essayant les différents "
147"contrôles et menus.\n"
148"Visitez le projet sur [Github](https://github.com/shaarli/Shaarli) ou [la "
149"documentation](https://shaarli.readthedocs.io/en/master/) pour en apprendre "
150"plus sur Shaarli.\n"
151"\n"
152"Maintenant, vous pouvez modifier ou supprimer les shaares créés par défaut.\n"
153
154#: application/bookmark/BookmarkInitializer.php:53
155msgid "Note: Shaare descriptions"
156msgstr "Note : Description des Shaares"
134 157
135#: application/bookmark/BookmarkInitializer.php:45 158#: application/bookmark/BookmarkInitializer.php:55
159msgid ""
160"Adding a shaare without entering a URL creates a text-only \"note\" post "
161"such as this one.\n"
162"This note is private, so you are the only one able to see it while logged "
163"in.\n"
164"\n"
165"You can use this to keep notes, post articles, code snippets, and much "
166"more.\n"
167"\n"
168"The Markdown formatting setting allows you to format your notes and bookmark "
169"description:\n"
170"\n"
171"### Title headings\n"
172"\n"
173"#### Multiple headings levels\n"
174" * bullet lists\n"
175" * _italic_ text\n"
176" * **bold** text\n"
177" * ~~strike through~~ text\n"
178" * `code` blocks\n"
179" * images\n"
180" * [links](https://en.wikipedia.org/wiki/Markdown)\n"
181"\n"
182"Markdown also supports tables:\n"
183"\n"
184"| Name | Type | Color | Qty |\n"
185"| ------- | --------- | ------ | ----- |\n"
186"| Orange | Fruit | Orange | 126 |\n"
187"| Apple | Fruit | Any | 62 |\n"
188"| Lemon | Fruit | Yellow | 30 |\n"
189"| Carrot | Vegetable | Red | 14 |\n"
190msgstr ""
191"Ajouter un shaare sans préciser d'URL créé une « note » textuelle, telle que "
192"celle-ci.\n"
193"Cette note est privée, donc vous êtes seul à pouvoir la voir lorsque vous "
194"êtes connecté.\n"
195"\n"
196"Vous pouvez utiliser cette fonctionnalité pour prendre des notes, publier "
197"des articles, des extraits de code, et bien plus.\n"
198"\n"
199"L'option du formatage par Markdown vous permet de formater vos description "
200"de notes et marque-pages :\n"
201"\n"
202"### Titre d'en-tête\n"
203"\n"
204"#### Sur plusieurs niveaux\n"
205" * liste à puce\n"
206" * texte en _italique_\n"
207" * texte en **gras**\n"
208" * texte ~~barré~~\n"
209" * blocs de `code`\n"
210" * images\n"
211" * [liens](https://en.wikipedia.org/wiki/Markdown)\n"
212"\n"
213"Markdown supporte aussi les tableaux :\n"
214"\n"
215"| Nom | Type | Couleur | Qte |\n"
216"| ------- | --------- | ------ | ----- |\n"
217"| Orange | Fruit | Orange | 126 |\n"
218"| Pomme | Fruit | Multiple | 62 |\n"
219"| Citron | Fruit | Jaune | 30 |\n"
220"| Carotte | Légume | Orange | 14 |\n"
221
222#: application/bookmark/BookmarkInitializer.php:89
136#: application/legacy/LegacyLinkDB.php:246 223#: application/legacy/LegacyLinkDB.php:246
137#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 224#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15
138#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:49 225#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:49
@@ -144,26 +231,54 @@ msgstr ""
144"Le gestionnaire de marque-pages personnel, minimaliste, et sans base de " 231"Le gestionnaire de marque-pages personnel, minimaliste, et sans base de "
145"données" 232"données"
146 233
147#: application/bookmark/BookmarkInitializer.php:48 234#: application/bookmark/BookmarkInitializer.php:92
148#: application/legacy/LegacyLinkDB.php:249
149msgid "" 235msgid ""
150"Welcome to Shaarli! This is your first public bookmark. To edit or delete " 236"Welcome to Shaarli!\n"
151"me, you must first login.\n"
152"\n" 237"\n"
153"To learn how to use Shaarli, consult the link \"Documentation\" at the " 238"Shaarli allows you to bookmark your favorite pages, and share them with "
154"bottom of this page.\n" 239"others or store them privately.\n"
240"You can add a description to your bookmarks, such as this one, and tag "
241"them.\n"
155"\n" 242"\n"
156"You use the community supported version of the original Shaarli project, by " 243"Create a new shaare by clicking the `+Shaare` button, or using any of the "
157"Sebastien Sauvage." 244"recommended tools (browser extension, mobile app, bookmarklet, REST API, "
245"etc.).\n"
246"\n"
247"You can easily retrieve your links, even with thousands of them, using the "
248"internal search engine, or search through tags (e.g. this Shaare is tagged "
249"with `shaarli` and `help`).\n"
250"Hashtags such as #shaarli #help are also supported.\n"
251"You can also filter the available [RSS feed](/feed/atom) and picture wall by "
252"tag or plaintext search.\n"
253"\n"
254"We hope that you will enjoy using Shaarli, maintained with ❤️ by the "
255"community!\n"
256"Feel free to open [an issue](https://github.com/shaarli/Shaarli/issues) if "
257"you have a suggestion or encounter an issue.\n"
158msgstr "" 258msgstr ""
159"Bienvenue sur Shaarli ! Ceci est votre premier marque-page public. Pour me " 259"Bienvenue sur Shaarli !\n"
160"modifier ou me supprimer, vous devez d'abord vous connecter.\n"
161"\n" 260"\n"
162"Pour apprendre à utiliser Shaarli, consultez le lien « Documentation » en " 261"Shaarli vous permet de sauvegarder des marque-pages de vos pages favorites, "
163"bas de page.\n" 262"et de les partager avec d'autres, ou de les enregistrer en privé.\n"
263"Vous pouvez ajouter une description à vos marque-pages, comme celle-ci, et y "
264"ajouter des tags.\n"
164"\n" 265"\n"
165"Vous utilisez la version supportée par la communauté du projet original " 266"Créez un nouveau shaare en cliquant sur le bouton `+Shaare`, ou en utilisant "
166"Shaarli de Sébastien Sauvage." 267"l'un des outils recommandés (extension de navigateur, application mobile, "
268"bookmarklet, REST API, etc.).\n"
269"\n"
270"Vous pouvez facilement retrouver vos liens, même parmi des milliers, en "
271"utilisant le moteur de recherche interne, ou en filtrant par tags (par "
272"exemple ce Shaare est taggé avec `shaarli` et `help`).\n"
273"Les hashtags comme #shaarli #help sont aussi supportés.\n"
274"Vous pouvez aussi filtrer les [flux RSS](/feed/atom) et [mur d'images]() par "
275"tag ou par texte brut.\n"
276"\n"
277"Nous espérons que vous apprécierez utiliser Shaarli, maintenu avec ❤️ par la "
278"communauté !\n"
279"N'hésitez pas à ouvrir [un ticket (en)](https://github.com/shaarli/Shaarli/"
280"issues) si vous avez une suggestion ou si vous rencontrez un problème.\n"
281" \n"
167 282
168#: application/bookmark/exception/BookmarkNotFoundException.php:13 283#: application/bookmark/exception/BookmarkNotFoundException.php:13
169msgid "The link you are trying to reach does not exist or has been deleted." 284msgid "The link you are trying to reach does not exist or has been deleted."
@@ -489,6 +604,36 @@ msgstr "Vous devez utiliser un entier comme clé."
489msgid "Array offset and link ID must be equal." 604msgid "Array offset and link ID must be equal."
490msgstr "La clé du tableau et l'ID du lien doivent être identiques." 605msgstr "La clé du tableau et l'ID du lien doivent être identiques."
491 606
607#: application/legacy/LegacyLinkDB.php:249
608msgid ""
609"Welcome to Shaarli! This is your first public bookmark. To edit or delete "
610"me, you must first login.\n"
611"\n"
612"To learn how to use Shaarli, consult the link \"Documentation\" at the "
613"bottom of this page.\n"
614"\n"
615"You use the community supported version of the original Shaarli project, by "
616"Sebastien Sauvage."
617msgstr ""
618"Bienvenue sur Shaarli ! Ceci est votre premier marque-page public. Pour me "
619"modifier ou me supprimer, vous devez d'abord vous connecter.\n"
620"\n"
621"Pour apprendre à utiliser Shaarli, consultez le lien « Documentation » en "
622"bas de page.\n"
623"\n"
624"Vous utilisez la version supportée par la communauté du projet original "
625"Shaarli de Sébastien Sauvage."
626
627#: application/legacy/LegacyLinkDB.php:266
628msgid "My secret stuff... - Pastebin.com"
629msgstr "Mes trucs secrets... - Pastebin.com"
630
631#: application/legacy/LegacyLinkDB.php:268
632msgid "Shhhh! I'm a private link only YOU can see. You can delete me too."
633msgstr ""
634"Pssst ! Je suis un lien privé que VOUS êtes le seul à voir. Vous pouvez me "
635"supprimer aussi."
636
492#: application/legacy/LegacyUpdater.php:104 637#: application/legacy/LegacyUpdater.php:104
493msgid "Couldn't retrieve updater class methods." 638msgid "Couldn't retrieve updater class methods."
494msgstr "Impossible de récupérer les méthodes de la classe Updater." 639msgstr "Impossible de récupérer les méthodes de la classe Updater."
@@ -562,7 +707,7 @@ msgstr "Voir sur archive.org"
562msgid "For each link, add an Archive.org icon." 707msgid "For each link, add an Archive.org icon."
563msgstr "Pour chaque lien, ajoute une icône pour Archive.org." 708msgstr "Pour chaque lien, ajoute une icône pour Archive.org."
564 709
565#: plugins/default_colors/default_colors.php:33 710#: plugins/default_colors/default_colors.php:38
566msgid "" 711msgid ""
567"Default colors plugin error: This plugin is active and no custom color is " 712"Default colors plugin error: This plugin is active and no custom color is "
568"configured." 713"configured."
@@ -570,21 +715,21 @@ msgstr ""
570"Erreur du plugin default colors : ce plugin est actif et aucune couleur " 715"Erreur du plugin default colors : ce plugin est actif et aucune couleur "
571"n'est configurée." 716"n'est configurée."
572 717
573#: plugins/default_colors/default_colors.php:107 718#: plugins/default_colors/default_colors.php:113
574msgid "Override default theme colors. Use any CSS valid color." 719msgid "Override default theme colors. Use any CSS valid color."
575msgstr "" 720msgstr ""
576"Remplacer les couleurs du thème par défaut. Utiliser n'importe quelle " 721"Remplacer les couleurs du thème par défaut. Utiliser n'importe quelle "
577"couleur CSS valide." 722"couleur CSS valide."
578 723
579#: plugins/default_colors/default_colors.php:108 724#: plugins/default_colors/default_colors.php:114
580msgid "Main color (navbar green)" 725msgid "Main color (navbar green)"
581msgstr "Couleur principale (vert de la barre de navigation)" 726msgstr "Couleur principale (vert de la barre de navigation)"
582 727
583#: plugins/default_colors/default_colors.php:109 728#: plugins/default_colors/default_colors.php:115
584msgid "Background color (light grey)" 729msgid "Background color (light grey)"
585msgstr "Couleur de fond (gris léger)" 730msgstr "Couleur de fond (gris léger)"
586 731
587#: plugins/default_colors/default_colors.php:110 732#: plugins/default_colors/default_colors.php:116
588msgid "Dark main color (e.g. visited links)" 733msgid "Dark main color (e.g. visited links)"
589msgstr "Couleur principale sombre (ex : les liens visités)" 734msgstr "Couleur principale sombre (ex : les liens visités)"
590 735
@@ -1168,23 +1313,23 @@ msgstr "Changer statut épinglé"
1168msgid "Sticky" 1313msgid "Sticky"
1169msgstr "Épinglé" 1314msgstr "Épinglé"
1170 1315
1171#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:7 1316#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:5
1172#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:7 1317#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:5
1173msgid "Filters" 1318msgid "Filters"
1174msgstr "Filtres" 1319msgstr "Filtres"
1175 1320
1176#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:12 1321#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:10
1177#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:12 1322#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:10
1178msgid "Only display private links" 1323msgid "Only display private links"
1179msgstr "Afficher uniquement les liens privés" 1324msgstr "Afficher uniquement les liens privés"
1180 1325
1181#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 1326#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13
1182#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:15 1327#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:13
1183msgid "Only display public links" 1328msgid "Only display public links"
1184msgstr "Afficher uniquement les liens publics" 1329msgstr "Afficher uniquement les liens publics"
1185 1330
1186#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:20 1331#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:18
1187#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:20 1332#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:18
1188msgid "Filter untagged links" 1333msgid "Filter untagged links"
1189msgstr "Filtrer par liens privés" 1334msgstr "Filtrer par liens privés"
1190 1335
@@ -1193,17 +1338,17 @@ msgstr "Filtrer par liens privés"
1193msgid "Select all" 1338msgid "Select all"
1194msgstr "Tout sélectionner" 1339msgstr "Tout sélectionner"
1195 1340
1196#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:27 1341#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29
1197#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:79 1342#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:89
1198#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:27 1343#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:29
1199#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:79 1344#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:89
1200#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 1345#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44
1201#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:44 1346#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:44
1202msgid "Fold all" 1347msgid "Fold all"
1203msgstr "Replier tout" 1348msgstr "Replier tout"
1204 1349
1205#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 1350#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:76
1206#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:72 1351#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:76
1207msgid "Links per page" 1352msgid "Links per page"
1208msgstr "Liens par page" 1353msgstr "Liens par page"
1209 1354
@@ -1429,32 +1574,24 @@ msgid "Rename or delete a tag in all links"
1429msgstr "Renommer ou supprimer un tag dans tous les liens" 1574msgstr "Renommer ou supprimer un tag dans tous les liens"
1430 1575
1431#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 1576#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41
1432#, fuzzy
1433#| msgid ""
1434#| "Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, "
1435#| "delicious…)"
1436msgid "" 1577msgid ""
1437"Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, " 1578"Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, "
1438"delicious...)" 1579"delicious...)"
1439msgstr "" 1580msgstr ""
1440"Importer des marques pages au format Netscape HTML (comme exportés depuis " 1581"Importer des marques pages au format Netscape HTML (comme exportés depuis "
1441"Firefox, Chrome, Opera, delicious)" 1582"Firefox, Chrome, Opera, delicious...)"
1442 1583
1443#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 1584#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42
1444msgid "Import links" 1585msgid "Import links"
1445msgstr "Importer des liens" 1586msgstr "Importer des liens"
1446 1587
1447#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47 1588#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47
1448#, fuzzy
1449#| msgid ""
1450#| "Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, "
1451#| "Opera, delicious…)"
1452msgid "" 1589msgid ""
1453"Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, " 1590"Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, "
1454"Opera, delicious...)" 1591"Opera, delicious...)"
1455msgstr "" 1592msgstr ""
1456"Exporter les marques pages au format Netscape HTML (comme exportés depuis " 1593"Exporter les marques pages au format Netscape HTML (comme exportés depuis "
1457"Firefox, Chrome, Opera, delicious)" 1594"Firefox, Chrome, Opera, delicious...)"
1458 1595
1459#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 1596#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48
1460msgid "Export database" 1597msgid "Export database"
diff --git a/mkdocs.yml b/mkdocs.yml
index cee2c5fb..2e201d03 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -15,41 +15,25 @@ site_dir: doc/html
15pages: 15pages:
16- Home: index.md 16- Home: index.md
17- Setup: 17- Setup:
18 - Download and Installation: Download-and-Installation.md
19 - Upgrade and migration: Upgrade-and-migration.md
20 - Server configuration: Server-configuration.md 18 - Server configuration: Server-configuration.md
21 - Server security: Server-security.md 19 - Installation: Installation.md
20 - Docker: Docker.md
21 - Reverse Proxy: Reverse-proxy.md
22 - Backup and restore: Backup-and-restore.md
22 - Shaarli configuration: Shaarli-configuration.md 23 - Shaarli configuration: Shaarli-configuration.md
23 - Plugins: Plugins.md 24 - Plugins: Plugins.md
24- Docker: 25 - Upgrade and migration: Upgrade-and-migration.md
25 - Docker 101: docker/docker-101.md
26 - Shaarli images: docker/shaarli-images.md
27 - Reverse proxy configuration: docker/reverse-proxy-configuration.md
28 - Docker resources: docker/resources.md
29- Usage: 26- Usage:
30 - Browsing and searching: Browsing-and-searching.md 27 - Usage: Usage.md
31 - Sharing content: Sharing-content.md
32 - RSS feeds: RSS-feeds.md
33 - REST API: REST-API.md 28 - REST API: REST-API.md
34 - Community & Related software: Community-&-Related-software.md 29 - Community and Related software: Community-and-related-software.md
35- Guides:
36 - Install Shaarli on Debian 9 with Docker: guides/install-shaarli-with-debian9-and-docker.md
37 - Backup, restore, import and export: guides/backup-restore-import-export.md
38 - Various hacks: guides/various-hacks.md
39- Development: 30- Development:
40 - Development guidelines: Development-guidelines.md 31 - Development: dev/Development.md
41 - Continuous integration tools: Continuous-integration-tools.md 32 - Versioning: dev/Versioning.md
42 - GnuPG signature: GnuPG-signature.md 33 - GnuPG signature: dev/GnuPG-signature.md
43 - Directory structure: Directory-structure.md 34 - Plugin System: dev/Plugin-system.md
44 - Link Structure: Link-structure.md 35 - Translations: dev/Translations.md
45 - 3rd party libraries: 3rd-party-libraries.md 36 - Release Shaarli: dev/Release-Shaarli.md
46 - Plugin System: Plugin-System.md 37 - Theming: dev/Theming.md
47 - Release Shaarli: Release-Shaarli.md 38 - Unit tests: dev/Unit-tests.md
48 - Versioning and Branches: Versioning-and-Branches.md
49 - Security: Security.md
50 - Static analysis: Static-analysis.md
51 - Translations: Translations.md
52 - Theming: Theming.md
53 - Unit tests: Unit-tests.md
54- FAQ: FAQ.md
55- Troubleshooting: Troubleshooting.md 39- Troubleshooting: Troubleshooting.md
diff --git a/plugins/playvideos/README.md b/plugins/playvideos/README.md
index ab4be22a..32a94e88 100644
--- a/plugins/playvideos/README.md
+++ b/plugins/playvideos/README.md
@@ -8,22 +8,21 @@ This uses code from https://zaius.github.io/youtube_playlist/ and is currently o
8 8
9#### Installation and setup 9#### Installation and setup
10 10
11This is a default Shaarli plugin, you just have to enable it. See https://shaarli.readthedocs.io/en/master/Shaarli-configuration/ 11This is a default Shaarli plugin, you just have to enable it. See [Shaarli configuration](../../doc/md/Shaarli-configuration.md).
12 12
13 13
14#### Troubleshooting 14#### Troubleshooting
15 15
16If your server has [Content Security Policy](http://content-security-policy.com/) headers enabled, this may prevent the script from loading fully. You should relax the CSP in your server settings. Example CSP rule for apache2: 16If your server has [Content Security Policy](http://content-security-policy.com/) headers enabled, this may prevent the script from loading fully. You should relax the CSP in your server settings. Example CSP rule for apache2:
17
18In `/etc/apache2/conf-available/shaarli-csp.conf`:
19 17
20```apache 18```apache
21<Directory /path/to/shaarli> 19<Directory /path/to/shaarli>
20 # Required for playvideos plugin
22 Header set Content-Security-Policy "script-src 'self' 'unsafe-inline' https://www.youtube.com https://s.ytimg.com 'unsafe-eval'" 21 Header set Content-Security-Policy "script-src 'self' 'unsafe-inline' https://www.youtube.com https://s.ytimg.com 'unsafe-eval'"
23</Directory> 22</Directory>
24``` 23```
25 24
26Then run `a2enconf shaarli-csp; service apache2 reload` 25You may place the `Header` directive in the `<Directory...` section of your [webserver configuration](../../doc/md/Server-configuration.md)/virtualhost file, or write the above snippet to `/etc/apache2/conf-available/shaarli-csp.conf`; then run `a2enconf shaarli-csp; service apache2 reload`.
27 26
28### License 27### License
29``` 28```
diff --git a/tests/PluginManagerTest.php b/tests/PluginManagerTest.php
index a5d5dbe9..3018999c 100644
--- a/tests/PluginManagerTest.php
+++ b/tests/PluginManagerTest.php
@@ -41,17 +41,31 @@ class PluginManagerTest extends \PHPUnit\Framework\TestCase
41 41
42 $this->assertTrue(function_exists('hook_test_random')); 42 $this->assertTrue(function_exists('hook_test_random'));
43 43
44 $data = array(0 => 'woot'); 44 $data = [0 => 'woot'];
45 $this->pluginManager->executeHooks('random', $data); 45 $this->pluginManager->executeHooks('random', $data);
46 $this->assertEquals('woot', $data[1]);
47 46
48 $data = array(0 => 'woot'); 47 static::assertCount(2, $data);
48 static::assertSame('woot', $data[1]);
49
50 $data = [0 => 'woot'];
49 $this->pluginManager->executeHooks('random', $data, array('target' => 'test')); 51 $this->pluginManager->executeHooks('random', $data, array('target' => 'test'));
50 $this->assertEquals('page test', $data[1]);
51 52
52 $data = array(0 => 'woot'); 53 static::assertCount(2, $data);
54 static::assertSame('page test', $data[1]);
55
56 $data = [0 => 'woot'];
53 $this->pluginManager->executeHooks('random', $data, array('loggedin' => true)); 57 $this->pluginManager->executeHooks('random', $data, array('loggedin' => true));
54 $this->assertEquals('loggedin', $data[1]); 58
59 static::assertCount(2, $data);
60 static::assertEquals('loggedin', $data[1]);
61
62 $data = [0 => 'woot'];
63 $this->pluginManager->executeHooks('random', $data, array('loggedin' => null));
64
65 static::assertCount(3, $data);
66 static::assertEquals('loggedin', $data[1]);
67 static::assertArrayHasKey(2, $data);
68 static::assertNull($data[2]);
55 } 69 }
56 70
57 /** 71 /**
@@ -78,8 +92,8 @@ class PluginManagerTest extends \PHPUnit\Framework\TestCase
78 */ 92 */
79 public function testPluginNotFound(): void 93 public function testPluginNotFound(): void
80 { 94 {
81 $this->pluginManager->load(array()); 95 $this->pluginManager->load([]);
82 $this->pluginManager->load(array('nope', 'renope')); 96 $this->pluginManager->load(['nope', 'renope']);
83 $this->addToAssertionCount(1); 97 $this->addToAssertionCount(1);
84 } 98 }
85 99
@@ -89,18 +103,18 @@ class PluginManagerTest extends \PHPUnit\Framework\TestCase
89 public function testGetPluginsMeta(): void 103 public function testGetPluginsMeta(): void
90 { 104 {
91 PluginManager::$PLUGINS_PATH = self::$pluginPath; 105 PluginManager::$PLUGINS_PATH = self::$pluginPath;
92 $this->pluginManager->load(array(self::$pluginName)); 106 $this->pluginManager->load([self::$pluginName]);
93 107
94 $expectedParameters = array( 108 $expectedParameters = [
95 'pop' => array( 109 'pop' => [
96 'value' => '', 110 'value' => '',
97 'desc' => 'pop description', 111 'desc' => 'pop description',
98 ), 112 ],
99 'hip' => array( 113 'hip' => [
100 'value' => '', 114 'value' => '',
101 'desc' => '', 115 'desc' => '',
102 ), 116 ],
103 ); 117 ];
104 $meta = $this->pluginManager->getPluginsMeta(); 118 $meta = $this->pluginManager->getPluginsMeta();
105 $this->assertEquals('test plugin', $meta[self::$pluginName]['description']); 119 $this->assertEquals('test plugin', $meta[self::$pluginName]['description']);
106 $this->assertEquals($expectedParameters, $meta[self::$pluginName]['parameters']); 120 $this->assertEquals($expectedParameters, $meta[self::$pluginName]['parameters']);
diff --git a/tests/bookmark/BookmarkFileServiceTest.php b/tests/bookmark/BookmarkFileServiceTest.php
index c59fd443..a4ec1013 100644
--- a/tests/bookmark/BookmarkFileServiceTest.php
+++ b/tests/bookmark/BookmarkFileServiceTest.php
@@ -615,14 +615,18 @@ class BookmarkFileServiceTest extends TestCase
615 { 615 {
616 $dbSize = $this->privateLinkDB->count(); 616 $dbSize = $this->privateLinkDB->count();
617 $this->privateLinkDB->initialize(); 617 $this->privateLinkDB->initialize();
618 $this->assertEquals($dbSize + 2, $this->privateLinkDB->count()); 618 $this->assertEquals($dbSize + 3, $this->privateLinkDB->count());
619 $this->assertEquals( 619 $this->assertStringStartsWith(
620 'My secret stuff... - Pastebin.com', 620 'Shaarli will automatically pick up the thumbnail for links to a variety of websites.',
621 $this->privateLinkDB->get(43)->getTitle() 621 $this->privateLinkDB->get(43)->getDescription()
622 ); 622 );
623 $this->assertEquals( 623 $this->assertStringStartsWith(
624 'The personal, minimalist, super-fast, database free, bookmarking service', 624 'Adding a shaare without entering a URL creates a text-only "note" post such as this one.',
625 $this->privateLinkDB->get(44)->getTitle() 625 $this->privateLinkDB->get(44)->getDescription()
626 );
627 $this->assertStringStartsWith(
628 'Welcome to Shaarli!',
629 $this->privateLinkDB->get(45)->getDescription()
626 ); 630 );
627 } 631 }
628 632
diff --git a/tests/bookmark/BookmarkInitializerTest.php b/tests/bookmark/BookmarkInitializerTest.php
index 3906cc7f..454269bb 100644
--- a/tests/bookmark/BookmarkInitializerTest.php
+++ b/tests/bookmark/BookmarkInitializerTest.php
@@ -37,7 +37,7 @@ class BookmarkInitializerTest extends TestCase
37 /** 37 /**
38 * Initialize an empty BookmarkFileService 38 * Initialize an empty BookmarkFileService
39 */ 39 */
40 public function setUp() 40 public function setUp(): void
41 { 41 {
42 if (file_exists(self::$testDatastore)) { 42 if (file_exists(self::$testDatastore)) {
43 unlink(self::$testDatastore); 43 unlink(self::$testDatastore);
@@ -64,17 +64,26 @@ class BookmarkInitializerTest extends TestCase
64 64
65 $this->initializer->initialize(); 65 $this->initializer->initialize();
66 66
67 $this->assertEquals($refDB->countLinks() + 2, $this->bookmarkService->count()); 67 $this->assertEquals($refDB->countLinks() + 3, $this->bookmarkService->count());
68
68 $bookmark = $this->bookmarkService->get(43); 69 $bookmark = $this->bookmarkService->get(43);
69 $this->assertEquals(43, $bookmark->getId()); 70 $this->assertStringStartsWith(
70 $this->assertEquals('My secret stuff... - Pastebin.com', $bookmark->getTitle()); 71 'Shaarli will automatically pick up the thumbnail for links to a variety of websites.',
72 $bookmark->getDescription()
73 );
71 $this->assertTrue($bookmark->isPrivate()); 74 $this->assertTrue($bookmark->isPrivate());
72 75
73 $bookmark = $this->bookmarkService->get(44); 76 $bookmark = $this->bookmarkService->get(44);
74 $this->assertEquals(44, $bookmark->getId()); 77 $this->assertStringStartsWith(
75 $this->assertEquals( 78 'Adding a shaare without entering a URL creates a text-only "note" post such as this one.',
76 'The personal, minimalist, super-fast, database free, bookmarking service', 79 $bookmark->getDescription()
77 $bookmark->getTitle() 80 );
81 $this->assertTrue($bookmark->isPrivate());
82
83 $bookmark = $this->bookmarkService->get(45);
84 $this->assertStringStartsWith(
85 'Welcome to Shaarli!',
86 $bookmark->getDescription()
78 ); 87 );
79 $this->assertFalse($bookmark->isPrivate()); 88 $this->assertFalse($bookmark->isPrivate());
80 89
@@ -82,17 +91,26 @@ class BookmarkInitializerTest extends TestCase
82 91
83 // Reload from file 92 // Reload from file
84 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true); 93 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true);
85 $this->assertEquals($refDB->countLinks() + 2, $this->bookmarkService->count()); 94 $this->assertEquals($refDB->countLinks() + 3, $this->bookmarkService->count());
95
86 $bookmark = $this->bookmarkService->get(43); 96 $bookmark = $this->bookmarkService->get(43);
87 $this->assertEquals(43, $bookmark->getId()); 97 $this->assertStringStartsWith(
88 $this->assertEquals('My secret stuff... - Pastebin.com', $bookmark->getTitle()); 98 'Shaarli will automatically pick up the thumbnail for links to a variety of websites.',
99 $bookmark->getDescription()
100 );
89 $this->assertTrue($bookmark->isPrivate()); 101 $this->assertTrue($bookmark->isPrivate());
90 102
91 $bookmark = $this->bookmarkService->get(44); 103 $bookmark = $this->bookmarkService->get(44);
92 $this->assertEquals(44, $bookmark->getId()); 104 $this->assertStringStartsWith(
93 $this->assertEquals( 105 'Adding a shaare without entering a URL creates a text-only "note" post such as this one.',
94 'The personal, minimalist, super-fast, database free, bookmarking service', 106 $bookmark->getDescription()
95 $bookmark->getTitle() 107 );
108 $this->assertTrue($bookmark->isPrivate());
109
110 $bookmark = $this->bookmarkService->get(45);
111 $this->assertStringStartsWith(
112 'Welcome to Shaarli!',
113 $bookmark->getDescription()
96 ); 114 );
97 $this->assertFalse($bookmark->isPrivate()); 115 $this->assertFalse($bookmark->isPrivate());
98 } 116 }
@@ -107,17 +125,25 @@ class BookmarkInitializerTest extends TestCase
107 125
108 $this->initializer->initialize(); 126 $this->initializer->initialize();
109 127
110 $this->assertEquals(2, $this->bookmarkService->count()); 128 $this->assertEquals(3, $this->bookmarkService->count());
111 $bookmark = $this->bookmarkService->get(0); 129 $bookmark = $this->bookmarkService->get(0);
112 $this->assertEquals(0, $bookmark->getId()); 130 $this->assertStringStartsWith(
113 $this->assertEquals('My secret stuff... - Pastebin.com', $bookmark->getTitle()); 131 'Shaarli will automatically pick up the thumbnail for links to a variety of websites.',
132 $bookmark->getDescription()
133 );
114 $this->assertTrue($bookmark->isPrivate()); 134 $this->assertTrue($bookmark->isPrivate());
115 135
116 $bookmark = $this->bookmarkService->get(1); 136 $bookmark = $this->bookmarkService->get(1);
117 $this->assertEquals(1, $bookmark->getId()); 137 $this->assertStringStartsWith(
118 $this->assertEquals( 138 'Adding a shaare without entering a URL creates a text-only "note" post such as this one.',
119 'The personal, minimalist, super-fast, database free, bookmarking service', 139 $bookmark->getDescription()
120 $bookmark->getTitle() 140 );
141 $this->assertTrue($bookmark->isPrivate());
142
143 $bookmark = $this->bookmarkService->get(2);
144 $this->assertStringStartsWith(
145 'Welcome to Shaarli!',
146 $bookmark->getDescription()
121 ); 147 );
122 $this->assertFalse($bookmark->isPrivate()); 148 $this->assertFalse($bookmark->isPrivate());
123 } 149 }
diff --git a/tests/front/controller/admin/PluginsControllerTest.php b/tests/front/controller/admin/PluginsControllerTest.php
index 5b59285c..9526474c 100644
--- a/tests/front/controller/admin/PluginsControllerTest.php
+++ b/tests/front/controller/admin/PluginsControllerTest.php
@@ -32,7 +32,7 @@ class PluginsControllerTest extends TestCase
32 array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, static::PLUGIN_NAMES); 32 array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, static::PLUGIN_NAMES);
33 } 33 }
34 34
35 public function tearDown() 35 public function tearDown(): void
36 { 36 {
37 $path = __DIR__ . '/folder'; 37 $path = __DIR__ . '/folder';
38 array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, static::PLUGIN_NAMES); 38 array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, static::PLUGIN_NAMES);
@@ -125,6 +125,7 @@ class PluginsControllerTest extends TestCase
125 'parameters_form' => true, 125 'parameters_form' => true,
126 'parameter1' => 'blip', 126 'parameter1' => 'blip',
127 'parameter2' => 'blop', 127 'parameter2' => 'blop',
128 'token' => 'this parameter should not be saved'
128 ]; 129 ];
129 130
130 $request = $this->createMock(Request::class); 131 $request = $this->createMock(Request::class);
@@ -143,7 +144,7 @@ class PluginsControllerTest extends TestCase
143 ->with('save_plugin_parameters', $parameters) 144 ->with('save_plugin_parameters', $parameters)
144 ; 145 ;
145 $this->container->conf 146 $this->container->conf
146 ->expects(static::atLeastOnce()) 147 ->expects(static::exactly(2))
147 ->method('set') 148 ->method('set')
148 ->withConsecutive(['plugins.parameter1', 'blip'], ['plugins.parameter2', 'blop']) 149 ->withConsecutive(['plugins.parameter1', 'blip'], ['plugins.parameter2', 'blop'])
149 ; 150 ;
diff --git a/tests/plugins/test/test.php b/tests/plugins/test/test.php
index ae5032dd..03be4f4e 100644
--- a/tests/plugins/test/test.php
+++ b/tests/plugins/test/test.php
@@ -13,6 +13,9 @@ function hook_test_random($data)
13 $data[1] = 'page test'; 13 $data[1] = 'page test';
14 } elseif (isset($data['_LOGGEDIN_']) && $data['_LOGGEDIN_'] === true) { 14 } elseif (isset($data['_LOGGEDIN_']) && $data['_LOGGEDIN_'] === true) {
15 $data[1] = 'loggedin'; 15 $data[1] = 'loggedin';
16 } elseif (array_key_exists('_LOGGEDIN_', $data)) {
17 $data[1] = 'loggedin';
18 $data[2] = $data['_LOGGEDIN_'];
16 } else { 19 } else {
17 $data[1] = $data[0]; 20 $data[1] = $data[0];
18 } 21 }