diff --git a/phpBB/common.php b/phpBB/common.php index c69ee4395e..f5e81ad1a6 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -99,7 +99,15 @@ else if (defined('IN_CRON')) { chdir($phpbb_root_path); - $phpbb_root_path = getcwd() . '/'; + if (@function_exists('getcwd')) + { + $phpbb_root_path = getcwd() . '/'; + } + else + { + // This is a best guess + $phpbb_root_path = pathinfo($_SERVER['SCRIPT_FILENAME'], PATHINFO_DIRNAME) . '/'; + } } if (!file_exists($phpbb_root_path . 'config.' . $phpEx)) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index ebe94adac7..3e89769234 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -378,56 +378,183 @@ if (!function_exists('stripos')) if (!function_exists('realpath')) { - /** - * Replacement for realpath if it is disabled - * This function is from the php manual by nospam at savvior dot com - */ - function phpbb_realpath($path) + if (substr(PHP_OS, 0, 3) != 'WIN' && !(bool) ini_get('safe_mode') && function_exists('shell_exec') && trim(`realpath .`)) { - $translated_path = getenv('PATH_TRANSLATED'); - - $translated_path = str_replace('\\', '/', $translated_path); - $translated_path = str_replace(basename(getenv('PATH_INFO')), '', $translated_path); - - $translated_path .= '/'; - - if ($path == '.' || $path == './') + /** + * @author Chris Smith + * @copyright 2006 Project Minerva Team + * @param string $path The path which we should attempt to resolve. + * @return mixed + */ + function phpbb_realpath($path) { - return $translated_path; + $arg = escapeshellarg($path); + return trim(`realpath '$arg'`); + } + } + else + { + /** + * Checks if a path ($path) is absolute or relative + * + * @param string $path Path to check absoluteness of + * @return boolean + */ + function is_absolute($path) + { + return ($path[0] == '/' || (substr(PHP_OS, 0, 3) == 'WIN' && preg_match('#^[a-z]:/#i', $path))) ? true : false; } - // now check for back directory - $translated_path .= $path; - - $dirs = explode('/', $translated_path); - - foreach ($dirs as $key => $value) + /** + * @author Chris Smith + * @copyright 2006 Project Minerva Team + * @param string $path The path which we should attempt to resolve. + * @return mixed + */ + function phpbb_realpath($path) { - if ($value == '..') + // Now to perform funky shizzle + + // Switch to use UNIX slashes + $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); + $path_prefix = ''; + + // Determine what sort of path we have + if (is_absolute($path)) { - $dirs[$key] = ''; - $dirs[$key - 2] = ''; + $absolute = true; + + if ($path[0] == '/') + { + // Absolute path, *NIX style + $path_prefix = ''; + } + else + { + // Absolute path, Windows style + // Remove the drive letter and colon + $path_prefix = $path[0] . ':'; + $path = substr($path, 2); + } } - } - - $translated_path = ''; - - foreach ($dirs as $key => $value) - { - if (strlen($value) > 0) + else { - $translated_path .= $value . '/'; + // Relative Path + // Prepend the current working directory + if (function_exists('getcwd')) + { + // This is the best method, hopefully it is enabled! + $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path; + $absolute = true; + if (preg_match('#^[a-z]:#i', $path)) + { + $path_prefix = $path[0] . ':'; + $path = substr($path, 2); + } + else + { + $path_prefix = ''; + } + } + else if (isset($_SERVER['SCRIPT_FILENAME']) && !empty($_SERVER['SCRIPT_FILENAME'])) + { + // Warning: If chdir() has been used this will lie! + // @todo This has some problems sometime (CLI can create them easily) + $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($_SERVER['SCRIPT_FILENAME'])) . '/' . $path; + $absolute = true; + $path_prefix = ''; + } + else + { + // We have no way of getting the absolute path, just run on using relative ones. + $absolute = false; + $path_prefix = '.'; + } } + + // Remove any repeated slashes + $path = preg_replace('#/{2,}#', '/', $path); + + // Remove the slashes from the start and end of the path + $path = trim($path, '/'); + + // Break the string into little bits for us to nibble on + $bits = explode('/', $path); + + // Remove any . in the path + $bits = array_diff($bits, array('.')); + + // Lets get looping, run over and resolve any .. (up directory) + for ($i = 0, $max = sizeof($bits); $i < $max; $i++) + { + // @todo Optimise + if ($bits[$i] == '..' ) + { + if (isset($bits[$i - 1])) + { + if ($bits[$i - 1] != '..') + { + // We found a .. and we are able to traverse upwards, lets do it! + unset($bits[$i]); + unset($bits[$i - 1]); + $i -= 2; + $max -= 2; + $bits = array_values($bits); + } + } + else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute + { + // We have an absolute path trying to descend above the root of the filesystem + // ... Error! + return false; + } + } + } + + // Prepend the path prefix + array_unshift($bits, $path_prefix); + + $resolved = ''; + + $max = sizeof($bits) - 1; + + // Check if we are able to resolve symlinks, Windows cannot. + $symlink_resolve = (function_exists('readlink')) ? true : false; + + foreach ($bits as $i => $bit) + { + if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit"))) + { + // Path Exists + if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit"))) + { + // Resolved a symlink. + $resolved = $link . (($i == $max) ? '' : '/'); + continue; + } + } + else + { + // Something doesn't exist here! + // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic + // return false; + } + $resolved .= $bit . (($i == $max) ? '' : '/'); + } + + // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it + // because we must be inside that basedir, the question is where... + // @interal The slash in is_dir() gets around an open_basedir restriction + if (!@file_exists($resolved) || (!is_dir($resolved . '/') && !is_file($resolved))) + { + return false; + } + + // Put the slashes back to the native operating systems slashes + $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved); + + return $resolved; // We got here, in the end! } - - $translated_path = substr($translated_path, 0, strlen($translated_path) - 1); - - if (is_dir($translated_path) || is_file($translated_path)) - { - return $translated_path; - } - - return false; } } else @@ -1919,7 +2046,7 @@ function decode_message(&$message, $bbcode_uid = '') */ function generate_text_for_display($text, $uid, $bitfield, $flags) { - global $__bbcode; + static $bbcode; if (!$text) { @@ -1937,14 +2064,14 @@ function generate_text_for_display($text, $uid, $bitfield, $flags) if (empty($__bbcode)) { - $__bbcode = new bbcode($bitfield); + $bbcode = new bbcode($bitfield); } else { - $__bbcode->bbcode($bitfield); + $bbcode->bbcode($bitfield); } - $__bbcode->bbcode_second_pass($text, $uid); + $bbcode->bbcode_second_pass($text, $uid); } $text = smiley_text($text, !($flags & 2));