diff options
-rw-r--r-- | application/feed/FeedBuilder.php | 6 | ||||
-rw-r--r-- | application/http/HttpUtils.php | 8 | ||||
-rw-r--r-- | doc/md/Shaarli-configuration.md | 71 | ||||
-rw-r--r-- | index.php | 3 | ||||
-rw-r--r-- | tests/http/HttpUtils/IndexUrlTest.php | 36 | ||||
-rw-r--r-- | tests/http/HttpUtils/IndexUrlTestWithConstant.php | 51 |
6 files changed, 134 insertions, 41 deletions
diff --git a/application/feed/FeedBuilder.php b/application/feed/FeedBuilder.php index 3653c32f..f6def630 100644 --- a/application/feed/FeedBuilder.php +++ b/application/feed/FeedBuilder.php | |||
@@ -122,9 +122,9 @@ class FeedBuilder | |||
122 | $data['language'] = $this->getTypeLanguage($feedType); | 122 | $data['language'] = $this->getTypeLanguage($feedType); |
123 | $data['last_update'] = $this->getLatestDateFormatted($feedType); | 123 | $data['last_update'] = $this->getLatestDateFormatted($feedType); |
124 | $data['show_dates'] = !$this->hideDates || $this->isLoggedIn; | 124 | $data['show_dates'] = !$this->hideDates || $this->isLoggedIn; |
125 | // Remove leading slash from REQUEST_URI. | 125 | // Remove leading path from REQUEST_URI (already contained in $pageaddr). |
126 | $data['self_link'] = escape(server_url($this->serverInfo)) | 126 | $requestUri = preg_replace('#(.*?/)(feed.*)#', '$2', escape($this->serverInfo['REQUEST_URI'])); |
127 | . escape($this->serverInfo['REQUEST_URI']); | 127 | $data['self_link'] = $pageaddr . $requestUri; |
128 | $data['index_url'] = $pageaddr; | 128 | $data['index_url'] = $pageaddr; |
129 | $data['usepermalinks'] = $this->usePermalinks === true; | 129 | $data['usepermalinks'] = $this->usePermalinks === true; |
130 | $data['links'] = $linkDisplayed; | 130 | $data['links'] = $linkDisplayed; |
diff --git a/application/http/HttpUtils.php b/application/http/HttpUtils.php index 4fc4e3dc..9f414073 100644 --- a/application/http/HttpUtils.php +++ b/application/http/HttpUtils.php | |||
@@ -369,7 +369,11 @@ function server_url($server) | |||
369 | */ | 369 | */ |
370 | function index_url($server) | 370 | function index_url($server) |
371 | { | 371 | { |
372 | $scriptname = $server['SCRIPT_NAME'] ?? ''; | 372 | if (defined('SHAARLI_ROOT_URL') && null !== SHAARLI_ROOT_URL) { |
373 | return rtrim(SHAARLI_ROOT_URL, '/') . '/'; | ||
374 | } | ||
375 | |||
376 | $scriptname = !empty($server['SCRIPT_NAME']) ? $server['SCRIPT_NAME'] : '/'; | ||
373 | if (endsWith($scriptname, 'index.php')) { | 377 | if (endsWith($scriptname, 'index.php')) { |
374 | $scriptname = substr($scriptname, 0, -9); | 378 | $scriptname = substr($scriptname, 0, -9); |
375 | } | 379 | } |
@@ -392,7 +396,7 @@ function page_url($server) | |||
392 | $scriptname = substr($scriptname, 0, -9); | 396 | $scriptname = substr($scriptname, 0, -9); |
393 | } | 397 | } |
394 | 398 | ||
395 | $route = ltrim($server['REQUEST_URI'] ?? '', $scriptname); | 399 | $route = preg_replace('@^' . $scriptname . '@', '', $server['REQUEST_URI'] ?? ''); |
396 | if (! empty($server['QUERY_STRING'])) { | 400 | if (! empty($server['QUERY_STRING'])) { |
397 | return index_url($server) . $route . '?' . $server['QUERY_STRING']; | 401 | return index_url($server) . $route . '?' . $server['QUERY_STRING']; |
398 | } | 402 | } |
diff --git a/doc/md/Shaarli-configuration.md b/doc/md/Shaarli-configuration.md index 14eec7b2..263fb761 100644 --- a/doc/md/Shaarli-configuration.md +++ b/doc/md/Shaarli-configuration.md | |||
@@ -7,7 +7,7 @@ Once your Shaarli instance is installed, the file `data/config.json.php` is gene | |||
7 | - its values override those defined in `index.php` | 7 | - its values override those defined in `index.php` |
8 | - it is wrapped in a PHP comment so that its contents are never served by the web server, regardless of configuration | 8 | - it is wrapped in a PHP comment so that its contents are never served by the web server, regardless of configuration |
9 | 9 | ||
10 | **Do not edit configuration options in index.php! Your changes would be lost.** | 10 | **Do not edit configuration options in index.php! Your changes would be lost.** |
11 | 11 | ||
12 | ## Tools menu | 12 | ## Tools menu |
13 | 13 | ||
@@ -135,71 +135,72 @@ Some settings can be configured directly from a web browser by accesing the `Too | |||
135 | ## Settings | 135 | ## Settings |
136 | 136 | ||
137 | ### Credentials | 137 | ### Credentials |
138 | 138 | ||
139 | _These settings should not be edited_ | 139 | _These settings should not be edited_ |
140 | 140 | ||
141 | - **login**: Login username. | 141 | - **login**: Login username. |
142 | - **hash**: Generated password hash. | 142 | - **hash**: Generated password hash. |
143 | - **salt**: Password salt. | 143 | - **salt**: Password salt. |
144 | 144 | ||
145 | ### General | 145 | ### General |
146 | 146 | ||
147 | - **title**: Shaarli's instance title. | 147 | - **title**: Shaarli's instance title. |
148 | - **header_link**: Link to the homepage. | 148 | - **header_link**: Link to the homepage. |
149 | - **links_per_page**: Number of Shaares displayed per page. | 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). | 150 | - **timezone**: See [the list of supported timezones](http://php.net/manual/en/timezones.php). |
151 | - **enabled_plugins**: List of enabled plugins. | 151 | - **enabled_plugins**: List of enabled plugins. |
152 | - **default_note_title**: Default title of a new note. | 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. | 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 | - **root_url**: Overrides automatic discovery of Shaarli instance's URL (e.g.) `https://sub.domain.tld/shaarli-folder/`. | ||
154 | 155 | ||
155 | ### Security | 156 | ### Security |
156 | 157 | ||
157 | - **session_protection_disabled**: Disable session cookie hijacking protection (not recommended). | 158 | - **session_protection_disabled**: Disable session cookie hijacking protection (not recommended). |
158 | It might be useful if your IP adress often changes. | 159 | It might be useful if your IP adress often changes. |
159 | - **ban_after**: Failed login attempts before being IP banned. | 160 | - **ban_after**: Failed login attempts before being IP banned. |
160 | - **ban_duration**: IP ban duration in seconds. | 161 | - **ban_duration**: IP ban duration in seconds. |
161 | - **open_shaarli**: Anyone can add a new Shaare while logged out if enabled. | 162 | - **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 | - **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 | - **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 | ||
165 | ### Resources | 166 | ### Resources |
166 | 167 | ||
167 | - **data_dir**: Data directory. | 168 | - **data_dir**: Data directory. |
168 | - **datastore**: Shaarli's Shaares database file path. | 169 | - **datastore**: Shaarli's Shaares database file path. |
169 | - **history**: Shaarli's operation history file path. | 170 | - **history**: Shaarli's operation history file path. |
170 | - **updates**: File path for the ran updates file. | 171 | - **updates**: File path for the ran updates file. |
171 | - **log**: Log file path. | 172 | - **log**: Log file path. |
172 | - **update_check**: Last update check file path. | 173 | - **update_check**: Last update check file path. |
173 | - **raintpl_tpl**: Templates directory. | 174 | - **raintpl_tpl**: Templates directory. |
174 | - **raintpl_tmp**: Template engine cache directory. | 175 | - **raintpl_tmp**: Template engine cache directory. |
175 | - **thumbnails_cache**: Thumbnails cache directory. | 176 | - **thumbnails_cache**: Thumbnails cache directory. |
176 | - **page_cache**: Shaarli's internal cache directory. | 177 | - **page_cache**: Shaarli's internal cache directory. |
177 | - **ban_file**: Banned IP file path. | 178 | - **ban_file**: Banned IP file path. |
178 | 179 | ||
179 | ### Translation | 180 | ### Translation |
180 | 181 | ||
181 | - **language**: translation language (also see [Translations](Translations)) | 182 | - **language**: translation language (also see [Translations](Translations)) |
182 | - **auto** (default): The translation language is chosen from the browser locale. | 183 | - **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 | It means that the language can be different for 2 different visitors depending on their locale. |
184 | - **en**: Use the English translation. | 185 | - **en**: Use the English translation. |
185 | - **fr**: Use the French translation. | 186 | - **fr**: Use the French translation. |
186 | - **mode**: | 187 | - **mode**: |
187 | - **auto** or **php** (default): Use the PHP implementation of gettext (slower) | 188 | - **auto** or **php** (default): Use the PHP implementation of gettext (slower) |
188 | - **gettext**: Use PHP builtin gettext extension | 189 | - **gettext**: Use PHP builtin gettext extension |
189 | (faster, but requires `php-gettext` to be installed and to reload the web server on update) | 190 | (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. | 191 | - **extension**: Translation extensions for custom themes or plugins. |
191 | Must be an associative array: `translation domain => translation path`. | 192 | Must be an associative array: `translation domain => translation path`. |
192 | 193 | ||
193 | ### Updates | 194 | ### Updates |
194 | 195 | ||
195 | - **check_updates**: Enable or disable update check to the git repository. | 196 | - **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_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 | - **check_updates_interval**: Look for new version every N seconds (default: every day). |
198 | 199 | ||
199 | ### Privacy | 200 | ### Privacy |
200 | 201 | ||
201 | - **default_private_links**: Check the private checkbox by default for every new Shaare. | 202 | - **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 | - **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 | - **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 | - **hide_timestamps**: Timestamps are hidden. |
205 | - **remember_user_default**: Default state of the login page's *remember me* checkbox | 206 | - **remember_user_default**: Default state of the login page's *remember me* checkbox |
@@ -207,14 +208,14 @@ Must be an associative array: `translation domain => translation path`. | |||
207 | 208 | ||
208 | ### Feed | 209 | ### Feed |
209 | 210 | ||
210 | - **rss_permalinks**: Enable this to redirect RSS links to Shaarli's permalinks instead of shaared URL. | 211 | - **rss_permalinks**: Enable this to redirect RSS links to Shaarli's permalinks instead of shaared URL. |
211 | - **show_atom**: Display ATOM feed button. | 212 | - **show_atom**: Display ATOM feed button. |
212 | 213 | ||
213 | ### Thumbnail | 214 | ### Thumbnail |
214 | 215 | ||
215 | - **enable_thumbnails**: Enable or disable thumbnail display. | 216 | - **enable_thumbnails**: Enable or disable thumbnail display. |
216 | - **enable_localcache**: Enable or disable local cache. | 217 | - **enable_localcache**: Enable or disable local cache. |
217 | 218 | ||
218 | ## Plugins configuration | 219 | ## Plugins configuration |
219 | 220 | ||
220 | See [Plugins](Plugins.md) \ No newline at end of file | 221 | See [Plugins](Plugins.md) |
@@ -35,6 +35,9 @@ use Slim\App; | |||
35 | 35 | ||
36 | $conf = new ConfigManager(); | 36 | $conf = new ConfigManager(); |
37 | 37 | ||
38 | // Manually override root URL for complex server configurations | ||
39 | define('SHAARLI_ROOT_URL', $conf->get('general.root_url', null)); | ||
40 | |||
38 | // In dev mode, throw exception on any warning | 41 | // In dev mode, throw exception on any warning |
39 | if ($conf->get('dev.debug', false)) { | 42 | if ($conf->get('dev.debug', false)) { |
40 | // See all errors (for debugging only) | 43 | // See all errors (for debugging only) |
diff --git a/tests/http/HttpUtils/IndexUrlTest.php b/tests/http/HttpUtils/IndexUrlTest.php index 73d33cd4..cce45c51 100644 --- a/tests/http/HttpUtils/IndexUrlTest.php +++ b/tests/http/HttpUtils/IndexUrlTest.php | |||
@@ -5,12 +5,14 @@ | |||
5 | 5 | ||
6 | namespace Shaarli\Http; | 6 | namespace Shaarli\Http; |
7 | 7 | ||
8 | use PHPUnit\Framework\TestCase; | ||
9 | |||
8 | require_once 'application/http/HttpUtils.php'; | 10 | require_once 'application/http/HttpUtils.php'; |
9 | 11 | ||
10 | /** | 12 | /** |
11 | * Unitary tests for index_url() | 13 | * Unitary tests for index_url() |
12 | */ | 14 | */ |
13 | class IndexUrlTest extends \PHPUnit\Framework\TestCase | 15 | class IndexUrlTest extends TestCase |
14 | { | 16 | { |
15 | /** | 17 | /** |
16 | * If on the main page, remove "index.php" from the URL resource | 18 | * If on the main page, remove "index.php" from the URL resource |
@@ -103,4 +105,36 @@ class IndexUrlTest extends \PHPUnit\Framework\TestCase | |||
103 | ) | 105 | ) |
104 | ); | 106 | ); |
105 | } | 107 | } |
108 | |||
109 | /** | ||
110 | * The route is stored in REQUEST_URI and subfolder | ||
111 | */ | ||
112 | public function testPageUrlWithRouteUnderSubfolder() | ||
113 | { | ||
114 | $this->assertEquals( | ||
115 | 'http://host.tld/subfolder/picture-wall', | ||
116 | page_url( | ||
117 | array( | ||
118 | 'HTTPS' => 'Off', | ||
119 | 'SERVER_NAME' => 'host.tld', | ||
120 | 'SERVER_PORT' => '80', | ||
121 | 'SCRIPT_NAME' => '/subfolder/index.php', | ||
122 | 'REQUEST_URI' => '/subfolder/picture-wall', | ||
123 | ) | ||
124 | ) | ||
125 | ); | ||
126 | |||
127 | $this->assertEquals( | ||
128 | 'http://host.tld/subfolder/admin/picture-wall', | ||
129 | page_url( | ||
130 | array( | ||
131 | 'HTTPS' => 'Off', | ||
132 | 'SERVER_NAME' => 'host.tld', | ||
133 | 'SERVER_PORT' => '80', | ||
134 | 'SCRIPT_NAME' => '/subfolder/admin/index.php', | ||
135 | 'REQUEST_URI' => '/subfolder/admin/picture-wall', | ||
136 | ) | ||
137 | ) | ||
138 | ); | ||
139 | } | ||
106 | } | 140 | } |
diff --git a/tests/http/HttpUtils/IndexUrlTestWithConstant.php b/tests/http/HttpUtils/IndexUrlTestWithConstant.php new file mode 100644 index 00000000..15ca3d72 --- /dev/null +++ b/tests/http/HttpUtils/IndexUrlTestWithConstant.php | |||
@@ -0,0 +1,51 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Http; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | |||
9 | /** | ||
10 | * Test index_url with SHAARLI_ROOT_URL defined to override automatic retrieval. | ||
11 | * This should stay in its dedicated class to make sure to not alter other tests of the suite. | ||
12 | */ | ||
13 | class IndexUrlTestWithConstant extends TestCase | ||
14 | { | ||
15 | public static function setUpBeforeClass(): void | ||
16 | { | ||
17 | define('SHAARLI_ROOT_URL', 'http://other-host.tld/subfolder/'); | ||
18 | } | ||
19 | |||
20 | /** | ||
21 | * The route is stored in REQUEST_URI and subfolder | ||
22 | */ | ||
23 | public function testIndexUrlWithConstantDefined() | ||
24 | { | ||
25 | $this->assertEquals( | ||
26 | 'http://other-host.tld/subfolder/', | ||
27 | index_url( | ||
28 | array( | ||
29 | 'HTTPS' => 'Off', | ||
30 | 'SERVER_NAME' => 'host.tld', | ||
31 | 'SERVER_PORT' => '80', | ||
32 | 'SCRIPT_NAME' => '/index.php', | ||
33 | 'REQUEST_URI' => '/picture-wall', | ||
34 | ) | ||
35 | ) | ||
36 | ); | ||
37 | |||
38 | $this->assertEquals( | ||
39 | 'http://other-host.tld/subfolder/', | ||
40 | index_url( | ||
41 | array( | ||
42 | 'HTTPS' => 'Off', | ||
43 | 'SERVER_NAME' => 'host.tld', | ||
44 | 'SERVER_PORT' => '80', | ||
45 | 'SCRIPT_NAME' => '/admin/index.php', | ||
46 | 'REQUEST_URI' => '/admin/picture-wall', | ||
47 | ) | ||
48 | ) | ||
49 | ); | ||
50 | } | ||
51 | } | ||