From b7e84bf5cb3f83c9e639ace73472f9b069799a84 Mon Sep 17 00:00:00 2001 From: Chuck Hagenbuch Date: Thu, 15 Oct 2009 13:59:58 -0400 Subject: [PATCH] Don't include files using a relative path; always run through the include_path explicitly trying absolute paths. This avoids PHP checking the local directory for a file even if '.' isn't in the include_path. Also, we now use realpath() directly instead of Horde_Util::realPath(). This both reduces dependencies, and it removes invalid paths from the include_path. The generic realPath() has its use, but here we're dealing with real files on the filesystem. --- framework/Autoloader/lib/Horde/Autoloader.php | 61 ++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/framework/Autoloader/lib/Horde/Autoloader.php b/framework/Autoloader/lib/Horde/Autoloader.php index 4a3d5d310..f2740943f 100644 --- a/framework/Autoloader/lib/Horde/Autoloader.php +++ b/framework/Autoloader/lib/Horde/Autoloader.php @@ -43,35 +43,64 @@ class Horde_Autoloader if (!is_null($replace) && preg_match($pattern, $class, $matches, PREG_OFFSET_CAPTURE)) { if (strcasecmp($matches[0][0], $class) === 0) { - $file_path = $replace . '/' . $class; + $relativePath = $replace . '/' . $class; } else { - $file_path = str_replace(array('::', '_'), '/', substr($class, 0, $matches[0][1])) . + $relativePath = str_replace(array('::', '_'), '/', substr($class, 0, $matches[0][1])) . $replace . str_replace(array('::', '_'), '/', substr($class, $matches[0][1] + strlen($matches[0][0]))); } - if (self::_loadClass($file_path)) { + if (self::_loadClass($relativePath)) { return true; } } } /* Do a final search in the include path. */ - $file_path = str_replace(array('::', '_'), '/', $class); - return self::_loadClass($file_path); + $relativePath = str_replace(array('::', '_'), '/', $class); + return self::_loadClass($relativePath); } /** - * TODO + * Try to load the class from each path in the include_path. + * + * @param string $relativePath + */ + protected static function _loadClass($relativePath) + { + if (substr($relativePath, 0, 1) == '/') { + return self::_loadClassUsingAbsolutePath($relativePath); + } + + if (is_null(self::$_includeCache)) { + self::_cacheIncludePath(); + } + + foreach (self::$_includeCache as $includePath) { + if (self::_loadClassUsingAbsolutePath($includePath . DIRECTORY_SEPARATOR . $relativePath)) { + return true; + } + } + + return false; + } + + /** + * Include a PHP file using an absolute path, suppressing E_WARNING and + * E_DEPRECATED errors, but letting fatal/parse errors come through. + * + * @param string $absolutePath + * + * @TODO Remove E_DEPRECATED masking */ - protected static function _loadClass($file_path) + protected static function _loadClassUsingAbsolutePath($absolutePath) { $err_mask = E_ALL ^ E_WARNING; if (defined('E_DEPRECATED')) { $err_mask = $err_mask ^ E_DEPRECATED; } $oldErrorReporting = error_reporting($err_mask); - $included = include $file_path . '.php'; + $included = include $absolutePath . '.php'; error_reporting($oldErrorReporting); return $included; } @@ -86,12 +115,12 @@ class Horde_Autoloader */ public static function addClassPath($path, $prepend = true) { + $path = realpath($path); + if (is_null(self::$_includeCache)) { - self::$_includeCache = array_keys(array_flip(array_map(array('Horde_Util', 'realPath'), explode(PATH_SEPARATOR, get_include_path())))); + self::_cacheIncludePath(); } - $path = realpath($path); - if (in_array($path, self::$_includeCache)) { // The path is already present in our stack; don't re-add it. return implode(PATH_SEPARATOR, self::$_includeCache); @@ -129,6 +158,16 @@ class Horde_Autoloader self::$_classPatterns[] = array($pattern, $replace); } + static function _cacheIncludePath() + { + self::$_includeCache = array(); + foreach (explode(PATH_SEPARATOR, get_include_path()) as $path) { + $path = realpath($path); + if ($path) { + self::$_includeCache[] = $path; + } + } + } } /* Register the autoloader in a way to play well with as many configurations -- 2.11.0