Improved makeWritable() to set as much permissions as possible
authorAlexander Ebert <ebert@woltlab.com>
Sun, 2 Jun 2013 14:59:54 +0000 (16:59 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sun, 2 Jun 2013 14:59:54 +0000 (16:59 +0200)
This avoids issues on webspace environments where user and group of the webserver differ from the FTP user, preventing either the webserver or FTP user to modify the files.

wcfsetup/install.php
wcfsetup/install/files/lib/util/FileUtil.class.php

index 8e27f505f163923a9b319a928e8852b59af89800..fae7c23a3d411e936f9582d0f145f65b6fd25e54 100644 (file)
@@ -221,6 +221,12 @@ function handleError($errorNo, $message, $filename, $lineNo) {
  * @author     Marcel Werk
  */
 class BasicFileUtil {
+       /**
+        * chmod mode
+        * @var integer
+        */
+       protected static $mode = null;
+       
        /**
         * Tries to find the temp folder.
         *
@@ -289,33 +295,59 @@ class BasicFileUtil {
        
        /**
         * Tries to make a file or directory writable. It starts of with the least
-        * permissions and goes up until 0777.
+        * permissions and goes up until 0666 for files and 0777 for directories.
         *
         * @param       string          $filename
         */
        public static function makeWritable($filename) {
-               if (is_writable($filename)) {
+               if (!file_exists($filename) || is_writable($filename)) {
                        return;
                }
                
-               $chmods = array('0644', '0755', '0775', '0777');
+               // determine mode
+               if (self::$mode === null) {
+                       // do not use PHP_OS here, as this represents the system it was built on != running on
+                       if (strpos(php_uname(), 'Windows') !== false) {
+                               self::$mode = 0777;
+                       }
+                       else {
+                               self::$mode = 0666;
+                               
+                               $filename = '__permissions_'.sha1(time()).'.txt';
+                               @touch($filename);
+                               
+                               // create a new file and check the file owner, if it is the same
+                               // as this file (uploaded through FTP), we can safely grant write
+                               // permissions exclusively to the owner rather than everyone
+                               if (file_exists($filename)) {
+                                       $scriptOwner = fileowner(__FILE__);
+                                       $fileOwner = fileowner($filename);
+                                       
+                                       if ($scriptOwner === $fileOwner) {
+                                               self::$mode = 0644;
+                                       }
+                                       
+                                       @unlink($filename);
+                               }
+                       }
+               }
                
                $startIndex = 0;
                if (is_dir($filename)) {
-                       $startIndex = 1;
-               }
-               
-               for ($i = $startIndex; $i < 4; $i++) {
-                       @chmod($filename, octdec($chmods[$i]));
-                       
-                       if (is_writable($filename)) {
-                               break;
+                       if (self::$mode == 0644) {
+                               chmod($filename, 0755);
                        }
-                       else if ($i == 3) {
-                               // does not work with 0777
-                               throw new SystemException("Unable to make '".$filename."' writable. This is a misconfiguration of your server, please contact your system administrator or hosting provider.");
+                       else {
+                               chmod($filename, 0777);
                        }
                }
+               else {
+                       chmod($filename, self::$mode);
+               }
+               
+               if (!is_writable($filename)) {
+                       throw new SystemException("Unable to make '".$filename."' writable. This is a misconfiguration of your server, please contact your system administrator or hosting provider.");
+               }
        }
 }
 
index d119ee9346348091b3477fd853fe9c73da92c129..6528dcde0ec20f1a376cc3594e9120a7a6dfd87e 100644 (file)
@@ -21,6 +21,12 @@ final class FileUtil {
         */
        protected static $finfo = null;
        
+       /**
+        * chmod mode
+        * @var string
+        */
+       protected static $mode = null;
+       
        /**
         * Tries to find the temp folder.
         * 
@@ -480,33 +486,40 @@ final class FileUtil {
        
        /**
         * Tries to make a file or directory writable. It starts of with the least
-        * permissions and goes up until 0777.
+        * permissions and goes up until 0666 for files and 0777 for directories.
         * 
         * @param       string          $filename
         */
        public static function makeWritable($filename) {
-               if (is_writable($filename)) {
+               if (!file_exists($filename) || is_writable($filename)) {
                        return;
                }
                
-               $chmods = array('0644', '0755', '0775', '0777');
-               
-               $startIndex = 0;
-               if (is_dir($filename)) {
-                       $startIndex = 1;
+               // mirror permissions of WCF.class.php
+               if (self::$mode === null) {
+                       if (!file_exists(WCF_DIR . 'lib/system/WCF.class.php')) {
+                               throw new SystemException("Unable to find 'wcf/lib/system/WCF.class.php'.");
+                       }
+                       
+                       self::$mode = '0' . substr(sprintf('%o', fileperms(WCF_DIR . 'lib/system/WCF.class.php')), -3);
                }
                
-               for ($i = $startIndex; $i < 4; $i++) {
-                       @chmod($filename, octdec($chmods[$i]));
-                       
-                       if (is_writable($filename)) {
-                               break;
+               if (is_dir($filename)) {
+                       if (self::$mode == '0644') {
+                               chmod($filename, 0755);
                        }
-                       else if ($i == 3) {
-                               // does not work with 0777
-                               throw new SystemException("Unable to make '".$filename."' writable. This is a misconfiguration of your server, please contact your system administrator or hosting provider.");
+                       else {
+                               chmod($filename, 0777);
                        }
                }
+               else {
+                       chmod($filename, octdec(self::$mode));
+               }
+               
+               if (!is_writable($filename)) {
+                       // does not work with 0777
+                       throw new SystemException("Unable to make '".$filename."' writable. This is a misconfiguration of your server, please contact your system administrator or hosting provider.");
+               }
        }
        
        private function __construct() { }