]> git.immae.eu Git - github/shaarli/Shaarli.git/blobdiff - index.php
API: add DELETE endpoint
[github/shaarli/Shaarli.git] / index.php
index e553d1ddcfd3564f3a8abdeeb575a9f428ee248b..6eaa56c210931d5e5afcb296e71e51fc1614ae66 100644 (file)
--- a/index.php
+++ b/index.php
@@ -1,8 +1,6 @@
 <?php
 /**
- * Shaarli v0.8.1 - Shaare your links...
- *
- * The personal, minimalist, super-fast, database free, bookmarking service.
+ * Shaarli - The personal, minimalist, super-fast, database free, bookmarking service.
  *
  * Friendly fork by the Shaarli community:
  *  - https://github.com/shaarli/Shaarli
@@ -13,7 +11,7 @@
  *
  * Licence: http://www.opensource.org/licenses/zlib-license.php
  *
- * Requires: PHP 5.3.x
+ * Requires: PHP 5.5.x
  */
 
 // Set 'UTC' as the default timezone if it is not defined in php.ini
@@ -25,7 +23,6 @@ if (date_default_timezone_get() == '') {
 /*
  * PHP configuration
  */
-define('shaarli_version', '0.8.1');
 
 // http://server.com/x/shaarli --> /shaarli/
 define('WEB_PATH', substr($_SERVER['REQUEST_URI'], 0, 1+strrpos($_SERVER['REQUEST_URI'], '/', 0)));
@@ -62,7 +59,6 @@ require_once __DIR__ . '/vendor/autoload.php';
 require_once 'application/ApplicationUtils.php';
 require_once 'application/Cache.php';
 require_once 'application/CachedPage.php';
-require_once 'application/config/ConfigManager.php';
 require_once 'application/config/ConfigPlugin.php';
 require_once 'application/FeedBuilder.php';
 require_once 'application/FileUtils.php';
@@ -80,16 +76,19 @@ require_once 'application/PluginManager.php';
 require_once 'application/Router.php';
 require_once 'application/Updater.php';
 use \Shaarli\ThemeUtils;
+use \Shaarli\Config\ConfigManager;
 
 // Ensure the PHP version is supported
 try {
-    ApplicationUtils::checkPHPVersion('5.3', PHP_VERSION);
+    ApplicationUtils::checkPHPVersion('5.5', PHP_VERSION);
 } catch(Exception $exc) {
     header('Content-Type: text/plain; charset=utf-8');
     echo $exc->getMessage();
     exit;
 }
 
+define('shaarli_version', ApplicationUtils::getVersion(__DIR__ .'/'. ApplicationUtils::$VERSION_FILE));
+
 // Force cookie path (but do not change lifetime)
 $cookie = session_get_cookie_params();
 $cookiedir = '';
@@ -204,7 +203,7 @@ function setup_login_state($conf)
        }
        // If session does not exist on server side, or IP address has changed, or session has expired, logout.
        if (empty($_SESSION['uid'])
-        || ($conf->get('security.session_protection_disabled') == false && $_SESSION['ip'] != allIPs())
+        || ($conf->get('security.session_protection_disabled') === false && $_SESSION['ip'] != allIPs())
         || time() >= $_SESSION['expires_on'])
        {
            logout();
@@ -433,7 +432,7 @@ if (isset($_POST['login']))
         // Optional redirect after login:
         if (isset($_GET['post'])) {
             $uri = '?post='. urlencode($_GET['post']);
-            foreach (array('description', 'source', 'title') as $param) {
+            foreach (array('description', 'source', 'title', 'tags') as $param) {
                 if (!empty($_GET[$param])) {
                     $uri .= '&'.$param.'='.urlencode($_GET[$param]);
                 }
@@ -462,7 +461,7 @@ if (isset($_POST['login']))
         $redir = '&username='. $_POST['login'];
         if (isset($_GET['post'])) {
             $redir .= '&post=' . urlencode($_GET['post']);
-            foreach (array('description', 'source', 'title') as $param) {
+            foreach (array('description', 'source', 'title', 'tags') as $param) {
                 if (!empty($_GET[$param])) {
                     $redir .= '&' . $param . '=' . urlencode($_GET[$param]);
                 }
@@ -696,9 +695,11 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager)
 
     $dayDate = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $day.'_000000');
     $data = array(
+        'pagetitle' => $conf->get('general.title') .' - '. format_date($dayDate, false),
         'linksToDisplay' => $linksToDisplay,
         'cols' => $columns,
         'day' => $dayDate->getTimestamp(),
+        'dayDate' => $dayDate,
         'previousday' => $previousday,
         'nextday' => $nextday,
     );
@@ -1012,7 +1013,12 @@ function renderPage($conf, $pluginManager, $LINKSDB)
             $_SESSION['LINKS_PER_PAGE']=abs(intval($_GET['linksperpage']));
         }
 
-        header('Location: '. generateLocation($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST'], array('linksperpage')));
+        if (! empty($_SERVER['HTTP_REFERER'])) {
+            $location = generateLocation($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST'], array('linksperpage'));
+        } else {
+            $location = '?';
+        }
+        header('Location: '. $location);
         exit;
     }
 
@@ -1024,7 +1030,12 @@ function renderPage($conf, $pluginManager, $LINKSDB)
             unset($_SESSION['privateonly']); // See all links
         }
 
-        header('Location: '. generateLocation($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST'], array('privateonly')));
+        if (! empty($_SERVER['HTTP_REFERER'])) {
+            $location = generateLocation($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST'], array('privateonly'));
+        } else {
+            $location = '?';
+        }
+        header('Location: '. $location);
         exit;
     }
 
@@ -1035,7 +1046,13 @@ function renderPage($conf, $pluginManager, $LINKSDB)
         // Show login screen, then redirect to ?post=...
         if (isset($_GET['post']))
         {
-            header('Location: ?do=login&post='.urlencode($_GET['post']).(!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').(!empty($_GET['description'])?'&description='.urlencode($_GET['description']):'').(!empty($_GET['source'])?'&source='.urlencode($_GET['source']):'')); // Redirect to login page, then back to post link.
+            header( // Redirect to login page, then back to post link.
+                'Location: ?do=login&post='.urlencode($_GET['post']).
+                (!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').
+                (!empty($_GET['description'])?'&description='.urlencode($_GET['description']):'').
+                (!empty($_GET['tags'])?'&tags='.urlencode($_GET['tags']):'').
+                (!empty($_GET['source'])?'&source='.urlencode($_GET['source']):'')
+            );
             exit;
         }
 
@@ -1132,7 +1149,7 @@ function renderPage($conf, $pluginManager, $LINKSDB)
             $conf->set('feed.rss_permalinks', !empty($_POST['enableRssPermalinks']));
             $conf->set('updates.check_updates', !empty($_POST['updateCheck']));
             $conf->set('privacy.hide_public_links', !empty($_POST['hidePublicLinks']));
-            $conf->set('api.enabled', !empty($_POST['apiEnabled']));
+            $conf->set('api.enabled', !empty($_POST['enableApi']));
             $conf->set('api.secret', escape($_POST['apiSecret']));
             try {
                 $conf->write(isLoggedIn());
@@ -1198,7 +1215,7 @@ function renderPage($conf, $pluginManager, $LINKSDB)
                 $LINKSDB[$key]=$value;
             }
             $LINKSDB->save($conf->get('resource.page_cache'));
-            echo '<script>alert("Tag was removed from '.count($linksToAlter).' links.");document.location=\'?\';</script>';
+            echo '<script>alert("Tag was removed from '.count($linksToAlter).' links.");document.location=\'?do=changetag\';</script>';
             exit;
         }
 
@@ -1207,15 +1224,15 @@ function renderPage($conf, $pluginManager, $LINKSDB)
             $needle = trim($_POST['fromtag']);
             // True for case-sensitive tag search.
             $linksToAlter = $LINKSDB->filterSearch(array('searchtags' => $needle), true);
-            foreach($linksToAlter as $key=>$value)
-            {
-                $tags = explode(' ',trim($value['tags']));
-                $tags[array_search($needle,$tags)] = trim($_POST['totag']); // Replace tags value.
-                $value['tags']=trim(implode(' ',$tags));
-                $LINKSDB[$key]=$value;
+            foreach($linksToAlter as $key=>$value) {
+                $tags = preg_split('/\s+/', trim($value['tags']));
+                // Replace tags value.
+                $tags[array_search($needle, $tags)] = trim($_POST['totag']);
+                $value['tags'] = implode(' ', array_unique($tags));
+                $LINKSDB[$key] = $value;
             }
             $LINKSDB->save($conf->get('resource.page_cache')); // Save to disk.
-            echo '<script>alert("Tag was renamed in '.count($linksToAlter).' links.");document.location=\'?searchtags='.urlencode($_POST['totag']).'\';</script>';
+            echo '<script>alert("Tag was renamed in '.count($linksToAlter).' links.");document.location=\'?searchtags='.urlencode(escape($_POST['totag'])).'\';</script>';
             exit;
         }
     }
@@ -1236,7 +1253,7 @@ function renderPage($conf, $pluginManager, $LINKSDB)
         }
 
         // lf_id should only be present if the link exists.
-        $id = !empty($_POST['lf_id']) ? intval(escape($_POST['lf_id'])) : $LINKSDB->getNextId();
+        $id = isset($_POST['lf_id']) ? intval(escape($_POST['lf_id'])) : $LINKSDB->getNextId();
         // Linkdate is kept here to:
         //   - use the same permalink for notes as they're displayed when creating them
         //   - let users hack creation date of their posts
@@ -1309,9 +1326,13 @@ function renderPage($conf, $pluginManager, $LINKSDB)
     // -------- User clicked the "Cancel" button when editing a link.
     if (isset($_POST['cancel_edit']))
     {
+        $id = isset($_POST['lf_id']) ? (int) escape($_POST['lf_id']) : false;
+        if (! isset($LINKSDB[$id])) {
+            header('Location: ?');
+        }
         // If we are called from the bookmarklet, we must close the popup:
         if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; }
-        $link = $LINKSDB[(int) escape($_POST['lf_id'])];
+        $link = $LINKSDB[$id];
         $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' );
         // Scroll to the link which has been edited.
         $returnurl .= '#'. $link['shorturl'];
@@ -1339,31 +1360,15 @@ function renderPage($conf, $pluginManager, $LINKSDB)
 
         // If we are called from the bookmarklet, we must close the popup:
         if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; }
-        // Pick where we're going to redirect
-        // =============================================================
-        // Basically, we can't redirect to where we were previously if it was a permalink
-        // or an edit_link, because it would 404.
-        // Cases:
-        //    - /             : nothing in $_GET, redirect to self
-        //    - /?page        : redirect to self
-        //    - /?searchterm  : redirect to self (there might be other links)
-        //    - /?searchtags  : redirect to self
-        //    - /permalink    : redirect to / (the link does not exist anymore)
-        //    - /?edit_link   : redirect to / (the link does not exist anymore)
-        // PHP treats the permalink as a $_GET variable, so we need to check if every condition for self
-        // redirect is not satisfied, and only then redirect to /
-        $location = "?";
-        // Self redirection
-        if (count($_GET) == 0
-            || isset($_GET['page'])
-            || isset($_GET['searchterm'])
-            || isset($_GET['searchtags'])
-        ) {
-            if (isset($_POST['returnurl'])) {
-                $location = $_POST['returnurl']; // Handle redirects given by the form
-            } else {
-                $location = generateLocation($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST'], array('delete_link'));
-            }
+
+        $location = '?';
+        if (isset($_SERVER['HTTP_REFERER'])) {
+            // Don't redirect to where we were previously if it was a permalink or an edit_link, because it would 404.
+            $location = generateLocation(
+                    $_SERVER['HTTP_REFERER'],
+                    $_SERVER['HTTP_HOST'],
+                    ['delete_link', 'edit_link', $link['shorturl']]
+            );
         }
 
         header('Location: ' . $location); // After deleting the link, redirect to appropriate location
@@ -1534,7 +1539,7 @@ function renderPage($conf, $pluginManager, $LINKSDB)
             $_POST,
             $_FILES,
             $LINKSDB,
-            $conf->get('resource.page_cache')
+            $conf
         );
         echo '<script>alert("'.$status.'");document.location=\'?do='
              .Router::$PAGE_IMPORT .'\';</script>';
@@ -1620,8 +1625,8 @@ function buildLinkList($PAGE,$LINKSDB, $conf, $pluginManager)
         }
     } else {
         // Filter links according search parameters.
-        $privateonly = !empty($_SESSION['privateonly']);
-        $linksToDisplay = $LINKSDB->filterSearch($_GET, false, $privateonly);
+        $visibility = ! empty($_SESSION['privateonly']) ? 'private' : 'all';
+        $linksToDisplay = $LINKSDB->filterSearch($_GET, false, $visibility);
     }
 
     // ---- Handle paging.
@@ -1688,6 +1693,7 @@ function buildLinkList($PAGE,$LINKSDB, $conf, $pluginManager)
         'result_count' => count($linksToDisplay),
         'search_term' => $searchterm,
         'search_tags' => $searchtags,
+        'visibility' => ! empty($_SESSION['privateonly']) ? 'private' : '',
         'redirector' => $conf->get('redirector.url'),  // Optional redirector URL.
         'links' => $linkDisp,
         'tags' => $LINKSDB->allTags(),
@@ -2236,13 +2242,18 @@ $app = new \Slim\App($container);
 
 // REST API routes
 $app->group('/api/v1', function() {
-    $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo');
+    $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo')->setName('getInfo');
+    $this->get('/links', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks');
+    $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink');
+    $this->post('/links', '\Shaarli\Api\Controllers\Links:postLink')->setName('postLink');
+    $this->put('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:putLink')->setName('putLink');
+    $this->delete('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:deleteLink')->setName('deleteLink');
 })->add('\Shaarli\Api\ApiMiddleware');
 
 $response = $app->run(true);
 // Hack to make Slim and Shaarli router work together:
-// If a Slim route isn't found, we call renderPage().
-if ($response->getStatusCode() == 404) {
+// If a Slim route isn't found and NOT API call, we call renderPage().
+if ($response->getStatusCode() == 404 && strpos($_SERVER['REQUEST_URI'], '/api/v1') === false) {
     // We use UTF-8 for proper international characters handling.
     header('Content-Type: text/html; charset=utf-8');
     renderPage($conf, $pluginManager, $linkDb);