PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/standard/incubator/library/Zend/Loader.php

https://github.com/bhaumik25/zend-framework
PHP | 298 lines | 125 code | 20 blank | 153 comment | 29 complexity | 1a42006711bf525c13fee5f7f3b0304a MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Loader
  17. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id$
  20. */
  21. /**
  22. * Static methods for loading classes and files.
  23. *
  24. * @category Zend
  25. * @package Zend_Loader
  26. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  27. * @license http://framework.zend.com/license/new-bsd New BSD License
  28. */
  29. class Zend_Loader
  30. {
  31. /**
  32. * Accumulation of suppressed errors
  33. *
  34. * Each element is a stdClass object having the following properties that correspond to the values passed to the
  35. * error handling method: errno, errstr, errfile, errline, and errcontext.
  36. *
  37. * @var array
  38. */
  39. public static $errors = array();
  40. /**
  41. * Loads a class from a PHP file. The filename must be formatted
  42. * as "$class.php".
  43. *
  44. * If $dirs is a string or an array, it will search the directories
  45. * in the order supplied, and attempt to load the first matching file.
  46. *
  47. * If $dirs is null, it will split the class name at underscores to
  48. * generate a path hierarchy (e.g., "Zend_Example_Class" will map
  49. * to "Zend/Example/Class.php").
  50. *
  51. * If the file was not found in the $dirs, or if no $dirs were specified,
  52. * it will attempt to load it from PHP's include_path.
  53. *
  54. * @param string $class - The full class name of a Zend component.
  55. * @param string|array $dirs - OPTIONAL Either a path or an array of paths
  56. * to search.
  57. * @return void
  58. * @throws Zend_Exception
  59. */
  60. public static function loadClass($class, $dirs = null)
  61. {
  62. if (class_exists($class, false) || interface_exists($class, false)) {
  63. return;
  64. }
  65. if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) {
  66. require_once 'Zend/Exception.php';
  67. throw new Zend_Exception('Directory argument must be a string or an array');
  68. }
  69. // autodiscover the path from the class name
  70. $file = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
  71. if (!empty($dirs)) {
  72. // use the autodiscovered path
  73. $dirPath = dirname($file);
  74. if (is_string($dirs)) {
  75. $dirs = explode(PATH_SEPARATOR, $dirs);
  76. }
  77. foreach ($dirs as $key => $dir) {
  78. if ($dir == '.') {
  79. $dirs[$key] = $dirPath;
  80. } else {
  81. $dir = rtrim($dir, '\\/');
  82. $dirs[$key] = $dir . DIRECTORY_SEPARATOR . $dirPath;
  83. }
  84. }
  85. $file = basename($file);
  86. self::loadFile($file, $dirs, true);
  87. } else {
  88. self::_securityCheck($file);
  89. include_once $file;
  90. }
  91. if (!class_exists($class, false) && !interface_exists($class, false)) {
  92. require_once 'Zend/Exception.php';
  93. throw new Zend_Exception("File \"$file\" was loaded but class \"$class\" was not found in the file");
  94. }
  95. }
  96. /**
  97. * Loads a PHP file. This is a wrapper for PHP's include() function.
  98. *
  99. * $filename must be the complete filename, including any
  100. * extension such as ".php". Note that a security check is performed that
  101. * does not permit extended characters in the filename. This method is
  102. * intended for loading Zend Framework files.
  103. *
  104. * If $dirs is a string or an array, it will search the directories
  105. * in the order supplied, and attempt to load the first matching file.
  106. *
  107. * If the file was not found in the $dirs, or if no $dirs were specified,
  108. * it will attempt to load it from PHP's include_path.
  109. *
  110. * If $once is TRUE, it will use include_once() instead of include().
  111. *
  112. * @param string $filename
  113. * @param string|array $dirs - OPTIONAL either a path or array of paths
  114. * to search.
  115. * @param boolean $once
  116. * @return boolean
  117. * @throws Zend_Exception
  118. */
  119. public static function loadFile($filename, $dirs = null, $once = false)
  120. {
  121. self::_securityCheck($filename);
  122. /**
  123. * Search in provided directories, as well as include_path
  124. */
  125. $incPath = false;
  126. if (!empty($dirs) && (is_array($dirs) || is_string($dirs))) {
  127. if (is_array($dirs)) {
  128. $dirs = implode(PATH_SEPARATOR, $dirs);
  129. }
  130. $incPath = get_include_path();
  131. set_include_path($dirs . PATH_SEPARATOR . $incPath);
  132. }
  133. /**
  134. * Try finding for the plain filename in the include_path.
  135. */
  136. if ($once) {
  137. include_once $filename;
  138. } else {
  139. include $filename;
  140. }
  141. /**
  142. * If searching in directories, reset include_path
  143. */
  144. if ($incPath) {
  145. set_include_path($incPath);
  146. }
  147. return true;
  148. }
  149. /**
  150. * Returns TRUE if the $filename is readable, or FALSE otherwise.
  151. * This function uses the PHP include_path, where PHP's is_readable()
  152. * does not.
  153. *
  154. * @param string $filename
  155. * @return boolean
  156. */
  157. public static function isReadable($filename)
  158. {
  159. if (!$fh = @fopen($filename, 'r', true)) {
  160. return false;
  161. }
  162. return true;
  163. }
  164. /**
  165. * spl_autoload() suitable implementation for supporting class autoloading.
  166. *
  167. * Attach to spl_autoload() using the following:
  168. * <code>
  169. * spl_autoload_register(array('Zend_Loader', 'autoload'));
  170. * </code>
  171. *
  172. * @param string $class
  173. * @return string|false Class name on success; false on failure
  174. */
  175. public static function autoload($class)
  176. {
  177. set_error_handler(array('self', 'suppressFileNotFoundWarnings'));
  178. try {
  179. self::loadClass($class);
  180. restore_error_handler();
  181. return $class;
  182. } catch (Exception $e) {
  183. restore_error_handler();
  184. return false;
  185. }
  186. }
  187. /**
  188. * Register {@link autoload()} with spl_autoload()
  189. *
  190. * @param string $class (optional)
  191. * @param boolean $enabled (optional)
  192. * @return void
  193. * @throws Zend_Exception if spl_autoload() is not found
  194. * or if the specified class does not have an autoload() method.
  195. */
  196. public static function registerAutoload($class = 'Zend_Loader', $enabled = true)
  197. {
  198. if (!function_exists('spl_autoload_register')) {
  199. require_once 'Zend/Exception.php';
  200. throw new Zend_Exception('spl_autoload does not exist in this PHP installation');
  201. }
  202. self::loadClass($class);
  203. $methods = get_class_methods($class);
  204. if (!in_array('autoload', (array) $methods)) {
  205. require_once 'Zend/Exception.php';
  206. throw new Zend_Exception("The class \"$class\" does not have an autoload() method");
  207. }
  208. if ($enabled === true) {
  209. spl_autoload_register(array($class, 'autoload'));
  210. } else {
  211. spl_autoload_unregister(array($class, 'autoload'));
  212. }
  213. }
  214. /**
  215. * If the raised error appears to be a "file not found" warning, it is suppressed, accumulated, and exposed through
  216. * the $errors property. Otherwise, the raised error is passed along to be handled normally (this method returns
  217. * false).
  218. *
  219. * @param integer $errno
  220. * @param string $errstr
  221. * @param string $errfile
  222. * @param integer $errline
  223. * @param array $errcontext
  224. * @return void|false
  225. */
  226. public static function suppressFileNotFoundWarnings($errno, $errstr, $errfile, $errline, array $errcontext)
  227. {
  228. if (!preg_match('/failed (to open stream|opening .+ for inclusion)/i', $errstr)) {
  229. return false;
  230. }
  231. $error = new stdClass();
  232. $error->errno = $errno;
  233. $error->errstr = $errstr;
  234. $error->errfile = $errfile;
  235. $error->errline = $errline;
  236. $error->errcontext = $errcontext;
  237. self::$errors[] = $error;
  238. }
  239. /**
  240. * Ensure that filename does not contain exploits
  241. *
  242. * @param string $filename
  243. * @return void
  244. * @throws Zend_Exception
  245. */
  246. protected static function _securityCheck($filename)
  247. {
  248. /**
  249. * Security check
  250. */
  251. if (preg_match('/[^a-z0-9\\/\\\\_.-]/i', $filename)) {
  252. require_once 'Zend/Exception.php';
  253. throw new Zend_Exception('Security check: Illegal character in filename');
  254. }
  255. }
  256. /**
  257. * Attempt to include() the file.
  258. *
  259. * include() is not prefixed with the @ operator because if
  260. * the file is loaded and contains a parse error, execution
  261. * will halt silently and this is difficult to debug.
  262. *
  263. * Always set display_errors = Off on production servers!
  264. *
  265. * @param string $filespec
  266. * @param boolean $once
  267. * @return boolean
  268. * @deprecated Since 1.5.0; use loadFile() instead
  269. */
  270. protected static function _includeFile($filespec, $once = false)
  271. {
  272. if ($once) {
  273. return include_once $filespec;
  274. } else {
  275. return include $filespec ;
  276. }
  277. }
  278. }