]> git.immae.eu Git - github/shaarli/Shaarli.git/blobdiff - application/ApplicationUtils.php
namespacing: \Shaarli\ApplicationUtils
[github/shaarli/Shaarli.git] / application / ApplicationUtils.php
index 7f963e9786cc50901863789341bc802ed1e22403..7fe3cb3245a9791f2a0324a3f6fd3ec377421cfc 100644 (file)
@@ -1,12 +1,21 @@
 <?php
+namespace Shaarli;
+
+use Exception;
+use Shaarli\Config\ConfigManager;
+
 /**
  * Shaarli (application) utilities
  */
 class ApplicationUtils
 {
+    /**
+     * @var string File containing the current version
+     */
+    public static $VERSION_FILE = 'shaarli_version.php';
+
     private static $GIT_URL = 'https://raw.githubusercontent.com/shaarli/Shaarli';
-    private static $GIT_BRANCHES = array('master', 'stable');
-    private static $VERSION_FILE = 'shaarli_version.php';
+    private static $GIT_BRANCHES = array('latest', 'stable');
     private static $VERSION_START_TAG = '<?php /* ';
     private static $VERSION_END_TAG = ' */ ?>';
 
@@ -20,7 +29,7 @@ class ApplicationUtils
      *
      * @return mixed the version code from the repository if available, else 'false'
      */
-    public static function getLatestGitVersionCode($url, $timeout=2)
+    public static function getLatestGitVersionCode($url, $timeout = 2)
     {
         list($headers, $data) = get_http_response($url, $timeout);
 
@@ -29,6 +38,30 @@ class ApplicationUtils
             return false;
         }
 
+        return $data;
+    }
+
+    /**
+     * Retrieve the version from a remote URL or a file.
+     *
+     * @param string $remote  URL or file to fetch.
+     * @param int    $timeout For URLs fetching.
+     *
+     * @return bool|string The version or false if it couldn't be retrieved.
+     */
+    public static function getVersion($remote, $timeout = 2)
+    {
+        if (startsWith($remote, 'http')) {
+            if (($data = static::getLatestGitVersionCode($remote, $timeout)) === false) {
+                return false;
+            }
+        } else {
+            if (!is_file($remote)) {
+                return false;
+            }
+            $data = file_get_contents($remote);
+        }
+
         return str_replace(
             array(self::$VERSION_START_TAG, self::$VERSION_END_TAG, PHP_EOL),
             array('', '', ''),
@@ -58,20 +91,18 @@ class ApplicationUtils
      *
      * @return mixed the new version code if available and greater, else 'false'
      */
-    public static function checkUpdate($currentVersion,
-                                       $updateFile,
-                                       $checkInterval,
-                                       $enableCheck,
-                                       $isLoggedIn,
-                                       $branch='stable')
-    {
-        if (! $isLoggedIn) {
-            // Do not check versions for visitors
-            return false;
-        }
-
-        if (empty($enableCheck)) {
-            // Do not check if the user doesn't want to
+    public static function checkUpdate(
+        $currentVersion,
+        $updateFile,
+        $checkInterval,
+        $enableCheck,
+        $isLoggedIn,
+        $branch = 'stable'
+    ) {
+        // Do not check versions for visitors
+        // Do not check if the user doesn't want to
+        // Do not check with dev version
+        if (!$isLoggedIn || empty($enableCheck) || $currentVersion === 'dev') {
             return false;
         }
 
@@ -85,7 +116,7 @@ class ApplicationUtils
             return false;
         }
 
-        if (! in_array($branch, self::$GIT_BRANCHES)) {
+        if (!in_array($branch, self::$GIT_BRANCHES)) {
             throw new Exception(
                 'Invalid branch selected for updates: "' . $branch . '"'
             );
@@ -93,11 +124,11 @@ class ApplicationUtils
 
         // Late Static Binding allows overriding within tests
         // See http://php.net/manual/en/language.oop5.late-static-bindings.php
-        $latestVersion = static::getLatestGitVersionCode(
+        $latestVersion = static::getVersion(
             self::$GIT_URL . '/' . $branch . '/' . self::$VERSION_FILE
         );
 
-        if (! $latestVersion) {
+        if (!$latestVersion) {
             // Only update the file's modification date
             file_put_contents($updateFile, $currentVersion);
             return false;
@@ -124,12 +155,13 @@ class ApplicationUtils
     public static function checkPHPVersion($minVersion, $curVersion)
     {
         if (version_compare($curVersion, $minVersion) < 0) {
-            throw new Exception(
+            $msg = t(
                 'Your PHP version is obsolete!'
-                .' Shaarli requires at least PHP '.$minVersion.', and thus cannot run.'
-                .' Your PHP version has known security vulnerabilities and should be'
-                .' updated as soon as possible.'
+                . ' Shaarli requires at least PHP %s, and thus cannot run.'
+                . ' Your PHP version has known security vulnerabilities and should be'
+                . ' updated as soon as possible.'
             );
+            throw new Exception(sprintf($msg, $minVersion));
         }
     }
 
@@ -143,55 +175,72 @@ class ApplicationUtils
     public static function checkResourcePermissions($conf)
     {
         $errors = array();
+        $rainTplDir = rtrim($conf->get('resource.raintpl_tpl'), '/');
 
         // Check script and template directories are readable
         foreach (array(
-            'application',
-            'inc',
-            'plugins',
-            $conf->get('resource.raintpl_tpl'),
-        ) as $path) {
-            if (! is_readable(realpath($path))) {
-                $errors[] = '"'.$path.'" directory is not readable';
+                     'application',
+                     'inc',
+                     'plugins',
+                     $rainTplDir,
+                     $rainTplDir . '/' . $conf->get('resource.theme'),
+                 ) as $path) {
+            if (!is_readable(realpath($path))) {
+                $errors[] = '"' . $path . '" ' . t('directory is not readable');
             }
         }
 
         // Check cache and data directories are readable and writable
         foreach (array(
-            $conf->get('resource.thumbnails_cache'),
-            $conf->get('resource.data_dir'),
-            $conf->get('resource.page_cache'),
-            $conf->get('resource.raintpl_tmp'),
-        ) as $path) {
-            if (! is_readable(realpath($path))) {
-                $errors[] = '"'.$path.'" directory is not readable';
+                     $conf->get('resource.thumbnails_cache'),
+                     $conf->get('resource.data_dir'),
+                     $conf->get('resource.page_cache'),
+                     $conf->get('resource.raintpl_tmp'),
+                 ) as $path) {
+            if (!is_readable(realpath($path))) {
+                $errors[] = '"' . $path . '" ' . t('directory is not readable');
             }
-            if (! is_writable(realpath($path))) {
-                $errors[] = '"'.$path.'" directory is not writable';
+            if (!is_writable(realpath($path))) {
+                $errors[] = '"' . $path . '" ' . t('directory is not writable');
             }
         }
 
         // Check configuration files are readable and writable
         foreach (array(
-            $conf->getConfigFileExt(),
-            $conf->get('resource.datastore'),
-            $conf->get('resource.ban_file'),
-            $conf->get('resource.log'),
-            $conf->get('resource.update_check'),
-        ) as $path) {
-            if (! is_file(realpath($path))) {
+                     $conf->getConfigFileExt(),
+                     $conf->get('resource.datastore'),
+                     $conf->get('resource.ban_file'),
+                     $conf->get('resource.log'),
+                     $conf->get('resource.update_check'),
+                 ) as $path) {
+            if (!is_file(realpath($path))) {
                 # the file may not exist yet
                 continue;
             }
 
-            if (! is_readable(realpath($path))) {
-                $errors[] = '"'.$path.'" file is not readable';
+            if (!is_readable(realpath($path))) {
+                $errors[] = '"' . $path . '" ' . t('file is not readable');
             }
-            if (! is_writable(realpath($path))) {
-                $errors[] = '"'.$path.'" file is not writable';
+            if (!is_writable(realpath($path))) {
+                $errors[] = '"' . $path . '" ' . t('file is not writable');
             }
         }
 
         return $errors;
     }
+
+    /**
+     * Returns a salted hash representing the current Shaarli version.
+     *
+     * Useful for assets browser cache.
+     *
+     * @param string $currentVersion of Shaarli
+     * @param string $salt           User personal salt, also used for the authentication
+     *
+     * @return string version hash
+     */
+    public static function getVersionHash($currentVersion, $salt)
+    {
+        return hash_hmac('sha256', $currentVersion, $salt);
+    }
 }