From d8fa09e06c5c8098b3ab37573a7e1b2e474a1abc Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Sun, 2 Jun 2013 16:59:54 +0200 Subject: [PATCH] Improved makeWritable() to set as much permissions as possible 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 | 60 ++++++++++++++----- .../install/files/lib/util/FileUtil.class.php | 43 ++++++++----- 2 files changed, 74 insertions(+), 29 deletions(-) diff --git a/wcfsetup/install.php b/wcfsetup/install.php index 8e27f505f1..fae7c23a3d 100644 --- a/wcfsetup/install.php +++ b/wcfsetup/install.php @@ -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."); + } } } diff --git a/wcfsetup/install/files/lib/util/FileUtil.class.php b/wcfsetup/install/files/lib/util/FileUtil.class.php index d119ee9346..6528dcde0e 100644 --- a/wcfsetup/install/files/lib/util/FileUtil.class.php +++ b/wcfsetup/install/files/lib/util/FileUtil.class.php @@ -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() { } -- 2.20.1