/ */ class P4Cms_Loader { protected static $_packages = array(); /** * Load classes via package registry and with knowledge of 'special' * module classes such as: controllers, forms, models, etc. * * @param string $class the name of the class to load. * @return string|false class name on success - false on failure */ public static function autoload($class) { // optimistic (registered package) case. $package = substr($class, 0, strpos($class, '_')); if (isset(static::$_packages[$package])) { $file = static::$_packages[$package] . '/' . str_replace('_', '/', substr($class, strlen($package) + 1)) . '.php'; // if file exists (via direct or 'special' mapping), include it. if (is_readable($file) || $file = static::_resolveSpecialClass($class, $package) ) { include $file; return $class; } } // general case: autodiscover the path from the class name $file = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php'; self::_securityCheck($file); if (Zend_Loader::isReadable($file)) { include $file; return $class; } return false; } /** * Register a module path to be checked when auto-loading classes. * * @param string $namespace the module namespace. * @param string $path the absolute path to the module. */ public static function addPackagePath($namespace, $path) { self::$_packages[$namespace] = $path; } /** * Set module paths to the given array of paths keyed on namespaces. * * @param array $paths an array of module paths keyed on namespaces. */ public static function setPackagePaths($paths) { self::$_packages = $paths; } /** * Get the set of registered module paths. * * @return array an array of registered module paths keyed on namespaces. */ public static function getPackagePaths() { return self::$_packages; } /** * Find the path to a special class that resides in a registered package. * * @param string $class the name of the class to resolve. * @param string $package the name of the package. * @return false|string the path to the class, or false if unsuccessful. */ protected static function _resolveSpecialClass($class, $package) { // map various class types to their associated sub-folders. $classTypes = array( "Acl" => "acls", "Acl_Assert" => "acls/asserts", "Controller_Helper" => "controllers/helpers", "Filter" => "filters", "Form" => "forms", "Form_Decorator" => "forms/decorators", "Form_Element" => "forms/elements", "Model" => "models", "Test" => "tests", "Validate" => "validators", "View_Helper" => "views/helpers" ); // extract class prefix (sans package name) and suffix. $suffix = substr($class, strrpos($class, '_') + 1); $prefix = substr($class, strpos($class, '_') + 1, -(strlen($suffix) + 1)); // generate path according to class type: // controllers - special case ending in 'Controller' // special classes - map class prefix to path if (!$prefix && substr($suffix, -10) === "Controller") { $path = "controllers/" . $suffix; } else if (isset($classTypes[$prefix])) { $path = $classTypes[$prefix] . '/' . $suffix; } else { return false; } // return filename. $file = static::$_packages[$package] . '/' . $path . ".php"; if (is_readable($file)) { return $file; } else { return false; } } /** * Ensure that filename does not contain exploits * * @param string $filename the filename to check for exploits * @return void * @throws Zend_Exception if the filename contains illegal characters */ protected static function _securityCheck($filename) { if (preg_match('/[^a-z0-9\\/\\\\_.:-]/i', $filename)) { require_once 'Zend/Exception.php'; throw new Zend_Exception('Security check: Illegal character in filename'); } } }