aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2020-06-13 13:08:01 +0200
committerArthurHoaro <arthur@hoa.ro>2020-07-23 21:19:21 +0200
commit9c75f877935fa6adec951a4d8d32b328aaab314f (patch)
tree1cdd09ddfc00c6cebb92bb2b90381a06fd31246d
parent818b3193ffabec57501e3bdfa997206e3c0671ef (diff)
downloadShaarli-9c75f877935fa6adec951a4d8d32b328aaab314f.tar.gz
Shaarli-9c75f877935fa6adec951a4d8d32b328aaab314f.tar.zst
Shaarli-9c75f877935fa6adec951a4d8d32b328aaab314f.zip
Use multi-level routes for existing controllers instead of 1 level everywhere
Also prefix most admin routes with /admin/
-rw-r--r--application/container/ContainerBuilder.php10
-rw-r--r--application/container/ShaarliContainer.php17
-rw-r--r--application/front/ShaarliMiddleware.php6
-rw-r--r--application/front/controller/admin/ConfigureController.php6
-rw-r--r--application/front/controller/admin/LogoutController.php4
-rw-r--r--application/front/controller/admin/ManageTagController.php10
-rw-r--r--application/front/controller/admin/PasswordController.php4
-rw-r--r--application/front/controller/admin/PostBookmarkController.php17
-rw-r--r--application/front/controller/visitor/LoginController.php2
-rw-r--r--application/front/controller/visitor/ShaarliVisitorController.php13
-rw-r--r--application/front/controller/visitor/TagController.php8
-rw-r--r--assets/default/js/base.js8
-rw-r--r--doc/md/RSS-feeds.md8
-rw-r--r--doc/md/Translations.md12
-rw-r--r--index.php146
-rw-r--r--plugins/pubsubhubbub/pubsubhubbub.php4
-rw-r--r--tests/container/ContainerBuilderTest.php15
-rw-r--r--tests/feed/CachedPageTest.php6
-rw-r--r--tests/front/controller/admin/ConfigureControllerTest.php6
-rw-r--r--tests/front/controller/admin/LogoutControllerTest.php2
-rw-r--r--tests/front/controller/admin/ManageTagControllerTest.php10
-rw-r--r--tests/front/controller/admin/PostBookmarkControllerTest.php6
-rw-r--r--tests/front/controller/visitor/LoginControllerTest.php4
-rw-r--r--tests/front/controller/visitor/TagControllerTest.php8
-rw-r--r--tpl/default/addlink.html2
-rw-r--r--tpl/default/changepassword.html2
-rw-r--r--tpl/default/changetag.html4
-rw-r--r--tpl/default/configure.html2
-rw-r--r--tpl/default/editlink.html4
-rw-r--r--tpl/default/includes.html4
-rw-r--r--tpl/default/linklist.html8
-rw-r--r--tpl/default/opensearch.html4
-rw-r--r--tpl/default/page.header.html10
-rw-r--r--tpl/default/tag.list.html2
-rw-r--r--tpl/default/tag.sort.html6
-rw-r--r--tpl/default/tools.html6
-rw-r--r--tpl/vintage/addlink.html2
-rw-r--r--tpl/vintage/editlink.html2
-rw-r--r--tpl/vintage/includes.html4
-rw-r--r--tpl/vintage/opensearch.html4
-rw-r--r--tpl/vintage/page.header.html14
-rw-r--r--tpl/vintage/tools.html6
42 files changed, 191 insertions, 227 deletions
diff --git a/application/container/ContainerBuilder.php b/application/container/ContainerBuilder.php
index 85126246..72a85710 100644
--- a/application/container/ContainerBuilder.php
+++ b/application/container/ContainerBuilder.php
@@ -38,19 +38,17 @@ class ContainerBuilder
38 /** @var LoginManager */ 38 /** @var LoginManager */
39 protected $login; 39 protected $login;
40 40
41 /** @var string */ 41 /** @var string|null */
42 protected $webPath; 42 protected $basePath = null;
43 43
44 public function __construct( 44 public function __construct(
45 ConfigManager $conf, 45 ConfigManager $conf,
46 SessionManager $session, 46 SessionManager $session,
47 LoginManager $login, 47 LoginManager $login
48 string $webPath
49 ) { 48 ) {
50 $this->conf = $conf; 49 $this->conf = $conf;
51 $this->session = $session; 50 $this->session = $session;
52 $this->login = $login; 51 $this->login = $login;
53 $this->webPath = $webPath;
54 } 52 }
55 53
56 public function build(): ShaarliContainer 54 public function build(): ShaarliContainer
@@ -60,7 +58,7 @@ class ContainerBuilder
60 $container['conf'] = $this->conf; 58 $container['conf'] = $this->conf;
61 $container['sessionManager'] = $this->session; 59 $container['sessionManager'] = $this->session;
62 $container['loginManager'] = $this->login; 60 $container['loginManager'] = $this->login;
63 $container['webPath'] = $this->webPath; 61 $container['basePath'] = $this->basePath;
64 62
65 $container['plugins'] = function (ShaarliContainer $container): PluginManager { 63 $container['plugins'] = function (ShaarliContainer $container): PluginManager {
66 return new PluginManager($container->conf); 64 return new PluginManager($container->conf);
diff --git a/application/container/ShaarliContainer.php b/application/container/ShaarliContainer.php
index a95393cd..4b97aae2 100644
--- a/application/container/ShaarliContainer.php
+++ b/application/container/ShaarliContainer.php
@@ -21,21 +21,20 @@ use Slim\Container;
21/** 21/**
22 * Extension of Slim container to document the injected objects. 22 * Extension of Slim container to document the injected objects.
23 * 23 *
24 * @property mixed[] $environment $_SERVER automatically injected by Slim
25 * @property string $basePath Shaarli's instance base path (e.g. `/shaarli/`) 24 * @property string $basePath Shaarli's instance base path (e.g. `/shaarli/`)
25 * @property BookmarkServiceInterface $bookmarkService
26 * @property ConfigManager $conf 26 * @property ConfigManager $conf
27 * @property SessionManager $sessionManager 27 * @property mixed[] $environment $_SERVER automatically injected by Slim
28 * @property LoginManager $loginManager 28 * @property FeedBuilder $feedBuilder
29 * @property string $webPath 29 * @property FormatterFactory $formatterFactory
30 * @property History $history 30 * @property History $history
31 * @property BookmarkServiceInterface $bookmarkService 31 * @property HttpAccess $httpAccess
32 * @property LoginManager $loginManager
32 * @property PageBuilder $pageBuilder 33 * @property PageBuilder $pageBuilder
33 * @property PluginManager $pluginManager
34 * @property FormatterFactory $formatterFactory
35 * @property PageCacheManager $pageCacheManager 34 * @property PageCacheManager $pageCacheManager
36 * @property FeedBuilder $feedBuilder 35 * @property PluginManager $pluginManager
36 * @property SessionManager $sessionManager
37 * @property Thumbnailer $thumbnailer 37 * @property Thumbnailer $thumbnailer
38 * @property HttpAccess $httpAccess
39 */ 38 */
40class ShaarliContainer extends Container 39class ShaarliContainer extends Container
41{ 40{
diff --git a/application/front/ShaarliMiddleware.php b/application/front/ShaarliMiddleware.php
index 47aa61bb..7ad610c7 100644
--- a/application/front/ShaarliMiddleware.php
+++ b/application/front/ShaarliMiddleware.php
@@ -38,9 +38,9 @@ class ShaarliMiddleware
38 */ 38 */
39 public function __invoke(Request $request, Response $response, callable $next) 39 public function __invoke(Request $request, Response $response, callable $next)
40 { 40 {
41 try { 41 $this->container->basePath = rtrim($request->getUri()->getBasePath(), '/');
42 $this->container->basePath = rtrim($request->getUri()->getBasePath(), '/');
43 42
43 try {
44 $response = $next($request, $response); 44 $response = $next($request, $response);
45 } catch (ShaarliFrontException $e) { 45 } catch (ShaarliFrontException $e) {
46 $this->container->pageBuilder->assign('message', $e->getMessage()); 46 $this->container->pageBuilder->assign('message', $e->getMessage());
@@ -54,7 +54,7 @@ class ShaarliMiddleware
54 $response = $response->withStatus($e->getCode()); 54 $response = $response->withStatus($e->getCode());
55 $response = $response->write($this->container->pageBuilder->render('error')); 55 $response = $response->write($this->container->pageBuilder->render('error'));
56 } catch (UnauthorizedException $e) { 56 } catch (UnauthorizedException $e) {
57 return $response->withRedirect($request->getUri()->getBasePath() . '/login'); 57 return $response->withRedirect($this->container->basePath . '/login');
58 } 58 }
59 59
60 return $response; 60 return $response;
diff --git a/application/front/controller/admin/ConfigureController.php b/application/front/controller/admin/ConfigureController.php
index 5a482d8e..44971c43 100644
--- a/application/front/controller/admin/ConfigureController.php
+++ b/application/front/controller/admin/ConfigureController.php
@@ -19,7 +19,7 @@ use Throwable;
19class ConfigureController extends ShaarliAdminController 19class ConfigureController extends ShaarliAdminController
20{ 20{
21 /** 21 /**
22 * GET /configure - Displays the configuration page 22 * GET /admin/configure - Displays the configuration page
23 */ 23 */
24 public function index(Request $request, Response $response): Response 24 public function index(Request $request, Response $response): Response
25 { 25 {
@@ -56,7 +56,7 @@ class ConfigureController extends ShaarliAdminController
56 } 56 }
57 57
58 /** 58 /**
59 * POST /configure - Update Shaarli's configuration 59 * POST /admin/configure - Update Shaarli's configuration
60 */ 60 */
61 public function save(Request $request, Response $response): Response 61 public function save(Request $request, Response $response): Response
62 { 62 {
@@ -115,6 +115,6 @@ class ConfigureController extends ShaarliAdminController
115 115
116 $this->saveSuccessMessage(t('Configuration was saved.')); 116 $this->saveSuccessMessage(t('Configuration was saved.'));
117 117
118 return $response->withRedirect('./configure'); 118 return $this->redirect($response, '/admin/configure');
119 } 119 }
120} 120}
diff --git a/application/front/controller/admin/LogoutController.php b/application/front/controller/admin/LogoutController.php
index 41e81984..c5984814 100644
--- a/application/front/controller/admin/LogoutController.php
+++ b/application/front/controller/admin/LogoutController.php
@@ -22,8 +22,8 @@ class LogoutController extends ShaarliAdminController
22 $this->container->sessionManager->logout(); 22 $this->container->sessionManager->logout();
23 23
24 // TODO: switch to a simple Cookie manager allowing to check the session, and create mocks. 24 // TODO: switch to a simple Cookie manager allowing to check the session, and create mocks.
25 setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, 'false', 0, $this->container->webPath); 25 setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, 'false', 0, $this->container->basePath . '/');
26 26
27 return $response->withRedirect('./'); 27 return $this->redirect($response, '/');
28 } 28 }
29} 29}
diff --git a/application/front/controller/admin/ManageTagController.php b/application/front/controller/admin/ManageTagController.php
index e015e613..7dab288a 100644
--- a/application/front/controller/admin/ManageTagController.php
+++ b/application/front/controller/admin/ManageTagController.php
@@ -16,7 +16,7 @@ use Slim\Http\Response;
16class ManageTagController extends ShaarliAdminController 16class ManageTagController extends ShaarliAdminController
17{ 17{
18 /** 18 /**
19 * GET /manage-tags - Displays the manage tags page 19 * GET /admin/tags - Displays the manage tags page
20 */ 20 */
21 public function index(Request $request, Response $response): Response 21 public function index(Request $request, Response $response): Response
22 { 22 {
@@ -32,7 +32,7 @@ class ManageTagController extends ShaarliAdminController
32 } 32 }
33 33
34 /** 34 /**
35 * POST /manage-tags - Update or delete provided tag 35 * POST /admin/tags - Update or delete provided tag
36 */ 36 */
37 public function save(Request $request, Response $response): Response 37 public function save(Request $request, Response $response): Response
38 { 38 {
@@ -46,7 +46,7 @@ class ManageTagController extends ShaarliAdminController
46 if (0 === strlen($fromTag) || false === $isDelete && 0 === strlen($toTag)) { 46 if (0 === strlen($fromTag) || false === $isDelete && 0 === strlen($toTag)) {
47 $this->saveWarningMessage(t('Invalid tags provided.')); 47 $this->saveWarningMessage(t('Invalid tags provided.'));
48 48
49 return $response->withRedirect('./manage-tags'); 49 return $this->redirect($response, '/admin/tags');
50 } 50 }
51 51
52 // TODO: move this to bookmark service 52 // TODO: move this to bookmark service
@@ -80,8 +80,8 @@ class ManageTagController extends ShaarliAdminController
80 80
81 $this->saveSuccessMessage($alert); 81 $this->saveSuccessMessage($alert);
82 82
83 $redirect = true === $isDelete ? './manage-tags' : './?searchtags='. urlencode($toTag); 83 $redirect = true === $isDelete ? '/admin/tags' : '/?searchtags='. urlencode($toTag);
84 84
85 return $response->withRedirect($redirect); 85 return $this->redirect($response, $redirect);
86 } 86 }
87} 87}
diff --git a/application/front/controller/admin/PasswordController.php b/application/front/controller/admin/PasswordController.php
index 6e8f0bcb..bcce01a6 100644
--- a/application/front/controller/admin/PasswordController.php
+++ b/application/front/controller/admin/PasswordController.php
@@ -29,7 +29,7 @@ class PasswordController extends ShaarliAdminController
29 } 29 }
30 30
31 /** 31 /**
32 * GET /password - Displays the change password template 32 * GET /admin/password - Displays the change password template
33 */ 33 */
34 public function index(Request $request, Response $response): Response 34 public function index(Request $request, Response $response): Response
35 { 35 {
@@ -37,7 +37,7 @@ class PasswordController extends ShaarliAdminController
37 } 37 }
38 38
39 /** 39 /**
40 * POST /password - Change admin password - existing and new passwords need to be provided. 40 * POST /admin/password - Change admin password - existing and new passwords need to be provided.
41 */ 41 */
42 public function change(Request $request, Response $response): Response 42 public function change(Request $request, Response $response): Response
43 { 43 {
diff --git a/application/front/controller/admin/PostBookmarkController.php b/application/front/controller/admin/PostBookmarkController.php
index dbe570e2..f3ee5dea 100644
--- a/application/front/controller/admin/PostBookmarkController.php
+++ b/application/front/controller/admin/PostBookmarkController.php
@@ -19,7 +19,7 @@ use Slim\Http\Response;
19class PostBookmarkController extends ShaarliAdminController 19class PostBookmarkController extends ShaarliAdminController
20{ 20{
21 /** 21 /**
22 * GET /add-shaare - Displays the form used to create a new bookmark from an URL 22 * GET /admin/add-shaare - Displays the form used to create a new bookmark from an URL
23 */ 23 */
24 public function addShaare(Request $request, Response $response): Response 24 public function addShaare(Request $request, Response $response): Response
25 { 25 {
@@ -32,7 +32,7 @@ class PostBookmarkController extends ShaarliAdminController
32 } 32 }
33 33
34 /** 34 /**
35 * GET /shaare - Displays the bookmark form for creation. 35 * GET /admin/shaare - Displays the bookmark form for creation.
36 * Note that if the URL is found in existing bookmarks, then it will be in edit mode. 36 * Note that if the URL is found in existing bookmarks, then it will be in edit mode.
37 */ 37 */
38 public function displayCreateForm(Request $request, Response $response): Response 38 public function displayCreateForm(Request $request, Response $response): Response
@@ -93,7 +93,7 @@ class PostBookmarkController extends ShaarliAdminController
93 } 93 }
94 94
95 /** 95 /**
96 * GET /shaare-{id} - Displays the bookmark form in edition mode. 96 * GET /admin/shaare/{id} - Displays the bookmark form in edition mode.
97 */ 97 */
98 public function displayEditForm(Request $request, Response $response, array $args): Response 98 public function displayEditForm(Request $request, Response $response, array $args): Response
99 { 99 {
@@ -106,7 +106,7 @@ class PostBookmarkController extends ShaarliAdminController
106 } catch (BookmarkNotFoundException $e) { 106 } catch (BookmarkNotFoundException $e) {
107 $this->saveErrorMessage(t('Bookmark not found')); 107 $this->saveErrorMessage(t('Bookmark not found'));
108 108
109 return $response->withRedirect('./'); 109 return $this->redirect($response, '/');
110 } 110 }
111 111
112 $formatter = $this->container->formatterFactory->getFormatter('raw'); 112 $formatter = $this->container->formatterFactory->getFormatter('raw');
@@ -116,7 +116,7 @@ class PostBookmarkController extends ShaarliAdminController
116 } 116 }
117 117
118 /** 118 /**
119 * POST /shaare 119 * POST /admin/shaare
120 */ 120 */
121 public function save(Request $request, Response $response): Response 121 public function save(Request $request, Response $response): Response
122 { 122 {
@@ -170,11 +170,14 @@ class PostBookmarkController extends ShaarliAdminController
170 ); 170 );
171 } 171 }
172 172
173 /**
174 * GET /admin/shaare/delete
175 */
173 public function deleteBookmark(Request $request, Response $response): Response 176 public function deleteBookmark(Request $request, Response $response): Response
174 { 177 {
175 $this->checkToken($request); 178 $this->checkToken($request);
176 179
177 $ids = escape(trim($request->getParam('lf_linkdate'))); 180 $ids = escape(trim($request->getParam('id')));
178 if (strpos($ids, ' ') !== false) { 181 if (strpos($ids, ' ') !== false) {
179 // multiple, space-separated ids provided 182 // multiple, space-separated ids provided
180 $ids = array_values(array_filter(preg_split('/\s+/', $ids), 'strlen')); 183 $ids = array_values(array_filter(preg_split('/\s+/', $ids), 'strlen'));
@@ -207,7 +210,7 @@ class PostBookmarkController extends ShaarliAdminController
207 } 210 }
208 211
209 // Don't redirect to where we were previously because the datastore has changed. 212 // Don't redirect to where we were previously because the datastore has changed.
210 return $response->withRedirect('./'); 213 return $this->redirect($response, '/');
211 } 214 }
212 215
213 protected function displayForm(array $link, bool $isNew, Request $request, Response $response): Response 216 protected function displayForm(array $link, bool $isNew, Request $request, Response $response): Response
diff --git a/application/front/controller/visitor/LoginController.php b/application/front/controller/visitor/LoginController.php
index 4de2f55d..0db1f463 100644
--- a/application/front/controller/visitor/LoginController.php
+++ b/application/front/controller/visitor/LoginController.php
@@ -23,7 +23,7 @@ class LoginController extends ShaarliVisitorController
23 if ($this->container->loginManager->isLoggedIn() 23 if ($this->container->loginManager->isLoggedIn()
24 || $this->container->conf->get('security.open_shaarli', false) 24 || $this->container->conf->get('security.open_shaarli', false)
25 ) { 25 ) {
26 return $response->withRedirect('./'); 26 return $this->redirect($response, '/');
27 } 27 }
28 28
29 $userCanLogin = $this->container->loginManager->canLogin($request->getServerParams()); 29 $userCanLogin = $this->container->loginManager->canLogin($request->getServerParams());
diff --git a/application/front/controller/visitor/ShaarliVisitorController.php b/application/front/controller/visitor/ShaarliVisitorController.php
index b90b1e8f..b494a8e6 100644
--- a/application/front/controller/visitor/ShaarliVisitorController.php
+++ b/application/front/controller/visitor/ShaarliVisitorController.php
@@ -105,6 +105,19 @@ abstract class ShaarliVisitorController
105 } 105 }
106 106
107 /** 107 /**
108 * Simple helper which prepend the base path to redirect path.
109 *
110 * @param Response $response
111 * @param string $path Absolute path, e.g.: `/`, or `/admin/shaare/123` regardless of install directory
112 *
113 * @return Response updated
114 */
115 protected function redirect(Response $response, string $path): Response
116 {
117 return $response->withRedirect($this->container->basePath . $path);
118 }
119
120 /**
108 * Generates a redirection to the previous page, based on the HTTP_REFERER. 121 * Generates a redirection to the previous page, based on the HTTP_REFERER.
109 * It fails back to the home page. 122 * It fails back to the home page.
110 * 123 *
diff --git a/application/front/controller/visitor/TagController.php b/application/front/controller/visitor/TagController.php
index a0bc1d1b..c176f43f 100644
--- a/application/front/controller/visitor/TagController.php
+++ b/application/front/controller/visitor/TagController.php
@@ -11,6 +11,8 @@ use Slim\Http\Response;
11 * Class TagController 11 * Class TagController
12 * 12 *
13 * Slim controller handle tags. 13 * Slim controller handle tags.
14 *
15 * TODO: check redirections with new helper
14 */ 16 */
15class TagController extends ShaarliVisitorController 17class TagController extends ShaarliVisitorController
16{ 18{
@@ -27,10 +29,10 @@ class TagController extends ShaarliVisitorController
27 // In case browser does not send HTTP_REFERER, we search a single tag 29 // In case browser does not send HTTP_REFERER, we search a single tag
28 if (null === $referer) { 30 if (null === $referer) {
29 if (null !== $newTag) { 31 if (null !== $newTag) {
30 return $response->withRedirect('./?searchtags='. urlencode($newTag)); 32 return $this->redirect($response, '/?searchtags='. urlencode($newTag));
31 } 33 }
32 34
33 return $response->withRedirect('./'); 35 return $this->redirect($response, '/');
34 } 36 }
35 37
36 $currentUrl = parse_url($referer); 38 $currentUrl = parse_url($referer);
@@ -81,7 +83,7 @@ class TagController extends ShaarliVisitorController
81 83
82 // If the referrer is not provided, we can update the search, so we failback on the bookmark list 84 // If the referrer is not provided, we can update the search, so we failback on the bookmark list
83 if (empty($referer)) { 85 if (empty($referer)) {
84 return $response->withRedirect('./'); 86 return $this->redirect($response, '/');
85 } 87 }
86 88
87 $tagToRemove = $args['tag'] ?? null; 89 $tagToRemove = $args['tag'] ?? null;
diff --git a/assets/default/js/base.js b/assets/default/js/base.js
index b428a420..9f67d980 100644
--- a/assets/default/js/base.js
+++ b/assets/default/js/base.js
@@ -463,7 +463,7 @@ function init(description) {
463 }); 463 });
464 464
465 if (window.confirm(message)) { 465 if (window.confirm(message)) {
466 window.location = `${basePath}/?delete_link&lf_linkdate=${ids.join('+')}&token=${token.value}`; 466 window.location = `${basePath}/admin/shaare/delete?id=${ids.join('+')}&token=${token.value}`;
467 } 467 }
468 }); 468 });
469 } 469 }
@@ -549,7 +549,7 @@ function init(description) {
549 const refreshedToken = document.getElementById('token').value; 549 const refreshedToken = document.getElementById('token').value;
550 const fromtag = block.getAttribute('data-tag'); 550 const fromtag = block.getAttribute('data-tag');
551 const xhr = new XMLHttpRequest(); 551 const xhr = new XMLHttpRequest();
552 xhr.open('POST', `${basePath}/manage-tags`); 552 xhr.open('POST', `${basePath}/admin/tags`);
553 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 553 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
554 xhr.onload = () => { 554 xhr.onload = () => {
555 if (xhr.status !== 200) { 555 if (xhr.status !== 200) {
@@ -566,7 +566,7 @@ function init(description) {
566 .setAttribute('href', `${basePath}/?searchtags=${encodeURIComponent(totag)}`); 566 .setAttribute('href', `${basePath}/?searchtags=${encodeURIComponent(totag)}`);
567 block 567 block
568 .querySelector('a.rename-tag') 568 .querySelector('a.rename-tag')
569 .setAttribute('href', `${basePath}/manage-tags?fromtag=${encodeURIComponent(totag)}`); 569 .setAttribute('href', `${basePath}/admin/tags?fromtag=${encodeURIComponent(totag)}`);
570 570
571 // Refresh awesomplete values 571 // Refresh awesomplete values
572 existingTags = existingTags.map(tag => (tag === fromtag ? totag : tag)); 572 existingTags = existingTags.map(tag => (tag === fromtag ? totag : tag));
@@ -600,7 +600,7 @@ function init(description) {
600 600
601 if (confirm(`Are you sure you want to delete the tag "${tag}"?`)) { 601 if (confirm(`Are you sure you want to delete the tag "${tag}"?`)) {
602 const xhr = new XMLHttpRequest(); 602 const xhr = new XMLHttpRequest();
603 xhr.open('POST', `${basePath}/manage-tags`); 603 xhr.open('POST', `${basePath}/admin/tags`);
604 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 604 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
605 xhr.onload = () => { 605 xhr.onload = () => {
606 block.remove(); 606 block.remove();
diff --git a/doc/md/RSS-feeds.md b/doc/md/RSS-feeds.md
index cdfb8c78..ecbff09a 100644
--- a/doc/md/RSS-feeds.md
+++ b/doc/md/RSS-feeds.md
@@ -1,14 +1,14 @@
1### Feeds options 1### Feeds options
2 2
3Feeds are available in ATOM with `/feed-atom` and RSS with `/feed-rss`. 3Feeds are available in ATOM with `/feed/atom` and RSS with `/feed/rss`.
4 4
5Options: 5Options:
6 6
7- You can use `permalinks` in the feed URL to get permalink to Shaares instead of direct link to shaared URL. 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`. 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. 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` 10 - `https://my.shaarli.domain/feed/atom?permalinks&nb=42`
11 - `https://my.shaarli.domain/feed-atom?permalinks&nb=all` 11 - `https://my.shaarli.domain/feed/atom?permalinks&nb=all`
12 12
13### RSS Feeds or Picture Wall for a specific search/tag 13### RSS Feeds or Picture Wall for a specific search/tag
14 14
diff --git a/doc/md/Translations.md b/doc/md/Translations.md
index 5c775d30..75eeed7d 100644
--- a/doc/md/Translations.md
+++ b/doc/md/Translations.md
@@ -32,11 +32,11 @@ Here is a list :
32``` 32```
33http://<replace_domain>/ 33http://<replace_domain>/
34http://<replace_domain>/?nonope 34http://<replace_domain>/?nonope
35http://<replace_domain>/add-shaare 35http://<replace_domain>/admin/add-shaare
36http://<replace_domain>/?do=changepasswd 36http://<replace_domain>/admin/password
37http://<replace_domain>/?do=changetag 37http://<replace_domain>/?do=changetag
38http://<replace_domain>/configure 38http://<replace_domain>/admin/configure
39http://<replace_domain>/tools 39http://<replace_domain>/admin/tools
40http://<replace_domain>/daily 40http://<replace_domain>/daily
41http://<replace_domain>/?post 41http://<replace_domain>/?post
42http://<replace_domain>/?do=export 42http://<replace_domain>/?do=export
@@ -44,8 +44,8 @@ http://<replace_domain>/?do=import
44http://<replace_domain>/login 44http://<replace_domain>/login
45http://<replace_domain>/picture-wall 45http://<replace_domain>/picture-wall
46http://<replace_domain>/?do=pluginadmin 46http://<replace_domain>/?do=pluginadmin
47http://<replace_domain>/tag-cloud 47http://<replace_domain>/tags/cloud
48http://<replace_domain>/tag-list 48http://<replace_domain>/tags/list
49``` 49```
50 50
51#### Improve existing translation 51#### Improve existing translation
diff --git a/index.php b/index.php
index fb528eeb..aa358da0 100644
--- a/index.php
+++ b/index.php
@@ -412,13 +412,13 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM
412 412
413 // -------- Tag cloud 413 // -------- Tag cloud
414 if ($targetPage == Router::$PAGE_TAGCLOUD) { 414 if ($targetPage == Router::$PAGE_TAGCLOUD) {
415 header('Location: ./tag-cloud'); 415 header('Location: ./tags/cloud');
416 exit; 416 exit;
417 } 417 }
418 418
419 // -------- Tag list 419 // -------- Tag list
420 if ($targetPage == Router::$PAGE_TAGLIST) { 420 if ($targetPage == Router::$PAGE_TAGLIST) {
421 header('Location: ./tag-list'); 421 header('Location: ./tags/list');
422 exit; 422 exit;
423 } 423 }
424 424
@@ -433,7 +433,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM
433 if ($targetPage == Router::$PAGE_FEED_ATOM || $targetPage == Router::$PAGE_FEED_RSS) { 433 if ($targetPage == Router::$PAGE_FEED_ATOM || $targetPage == Router::$PAGE_FEED_RSS) {
434 $feedType = $targetPage == Router::$PAGE_FEED_RSS ? FeedBuilder::$FEED_RSS : FeedBuilder::$FEED_ATOM; 434 $feedType = $targetPage == Router::$PAGE_FEED_RSS ? FeedBuilder::$FEED_RSS : FeedBuilder::$FEED_ATOM;
435 435
436 header('Location: ./feed-'. $feedType .'?'. http_build_query($_GET)); 436 header('Location: ./feed/'. $feedType .'?'. http_build_query($_GET));
437 exit; 437 exit;
438 } 438 }
439 439
@@ -501,31 +501,31 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM
501 501
502 // -------- Display the Tools menu if requested (import/export/bookmarklet...) 502 // -------- Display the Tools menu if requested (import/export/bookmarklet...)
503 if ($targetPage == Router::$PAGE_TOOLS) { 503 if ($targetPage == Router::$PAGE_TOOLS) {
504 header('Location: ./tools'); 504 header('Location: ./admin/tools');
505 exit; 505 exit;
506 } 506 }
507 507
508 // -------- User wants to change his/her password. 508 // -------- User wants to change his/her password.
509 if ($targetPage == Router::$PAGE_CHANGEPASSWORD) { 509 if ($targetPage == Router::$PAGE_CHANGEPASSWORD) {
510 header('Location: ./password'); 510 header('Location: ./admin/password');
511 exit; 511 exit;
512 } 512 }
513 513
514 // -------- User wants to change configuration 514 // -------- User wants to change configuration
515 if ($targetPage == Router::$PAGE_CONFIGURE) { 515 if ($targetPage == Router::$PAGE_CONFIGURE) {
516 header('Location: ./configure'); 516 header('Location: ./admin/configure');
517 exit; 517 exit;
518 } 518 }
519 519
520 // -------- User wants to rename a tag or delete it 520 // -------- User wants to rename a tag or delete it
521 if ($targetPage == Router::$PAGE_CHANGETAG) { 521 if ($targetPage == Router::$PAGE_CHANGETAG) {
522 header('Location: ./manage-tags'); 522 header('Location: ./admin/tags');
523 exit; 523 exit;
524 } 524 }
525 525
526 // -------- User wants to add a link without using the bookmarklet: Show form. 526 // -------- User wants to add a link without using the bookmarklet: Show form.
527 if ($targetPage == Router::$PAGE_ADDLINK) { 527 if ($targetPage == Router::$PAGE_ADDLINK) {
528 header('Location: ./shaare'); 528 header('Location: ./admin/shaare');
529 exit; 529 exit;
530 } 530 }
531 531
@@ -538,56 +538,10 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM
538 538
539 // -------- User clicked the "Delete" button when editing a link: Delete link from database. 539 // -------- User clicked the "Delete" button when editing a link: Delete link from database.
540 if ($targetPage == Router::$PAGE_DELETELINK) { 540 if ($targetPage == Router::$PAGE_DELETELINK) {
541 if (! $sessionManager->checkToken($_GET['token'])) { 541 $ids = $_GET['lf_linkdate'] ?? '';
542 die(t('Wrong token.')); 542 $token = $_GET['token'] ?? '';
543 }
544
545 $ids = trim($_GET['lf_linkdate']);
546 if (strpos($ids, ' ') !== false) {
547 // multiple, space-separated ids provided
548 $ids = array_values(array_filter(
549 preg_split('/\s+/', escape($ids)),
550 function ($item) {
551 return $item !== '';
552 }
553 ));
554 } else {
555 // only a single id provided
556 $shortUrl = $bookmarkService->get($ids)->getShortUrl();
557 $ids = [$ids];
558 }
559 // assert at least one id is given
560 if (!count($ids)) {
561 die('no id provided');
562 }
563 $factory = new FormatterFactory($conf, $loginManager->isLoggedIn());
564 $formatter = $factory->getFormatter('raw');
565 foreach ($ids as $id) {
566 $id = (int) escape($id);
567 $bookmark = $bookmarkService->get($id);
568 $data = $formatter->format($bookmark);
569 $pluginManager->executeHooks('delete_link', $data);
570 $bookmarkService->remove($bookmark, false);
571 }
572 $bookmarkService->save();
573
574 // If we are called from the bookmarklet, we must close the popup:
575 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) {
576 echo '<script>self.close();</script>';
577 exit;
578 }
579 543
580 $location = '?'; 544 header('Location: ./admin/shaare/delete?id=' . $ids . '&token=' . $token);
581 if (isset($_SERVER['HTTP_REFERER'])) {
582 // Don't redirect to where we were previously if it was a permalink or an edit_link, because it would 404.
583 $location = generateLocation(
584 $_SERVER['HTTP_REFERER'],
585 $_SERVER['HTTP_HOST'],
586 ['delete_link', 'edit_link', ! empty($shortUrl) ? $shortUrl : null]
587 );
588 }
589
590 header('Location: ' . $location); // After deleting the link, redirect to appropriate location
591 exit; 545 exit;
592 } 546 }
593 547
@@ -646,13 +600,13 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM
646 // -------- User clicked the "EDIT" button on a link: Display link edit form. 600 // -------- User clicked the "EDIT" button on a link: Display link edit form.
647 if (isset($_GET['edit_link'])) { 601 if (isset($_GET['edit_link'])) {
648 $id = (int) escape($_GET['edit_link']); 602 $id = (int) escape($_GET['edit_link']);
649 header('Location: ./shaare-' . $id); 603 header('Location: ./admin/shaare/' . $id);
650 exit; 604 exit;
651 } 605 }
652 606
653 // -------- User want to post a new link: Display link edit form. 607 // -------- User want to post a new link: Display link edit form.
654 if (isset($_GET['post'])) { 608 if (isset($_GET['post'])) {
655 header('Location: ./shaare?' . http_build_query($_GET)); 609 header('Location: ./admin/shaare?' . http_build_query($_GET));
656 exit; 610 exit;
657 } 611 }
658 612
@@ -1160,7 +1114,7 @@ if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=
1160 exit; 1114 exit;
1161} 1115}
1162 1116
1163$containerBuilder = new ContainerBuilder($conf, $sessionManager, $loginManager, WEB_PATH); 1117$containerBuilder = new ContainerBuilder($conf, $sessionManager, $loginManager);
1164$container = $containerBuilder->build(); 1118$container = $containerBuilder->build();
1165$app = new App($container); 1119$app = new App($container);
1166 1120
@@ -1183,51 +1137,37 @@ $app->group('/api/v1', function () {
1183 1137
1184$app->group('', function () { 1138$app->group('', function () {
1185 /* -- PUBLIC --*/ 1139 /* -- PUBLIC --*/
1186 $this->get('/login', '\Shaarli\Front\Controller\Visitor\LoginController:index')->setName('login'); 1140 $this->get('/login', '\Shaarli\Front\Controller\Visitor\LoginController:index');
1187 $this->get('/picture-wall', '\Shaarli\Front\Controller\Visitor\PictureWallController:index')->setName('picwall'); 1141 $this->get('/picture-wall', '\Shaarli\Front\Controller\Visitor\PictureWallController:index');
1188 $this->get('/tag-cloud', '\Shaarli\Front\Controller\Visitor\TagCloudController:cloud')->setName('tagcloud'); 1142 $this->get('/tags/cloud', '\Shaarli\Front\Controller\Visitor\TagCloudController:cloud');
1189 $this->get('/tag-list', '\Shaarli\Front\Controller\Visitor\TagCloudController:list')->setName('taglist'); 1143 $this->get('/tags/list', '\Shaarli\Front\Controller\Visitor\TagCloudController:list');
1190 $this->get('/daily', '\Shaarli\Front\Controller\Visitor\DailyController:index')->setName('daily'); 1144 $this->get('/daily', '\Shaarli\Front\Controller\Visitor\DailyController:index');
1191 $this->get('/daily-rss', '\Shaarli\Front\Controller\Visitor\DailyController:rss')->setName('dailyrss'); 1145 $this->get('/daily-rss', '\Shaarli\Front\Controller\Visitor\DailyController:rss');
1192 $this->get('/feed-atom', '\Shaarli\Front\Controller\Visitor\FeedController:atom')->setName('feedatom'); 1146 $this->get('/feed/atom', '\Shaarli\Front\Controller\Visitor\FeedController:atom');
1193 $this->get('/feed-rss', '\Shaarli\Front\Controller\Visitor\FeedController:rss')->setName('feedrss'); 1147 $this->get('/feed/rss', '\Shaarli\Front\Controller\Visitor\FeedController:rss');
1194 $this->get('/open-search', '\Shaarli\Front\Controller\Visitor\OpenSearchController:index')->setName('opensearch'); 1148 $this->get('/open-search', '\Shaarli\Front\Controller\Visitor\OpenSearchController:index');
1195 1149
1196 $this->get('/add-tag/{newTag}', '\Shaarli\Front\Controller\Visitor\TagController:addTag')->setName('add-tag'); 1150 $this->get('/add-tag/{newTag}', '\Shaarli\Front\Controller\Visitor\TagController:addTag');
1197 $this->get('/remove-tag/{tag}', '\Shaarli\Front\Controller\Visitor\TagController:removeTag')->setName('remove-tag'); 1151 $this->get('/remove-tag/{tag}', '\Shaarli\Front\Controller\Visitor\TagController:removeTag');
1198 1152
1199 /* -- LOGGED IN -- */ 1153 /* -- LOGGED IN -- */
1200 $this->get('/logout', '\Shaarli\Front\Controller\Admin\LogoutController:index')->setName('logout'); 1154 $this->get('/logout', '\Shaarli\Front\Controller\Admin\LogoutController:index');
1201 $this->get('/tools', '\Shaarli\Front\Controller\Admin\ToolsController:index')->setName('tools'); 1155 $this->get('/admin/tools', '\Shaarli\Front\Controller\Admin\ToolsController:index');
1202 $this->get('/password', '\Shaarli\Front\Controller\Admin\PasswordController:index')->setName('password'); 1156 $this->get('/admin/password', '\Shaarli\Front\Controller\Admin\PasswordController:index');
1203 $this->post('/password', '\Shaarli\Front\Controller\Admin\PasswordController:change')->setName('changePassword'); 1157 $this->post('/admin/password', '\Shaarli\Front\Controller\Admin\PasswordController:change');
1204 $this->get('/configure', '\Shaarli\Front\Controller\Admin\ConfigureController:index')->setName('configure'); 1158 $this->get('/admin/configure', '\Shaarli\Front\Controller\Admin\ConfigureController:index');
1205 $this->post('/configure', '\Shaarli\Front\Controller\Admin\ConfigureController:save')->setName('saveConfigure'); 1159 $this->post('/admin/configure', '\Shaarli\Front\Controller\Admin\ConfigureController:save');
1206 $this->get('/manage-tags', '\Shaarli\Front\Controller\Admin\ManageTagController:index')->setName('manageTag'); 1160 $this->get('/admin/tags', '\Shaarli\Front\Controller\Admin\ManageTagController:index');
1207 $this->post('/manage-tags', '\Shaarli\Front\Controller\Admin\ManageTagController:save')->setName('saveManageTag'); 1161 $this->post('/admin/tags', '\Shaarli\Front\Controller\Admin\ManageTagController:save');
1208 $this->get('/add-shaare', '\Shaarli\Front\Controller\Admin\PostBookmarkController:addShaare')->setName('addShaare'); 1162 $this->get('/admin/add-shaare', '\Shaarli\Front\Controller\Admin\PostBookmarkController:addShaare');
1209 $this 1163 $this->get('/admin/shaare', '\Shaarli\Front\Controller\Admin\PostBookmarkController:displayCreateForm');
1210 ->get('/shaare', '\Shaarli\Front\Controller\Admin\PostBookmarkController:displayCreateForm') 1164 $this->get('/admin/shaare/{id:[0-9]+}', '\Shaarli\Front\Controller\Admin\PostBookmarkController:displayEditForm');
1211 ->setName('newShaare'); 1165 $this->post('/admin/shaare', '\Shaarli\Front\Controller\Admin\PostBookmarkController:save');
1212 $this 1166 $this->get('/admin/shaare/delete', '\Shaarli\Front\Controller\Admin\PostBookmarkController:deleteBookmark');
1213 ->get('/shaare-{id}', '\Shaarli\Front\Controller\Admin\PostBookmarkController:displayEditForm') 1167
1214 ->setName('editShaare'); 1168 $this->get('/links-per-page', '\Shaarli\Front\Controller\Admin\SessionFilterController:linksPerPage');
1215 $this 1169 $this->get('/visibility/{visibility}', '\Shaarli\Front\Controller\Admin\SessionFilterController:visibility');
1216 ->post('/shaare', '\Shaarli\Front\Controller\Admin\PostBookmarkController:save') 1170 $this->get('/untagged-only', '\Shaarli\Front\Controller\Admin\SessionFilterController:untaggedOnly');
1217 ->setName('saveShaare');
1218 $this
1219 ->get('/delete-shaare', '\Shaarli\Front\Controller\Admin\PostBookmarkController:deleteBookmark')
1220 ->setName('deleteShaare');
1221
1222 $this
1223 ->get('/links-per-page', '\Shaarli\Front\Controller\Admin\SessionFilterController:linksPerPage')
1224 ->setName('filter-links-per-page');
1225 $this
1226 ->get('/visibility/{visibility}', '\Shaarli\Front\Controller\Admin\SessionFilterController:visibility')
1227 ->setName('visibility');
1228 $this
1229 ->get('/untagged-only', '\Shaarli\Front\Controller\Admin\SessionFilterController:untaggedOnly')
1230 ->setName('untagged-only');
1231})->add('\Shaarli\Front\ShaarliMiddleware'); 1171})->add('\Shaarli\Front\ShaarliMiddleware');
1232 1172
1233$response = $app->run(true); 1173$response = $app->run(true);
diff --git a/plugins/pubsubhubbub/pubsubhubbub.php b/plugins/pubsubhubbub/pubsubhubbub.php
index 41634dda..170f3494 100644
--- a/plugins/pubsubhubbub/pubsubhubbub.php
+++ b/plugins/pubsubhubbub/pubsubhubbub.php
@@ -60,8 +60,8 @@ function hook_pubsubhubbub_render_feed($data, $conf)
60function hook_pubsubhubbub_save_link($data, $conf) 60function hook_pubsubhubbub_save_link($data, $conf)
61{ 61{
62 $feeds = array( 62 $feeds = array(
63 index_url($_SERVER) .'feed-atom', 63 index_url($_SERVER) .'feed/atom',
64 index_url($_SERVER) .'feed-rss', 64 index_url($_SERVER) .'feed/rss',
65 ); 65 );
66 66
67 $httpPost = function_exists('curl_version') ? false : 'nocurl_http_post'; 67 $httpPost = function_exists('curl_version') ? false : 'nocurl_http_post';
diff --git a/tests/container/ContainerBuilderTest.php b/tests/container/ContainerBuilderTest.php
index 65647249..db533f37 100644
--- a/tests/container/ContainerBuilderTest.php
+++ b/tests/container/ContainerBuilderTest.php
@@ -7,12 +7,16 @@ namespace Shaarli\Container;
7use PHPUnit\Framework\TestCase; 7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\BookmarkServiceInterface; 8use Shaarli\Bookmark\BookmarkServiceInterface;
9use Shaarli\Config\ConfigManager; 9use Shaarli\Config\ConfigManager;
10use Shaarli\Feed\FeedBuilder;
10use Shaarli\Formatter\FormatterFactory; 11use Shaarli\Formatter\FormatterFactory;
11use Shaarli\History; 12use Shaarli\History;
13use Shaarli\Http\HttpAccess;
14use Shaarli\Plugin\PluginManager;
12use Shaarli\Render\PageBuilder; 15use Shaarli\Render\PageBuilder;
13use Shaarli\Render\PageCacheManager; 16use Shaarli\Render\PageCacheManager;
14use Shaarli\Security\LoginManager; 17use Shaarli\Security\LoginManager;
15use Shaarli\Security\SessionManager; 18use Shaarli\Security\SessionManager;
19use Shaarli\Thumbnailer;
16 20
17class ContainerBuilderTest extends TestCase 21class ContainerBuilderTest extends TestCase
18{ 22{
@@ -39,8 +43,7 @@ class ContainerBuilderTest extends TestCase
39 $this->containerBuilder = new ContainerBuilder( 43 $this->containerBuilder = new ContainerBuilder(
40 $this->conf, 44 $this->conf,
41 $this->sessionManager, 45 $this->sessionManager,
42 $this->loginManager, 46 $this->loginManager
43 'UT web path'
44 ); 47 );
45 } 48 }
46 49
@@ -51,11 +54,17 @@ class ContainerBuilderTest extends TestCase
51 static::assertInstanceOf(ConfigManager::class, $container->conf); 54 static::assertInstanceOf(ConfigManager::class, $container->conf);
52 static::assertInstanceOf(SessionManager::class, $container->sessionManager); 55 static::assertInstanceOf(SessionManager::class, $container->sessionManager);
53 static::assertInstanceOf(LoginManager::class, $container->loginManager); 56 static::assertInstanceOf(LoginManager::class, $container->loginManager);
54 static::assertSame('UT web path', $container->webPath);
55 static::assertInstanceOf(History::class, $container->history); 57 static::assertInstanceOf(History::class, $container->history);
56 static::assertInstanceOf(BookmarkServiceInterface::class, $container->bookmarkService); 58 static::assertInstanceOf(BookmarkServiceInterface::class, $container->bookmarkService);
57 static::assertInstanceOf(PageBuilder::class, $container->pageBuilder); 59 static::assertInstanceOf(PageBuilder::class, $container->pageBuilder);
60 static::assertInstanceOf(PluginManager::class, $container->pluginManager);
58 static::assertInstanceOf(FormatterFactory::class, $container->formatterFactory); 61 static::assertInstanceOf(FormatterFactory::class, $container->formatterFactory);
59 static::assertInstanceOf(PageCacheManager::class, $container->pageCacheManager); 62 static::assertInstanceOf(PageCacheManager::class, $container->pageCacheManager);
63 static::assertInstanceOf(FeedBuilder::class, $container->feedBuilder);
64 static::assertInstanceOf(Thumbnailer::class, $container->thumbnailer);
65 static::assertInstanceOf(HttpAccess::class, $container->httpAccess);
66
67 // Set by the middleware
68 static::assertNull($container->basePath);
60 } 69 }
61} 70}
diff --git a/tests/feed/CachedPageTest.php b/tests/feed/CachedPageTest.php
index 57f3b09b..2e716432 100644
--- a/tests/feed/CachedPageTest.php
+++ b/tests/feed/CachedPageTest.php
@@ -11,7 +11,7 @@ class CachedPageTest extends \PHPUnit\Framework\TestCase
11{ 11{
12 // test cache directory 12 // test cache directory
13 protected static $testCacheDir = 'sandbox/pagecache'; 13 protected static $testCacheDir = 'sandbox/pagecache';
14 protected static $url = 'http://shaar.li/feed-atom'; 14 protected static $url = 'http://shaar.li/feed/atom';
15 protected static $filename; 15 protected static $filename;
16 16
17 /** 17 /**
@@ -42,8 +42,8 @@ class CachedPageTest extends \PHPUnit\Framework\TestCase
42 { 42 {
43 new CachedPage(self::$testCacheDir, '', true); 43 new CachedPage(self::$testCacheDir, '', true);
44 new CachedPage(self::$testCacheDir, '', false); 44 new CachedPage(self::$testCacheDir, '', false);
45 new CachedPage(self::$testCacheDir, 'http://shaar.li/feed-rss', true); 45 new CachedPage(self::$testCacheDir, 'http://shaar.li/feed/rss', true);
46 new CachedPage(self::$testCacheDir, 'http://shaar.li/feed-atom', false); 46 new CachedPage(self::$testCacheDir, 'http://shaar.li/feed/atom', false);
47 $this->addToAssertionCount(1); 47 $this->addToAssertionCount(1);
48 } 48 }
49 49
diff --git a/tests/front/controller/admin/ConfigureControllerTest.php b/tests/front/controller/admin/ConfigureControllerTest.php
index 40304a18..f2f84bac 100644
--- a/tests/front/controller/admin/ConfigureControllerTest.php
+++ b/tests/front/controller/admin/ConfigureControllerTest.php
@@ -142,7 +142,7 @@ class ConfigureControllerTest extends TestCase
142 142
143 $result = $this->controller->save($request, $response); 143 $result = $this->controller->save($request, $response);
144 static::assertSame(302, $result->getStatusCode()); 144 static::assertSame(302, $result->getStatusCode());
145 static::assertSame(['./configure'], $result->getHeader('Location')); 145 static::assertSame(['/subfolder/admin/configure'], $result->getHeader('Location'));
146 146
147 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); 147 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
148 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); 148 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
@@ -193,7 +193,7 @@ class ConfigureControllerTest extends TestCase
193 $result = $this->controller->save($request, $response); 193 $result = $this->controller->save($request, $response);
194 194
195 static::assertSame(302, $result->getStatusCode()); 195 static::assertSame(302, $result->getStatusCode());
196 static::assertSame(['./configure'], $result->getHeader('Location')); 196 static::assertSame(['/subfolder/admin/configure'], $result->getHeader('Location'));
197 197
198 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); 198 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
199 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); 199 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
@@ -242,7 +242,7 @@ class ConfigureControllerTest extends TestCase
242 $result = $this->controller->save($request, $response); 242 $result = $this->controller->save($request, $response);
243 243
244 static::assertSame(302, $result->getStatusCode()); 244 static::assertSame(302, $result->getStatusCode());
245 static::assertSame(['./configure'], $result->getHeader('Location')); 245 static::assertSame(['/subfolder/admin/configure'], $result->getHeader('Location'));
246 246
247 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); 247 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
248 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); 248 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
diff --git a/tests/front/controller/admin/LogoutControllerTest.php b/tests/front/controller/admin/LogoutControllerTest.php
index 78a0fe73..ca177085 100644
--- a/tests/front/controller/admin/LogoutControllerTest.php
+++ b/tests/front/controller/admin/LogoutControllerTest.php
@@ -49,7 +49,7 @@ class LogoutControllerTest extends TestCase
49 49
50 static::assertInstanceOf(Response::class, $result); 50 static::assertInstanceOf(Response::class, $result);
51 static::assertSame(302, $result->getStatusCode()); 51 static::assertSame(302, $result->getStatusCode());
52 static::assertContains('./', $result->getHeader('Location')); 52 static::assertSame(['/subfolder/'], $result->getHeader('location'));
53 static::assertSame('false', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); 53 static::assertSame('false', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]);
54 } 54 }
55} 55}
diff --git a/tests/front/controller/admin/ManageTagControllerTest.php b/tests/front/controller/admin/ManageTagControllerTest.php
index eed99231..09ba0b4b 100644
--- a/tests/front/controller/admin/ManageTagControllerTest.php
+++ b/tests/front/controller/admin/ManageTagControllerTest.php
@@ -93,7 +93,7 @@ class ManageTagControllerTest extends TestCase
93 $result = $this->controller->save($request, $response); 93 $result = $this->controller->save($request, $response);
94 94
95 static::assertSame(302, $result->getStatusCode()); 95 static::assertSame(302, $result->getStatusCode());
96 static::assertSame(['./?searchtags=new-tag'], $result->getHeader('location')); 96 static::assertSame(['/subfolder/?searchtags=new-tag'], $result->getHeader('location'));
97 97
98 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); 98 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
99 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); 99 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
@@ -146,7 +146,7 @@ class ManageTagControllerTest extends TestCase
146 $result = $this->controller->save($request, $response); 146 $result = $this->controller->save($request, $response);
147 147
148 static::assertSame(302, $result->getStatusCode()); 148 static::assertSame(302, $result->getStatusCode());
149 static::assertSame(['./manage-tags'], $result->getHeader('location')); 149 static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location'));
150 150
151 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); 151 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
152 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); 152 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
@@ -197,7 +197,7 @@ class ManageTagControllerTest extends TestCase
197 $result = $this->controller->save($request, $response); 197 $result = $this->controller->save($request, $response);
198 198
199 static::assertSame(302, $result->getStatusCode()); 199 static::assertSame(302, $result->getStatusCode());
200 static::assertSame(['./manage-tags'], $result->getHeader('location')); 200 static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location'));
201 201
202 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); 202 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
203 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); 203 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
@@ -229,7 +229,7 @@ class ManageTagControllerTest extends TestCase
229 $result = $this->controller->save($request, $response); 229 $result = $this->controller->save($request, $response);
230 230
231 static::assertSame(302, $result->getStatusCode()); 231 static::assertSame(302, $result->getStatusCode());
232 static::assertSame(['./manage-tags'], $result->getHeader('location')); 232 static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location'));
233 233
234 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); 234 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
235 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); 235 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
@@ -262,7 +262,7 @@ class ManageTagControllerTest extends TestCase
262 $result = $this->controller->save($request, $response); 262 $result = $this->controller->save($request, $response);
263 263
264 static::assertSame(302, $result->getStatusCode()); 264 static::assertSame(302, $result->getStatusCode());
265 static::assertSame(['./manage-tags'], $result->getHeader('location')); 265 static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location'));
266 266
267 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); 267 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
268 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); 268 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
diff --git a/tests/front/controller/admin/PostBookmarkControllerTest.php b/tests/front/controller/admin/PostBookmarkControllerTest.php
index 69673bd2..8dcd1b50 100644
--- a/tests/front/controller/admin/PostBookmarkControllerTest.php
+++ b/tests/front/controller/admin/PostBookmarkControllerTest.php
@@ -395,7 +395,7 @@ class PostBookmarkControllerTest extends TestCase
395 'lf_description' => 'Provided description.', 395 'lf_description' => 'Provided description.',
396 'lf_tags' => 'abc def', 396 'lf_tags' => 'abc def',
397 'lf_private' => '1', 397 'lf_private' => '1',
398 'returnurl' => 'http://shaarli.tld/subfolder/add-shaare' 398 'returnurl' => 'http://shaarli.tld/subfolder/admin/add-shaare'
399 ]; 399 ];
400 400
401 $request = $this->createMock(Request::class); 401 $request = $this->createMock(Request::class);
@@ -459,7 +459,7 @@ class PostBookmarkControllerTest extends TestCase
459 $result = $this->controller->save($request, $response); 459 $result = $this->controller->save($request, $response);
460 460
461 static::assertSame(302, $result->getStatusCode()); 461 static::assertSame(302, $result->getStatusCode());
462 static::assertRegExp('@/subfolder/#\w{6}@', $result->getHeader('location')[0]); 462 static::assertRegExp('@/subfolder/#[\w\-]{6}@', $result->getHeader('location')[0]);
463 } 463 }
464 464
465 465
@@ -545,7 +545,7 @@ class PostBookmarkControllerTest extends TestCase
545 $result = $this->controller->save($request, $response); 545 $result = $this->controller->save($request, $response);
546 546
547 static::assertSame(302, $result->getStatusCode()); 547 static::assertSame(302, $result->getStatusCode());
548 static::assertRegExp('@/subfolder/\?page=2#\w{6}@', $result->getHeader('location')[0]); 548 static::assertRegExp('@/subfolder/\?page=2#[\w\-]{6}@', $result->getHeader('location')[0]);
549 } 549 }
550 550
551 /** 551 /**
diff --git a/tests/front/controller/visitor/LoginControllerTest.php b/tests/front/controller/visitor/LoginControllerTest.php
index faa8ac71..e57f44b9 100644
--- a/tests/front/controller/visitor/LoginControllerTest.php
+++ b/tests/front/controller/visitor/LoginControllerTest.php
@@ -95,7 +95,7 @@ class LoginControllerTest extends TestCase
95 95
96 static::assertInstanceOf(Response::class, $result); 96 static::assertInstanceOf(Response::class, $result);
97 static::assertSame(302, $result->getStatusCode()); 97 static::assertSame(302, $result->getStatusCode());
98 static::assertSame(['./'], $result->getHeader('Location')); 98 static::assertSame(['/subfolder/'], $result->getHeader('Location'));
99 } 99 }
100 100
101 public function testLoginControllerOpenShaarli(): void 101 public function testLoginControllerOpenShaarli(): void
@@ -116,7 +116,7 @@ class LoginControllerTest extends TestCase
116 116
117 static::assertInstanceOf(Response::class, $result); 117 static::assertInstanceOf(Response::class, $result);
118 static::assertSame(302, $result->getStatusCode()); 118 static::assertSame(302, $result->getStatusCode());
119 static::assertSame(['./'], $result->getHeader('Location')); 119 static::assertSame(['/subfolder/'], $result->getHeader('Location'));
120 } 120 }
121 121
122 public function testLoginControllerWhileBanned(): void 122 public function testLoginControllerWhileBanned(): void
diff --git a/tests/front/controller/visitor/TagControllerTest.php b/tests/front/controller/visitor/TagControllerTest.php
index 1242a2e9..43076086 100644
--- a/tests/front/controller/visitor/TagControllerTest.php
+++ b/tests/front/controller/visitor/TagControllerTest.php
@@ -64,7 +64,7 @@ class TagControllerTest extends TestCase
64 64
65 static::assertInstanceOf(Response::class, $result); 65 static::assertInstanceOf(Response::class, $result);
66 static::assertSame(302, $result->getStatusCode()); 66 static::assertSame(302, $result->getStatusCode());
67 static::assertSame(['./?searchtags=abc'], $result->getHeader('location')); 67 static::assertSame(['/subfolder/?searchtags=abc'], $result->getHeader('location'));
68 } 68 }
69 69
70 public function testAddTagRemoveLegacyQueryParam(): void 70 public function testAddTagRemoveLegacyQueryParam(): void
@@ -138,7 +138,7 @@ class TagControllerTest extends TestCase
138 138
139 static::assertInstanceOf(Response::class, $result); 139 static::assertInstanceOf(Response::class, $result);
140 static::assertSame(302, $result->getStatusCode()); 140 static::assertSame(302, $result->getStatusCode());
141 static::assertSame(['./'], $result->getHeader('location')); 141 static::assertSame(['/subfolder/'], $result->getHeader('location'));
142 } 142 }
143 143
144 public function testRemoveTagWithoutMatchingTag(): void 144 public function testRemoveTagWithoutMatchingTag(): void
@@ -184,7 +184,7 @@ class TagControllerTest extends TestCase
184 184
185 static::assertInstanceOf(Response::class, $result); 185 static::assertInstanceOf(Response::class, $result);
186 static::assertSame(302, $result->getStatusCode()); 186 static::assertSame(302, $result->getStatusCode());
187 static::assertSame(['./'], $result->getHeader('location')); 187 static::assertSame(['/subfolder/'], $result->getHeader('location'));
188 } 188 }
189 189
190 public function testRemoveTagWithoutTag(): void 190 public function testRemoveTagWithoutTag(): void
@@ -210,6 +210,6 @@ class TagControllerTest extends TestCase
210 210
211 static::assertInstanceOf(Response::class, $result); 211 static::assertInstanceOf(Response::class, $result);
212 static::assertSame(302, $result->getStatusCode()); 212 static::assertSame(302, $result->getStatusCode());
213 static::assertSame(['./'], $result->getHeader('location')); 213 static::assertSame(['/subfolder/'], $result->getHeader('location'));
214 } 214 }
215} 215}
diff --git a/tpl/default/addlink.html b/tpl/default/addlink.html
index c37827f4..67d3ebd1 100644
--- a/tpl/default/addlink.html
+++ b/tpl/default/addlink.html
@@ -9,7 +9,7 @@
9 <div class="pure-u-lg-1-3 pure-u-1-24"></div> 9 <div class="pure-u-lg-1-3 pure-u-1-24"></div>
10 <div id="addlink-form" class="page-form page-form-light pure-u-lg-1-3 pure-u-22-24"> 10 <div id="addlink-form" class="page-form page-form-light pure-u-lg-1-3 pure-u-22-24">
11 <h2 class="window-title">{"Shaare a new link"|t}</h2> 11 <h2 class="window-title">{"Shaare a new link"|t}</h2>
12 <form method="GET" action="{$base_path}/shaare" name="addform" class="addform"> 12 <form method="GET" action="{$base_path}/admin/shaare" name="addform" class="addform">
13 <div> 13 <div>
14 <label for="shaare">{'URL or leave empty to post a note'|t}</label> 14 <label for="shaare">{'URL or leave empty to post a note'|t}</label>
15 <input type="text" name="post" id="shaare" class="autofocus"> 15 <input type="text" name="post" id="shaare" class="autofocus">
diff --git a/tpl/default/changepassword.html b/tpl/default/changepassword.html
index 80d2f2e1..736774f3 100644
--- a/tpl/default/changepassword.html
+++ b/tpl/default/changepassword.html
@@ -9,7 +9,7 @@
9 <div class="pure-u-lg-1-3 pure-u-1-24"></div> 9 <div class="pure-u-lg-1-3 pure-u-1-24"></div>
10 <div id="addlink-form" class="page-form page-form-light pure-u-lg-1-3 pure-u-22-24"> 10 <div id="addlink-form" class="page-form page-form-light pure-u-lg-1-3 pure-u-22-24">
11 <h2 class="window-title">{"Change password"|t}</h2> 11 <h2 class="window-title">{"Change password"|t}</h2>
12 <form method="POST" action="{$base_path}/password" name="changepasswordform" id="changepasswordform"> 12 <form method="POST" action="{$base_path}/admin/password" name="changepasswordform" id="changepasswordform">
13 <div> 13 <div>
14 <input type="password" name="oldpassword" aria-label="{'Current password'|t}" placeholder="{'Current password'|t}" class="autofocus"> 14 <input type="password" name="oldpassword" aria-label="{'Current password'|t}" placeholder="{'Current password'|t}" class="autofocus">
15 </div> 15 </div>
diff --git a/tpl/default/changetag.html b/tpl/default/changetag.html
index 4e3059d3..16c55896 100644
--- a/tpl/default/changetag.html
+++ b/tpl/default/changetag.html
@@ -9,7 +9,7 @@
9 <div class="pure-u-lg-1-3 pure-u-1-24"></div> 9 <div class="pure-u-lg-1-3 pure-u-1-24"></div>
10 <div id="addlink-form" class="page-form page-form-light pure-u-lg-1-3 pure-u-22-24"> 10 <div id="addlink-form" class="page-form page-form-light pure-u-lg-1-3 pure-u-22-24">
11 <h2 class="window-title">{"Manage tags"|t}</h2> 11 <h2 class="window-title">{"Manage tags"|t}</h2>
12 <form method="POST" action="{$base_path}/manage-tags" name="changetag" id="changetag"> 12 <form method="POST" action="{$base_path}/admin/tags" name="changetag" id="changetag">
13 <div> 13 <div>
14 <input type="text" name="fromtag" aria-label="{'Tag'|t}" placeholder="{'Tag'|t}" value="{$fromtag}" 14 <input type="text" name="fromtag" aria-label="{'Tag'|t}" placeholder="{'Tag'|t}" value="{$fromtag}"
15 list="tagsList" autocomplete="off" class="awesomplete autofocus" data-minChars="1"> 15 list="tagsList" autocomplete="off" class="awesomplete autofocus" data-minChars="1">
@@ -32,7 +32,7 @@
32 </div> 32 </div>
33 </form> 33 </form>
34 34
35 <p>{'You can also edit tags in the'|t} <a href="{$base_path}/tag-list?sort=usage">{'tag list'|t}</a>.</p> 35 <p>{'You can also edit tags in the'|t} <a href="{$base_path}/tags/list?sort=usage">{'tag list'|t}</a>.</p>
36 </div> 36 </div>
37</div> 37</div>
38{include="page.footer"} 38{include="page.footer"}
diff --git a/tpl/default/configure.html b/tpl/default/configure.html
index 9b4401a4..fa1f7aa6 100644
--- a/tpl/default/configure.html
+++ b/tpl/default/configure.html
@@ -11,7 +11,7 @@
11{$ratioInput='7-12'} 11{$ratioInput='7-12'}
12{$ratioInputMobile='1-8'} 12{$ratioInputMobile='1-8'}
13 13
14<form method="POST" action="{$base_path}/configure" name="configform" id="configform"> 14<form method="POST" action="{$base_path}/admin/configure" name="configform" id="configform">
15 <div class="pure-g"> 15 <div class="pure-g">
16 <div class="pure-u-lg-1-8 pure-u-1-24"></div> 16 <div class="pure-u-lg-1-8 pure-u-1-24"></div>
17 <div class="pure-u-lg-3-4 pure-u-22-24 page-form page-form-complete"> 17 <div class="pure-u-lg-3-4 pure-u-22-24 page-form page-form-complete">
diff --git a/tpl/default/editlink.html b/tpl/default/editlink.html
index f3adcbb0..15edb00d 100644
--- a/tpl/default/editlink.html
+++ b/tpl/default/editlink.html
@@ -9,7 +9,7 @@
9 <div class="pure-u-lg-1-5 pure-u-1-24"></div> 9 <div class="pure-u-lg-1-5 pure-u-1-24"></div>
10 <form method="post" 10 <form method="post"
11 name="linkform" 11 name="linkform"
12 action="{$base_path}/shaare" 12 action="{$base_path}/admin/shaare"
13 class="page-form pure-u-lg-3-5 pure-u-22-24 page-form page-form-light" 13 class="page-form pure-u-lg-3-5 pure-u-22-24 page-form page-form-light"
14 > 14 >
15 <h2 class="window-title"> 15 <h2 class="window-title">
@@ -73,7 +73,7 @@
73 <input type="submit" name="save_edit" class="" id="button-save-edit" 73 <input type="submit" name="save_edit" class="" id="button-save-edit"
74 value="{if="$link_is_new"}{'Save'|t}{else}{'Apply Changes'|t}{/if}"> 74 value="{if="$link_is_new"}{'Save'|t}{else}{'Apply Changes'|t}{/if}">
75 {if="!$link_is_new"} 75 {if="!$link_is_new"}
76 <a href="{$base_path}/?delete_link&amp;lf_linkdate={$link.id}&amp;token={$token}" 76 <a href="{$base_path}/admin/shaare/delete?id={$link.id}&amp;token={$token}"
77 title="" name="delete_link" class="button button-red confirm-delete"> 77 title="" name="delete_link" class="button button-red confirm-delete">
78 {'Delete'|t} 78 {'Delete'|t}
79 </a> 79 </a>
diff --git a/tpl/default/includes.html b/tpl/default/includes.html
index 0f6a6628..102314d5 100644
--- a/tpl/default/includes.html
+++ b/tpl/default/includes.html
@@ -3,8 +3,8 @@
3<meta name="format-detection" content="telephone=no" /> 3<meta name="format-detection" content="telephone=no" />
4<meta name="viewport" content="width=device-width, initial-scale=1"> 4<meta name="viewport" content="width=device-width, initial-scale=1">
5<meta name="referrer" content="same-origin"> 5<meta name="referrer" content="same-origin">
6<link rel="alternate" type="application/atom+xml" href="{$feedurl}feed-atom?{$searchcrits}#" title="ATOM Feed" /> 6<link rel="alternate" type="application/atom+xml" href="{$feedurl}feed/atom?{$searchcrits}#" title="ATOM Feed" />
7<link rel="alternate" type="application/rss+xml" href="{$feedurl}feed-rss?{$searchcrits}#" title="RSS Feed" /> 7<link rel="alternate" type="application/rss+xml" href="{$feedurl}feed/rss?{$searchcrits}#" title="RSS Feed" />
8<link href="{$asset_path}/img/favicon.png#" rel="shortcut icon" type="image/png" /> 8<link href="{$asset_path}/img/favicon.png#" rel="shortcut icon" type="image/png" />
9<link href="{$asset_path}/img/apple-touch-icon.png#" rel="apple-touch-icon" sizes="180x180" /> 9<link href="{$asset_path}/img/apple-touch-icon.png#" rel="apple-touch-icon" sizes="180x180" />
10<link type="text/css" rel="stylesheet" href="{$asset_path}/css/shaarli.min.css?v={$version_hash}#" /> 10<link type="text/css" rel="stylesheet" href="{$asset_path}/css/shaarli.min.css?v={$version_hash}#" />
diff --git a/tpl/default/linklist.html b/tpl/default/linklist.html
index 89513595..2e2f96d6 100644
--- a/tpl/default/linklist.html
+++ b/tpl/default/linklist.html
@@ -198,10 +198,10 @@
198 <input type="checkbox" class="link-checkbox" value="{$value.id}"> 198 <input type="checkbox" class="link-checkbox" value="{$value.id}">
199 </span> 199 </span>
200 <span class="linklist-item-infos-controls-item ctrl-edit"> 200 <span class="linklist-item-infos-controls-item ctrl-edit">
201 <a href="{$base_path}/?edit_link={$value.id}" aria-label="{$strEdit}" title="{$strEdit}"><i class="fa fa-pencil-square-o edit-link" aria-hidden="true"></i></a> 201 <a href="{$base_path}/admin/shaare/{$value.id}" aria-label="{$strEdit}" title="{$strEdit}"><i class="fa fa-pencil-square-o edit-link" aria-hidden="true"></i></a>
202 </span> 202 </span>
203 <span class="linklist-item-infos-controls-item ctrl-delete"> 203 <span class="linklist-item-infos-controls-item ctrl-delete">
204 <a href="{$base_path}/?delete_link&amp;lf_linkdate={$value.id}&amp;token={$token}" aria-label="{$strDelete}" 204 <a href="{$base_path}/admin/shaare/delete?id={$value.id}&amp;token={$token}" aria-label="{$strDelete}"
205 title="{$strDelete}" class="delete-link pure-u-0 pure-u-lg-visible confirm-delete"> 205 title="{$strDelete}" class="delete-link pure-u-0 pure-u-lg-visible confirm-delete">
206 <i class="fa fa-trash" aria-hidden="true"></i> 206 <i class="fa fa-trash" aria-hidden="true"></i>
207 </a> 207 </a>
@@ -267,12 +267,12 @@
267 {/if} 267 {/if}
268 {if="$is_logged_in"} 268 {if="$is_logged_in"}
269 &middot; 269 &middot;
270 <a href="{$base_path}/?delete_link&amp;lf_linkdate={$value.id}&amp;token={$token}" aria-label="{$strDelete}" 270 <a href="{$base_path}/admin/shaare/delete?id={$value.id}&amp;token={$token}" aria-label="{$strDelete}"
271 title="{$strDelete}" class="delete-link confirm-delete"> 271 title="{$strDelete}" class="delete-link confirm-delete">
272 <i class="fa fa-trash" aria-hidden="true"></i> 272 <i class="fa fa-trash" aria-hidden="true"></i>
273 </a> 273 </a>
274 &middot; 274 &middot;
275 <a href="{$base_path}/?edit_link={$value.id}" aria-label="{$strEdit}" title="{$strEdit}"><i class="fa fa-pencil-square-o edit-link" aria-hidden="true"></i></a> 275 <a href="{$base_path}/admin/shaare/{$value.id}" aria-label="{$strEdit}" title="{$strEdit}"><i class="fa fa-pencil-square-o edit-link" aria-hidden="true"></i></a>
276 {/if} 276 {/if}
277 </div> 277 </div>
278 </div> 278 </div>
diff --git a/tpl/default/opensearch.html b/tpl/default/opensearch.html
index 5774d38d..1c7f279b 100644
--- a/tpl/default/opensearch.html
+++ b/tpl/default/opensearch.html
@@ -3,8 +3,8 @@
3 <ShortName>Shaarli search - {$pagetitle}</ShortName> 3 <ShortName>Shaarli search - {$pagetitle}</ShortName>
4 <Description>Shaarli search - {$pagetitle}</Description> 4 <Description>Shaarli search - {$pagetitle}</Description>
5 <Url type="text/html" template="{$serverurl}?searchterm={searchTerms}" /> 5 <Url type="text/html" template="{$serverurl}?searchterm={searchTerms}" />
6 <Url type="application/atom+xml" template="{$serverurl}feed-atom?searchterm={searchTerms}"/> 6 <Url type="application/atom+xml" template="{$serverurl}feed/atom?searchterm={searchTerms}"/>
7 <Url type="application/rss+xml" template="{$serverurl}feed-rss?searchterm={searchTerms}"/> 7 <Url type="application/rss+xml" template="{$serverurl}feed/rss?searchterm={searchTerms}"/>
8 <InputEncoding>UTF-8</InputEncoding> 8 <InputEncoding>UTF-8</InputEncoding>
9 <Developer>Shaarli Community - https://github.com/shaarli/Shaarli/</Developer> 9 <Developer>Shaarli Community - https://github.com/shaarli/Shaarli/</Developer>
10 <Image width="16" height="16">data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAHRklE 10 <Image width="16" height="16">data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAHRklE
diff --git a/tpl/default/page.header.html b/tpl/default/page.header.html
index 7117e3ca..4fe2b69e 100644
--- a/tpl/default/page.header.html
+++ b/tpl/default/page.header.html
@@ -21,16 +21,16 @@
21 </li> 21 </li>
22 {if="$is_logged_in || $openshaarli"} 22 {if="$is_logged_in || $openshaarli"}
23 <li class="pure-menu-item"> 23 <li class="pure-menu-item">
24 <a href="{$base_path}/add-shaare" class="pure-menu-link" id="shaarli-menu-shaare"> 24 <a href="{$base_path}/admin/add-shaare" class="pure-menu-link" id="shaarli-menu-shaare">
25 <i class="fa fa-plus" aria-hidden="true"></i> {'Shaare'|t} 25 <i class="fa fa-plus" aria-hidden="true"></i> {'Shaare'|t}
26 </a> 26 </a>
27 </li> 27 </li>
28 <li class="pure-menu-item" id="shaarli-menu-tools"> 28 <li class="pure-menu-item" id="shaarli-menu-tools">
29 <a href="{$base_path}/tools" class="pure-menu-link">{'Tools'|t}</a> 29 <a href="{$base_path}/admin/tools" class="pure-menu-link">{'Tools'|t}</a>
30 </li> 30 </li>
31 {/if} 31 {/if}
32 <li class="pure-menu-item" id="shaarli-menu-tags"> 32 <li class="pure-menu-item" id="shaarli-menu-tags">
33 <a href="{$base_path}/tag-cloud" class="pure-menu-link">{'Tag cloud'|t}</a> 33 <a href="{$base_path}/tags/cloud" class="pure-menu-link">{'Tag cloud'|t}</a>
34 </li> 34 </li>
35 {if="$thumbnails_enabled"} 35 {if="$thumbnails_enabled"}
36 <li class="pure-menu-item" id="shaarli-menu-picwall"> 36 <li class="pure-menu-item" id="shaarli-menu-picwall">
@@ -52,7 +52,7 @@
52 </li> 52 </li>
53 {/loop} 53 {/loop}
54 <li class="pure-menu-item pure-u-lg-0 shaarli-menu-mobile" id="shaarli-menu-mobile-rss"> 54 <li class="pure-menu-item pure-u-lg-0 shaarli-menu-mobile" id="shaarli-menu-mobile-rss">
55 <a href="{$base_path}/feed-{$feed_type}?{$searchcrits}" class="pure-menu-link">{'RSS Feed'|t}</a> 55 <a href="{$base_path}/feed/{$feed_type}?{$searchcrits}" class="pure-menu-link">{'RSS Feed'|t}</a>
56 </li> 56 </li>
57 {if="$is_logged_in"} 57 {if="$is_logged_in"}
58 <li class="pure-menu-item pure-u-lg-0 shaarli-menu-mobile" id="shaarli-menu-mobile-logout"> 58 <li class="pure-menu-item pure-u-lg-0 shaarli-menu-mobile" id="shaarli-menu-mobile-logout">
@@ -74,7 +74,7 @@
74 </a> 74 </a>
75 </li> 75 </li>
76 <li class="pure-menu-item" id="shaarli-menu-desktop-rss"> 76 <li class="pure-menu-item" id="shaarli-menu-desktop-rss">
77 <a href="{$base_path}/feed-{$feed_type}?{$searchcrits}" class="pure-menu-link" title="{'RSS Feed'|t}" aria-label="{'RSS Feed'|t}"> 77 <a href="{$base_path}/feed/{$feed_type}?{$searchcrits}" class="pure-menu-link" title="{'RSS Feed'|t}" aria-label="{'RSS Feed'|t}">
78 <i class="fa fa-rss" aria-hidden="true"></i> 78 <i class="fa fa-rss" aria-hidden="true"></i>
79 </a> 79 </a>
80 </li> 80 </li>
diff --git a/tpl/default/tag.list.html b/tpl/default/tag.list.html
index 51f42333..99ae44d2 100644
--- a/tpl/default/tag.list.html
+++ b/tpl/default/tag.list.html
@@ -51,7 +51,7 @@
51 <div class="pure-u-1"> 51 <div class="pure-u-1">
52 {if="$is_logged_in===true"} 52 {if="$is_logged_in===true"}
53 <a href="#" class="delete-tag" aria-label="{'Delete'|t}"><i class="fa fa-trash" aria-hidden="true"></i></a>&nbsp;&nbsp; 53 <a href="#" class="delete-tag" aria-label="{'Delete'|t}"><i class="fa fa-trash" aria-hidden="true"></i></a>&nbsp;&nbsp;
54 <a href="{$base_path}/manage-tags?fromtag={$key|urlencode}" class="rename-tag" aria-label="{'Rename tag'|t}"> 54 <a href="{$base_path}/admin/tags?fromtag={$key|urlencode}" class="rename-tag" aria-label="{'Rename tag'|t}">
55 <i class="fa fa-pencil-square-o {$key}" aria-hidden="true"></i> 55 <i class="fa fa-pencil-square-o {$key}" aria-hidden="true"></i>
56 </a> 56 </a>
57 {/if} 57 {/if}
diff --git a/tpl/default/tag.sort.html b/tpl/default/tag.sort.html
index 6cb1a114..8718b188 100644
--- a/tpl/default/tag.sort.html
+++ b/tpl/default/tag.sort.html
@@ -1,8 +1,8 @@
1<div class="pure-g"> 1<div class="pure-g">
2 <div class="pure-u-1 pure-alert pure-alert-success tag-sort"> 2 <div class="pure-u-1 pure-alert pure-alert-success tag-sort">
3 {'Sort by:'|t} 3 {'Sort by:'|t}
4 <a href="{$base_path}/tag-cloud">{'Cloud'|t}</a> &middot; 4 <a href="{$base_path}/tags/cloud">{'Cloud'|t}</a> &middot;
5 <a href="{$base_path}/tag-list?sort=usage">{'Most used'|t}</a> &middot; 5 <a href="{$base_path}/tags/list?sort=usage">{'Most used'|t}</a> &middot;
6 <a href="{$base_path}/tag-list?sort=alpha">{'Alphabetical'|t}</a> 6 <a href="{$base_path}/tags/list?sort=alpha">{'Alphabetical'|t}</a>
7 </div> 7 </div>
8</div> 8</div>
diff --git a/tpl/default/tools.html b/tpl/default/tools.html
index 296abed1..fd58cca9 100644
--- a/tpl/default/tools.html
+++ b/tpl/default/tools.html
@@ -11,7 +11,7 @@
11 <div class="pure-u-lg-1-3 pure-u-22-24 page-form page-form-light"> 11 <div class="pure-u-lg-1-3 pure-u-22-24 page-form page-form-light">
12 <h2 class="window-title">{'Settings'|t}</h2> 12 <h2 class="window-title">{'Settings'|t}</h2>
13 <div class="tools-item"> 13 <div class="tools-item">
14 <a href="{$base_path}/configure" title="{'Change Shaarli settings: title, timezone, etc.'|t}"> 14 <a href="{$base_path}/admin/configure" title="{'Change Shaarli settings: title, timezone, etc.'|t}">
15 <span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Configure your Shaarli'|t}</span> 15 <span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Configure your Shaarli'|t}</span>
16 </a> 16 </a>
17 </div> 17 </div>
@@ -22,13 +22,13 @@
22 </div> 22 </div>
23 {if="!$openshaarli"} 23 {if="!$openshaarli"}
24 <div class="tools-item"> 24 <div class="tools-item">
25 <a href="{$base_path}/?do=changepasswd" title="{'Change your password'|t}"> 25 <a href="{$base_path}/admin/password" title="{'Change your password'|t}">
26 <span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Change password'|t}</span> 26 <span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Change password'|t}</span>
27 </a> 27 </a>
28 </div> 28 </div>
29 {/if} 29 {/if}
30 <div class="tools-item"> 30 <div class="tools-item">
31 <a href="{$base_path}/manage-tags" title="{'Rename or delete a tag in all links'|t}"> 31 <a href="{$base_path}/admin/tags" title="{'Rename or delete a tag in all links'|t}">
32 <span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Manage tags'|t}</span> 32 <span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Manage tags'|t}</span>
33 </a> 33 </a>
34 </div> 34 </div>
diff --git a/tpl/vintage/addlink.html b/tpl/vintage/addlink.html
index e1d65225..ade08c7c 100644
--- a/tpl/vintage/addlink.html
+++ b/tpl/vintage/addlink.html
@@ -5,7 +5,7 @@
5<div id="pageheader"> 5<div id="pageheader">
6 {include="page.header"} 6 {include="page.header"}
7 <div id="headerform"> 7 <div id="headerform">
8 <form method="GET" action="{$base_path}/shaare" name="addform" class="addform"> 8 <form method="GET" action="{$base_path}/admin/shaare" name="addform" class="addform">
9 <input type="text" name="post" class="linkurl"> 9 <input type="text" name="post" class="linkurl">
10 <input type="submit" value="Add link" class="bigbutton"> 10 <input type="submit" value="Add link" class="bigbutton">
11 </form> 11 </form>
diff --git a/tpl/vintage/editlink.html b/tpl/vintage/editlink.html
index 593fe71a..f751d50b 100644
--- a/tpl/vintage/editlink.html
+++ b/tpl/vintage/editlink.html
@@ -48,7 +48,7 @@
48 {/if} 48 {/if}
49 <input type="submit" value="Save" name="save_edit" class="bigbutton"> 49 <input type="submit" value="Save" name="save_edit" class="bigbutton">
50 {if="!$link_is_new && isset($link.id)"} 50 {if="!$link_is_new && isset($link.id)"}
51 <a href="{$base_path}/?delete_link&amp;lf_linkdate={$link.id}&amp;token={$token}" 51 <a href="{$base_path}/admin/shaare/delete?id={$link.id}&amp;token={$token}"
52 name="delete_link" class="bigbutton" 52 name="delete_link" class="bigbutton"
53 onClick="return confirmDeleteLink();"> 53 onClick="return confirmDeleteLink();">
54 {'Delete'|t} 54 {'Delete'|t}
diff --git a/tpl/vintage/includes.html b/tpl/vintage/includes.html
index 7c4d9311..aa2381c6 100644
--- a/tpl/vintage/includes.html
+++ b/tpl/vintage/includes.html
@@ -3,8 +3,8 @@
3<meta name="format-detection" content="telephone=no" /> 3<meta name="format-detection" content="telephone=no" />
4<meta name="viewport" content="width=device-width,initial-scale=1.0" /> 4<meta name="viewport" content="width=device-width,initial-scale=1.0" />
5<meta name="referrer" content="same-origin"> 5<meta name="referrer" content="same-origin">
6<link rel="alternate" type="application/rss+xml" href="{$feedurl}feed-rss?{$searchcrits}#" title="RSS Feed" /> 6<link rel="alternate" type="application/rss+xml" href="{$feedurl}feed/rss?{$searchcrits}#" title="RSS Feed" />
7<link rel="alternate" type="application/atom+xml" href="{$feedurl}feed-atom?{$searchcrits}#" title="ATOM Feed" /> 7<link rel="alternate" type="application/atom+xml" href="{$feedurl}feed/atom?{$searchcrits}#" title="ATOM Feed" />
8<link href="img/favicon.ico" rel="shortcut icon" type="image/x-icon" /> 8<link href="img/favicon.ico" rel="shortcut icon" type="image/x-icon" />
9<link type="text/css" rel="stylesheet" href="css/shaarli.min.css" /> 9<link type="text/css" rel="stylesheet" href="css/shaarli.min.css" />
10{if="$formatter==='markdown'"} 10{if="$formatter==='markdown'"}
diff --git a/tpl/vintage/opensearch.html b/tpl/vintage/opensearch.html
index 5774d38d..1c7f279b 100644
--- a/tpl/vintage/opensearch.html
+++ b/tpl/vintage/opensearch.html
@@ -3,8 +3,8 @@
3 <ShortName>Shaarli search - {$pagetitle}</ShortName> 3 <ShortName>Shaarli search - {$pagetitle}</ShortName>
4 <Description>Shaarli search - {$pagetitle}</Description> 4 <Description>Shaarli search - {$pagetitle}</Description>
5 <Url type="text/html" template="{$serverurl}?searchterm={searchTerms}" /> 5 <Url type="text/html" template="{$serverurl}?searchterm={searchTerms}" />
6 <Url type="application/atom+xml" template="{$serverurl}feed-atom?searchterm={searchTerms}"/> 6 <Url type="application/atom+xml" template="{$serverurl}feed/atom?searchterm={searchTerms}"/>
7 <Url type="application/rss+xml" template="{$serverurl}feed-rss?searchterm={searchTerms}"/> 7 <Url type="application/rss+xml" template="{$serverurl}feed/rss?searchterm={searchTerms}"/>
8 <InputEncoding>UTF-8</InputEncoding> 8 <InputEncoding>UTF-8</InputEncoding>
9 <Developer>Shaarli Community - https://github.com/shaarli/Shaarli/</Developer> 9 <Developer>Shaarli Community - https://github.com/shaarli/Shaarli/</Developer>
10 <Image width="16" height="16">data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAHRklE 10 <Image width="16" height="16">data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAHRklE
diff --git a/tpl/vintage/page.header.html b/tpl/vintage/page.header.html
index 0f79d321..1c00d19b 100644
--- a/tpl/vintage/page.header.html
+++ b/tpl/vintage/page.header.html
@@ -19,19 +19,19 @@
19<li><a href="{$titleLink}" class="nomobile">Home</a></li> 19<li><a href="{$titleLink}" class="nomobile">Home</a></li>
20 {if="$is_logged_in"} 20 {if="$is_logged_in"}
21 <li><a href="{$base_path}/logout">Logout</a></li> 21 <li><a href="{$base_path}/logout">Logout</a></li>
22 <li><a href="{$base_path}/tools">Tools</a></li> 22 <li><a href="{$base_path}/admin/tools">Tools</a></li>
23 <li><a href="{$base_path}/add-shaare">Add link</a></li> 23 <li><a href="{$base_path}/admin/add-shaare">Add link</a></li>
24 {elseif="$openshaarli"} 24 {elseif="$openshaarli"}
25 <li><a href="{$base_path}/tools">Tools</a></li> 25 <li><a href="{$base_path}/admin/tools">Tools</a></li>
26 <li><a href="{$base_path}/add-shaare">Add link</a></li> 26 <li><a href="{$base_path}/admin/add-shaare">Add link</a></li>
27 {else} 27 {else}
28 <li><a href="{$base_path}/login">Login</a></li> 28 <li><a href="{$base_path}/login">Login</a></li>
29 {/if} 29 {/if}
30 <li><a href="{$feedurl}/feed-rss?{$searchcrits}" class="nomobile">RSS Feed</a></li> 30 <li><a href="{$feedurl}/feed/rss?{$searchcrits}" class="nomobile">RSS Feed</a></li>
31 {if="$showatom"} 31 {if="$showatom"}
32 <li><a href="{$feedurl}/feed-atom?{$searchcrits}" class="nomobile">ATOM Feed</a></li> 32 <li><a href="{$feedurl}/feed/atom?{$searchcrits}" class="nomobile">ATOM Feed</a></li>
33 {/if} 33 {/if}
34 <li><a href="{$base_path}/tag-cloud">Tag cloud</a></li> 34 <li><a href="{$base_path}/tags/cloud">Tag cloud</a></li>
35 <li><a href="{$base_path}/picture-wall{function="ltrim($searchcrits, '&')"}">Picture wall</a></li> 35 <li><a href="{$base_path}/picture-wall{function="ltrim($searchcrits, '&')"}">Picture wall</a></li>
36 <li><a href="{$base_path}/daily">Daily</a></li> 36 <li><a href="{$base_path}/daily">Daily</a></li>
37 {loop="$plugins_header.buttons_toolbar"} 37 {loop="$plugins_header.buttons_toolbar"}
diff --git a/tpl/vintage/tools.html b/tpl/vintage/tools.html
index 9caea9cf..32707efa 100644
--- a/tpl/vintage/tools.html
+++ b/tpl/vintage/tools.html
@@ -5,13 +5,13 @@
5<div id="pageheader"> 5<div id="pageheader">
6 {include="page.header"} 6 {include="page.header"}
7 <div id="toolsdiv"> 7 <div id="toolsdiv">
8 <a href="{$base_path}/configure"><b>Configure your Shaarli</b><span>: Change Title, timezone...</span></a> 8 <a href="{$base_path}/admin/configure"><b>Configure your Shaarli</b><span>: Change Title, timezone...</span></a>
9 <br><br> 9 <br><br>
10 <a href="{$base_path}/?do=pluginadmin"><b>Plugin administration</b><span>: Enable, disable and configure plugins.</span></a> 10 <a href="{$base_path}/?do=pluginadmin"><b>Plugin administration</b><span>: Enable, disable and configure plugins.</span></a>
11 <br><br> 11 <br><br>
12 {if="!$openshaarli"}<a href="{$base_path}/?do=changepasswd"><b>Change password</b><span>: Change your password.</span></a> 12 {if="!$openshaarli"}<a href="{$base_path}/admin/password"><b>Change password</b><span>: Change your password.</span></a>
13 <br><br>{/if} 13 <br><br>{/if}
14 <a href="{$base_path}/manage-tags"><b>Rename/delete tags</b><span>: Rename or delete a tag in all links</span></a> 14 <a href="{$base_path}/admin/tags"><b>Rename/delete tags</b><span>: Rename or delete a tag in all links</span></a>
15 <br><br> 15 <br><br>
16 <a href="{$base_path}/?do=import"><b>Import</b><span>: Import Netscape html bookmarks (as exported from Firefox, Chrome, Opera, delicious...)</span></a> 16 <a href="{$base_path}/?do=import"><b>Import</b><span>: Import Netscape html bookmarks (as exported from Firefox, Chrome, Opera, delicious...)</span></a>
17 <br><br> 17 <br><br>