aboutsummaryrefslogtreecommitdiffhomepage
path: root/index.php
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2020-10-13 12:07:13 +0200
committerArthurHoaro <arthur@hoa.ro>2020-10-13 12:07:13 +0200
commitd9f6275ebca035fec8331652c677981056793ccc (patch)
tree37a64baf4f0eba6b781040605965383d8aded2cc /index.php
parent38672ba0d1c722e5d6d33a58255ceb55e9410e46 (diff)
parentd63ff87a009313141ae684ec447b902562ff6ee7 (diff)
downloadShaarli-d9f6275ebca035fec8331652c677981056793ccc.tar.gz
Shaarli-d9f6275ebca035fec8331652c677981056793ccc.tar.zst
Shaarli-d9f6275ebca035fec8331652c677981056793ccc.zip
Merge branch 'v0.11' into stablestable
Diffstat (limited to 'index.php')
-rw-r--r--index.php156
1 files changed, 98 insertions, 58 deletions
diff --git a/index.php b/index.php
index 27c67ce1..3a5c35c4 100644
--- a/index.php
+++ b/index.php
@@ -62,31 +62,33 @@ require_once 'inc/rain.tpl.class.php';
62require_once __DIR__ . '/vendor/autoload.php'; 62require_once __DIR__ . '/vendor/autoload.php';
63 63
64// Shaarli library 64// Shaarli library
65require_once 'application/ApplicationUtils.php'; 65require_once 'application/bookmark/LinkUtils.php';
66require_once 'application/Cache.php';
67require_once 'application/CachedPage.php';
68require_once 'application/config/ConfigPlugin.php'; 66require_once 'application/config/ConfigPlugin.php';
69require_once 'application/FeedBuilder.php'; 67require_once 'application/feed/Cache.php';
68require_once 'application/http/HttpUtils.php';
69require_once 'application/http/UrlUtils.php';
70require_once 'application/updater/UpdaterUtils.php';
70require_once 'application/FileUtils.php'; 71require_once 'application/FileUtils.php';
71require_once 'application/History.php';
72require_once 'application/HttpUtils.php';
73require_once 'application/LinkDB.php';
74require_once 'application/LinkFilter.php';
75require_once 'application/LinkUtils.php';
76require_once 'application/NetscapeBookmarkUtils.php';
77require_once 'application/PageBuilder.php';
78require_once 'application/TimeZone.php'; 72require_once 'application/TimeZone.php';
79require_once 'application/Url.php';
80require_once 'application/Utils.php'; 73require_once 'application/Utils.php';
81require_once 'application/PluginManager.php'; 74
82require_once 'application/Router.php'; 75use \Shaarli\ApplicationUtils;
83require_once 'application/Updater.php'; 76use \Shaarli\Bookmark\Exception\LinkNotFoundException;
77use \Shaarli\Bookmark\LinkDB;
84use \Shaarli\Config\ConfigManager; 78use \Shaarli\Config\ConfigManager;
79use \Shaarli\Feed\CachedPage;
80use \Shaarli\Feed\FeedBuilder;
81use \Shaarli\History;
85use \Shaarli\Languages; 82use \Shaarli\Languages;
83use \Shaarli\Netscape\NetscapeBookmarkUtils;
84use \Shaarli\Plugin\PluginManager;
85use \Shaarli\Render\PageBuilder;
86use \Shaarli\Render\ThemeUtils;
87use \Shaarli\Router;
86use \Shaarli\Security\LoginManager; 88use \Shaarli\Security\LoginManager;
87use \Shaarli\Security\SessionManager; 89use \Shaarli\Security\SessionManager;
88use \Shaarli\ThemeUtils;
89use \Shaarli\Thumbnailer; 90use \Shaarli\Thumbnailer;
91use \Shaarli\Updater\Updater;
90 92
91// Ensure the PHP version is supported 93// Ensure the PHP version is supported
92try { 94try {
@@ -129,7 +131,7 @@ if (isset($_COOKIE['shaarli']) && !SessionManager::checkId($_COOKIE['shaarli']))
129 131
130$conf = new ConfigManager(); 132$conf = new ConfigManager();
131$sessionManager = new SessionManager($_SESSION, $conf); 133$sessionManager = new SessionManager($_SESSION, $conf);
132$loginManager = new LoginManager($GLOBALS, $conf, $sessionManager); 134$loginManager = new LoginManager($conf, $sessionManager);
133$loginManager->generateStaySignedInToken($_SERVER['REMOTE_ADDR']); 135$loginManager->generateStaySignedInToken($_SERVER['REMOTE_ADDR']);
134$clientIpId = client_ip_id($_SERVER); 136$clientIpId = client_ip_id($_SERVER);
135 137
@@ -316,9 +318,7 @@ function showDailyRSS($conf, $loginManager)
316 $LINKSDB = new LinkDB( 318 $LINKSDB = new LinkDB(
317 $conf->get('resource.datastore'), 319 $conf->get('resource.datastore'),
318 $loginManager->isLoggedIn(), 320 $loginManager->isLoggedIn(),
319 $conf->get('privacy.hide_public_links'), 321 $conf->get('privacy.hide_public_links')
320 $conf->get('redirector.url'),
321 $conf->get('redirector.encode_url')
322 ); 322 );
323 323
324 /* Some Shaarlies may have very few links, so we need to look 324 /* Some Shaarlies may have very few links, so we need to look
@@ -360,13 +360,9 @@ function showDailyRSS($conf, $loginManager)
360 360
361 // We pre-format some fields for proper output. 361 // We pre-format some fields for proper output.
362 foreach ($links as &$link) { 362 foreach ($links as &$link) {
363 $link['formatedDescription'] = format_description( 363 $link['formatedDescription'] = format_description($link['description']);
364 $link['description'],
365 $conf->get('redirector.url'),
366 $conf->get('redirector.encode_url')
367 );
368 $link['timestamp'] = $link['created']->getTimestamp(); 364 $link['timestamp'] = $link['created']->getTimestamp();
369 if (startsWith($link['url'], '?')) { 365 if (is_note($link['url'])) {
370 $link['url'] = index_url($_SERVER) . $link['url']; // make permalink URL absolute 366 $link['url'] = index_url($_SERVER) . $link['url']; // make permalink URL absolute
371 } 367 }
372 } 368 }
@@ -402,9 +398,16 @@ function showDailyRSS($conf, $loginManager)
402 */ 398 */
403function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager) 399function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
404{ 400{
405 $day = date('Ymd', strtotime('-1 day')); // Yesterday, in format YYYYMMDD.
406 if (isset($_GET['day'])) { 401 if (isset($_GET['day'])) {
407 $day = $_GET['day']; 402 $day = $_GET['day'];
403 if ($day === date('Ymd', strtotime('now'))) {
404 $pageBuilder->assign('dayDesc', t('Today'));
405 } elseif ($day === date('Ymd', strtotime('-1 days'))) {
406 $pageBuilder->assign('dayDesc', t('Yesterday'));
407 }
408 } else {
409 $day = date('Ymd', strtotime('now')); // Today, in format YYYYMMDD.
410 $pageBuilder->assign('dayDesc', t('Today'));
408 } 411 }
409 412
410 $days = $LINKSDB->days(); 413 $days = $LINKSDB->days();
@@ -437,11 +440,7 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
437 $taglist = explode(' ', $link['tags']); 440 $taglist = explode(' ', $link['tags']);
438 uasort($taglist, 'strcasecmp'); 441 uasort($taglist, 'strcasecmp');
439 $linksToDisplay[$key]['taglist']=$taglist; 442 $linksToDisplay[$key]['taglist']=$taglist;
440 $linksToDisplay[$key]['formatedDescription'] = format_description( 443 $linksToDisplay[$key]['formatedDescription'] = format_description($link['description']);
441 $link['description'],
442 $conf->get('redirector.url'),
443 $conf->get('redirector.encode_url')
444 );
445 $linksToDisplay[$key]['timestamp'] = $link['created']->getTimestamp(); 444 $linksToDisplay[$key]['timestamp'] = $link['created']->getTimestamp();
446 } 445 }
447 446
@@ -1022,6 +1021,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1022 $conf->set('general.timezone', $tz); 1021 $conf->set('general.timezone', $tz);
1023 $conf->set('general.title', escape($_POST['title'])); 1022 $conf->set('general.title', escape($_POST['title']));
1024 $conf->set('general.header_link', escape($_POST['titleLink'])); 1023 $conf->set('general.header_link', escape($_POST['titleLink']));
1024 $conf->set('general.retrieve_description', !empty($_POST['retrieveDescription']));
1025 $conf->set('resource.theme', escape($_POST['theme'])); 1025 $conf->set('resource.theme', escape($_POST['theme']));
1026 $conf->set('security.session_protection_disabled', !empty($_POST['disablesessionprotection'])); 1026 $conf->set('security.session_protection_disabled', !empty($_POST['disablesessionprotection']));
1027 $conf->set('privacy.default_private_links', !empty($_POST['privateLinkByDefault'])); 1027 $conf->set('privacy.default_private_links', !empty($_POST['privateLinkByDefault']));
@@ -1070,6 +1070,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1070 ); 1070 );
1071 $PAGE->assign('continents', $continents); 1071 $PAGE->assign('continents', $continents);
1072 $PAGE->assign('cities', $cities); 1072 $PAGE->assign('cities', $cities);
1073 $PAGE->assign('retrieve_description', $conf->get('general.retrieve_description'));
1073 $PAGE->assign('private_links_default', $conf->get('privacy.default_private_links', false)); 1074 $PAGE->assign('private_links_default', $conf->get('privacy.default_private_links', false));
1074 $PAGE->assign('session_protection_disabled', $conf->get('security.session_protection_disabled', false)); 1075 $PAGE->assign('session_protection_disabled', $conf->get('security.session_protection_disabled', false));
1075 $PAGE->assign('enable_rss_permalinks', $conf->get('feed.rss_permalinks', false)); 1076 $PAGE->assign('enable_rss_permalinks', $conf->get('feed.rss_permalinks', false));
@@ -1078,7 +1079,6 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1078 $PAGE->assign('api_enabled', $conf->get('api.enabled', true)); 1079 $PAGE->assign('api_enabled', $conf->get('api.enabled', true));
1079 $PAGE->assign('api_secret', $conf->get('api.secret')); 1080 $PAGE->assign('api_secret', $conf->get('api.secret'));
1080 $PAGE->assign('languages', Languages::getAvailableLanguages()); 1081 $PAGE->assign('languages', Languages::getAvailableLanguages());
1081 $PAGE->assign('language', $conf->get('translation.language'));
1082 $PAGE->assign('gd_enabled', extension_loaded('gd')); 1082 $PAGE->assign('gd_enabled', extension_loaded('gd'));
1083 $PAGE->assign('thumbnails_mode', $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)); 1083 $PAGE->assign('thumbnails_mode', $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE));
1084 $PAGE->assign('pagetitle', t('Configure') .' - '. $conf->get('general.title', 'Shaarli')); 1084 $PAGE->assign('pagetitle', t('Configure') .' - '. $conf->get('general.title', 'Shaarli'));
@@ -1132,22 +1132,24 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1132 1132
1133 // lf_id should only be present if the link exists. 1133 // lf_id should only be present if the link exists.
1134 $id = isset($_POST['lf_id']) ? intval(escape($_POST['lf_id'])) : $LINKSDB->getNextId(); 1134 $id = isset($_POST['lf_id']) ? intval(escape($_POST['lf_id'])) : $LINKSDB->getNextId();
1135 $link['id'] = $id;
1135 // Linkdate is kept here to: 1136 // Linkdate is kept here to:
1136 // - use the same permalink for notes as they're displayed when creating them 1137 // - use the same permalink for notes as they're displayed when creating them
1137 // - let users hack creation date of their posts 1138 // - let users hack creation date of their posts
1138 // See: https://shaarli.readthedocs.io/en/master/guides/various-hacks/#changing-the-timestamp-for-a-shaare 1139 // See: https://shaarli.readthedocs.io/en/master/guides/various-hacks/#changing-the-timestamp-for-a-shaare
1139 $linkdate = escape($_POST['lf_linkdate']); 1140 $linkdate = escape($_POST['lf_linkdate']);
1141 $link['created'] = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $linkdate);
1140 if (isset($LINKSDB[$id])) { 1142 if (isset($LINKSDB[$id])) {
1141 // Edit 1143 // Edit
1142 $created = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $linkdate); 1144 $link['updated'] = new DateTime();
1143 $updated = new DateTime(); 1145 $link['shorturl'] = $LINKSDB[$id]['shorturl'];
1144 $shortUrl = $LINKSDB[$id]['shorturl']; 1146 $link['sticky'] = isset($LINKSDB[$id]['sticky']) ? $LINKSDB[$id]['sticky'] : false;
1145 $new = false; 1147 $new = false;
1146 } else { 1148 } else {
1147 // New link 1149 // New link
1148 $created = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $linkdate); 1150 $link['updated'] = null;
1149 $updated = null; 1151 $link['shorturl'] = link_small_hash($link['created'], $id);
1150 $shortUrl = link_small_hash($created, $id); 1152 $link['sticky'] = false;
1151 $new = true; 1153 $new = true;
1152 } 1154 }
1153 1155
@@ -1163,24 +1165,22 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1163 } 1165 }
1164 $url = whitelist_protocols(trim($_POST['lf_url']), $conf->get('security.allowed_protocols')); 1166 $url = whitelist_protocols(trim($_POST['lf_url']), $conf->get('security.allowed_protocols'));
1165 1167
1166 $link = array( 1168 $link = array_merge($link, [
1167 'id' => $id,
1168 'title' => trim($_POST['lf_title']), 1169 'title' => trim($_POST['lf_title']),
1169 'url' => $url, 1170 'url' => $url,
1170 'description' => $_POST['lf_description'], 1171 'description' => $_POST['lf_description'],
1171 'private' => (isset($_POST['lf_private']) ? 1 : 0), 1172 'private' => (isset($_POST['lf_private']) ? 1 : 0),
1172 'created' => $created,
1173 'updated' => $updated,
1174 'tags' => str_replace(',', ' ', $tags), 1173 'tags' => str_replace(',', ' ', $tags),
1175 'shorturl' => $shortUrl, 1174 ]);
1176 );
1177 1175
1178 // If title is empty, use the URL as title. 1176 // If title is empty, use the URL as title.
1179 if ($link['title'] == '') { 1177 if ($link['title'] == '') {
1180 $link['title'] = $link['url']; 1178 $link['title'] = $link['url'];
1181 } 1179 }
1182 1180
1183 if ($conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE) { 1181 if ($conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE
1182 && ! is_note($link['url'])
1183 ) {
1184 $thumbnailer = new Thumbnailer($conf); 1184 $thumbnailer = new Thumbnailer($conf);
1185 $link['thumbnail'] = $thumbnailer->get($url); 1185 $link['thumbnail'] = $thumbnailer->get($url);
1186 } 1186 }
@@ -1279,6 +1279,51 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1279 exit; 1279 exit;
1280 } 1280 }
1281 1281
1282 // -------- User clicked either "Set public" or "Set private" bulk operation
1283 if ($targetPage == Router::$PAGE_CHANGE_VISIBILITY) {
1284 if (! $sessionManager->checkToken($_GET['token'])) {
1285 die(t('Wrong token.'));
1286 }
1287
1288 $ids = trim($_GET['ids']);
1289 if (strpos($ids, ' ') !== false) {
1290 // multiple, space-separated ids provided
1291 $ids = array_values(array_filter(preg_split('/\s+/', escape($ids))));
1292 } else {
1293 // only a single id provided
1294 $ids = [$ids];
1295 }
1296
1297 // assert at least one id is given
1298 if (!count($ids)) {
1299 die('no id provided');
1300 }
1301 // assert that the visibility is valid
1302 if (!isset($_GET['newVisibility']) || !in_array($_GET['newVisibility'], ['public', 'private'])) {
1303 die('invalid visibility');
1304 } else {
1305 $private = $_GET['newVisibility'] === 'private';
1306 }
1307 foreach ($ids as $id) {
1308 $id = (int) escape($id);
1309 $link = $LINKSDB[$id];
1310 $link['private'] = $private;
1311 $pluginManager->executeHooks('save_link', $link);
1312 $LINKSDB[$id] = $link;
1313 }
1314 $LINKSDB->save($conf->get('resource.page_cache')); // save to disk
1315
1316 $location = '?';
1317 if (isset($_SERVER['HTTP_REFERER'])) {
1318 $location = generateLocation(
1319 $_SERVER['HTTP_REFERER'],
1320 $_SERVER['HTTP_HOST']
1321 );
1322 }
1323 header('Location: ' . $location); // After deleting the link, redirect to appropriate location
1324 exit;
1325 }
1326
1282 // -------- User clicked the "EDIT" button on a link: Display link edit form. 1327 // -------- User clicked the "EDIT" button on a link: Display link edit form.
1283 if (isset($_GET['edit_link'])) { 1328 if (isset($_GET['edit_link'])) {
1284 $id = (int) escape($_GET['edit_link']); 1329 $id = (int) escape($_GET['edit_link']);
@@ -1325,13 +1370,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1325 // If this is an HTTP(S) link, we try go get the page to extract 1370 // If this is an HTTP(S) link, we try go get the page to extract
1326 // the title (otherwise we will to straight to the edit form.) 1371 // the title (otherwise we will to straight to the edit form.)
1327 if (empty($title) && strpos(get_url_scheme($url), 'http') !== false) { 1372 if (empty($title) && strpos(get_url_scheme($url), 'http') !== false) {
1373 $retrieveDescription = $conf->get('general.retrieve_description');
1328 // Short timeout to keep the application responsive 1374 // Short timeout to keep the application responsive
1329 // The callback will fill $charset and $title with data from the downloaded page. 1375 // The callback will fill $charset and $title with data from the downloaded page.
1330 get_http_response( 1376 get_http_response(
1331 $url, 1377 $url,
1332 $conf->get('general.download_timeout', 30), 1378 $conf->get('general.download_timeout', 30),
1333 $conf->get('general.download_max_size', 4194304), 1379 $conf->get('general.download_max_size', 4194304),
1334 get_curl_download_callback($charset, $title) 1380 get_curl_download_callback($charset, $title, $description, $tags, $retrieveDescription)
1335 ); 1381 );
1336 if (! empty($title) && strtolower($charset) != 'utf-8') { 1382 if (! empty($title) && strtolower($charset) != 'utf-8') {
1337 $title = mb_convert_encoding($title, 'utf-8', $charset); 1383 $title = mb_convert_encoding($title, 'utf-8', $charset);
@@ -1525,6 +1571,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1525 if ($targetPage == Router::$PAGE_SAVE_PLUGINSADMIN) { 1571 if ($targetPage == Router::$PAGE_SAVE_PLUGINSADMIN) {
1526 try { 1572 try {
1527 if (isset($_POST['parameters_form'])) { 1573 if (isset($_POST['parameters_form'])) {
1574 $pluginManager->executeHooks('save_plugin_parameters', $_POST);
1528 unset($_POST['parameters_form']); 1575 unset($_POST['parameters_form']);
1529 foreach ($_POST as $param => $value) { 1576 foreach ($_POST as $param => $value) {
1530 $conf->set('plugins.'. $param, escape($value)); 1577 $conf->set('plugins.'. $param, escape($value));
@@ -1564,7 +1611,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1564 $ids = []; 1611 $ids = [];
1565 foreach ($LINKSDB as $link) { 1612 foreach ($LINKSDB as $link) {
1566 // A note or not HTTP(S) 1613 // A note or not HTTP(S)
1567 if ($link['url'][0] === '?' || ! startsWith(strtolower($link['url']), 'http')) { 1614 if (is_note($link['url']) || ! startsWith(strtolower($link['url']), 'http')) {
1568 continue; 1615 continue;
1569 } 1616 }
1570 $ids[] = $link['id']; 1617 $ids[] = $link['id'];
@@ -1668,11 +1715,7 @@ function buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager)
1668 $linkDisp = array(); 1715 $linkDisp = array();
1669 while ($i<$end && $i<count($keys)) { 1716 while ($i<$end && $i<count($keys)) {
1670 $link = $linksToDisplay[$keys[$i]]; 1717 $link = $linksToDisplay[$keys[$i]];
1671 $link['description'] = format_description( 1718 $link['description'] = format_description($link['description']);
1672 $link['description'],
1673 $conf->get('redirector.url'),
1674 $conf->get('redirector.encode_url')
1675 );
1676 $classLi = ($i % 2) != 0 ? '' : 'publicLinkHightLight'; 1719 $classLi = ($i % 2) != 0 ? '' : 'publicLinkHightLight';
1677 $link['class'] = $link['private'] == 0 ? $classLi : 'private'; 1720 $link['class'] = $link['private'] == 0 ? $classLi : 'private';
1678 $link['timestamp'] = $link['created']->getTimestamp(); 1721 $link['timestamp'] = $link['created']->getTimestamp();
@@ -1733,7 +1776,6 @@ function buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager)
1733 'search_term' => $searchterm, 1776 'search_term' => $searchterm,
1734 'search_tags' => $searchtags, 1777 'search_tags' => $searchtags,
1735 'visibility' => ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : '', 1778 'visibility' => ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : '',
1736 'redirector' => $conf->get('redirector.url'), // Optional redirector URL.
1737 'links' => $linkDisp, 1779 'links' => $linkDisp,
1738 ); 1780 );
1739 1781
@@ -1883,9 +1925,7 @@ try {
1883$linkDb = new LinkDB( 1925$linkDb = new LinkDB(
1884 $conf->get('resource.datastore'), 1926 $conf->get('resource.datastore'),
1885 $loginManager->isLoggedIn(), 1927 $loginManager->isLoggedIn(),
1886 $conf->get('privacy.hide_public_links'), 1928 $conf->get('privacy.hide_public_links')
1887 $conf->get('redirector.url'),
1888 $conf->get('redirector.encode_url')
1889); 1929);
1890 1930
1891$container = new \Slim\Container(); 1931$container = new \Slim\Container();
@@ -1908,7 +1948,7 @@ $app->group('/api/v1', function () {
1908 $this->put('/tags/{tagName:[\w]+}', '\Shaarli\Api\Controllers\Tags:putTag')->setName('putTag'); 1948 $this->put('/tags/{tagName:[\w]+}', '\Shaarli\Api\Controllers\Tags:putTag')->setName('putTag');
1909 $this->delete('/tags/{tagName:[\w]+}', '\Shaarli\Api\Controllers\Tags:deleteTag')->setName('deleteTag'); 1949 $this->delete('/tags/{tagName:[\w]+}', '\Shaarli\Api\Controllers\Tags:deleteTag')->setName('deleteTag');
1910 1950
1911 $this->get('/history', '\Shaarli\Api\Controllers\History:getHistory')->setName('getHistory'); 1951 $this->get('/history', '\Shaarli\Api\Controllers\HistoryController:getHistory')->setName('getHistory');
1912})->add('\Shaarli\Api\ApiMiddleware'); 1952})->add('\Shaarli\Api\ApiMiddleware');
1913 1953
1914$response = $app->run(true); 1954$response = $app->run(true);