diff --git a/phpBB/includes/acm/acm_file.php b/phpBB/includes/acm/acm_file.php index e05977d158..a6733245bf 100644 --- a/phpBB/includes/acm/acm_file.php +++ b/phpBB/includes/acm/acm_file.php @@ -93,12 +93,7 @@ class phpbb_acm_file extends phpbb_acm_abstract @flock($fp, LOCK_UN); fclose($fp); - if (!function_exists('phpbb_chmod')) - { - include(PHPBB_ROOT_PATH . 'includes/functions.' . PHP_EXT); - } - - phpbb_chmod($filename, phpbb::CHMOD_WRITE); + phpbb::$system->chmod($filename, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); } return $data; @@ -172,12 +167,7 @@ class phpbb_acm_file extends phpbb_acm_abstract @flock($fp, LOCK_UN); fclose($fp); - if (!function_exists('phpbb_chmod')) - { - include(PHPBB_ROOT_PATH . 'includes/functions.' . PHP_EXT); - } - - phpbb_chmod($filename, phpbb::CHMOD_WRITE); + phpbb::$system->chmod($filename, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); } else { diff --git a/phpBB/includes/classes/template_compile.php b/phpBB/includes/classes/template_compile.php index a5ead08b35..3f6f82f5df 100644 --- a/phpBB/includes/classes/template_compile.php +++ b/phpBB/includes/classes/template_compile.php @@ -844,7 +844,7 @@ class phpbb_template_compile @flock($destination_handle, LOCK_UN); @fclose($destination_handle); - phpbb_chmod($filename, phpbb::CHMOD_WRITE); + phpbb::$system->chmod($filename, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); clearstatcache(); diff --git a/phpBB/includes/core/bootstrap.php b/phpBB/includes/core/bootstrap.php index 0a4910b052..f44b48c7db 100644 --- a/phpBB/includes/core/bootstrap.php +++ b/phpBB/includes/core/bootstrap.php @@ -2,7 +2,7 @@ /** * * @package core -* @version $Id: bootstrap.php 9216 2008-12-23 18:40:33Z acydburn $ +* @version $Id$ * @copyright (c) 2008 phpBB Group * @license http://opensource.org/licenses/gpl-license.php GNU Public License * diff --git a/phpBB/includes/core/core.php b/phpBB/includes/core/core.php index 36fef1fccc..2b2c4bea13 100644 --- a/phpBB/includes/core/core.php +++ b/phpBB/includes/core/core.php @@ -2,7 +2,7 @@ /** * * @package core -* @version $Id: core.php 9216 2008-12-23 18:40:33Z acydburn $ +* @version $Id$ * @copyright (c) 2008 phpBB Group * @license http://opensource.org/licenses/gpl-license.php GNU Public License * diff --git a/phpBB/includes/core/request.php b/phpBB/includes/core/request.php index 53d9b34b6c..7f3f158dc0 100644 --- a/phpBB/includes/core/request.php +++ b/phpBB/includes/core/request.php @@ -2,7 +2,7 @@ /** * * @package core -* @version $Id: request.php 9212 2008-12-21 19:15:55Z acydburn $ +* @version $Id$ * @copyright (c) 2008 phpBB Group * @license http://opensource.org/licenses/gpl-license.php GNU Public License * diff --git a/phpBB/includes/core/security.php b/phpBB/includes/core/security.php index 5079c361a2..f5aca65e8d 100644 --- a/phpBB/includes/core/security.php +++ b/phpBB/includes/core/security.php @@ -2,7 +2,7 @@ /** * * @package core -* @version $Id: core.php 9200 2008-12-15 18:06:53Z acydburn $ +* @version $Id$ * @copyright (c) 2008 phpBB Group * @license http://opensource.org/licenses/gpl-license.php GNU Public License * diff --git a/phpBB/includes/core/system.php b/phpBB/includes/core/system.php index 204917856c..55dca1d311 100644 --- a/phpBB/includes/core/system.php +++ b/phpBB/includes/core/system.php @@ -1,33 +1,210 @@ -chmod_info)) + { + if (!function_exists('fileowner') || !function_exists('filegroup')) + { + // No need to further determine owner/group - it is unknown + $this->chmod_info['process'] = false; + } + else + { + // Determine owner/group of common.php file and the filename we want to change here + $common_php_owner = fileowner(PHPBB_ROOT_PATH . 'common.' . PHP_EXT); + $common_php_group = filegroup(PHPBB_ROOT_PATH . 'common.' . PHP_EXT); + + // And the owner and the groups PHP is running under. + $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false; + $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; + + if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group) + { + $this->chmod_info['process'] = false; + } + else + { + $this->chmod_info = array( + 'process' => true, + 'common_owner' => $common_php_owner, + 'common_group' => $common_php_group, + 'php_uid' => $php_uid, + 'php_gids' => $php_gids, + ); + } + } + } + + if ($this->chmod_info['process']) + { + // Change owner + if (@chown($filename, $this->chmod_info['common_owner'])) + { + clearstatcache(); + $file_uid = fileowner($filename); + } + + // Change group + if (@chgrp($filename, $this->chmod_info['common_group'])) + { + clearstatcache(); + $file_gid = filegroup($filename); + } + + // If the file_uid/gid now match the one from common.php we can process further, else we are not able to change something + if ($file_uid != $this->chmod_info['common_owner'] || $file_gid != $this->chmod_info['common_group']) + { + $this->chmod_info['process'] = false; + } + } + + // Still able to process? + if ($this->chmod_info['process']) + { + if ($file_uid == $this->chmod_info['php_uid']) + { + $php = 'owner'; + } + else if (in_array($file_gid, $this->chmod_info['php_gids'])) + { + $php = 'group'; + } + else + { + // Since we are setting the everyone bit anyway, no need to do expensive operations + $this->chmod_info['process'] = false; + } + } + + // We are not able to determine or change something + if (!$this->chmod_info['process']) + { + $php = 'other'; + } + + // Owner always has read/write permission + $owner = phpbb::CHMOD_READ | phpbb::CHMOD_WRITE; + if (is_dir($filename)) + { + $owner |= phpbb::CHMOD_EXECUTE; + + // Only add execute bit to the permission if the dir needs to be readable + if ($perms & phpbb::CHMOD_READ) + { + $perms |= phpbb::CHMOD_EXECUTE; + } + } + + switch ($php) + { + case 'owner': + $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); + + clearstatcache(); + + if (!is_null($php) || (is_readable($filename) && is_writable($filename))) + { + break; + } + + case 'group': + $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); + + clearstatcache(); + + if (!is_null($php) || ((!($perms & phpbb::CHMOD_READ) || is_readable($filename)) && (!($perms & phpbb::CHMOD_WRITE) || is_writable($filename)))) + { + break; + } + + case 'other': + $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); + + clearstatcache(); + + if (!is_null($php) || ((!($perms & phpbb::CHMOD_READ) || is_readable($filename)) && (!($perms & phpbb::CHMOD_WRITE) || is_writable($filename)))) + { + break; + } + + default: + return false; + break; + } + + return $result; + } + +} + ?> \ No newline at end of file diff --git a/phpBB/includes/core/system_info.php b/phpBB/includes/core/system_info.php index 870ee7895b..56a5d3bcd0 100644 --- a/phpBB/includes/core/system_info.php +++ b/phpBB/includes/core/system_info.php @@ -1,376 +1,376 @@ -data[$offset] = $value; - } - - public function offsetExists($offset) - { - return isset($this->data[$offset]); - } - - public function offsetUnset($offset) - { - unset($this->data[$offset]); - } - /**#@-*/ - - /** - * Get system information - Part of the ArrayAccess implementation. - * - * System information ought to be received from {@link $data phpbb::$user->system[key]}. - * The key used is mapped to a method with get_ as prefix. - * For example getting phpbb::$user->system['host'] results in calling the method get_host(). - * - * @param string $offset The key to get. - * @return mixed The result - * @access public - */ - public function offsetGet($offset) - { - if (isset($this->data[$offset])) - { - return $this->data[$offset]; - } - - $identifier = 'get_' . strtolower($offset); - - // Not static, because we are not able to use late static bindings - $this->data[$offset] = $this->$identifier(); - return $this->data[$offset]; - } - - /** - * Get valid hostname/port. HTTP_HOST is used, SERVER_NAME if HTTP_HOST not present. - * - * @return string Host (lowercase, not specialchared) - * @access protected - */ - protected function get_host() - { - // Get hostname - $host = (!empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME')); - - // Should be a string and lowered - $host = (string) strtolower($host); - - // If host is equal the cookie domain or the server name (if config is set), then we assume it is valid - if ((isset(phpbb::$config['cookie_domain']) && $host === phpbb::$config['cookie_domain']) || (isset(phpbb::$config['server_name']) && $host === phpbb::$config['server_name'])) - { - return $host; - } - - // Is the host actually a IP? If so, we use the IP... (IPv4) - if (long2ip(ip2long($host)) === $host) - { - return $host; - } - - // Now return the hostname (this also removes any port definition). The http:// is prepended to construct a valid URL, hosts never have a scheme assigned - $host = @parse_url('http://' . $host, PHP_URL_HOST); - - // Remove any portions not removed by parse_url (#) - $host = str_replace('#', '', $host); - - // If, by any means, the host is now empty, we will use a "best approach" way to guess one - if (empty($host)) - { - if (!empty(phpbb::$config['server_name'])) - { - $host = phpbb::$config['server_name']; - } - else if (!empty(phpbb::$config['cookie_domain'])) - { - $host = (strpos(phpbb::$config['cookie_domain'], '.') === 0) ? substr(phpbb::$config['cookie_domain'], 1) : phpbb::$config['cookie_domain']; - } - else - { - // Set to OS hostname or localhost - $host = (function_exists('php_uname')) ? strtolower(php_uname('n')) : 'localhost'; - } - } - - // It may be still no valid host, but for sure only a hostname (we may further expand on the cookie domain... if set) - return $host; - } - - /** - * Extract current session page, relative from current root path (PHPBB_ROOT_PATH) - * - * The array returned consist of the following key/value pairs: - * page_name: The current basename'd page name, for example: index.php (urlencoded, htmlspecialchared) - * page_dir: The current directory within the phpBB root, for example: adm - * query_string: The current query string, for example: i=10&b=2 (the parameter 'sid' is never included) - * script_path: The script path from the webroot to the current directory, for example: /phpBB3/adm/ - * The script path is always prefixed with / and ends in /. Specialchared, whitespace replaced with %20. - * root_script_path: The script path from the webroot to the phpBB root, for example: /phpBB3/ - * The root script path is always prefixed with / and ends in /. Specialchared, whitespace replaced with %20. - * page: Current page from phpBB root, for example: adm/index.php?i=10&b=2 - * forum: Current forum id (determined by {@link request_var() request_var('f', 0)}) - * - * @return array Array containing page information. - * @plugin-support return - * @access protected - */ - protected function get_page() - { - $page_array = array(); - - // First of all, get the request uri... - $script_name = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : getenv('PHP_SELF'); - $args = (!empty($_SERVER['QUERY_STRING'])) ? explode('&', $_SERVER['QUERY_STRING']) : explode('&', getenv('QUERY_STRING')); - - // If we are unable to get the script name we use REQUEST_URI as a failover and note it within the page array for easier support... - if (!$script_name) - { - $script_name = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : getenv('REQUEST_URI'); - $script_name = (($pos = strpos($script_name, '?')) !== false) ? substr($script_name, 0, $pos) : $script_name; - $page_array['failover'] = 1; - } - - // Replace backslashes and doubled slashes (could happen on some proxy setups) - $script_name = str_replace(array('\\', '//'), '/', $script_name); - - // Now, remove the sid and let us get a clean query string... - $use_args = array(); - - // Since some browser do not encode correctly we need to do this with some "special" characters... - // " -> %22, ' => %27, < -> %3C, > -> %3E - $find = array('"', "'", '<', '>'); - $replace = array('%22', '%27', '%3C', '%3E'); - - foreach ($args as $argument) - { - if (strpos($argument, 'sid=') === 0) - { - continue; - } - - $use_args[] = str_replace($find, $replace, $argument); - } - unset($args); - - // The following examples given are for an request uri of {path to the phpbb directory}/adm/index.php?i=10&b=2 - - // The current query string - $query_string = trim(implode('&', $use_args)); - - // basenamed page name (for example: index.php) - $page_name = basename($script_name); - $page_name = urlencode(htmlspecialchars($page_name)); - - // current directory within the phpBB root (for example: adm) - $root_dirs = explode('/', str_replace('\\', '/', phpbb::$url->realpath(PHPBB_ROOT_PATH))); - $page_dirs = explode('/', str_replace('\\', '/', phpbb::$url->realpath('./'))); - $intersection = array_intersect_assoc($root_dirs, $page_dirs); - - $root_dirs = array_diff_assoc($root_dirs, $intersection); - $page_dirs = array_diff_assoc($page_dirs, $intersection); - - $page_dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs); - - if ($page_dir && substr($page_dir, -1, 1) == '/') - { - $page_dir = substr($page_dir, 0, -1); - } - - // Current page from phpBB root (for example: adm/index.php?i=10&b=2) - $page = (($page_dir) ? $page_dir . '/' : '') . $page_name . (($query_string) ? "?$query_string" : ''); - - // The script path from the webroot to the current directory (for example: /phpBB3/adm/) : always prefixed with / and ends in / - $script_path = trim(str_replace('\\', '/', dirname($script_name))); - - // The script path from the webroot to the phpBB root (for example: /phpBB3/) - $script_dirs = explode('/', $script_path); - array_splice($script_dirs, -sizeof($page_dirs)); - $root_script_path = implode('/', $script_dirs) . (sizeof($root_dirs) ? '/' . implode('/', $root_dirs) : ''); - - // We are on the base level (phpBB root == webroot), lets adjust the variables a bit... - if (!$root_script_path) - { - $root_script_path = ($page_dir) ? str_replace($page_dir, '', $script_path) : $script_path; - } - - $script_path .= (substr($script_path, -1, 1) == '/') ? '' : '/'; - $root_script_path .= (substr($root_script_path, -1, 1) == '/') ? '' : '/'; - - $page_array += array( - 'page_name' => $page_name, - 'page_dir' => $page_dir, - - 'query_string' => $query_string, - 'script_path' => str_replace(' ', '%20', htmlspecialchars($script_path)), - 'root_script_path' => str_replace(' ', '%20', htmlspecialchars($root_script_path)), - - 'page' => $page, - 'forum' => request_var('f', 0), - ); - - return ($this->method_inject(__FUNCTION__, 'return')) ? $this->call_inject(__FUNCTION__, array('return', $page_array)) : $page_array; - } - - /** - * Get user agent string. - * - * @return string User agent, determined from $_SERVER['HTTP_USER_AGENT']. Specialchared. - * @access protected - */ - protected function get_browser() - { - return (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : ''; - } - - /** - * Get current referer - * - * @return string Referer, determined from $_SERVER['HTTP_REFERER']. Specialchared. - * @access protected - */ - protected function get_referer() - { - return (!empty($_SERVER['HTTP_REFERER'])) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : ''; - } - - /** - * Get server port - * - * @return int Sertver port, determined from $_SERVER/$_ENV['SERVER_PORT']. - * @access protected - */ - protected function get_port() - { - return (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT'); - } - - /** - * Get forwarded-for string. - * If the forwarded for check is enabled in phpBB the ip's are checked for valid data and invalid data being removed. - * - * @return string Forwarded-for string, determined from $_SERVER['HTTP_X_FORWARDED_FOR']. - * @access protected - */ - protected function get_forwarded_for() - { - $forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? (string) $_SERVER['HTTP_X_FORWARDED_FOR'] : ''; - - // if the forwarded for header shall be checked we have to validate its contents - if (phpbb::$config['forwarded_for_check']) - { - $forwarded_for = preg_replace('#, +#', ', ', $forwarded_for); - - // split the list of IPs - $ips = explode(', ', $forwarded_for); - foreach ($ips as $ip) - { - // check IPv4 first, the IPv6 is hopefully only going to be used very seldomly - if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip)) - { - // contains invalid data, don't use the forwarded for header - return ''; - } - } - } - else - { - return ''; - } - } - - /** - * Get remote ip - * - * @return string Remote IP, determined from $_SERVER['REMOTE_ADDR']. Specialchared. - * @access protected - */ - protected function get_ip() - { - return (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : ''; - } - - /** - * Get server load. - * - * Server load is retrieved if load limitation is enabled in phpBB and server supports {@link sys_getloadavg() sys_getloadavg} - * or file /proc/loadavg exists on the server. - * - * @return double Server load. - * @access protected - */ - protected function get_load() - { - $load = false; - - // Load limit check (if applicable) - if (phpbb::$config['limit_load'] || phpbb::$config['limit_search_load']) - { - if ((function_exists('sys_getloadavg') && $load = sys_getloadavg()) || ($load = explode(' ', @file_get_contents('/proc/loadavg')))) - { - $load = array_slice($load, 0, 1); - $load = floatval($load[0]); - } - else - { - set_config('limit_load', '0'); - set_config('limit_search_load', '0'); - } - } - - return $load; - } - - /** - * Get current request method. - * - * @return string Request method, determined from $_SERVER['REQUEST_METHOD']. Specialchared, lowercase. - * @access protected - */ - protected function get_request_method() - { - return (isset($_SERVER['REQUEST_METHOD'])) ? strtolower(htmlspecialchars((string) $_SERVER['REQUEST_METHOD'])) : ''; - } -} - +data[$offset] = $value; + } + + public function offsetExists($offset) + { + return isset($this->data[$offset]); + } + + public function offsetUnset($offset) + { + unset($this->data[$offset]); + } + /**#@-*/ + + /** + * Get system information - Part of the ArrayAccess implementation. + * + * System information ought to be received from {@link $data phpbb::$user->system[key]}. + * The key used is mapped to a method with get_ as prefix. + * For example getting phpbb::$user->system['host'] results in calling the method get_host(). + * + * @param string $offset The key to get. + * @return mixed The result + * @access public + */ + public function offsetGet($offset) + { + if (isset($this->data[$offset])) + { + return $this->data[$offset]; + } + + $identifier = 'get_' . strtolower($offset); + + // Not static, because we are not able to use late static bindings + $this->data[$offset] = $this->$identifier(); + return $this->data[$offset]; + } + + /** + * Get valid hostname/port. HTTP_HOST is used, SERVER_NAME if HTTP_HOST not present. + * + * @return string Host (lowercase, not specialchared) + * @access protected + */ + protected function get_host() + { + // Get hostname + $host = (!empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME')); + + // Should be a string and lowered + $host = (string) strtolower($host); + + // If host is equal the cookie domain or the server name (if config is set), then we assume it is valid + if ((isset(phpbb::$config['cookie_domain']) && $host === phpbb::$config['cookie_domain']) || (isset(phpbb::$config['server_name']) && $host === phpbb::$config['server_name'])) + { + return $host; + } + + // Is the host actually a IP? If so, we use the IP... (IPv4) + if (long2ip(ip2long($host)) === $host) + { + return $host; + } + + // Now return the hostname (this also removes any port definition). The http:// is prepended to construct a valid URL, hosts never have a scheme assigned + $host = @parse_url('http://' . $host, PHP_URL_HOST); + + // Remove any portions not removed by parse_url (#) + $host = str_replace('#', '', $host); + + // If, by any means, the host is now empty, we will use a "best approach" way to guess one + if (empty($host)) + { + if (!empty(phpbb::$config['server_name'])) + { + $host = phpbb::$config['server_name']; + } + else if (!empty(phpbb::$config['cookie_domain'])) + { + $host = (strpos(phpbb::$config['cookie_domain'], '.') === 0) ? substr(phpbb::$config['cookie_domain'], 1) : phpbb::$config['cookie_domain']; + } + else + { + // Set to OS hostname or localhost + $host = (function_exists('php_uname')) ? strtolower(php_uname('n')) : 'localhost'; + } + } + + // It may be still no valid host, but for sure only a hostname (we may further expand on the cookie domain... if set) + return $host; + } + + /** + * Extract current session page, relative from current root path (PHPBB_ROOT_PATH) + * + * The array returned consist of the following key/value pairs: + * page_name: The current basename'd page name, for example: index.php (urlencoded, htmlspecialchared) + * page_dir: The current directory within the phpBB root, for example: adm + * query_string: The current query string, for example: i=10&b=2 (the parameter 'sid' is never included) + * script_path: The script path from the webroot to the current directory, for example: /phpBB3/adm/ + * The script path is always prefixed with / and ends in /. Specialchared, whitespace replaced with %20. + * root_script_path: The script path from the webroot to the phpBB root, for example: /phpBB3/ + * The root script path is always prefixed with / and ends in /. Specialchared, whitespace replaced with %20. + * page: Current page from phpBB root, for example: adm/index.php?i=10&b=2 + * forum: Current forum id (determined by {@link request_var() request_var('f', 0)}) + * + * @return array Array containing page information. + * @plugin-support return + * @access protected + */ + protected function get_page() + { + $page_array = array(); + + // First of all, get the request uri... + $script_name = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : getenv('PHP_SELF'); + $args = (!empty($_SERVER['QUERY_STRING'])) ? explode('&', $_SERVER['QUERY_STRING']) : explode('&', getenv('QUERY_STRING')); + + // If we are unable to get the script name we use REQUEST_URI as a failover and note it within the page array for easier support... + if (!$script_name) + { + $script_name = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : getenv('REQUEST_URI'); + $script_name = (($pos = strpos($script_name, '?')) !== false) ? substr($script_name, 0, $pos) : $script_name; + $page_array['failover'] = 1; + } + + // Replace backslashes and doubled slashes (could happen on some proxy setups) + $script_name = str_replace(array('\\', '//'), '/', $script_name); + + // Now, remove the sid and let us get a clean query string... + $use_args = array(); + + // Since some browser do not encode correctly we need to do this with some "special" characters... + // " -> %22, ' => %27, < -> %3C, > -> %3E + $find = array('"', "'", '<', '>'); + $replace = array('%22', '%27', '%3C', '%3E'); + + foreach ($args as $argument) + { + if (strpos($argument, 'sid=') === 0) + { + continue; + } + + $use_args[] = str_replace($find, $replace, $argument); + } + unset($args); + + // The following examples given are for an request uri of {path to the phpbb directory}/adm/index.php?i=10&b=2 + + // The current query string + $query_string = trim(implode('&', $use_args)); + + // basenamed page name (for example: index.php) + $page_name = basename($script_name); + $page_name = urlencode(htmlspecialchars($page_name)); + + // current directory within the phpBB root (for example: adm) + $root_dirs = explode('/', str_replace('\\', '/', phpbb::$url->realpath(PHPBB_ROOT_PATH))); + $page_dirs = explode('/', str_replace('\\', '/', phpbb::$url->realpath('./'))); + $intersection = array_intersect_assoc($root_dirs, $page_dirs); + + $root_dirs = array_diff_assoc($root_dirs, $intersection); + $page_dirs = array_diff_assoc($page_dirs, $intersection); + + $page_dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs); + + if ($page_dir && substr($page_dir, -1, 1) == '/') + { + $page_dir = substr($page_dir, 0, -1); + } + + // Current page from phpBB root (for example: adm/index.php?i=10&b=2) + $page = (($page_dir) ? $page_dir . '/' : '') . $page_name . (($query_string) ? "?$query_string" : ''); + + // The script path from the webroot to the current directory (for example: /phpBB3/adm/) : always prefixed with / and ends in / + $script_path = trim(str_replace('\\', '/', dirname($script_name))); + + // The script path from the webroot to the phpBB root (for example: /phpBB3/) + $script_dirs = explode('/', $script_path); + array_splice($script_dirs, -sizeof($page_dirs)); + $root_script_path = implode('/', $script_dirs) . (sizeof($root_dirs) ? '/' . implode('/', $root_dirs) : ''); + + // We are on the base level (phpBB root == webroot), lets adjust the variables a bit... + if (!$root_script_path) + { + $root_script_path = ($page_dir) ? str_replace($page_dir, '', $script_path) : $script_path; + } + + $script_path .= (substr($script_path, -1, 1) == '/') ? '' : '/'; + $root_script_path .= (substr($root_script_path, -1, 1) == '/') ? '' : '/'; + + $page_array += array( + 'page_name' => $page_name, + 'page_dir' => $page_dir, + + 'query_string' => $query_string, + 'script_path' => str_replace(' ', '%20', htmlspecialchars($script_path)), + 'root_script_path' => str_replace(' ', '%20', htmlspecialchars($root_script_path)), + + 'page' => $page, + 'forum' => request_var('f', 0), + ); + + return ($this->method_inject(__FUNCTION__, 'return')) ? $this->call_inject(__FUNCTION__, array('return', $page_array)) : $page_array; + } + + /** + * Get user agent string. + * + * @return string User agent, determined from $_SERVER['HTTP_USER_AGENT']. Specialchared. + * @access protected + */ + protected function get_browser() + { + return (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : ''; + } + + /** + * Get current referer + * + * @return string Referer, determined from $_SERVER['HTTP_REFERER']. Specialchared. + * @access protected + */ + protected function get_referer() + { + return (!empty($_SERVER['HTTP_REFERER'])) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : ''; + } + + /** + * Get server port + * + * @return int Sertver port, determined from $_SERVER/$_ENV['SERVER_PORT']. + * @access protected + */ + protected function get_port() + { + return (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT'); + } + + /** + * Get forwarded-for string. + * If the forwarded for check is enabled in phpBB the ip's are checked for valid data and invalid data being removed. + * + * @return string Forwarded-for string, determined from $_SERVER['HTTP_X_FORWARDED_FOR']. + * @access protected + */ + protected function get_forwarded_for() + { + $forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? (string) $_SERVER['HTTP_X_FORWARDED_FOR'] : ''; + + // if the forwarded for header shall be checked we have to validate its contents + if (phpbb::$config['forwarded_for_check']) + { + $forwarded_for = preg_replace('#, +#', ', ', $forwarded_for); + + // split the list of IPs + $ips = explode(', ', $forwarded_for); + foreach ($ips as $ip) + { + // check IPv4 first, the IPv6 is hopefully only going to be used very seldomly + if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip)) + { + // contains invalid data, don't use the forwarded for header + return ''; + } + } + } + else + { + return ''; + } + } + + /** + * Get remote ip + * + * @return string Remote IP, determined from $_SERVER['REMOTE_ADDR']. Specialchared. + * @access protected + */ + protected function get_ip() + { + return (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : ''; + } + + /** + * Get server load. + * + * Server load is retrieved if load limitation is enabled in phpBB and server supports {@link sys_getloadavg() sys_getloadavg} + * or file /proc/loadavg exists on the server. + * + * @return double Server load. + * @access protected + */ + protected function get_load() + { + $load = false; + + // Load limit check (if applicable) + if (phpbb::$config['limit_load'] || phpbb::$config['limit_search_load']) + { + if ((function_exists('sys_getloadavg') && $load = sys_getloadavg()) || ($load = explode(' ', @file_get_contents('/proc/loadavg')))) + { + $load = array_slice($load, 0, 1); + $load = floatval($load[0]); + } + else + { + set_config('limit_load', '0'); + set_config('limit_search_load', '0'); + } + } + + return $load; + } + + /** + * Get current request method. + * + * @return string Request method, determined from $_SERVER['REQUEST_METHOD']. Specialchared, lowercase. + * @access protected + */ + protected function get_request_method() + { + return (isset($_SERVER['REQUEST_METHOD'])) ? strtolower(htmlspecialchars((string) $_SERVER['REQUEST_METHOD'])) : ''; + } +} + ?> \ No newline at end of file diff --git a/phpBB/includes/core/url.php b/phpBB/includes/core/url.php index 70315b4188..c743b36641 100644 --- a/phpBB/includes/core/url.php +++ b/phpBB/includes/core/url.php @@ -2,7 +2,7 @@ /** * * @package core -* @version $Id: url.php 9219 2008-12-24 12:43:15Z acydburn $ +* @version $Id$ * @copyright (c) 2008 phpBB Group * @license http://opensource.org/licenses/gpl-license.php GNU Public License * diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 9473f823e4..bdd175e9da 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -126,150 +126,6 @@ function still_on_time($extra_time = 15) return (ceil($current_time - $start_time) < $max_execution_time) ? true : false; } -/** -* Global function for chmodding directories and files for internal use -* This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. -* The function determines owner and group from common.php file and sets the same to the provided file. Permissions are mapped to the group, user always has rw(x) permission. -* The function uses bit fields to build the permissions. -* The function sets the appropiate execute bit on directories. -* -* Supported constants representing bit fields are: -* -* phpbb::CHMOD_ALL - all permissions (7) -* phpbb::CHMOD_READ - read permission (4) -* phpbb::CHMOD_WRITE - write permission (2) -* phpbb::CHMOD_EXECUTE - execute permission (1) -* -* NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. -* -* @param $filename The file/directory to be chmodded -* @param $perms Permissions to set -* @return true on success, otherwise false -* -* @author faw, phpBB Group -*/ -function phpbb_chmod($filename, $perms = phpbb::CHMOD_READ) -{ - // Return if the file no longer exists. - if (!file_exists($filename)) - { - return false; - } - - if (!function_exists('fileowner') || !function_exists('filegroup')) - { - $file_uid = $file_gid = false; - $common_php_owner = $common_php_group = false; - } - else - { - // Determine owner/group of common.php file and the filename we want to change here - $common_php_owner = fileowner(PHPBB_ROOT_PATH . 'common.' . PHP_EXT); - $common_php_group = filegroup(PHPBB_ROOT_PATH . 'common.' . PHP_EXT); - - $file_uid = fileowner($filename); - $file_gid = filegroup($filename); - - // Try to set the owner to the same common.php has - if ($common_php_owner !== $file_uid && $common_php_owner !== false && $file_uid !== false) - { - // Will most likely not work - if (@chown($filename, $common_php_owner)); - { - clearstatcache(); - $file_uid = fileowner($filename); - } - } - - // Try to set the group to the same common.php has - if ($common_php_group !== $file_gid && $common_php_group !== false && $file_gid !== false) - { - if (@chgrp($filename, $common_php_group)); - { - clearstatcache(); - $file_gid = filegroup($filename); - } - } - } - - // And the owner and the groups PHP is running under. - $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false; - $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; - - // Who is PHP? - if ($file_uid === false || $file_gid === false || $php_uid === false || $php_gids === false) - { - $php = NULL; - } - else if ($file_uid == $php_uid /* && $common_php_owner !== false && $common_php_owner === $file_uid*/) - { - $php = 'owner'; - } - else if (in_array($file_gid, $php_gids)) - { - $php = 'group'; - } - else - { - $php = 'other'; - } - - // Owner always has read/write permission - $owner = phpbb::CHMOD_READ | phpbb::CHMOD_WRITE; - if (is_dir($filename)) - { - $owner |= phpbb::CHMOD_EXECUTE; - - // Only add execute bit to the permission if the dir needs to be readable - if ($perms & phpbb::CHMOD_READ) - { - $perms |= phpbb::CHMOD_EXECUTE; - } - } - - switch ($php) - { - case null: - case 'owner': - /* ATTENTION: if php is owner or NULL we set it to group here. This is the most failsafe combination for the vast majority of server setups. - - $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); - - clearstatcache(); - - if (!is_null($php) || (is_readable($filename) && is_writable($filename))) - { - break; - } - */ - - case 'group': - $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); - - clearstatcache(); - - if (!is_null($php) || ((!($perms & phpbb::CHMOD_READ) || is_readable($filename)) && (!($perms & phpbb::CHMOD_WRITE) || is_writable($filename)))) - { - break; - } - - case 'other': - $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); - - clearstatcache(); - - if (!is_null($php) || ((!($perms & phpbb::CHMOD_READ) || is_readable($filename)) && (!($perms & phpbb::CHMOD_WRITE) || is_writable($filename)))) - { - break; - } - - default: - return false; - break; - } - - return $result; -} /** * Add a secret hash for use in links/GET requests diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php index dd3ea9bbf0..eebc82b9d0 100644 --- a/phpBB/includes/functions_compress.php +++ b/phpBB/includes/functions_compress.php @@ -226,7 +226,7 @@ class compress_zip extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); + phpbb::$system->chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); } } } @@ -255,7 +255,7 @@ class compress_zip extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); + phpbb::$system->chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); } } } @@ -540,7 +540,7 @@ class compress_tar extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); + phpbb::$system->chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); } } } @@ -567,7 +567,7 @@ class compress_tar extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); + phpbb::$system->chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); } } @@ -576,7 +576,7 @@ class compress_tar extends compress { trigger_error("Couldn't create file $filename"); } - phpbb_chmod($target_filename, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); + phpbb::$system->chmod($target_filename, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); // Grab the file contents fwrite($fp, ($filesize) ? $fzread($this->fp, ($filesize + 511) &~ 511) : '', $filesize); diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 98162eeb6e..dd89fa260e 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -561,7 +561,7 @@ class queue $fp = @fopen($this->cache_file . '.lock', 'wb'); fclose($fp); - @chmod($this->cache_file . '.lock', 0666); + phpbb::$system->chmod($this->cache_file . '.lock', phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); include($this->cache_file); @@ -696,7 +696,7 @@ class queue @flock($fp, LOCK_UN); fclose($fp); - phpbb_chmod($this->cache_file, phpbb::CHMOD_WRITE); + phpbb::$system->chmod($this->cache_file, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); } } @@ -737,7 +737,7 @@ class queue @flock($fp, LOCK_UN); fclose($fp); - phpbb_chmod($this->cache_file, phpbb::CHMOD_WRITE); + phpbb::$system->chmod($this->cache_file, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); } } } diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 29d6e3ea7c..5df9f6ff21 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -727,7 +727,7 @@ function create_thumbnail($source, $destination, $mimetype) return false; } - phpbb_chmod($destination, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); + phpbb::$system->chmod($destination, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); return true; } diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index f50394cc09..142ec1537a 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -263,7 +263,7 @@ class filespec * * @param string $destination_path Destination path, for example phpbb::$config['avatar_path'] * @param bool $overwrite If set to true, an already existing file will be overwritten - * @param string $chmod Permission mask for chmodding the file after a successful move. The mode entered here reflects the mode defined by {@link phpbb_chmod()} + * @param string $chmod Permission mask for chmodding the file after a successful move. The mode entered here is the octal permission mask. * * @access public */ @@ -348,7 +348,7 @@ class filespec break; } - phpbb_chmod($this->destination_file, $chmod); + phpbb::$system->chmod($this->destination_file, $chmod); } // Try to get real filesize from destination folder diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index 204634f6b0..c8d9df2b28 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -506,13 +506,13 @@ class install_install extends module if (!file_exists(PHPBB_ROOT_PATH . $dir)) { @mkdir(PHPBB_ROOT_PATH . $dir, 0777); - phpbb_chmod(PHPBB_ROOT_PATH . $dir, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); + phpbb::$system->chmod(PHPBB_ROOT_PATH . $dir, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); } // Now really check if (file_exists(PHPBB_ROOT_PATH . $dir) && is_dir(PHPBB_ROOT_PATH . $dir)) { - phpbb_chmod(PHPBB_ROOT_PATH . $dir, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); + phpbb::$system->chmod(PHPBB_ROOT_PATH . $dir, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); $exists = true; } @@ -827,7 +827,7 @@ class install_install extends module } @fclose($fp); - @chmod(PHPBB_ROOT_PATH . 'cache/install_lock', 0666); + phpbb::$system->chmod(PHPBB_ROOT_PATH . 'cache/install_lock', phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); $load_extensions = implode(',', $load_extensions); @@ -880,8 +880,7 @@ class install_install extends module if ($written) { - // We may revert back to chmod() if we see problems with users not able to change their config.php file directly - phpbb_chmod(PHPBB_ROOT_PATH . 'config.' . PHP_EXT, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); + @chmod(PHPBB_ROOT_PATH . 'config.' . PHP_EXT, 0644); } } diff --git a/phpBB/modules/acp/acp_attachments.php b/phpBB/modules/acp/acp_attachments.php index 5e8e28a1ed..97c679173d 100644 --- a/phpBB/modules/acp/acp_attachments.php +++ b/phpBB/modules/acp/acp_attachments.php @@ -1201,7 +1201,7 @@ class acp_attachments if (!file_exists(PHPBB_ROOT_PATH . $upload_dir)) { @mkdir(PHPBB_ROOT_PATH . $upload_dir, 0777); - phpbb_chmod(PHPBB_ROOT_PATH . $upload_dir, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); + phpbb::$system->chmod(PHPBB_ROOT_PATH . $upload_dir, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); } } diff --git a/phpBB/modules/acp/acp_language.php b/phpBB/modules/acp/acp_language.php index 71523dfa6d..65255a18d3 100644 --- a/phpBB/modules/acp/acp_language.php +++ b/phpBB/modules/acp/acp_language.php @@ -290,7 +290,7 @@ class acp_language { trigger_error("Could not create directory $dir", E_USER_ERROR); } - @chmod($dir, 0777); + phpbb::$system->chmod($dir, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); } } }