/fuel/core/classes/file/area.php

https://github.com/Keilaron/TweetBeagle · PHP · 264 lines · 146 code · 45 blank · 73 comment · 13 complexity · 6ed24dd3d4d1b08215e530b0db04e1cb MD5 · raw file

  1. <?php
  2. /**
  3. * Fuel is a fast, lightweight, community driven PHP5 framework.
  4. *
  5. * @package Fuel
  6. * @version 1.0
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2011 Fuel Development Team
  10. * @link http://fuelphp.com
  11. */
  12. namespace Fuel\Core;
  13. class File_Area {
  14. /**
  15. * @var string path to basedir restriction, null for no restriction
  16. */
  17. protected $basedir = null;
  18. /**
  19. * @var array array of allowed extensions, null for all
  20. */
  21. protected $extensions = null;
  22. /**
  23. * @var string base url for files, null for not available
  24. */
  25. protected $url = null;
  26. /**
  27. * @var bool whether or not to use file locks when doing file operations
  28. */
  29. protected $use_locks = false;
  30. /**
  31. * @var array contains file handler per file extension
  32. */
  33. protected $file_handlers = array();
  34. protected function __construct(Array $config = array())
  35. {
  36. foreach ($config as $key => $value)
  37. {
  38. if (property_exists($this, $key))
  39. {
  40. $this->{$key} = $value;
  41. }
  42. }
  43. if ( ! empty($this->basedir))
  44. {
  45. $this->basedir = realpath($this->basedir) ?: $this->basedir;
  46. }
  47. }
  48. /**
  49. * Factory for area objects
  50. *
  51. * @param array
  52. * @return File_Area
  53. */
  54. public static function factory(Array $config = array())
  55. {
  56. return new static($config);
  57. }
  58. /**
  59. * Handler factory for given path
  60. *
  61. * @param string path to file or directory
  62. * @param array optional config
  63. * @return File_Handler_File
  64. * @throws FileAccessException when outside basedir restriction or disallowed file extension
  65. */
  66. public function get_handler($path, Array $config = array(), $content = array())
  67. {
  68. $path = $this->get_path($path);
  69. if (is_file($path))
  70. {
  71. $info = pathinfo($path);
  72. // check file extension
  73. $info = pathinfo($path);
  74. if ( ! empty($this->extensions) && ! in_array($info['extension'], $this->extensions))
  75. {
  76. throw new \FileAccessException('File operation not allowed: disallowed file extension.');
  77. }
  78. // create specific handler when available
  79. if (array_key_exists($info['extension'], $this->file_handlers))
  80. {
  81. $class = '\\'.ltrim($this->file_handlers[$info['extension']], '\\');
  82. return $class::factory($path, $config, $this);
  83. }
  84. return \File_Handler_File::factory($path, $config, $this);
  85. }
  86. elseif (is_dir($path))
  87. {
  88. return \File_Handler_Directory::factory($path, $config, $this, $content);
  89. }
  90. // still here? path is invalid
  91. throw new \FileAccessException('Invalid path for file or directory.');
  92. }
  93. /**
  94. * Does this area use file locks?
  95. *
  96. * @return bool
  97. */
  98. public function use_locks()
  99. {
  100. return $this->use_locks;
  101. }
  102. /**
  103. * Are the shown extensions limited, and if so to which?
  104. *
  105. * @return array
  106. */
  107. public function extensions()
  108. {
  109. return $this->extensions;
  110. }
  111. /**
  112. * Translate relative path to real path, throws error when operation is not allowed
  113. *
  114. * @param string
  115. * @return string
  116. * @throws FileAccessException when outside basedir restriction or disallowed file extension
  117. */
  118. public function get_path($path)
  119. {
  120. // attempt to get the realpath(), otherwise just use path with any double dots taken out when basedir is set (for security)
  121. $path = ( ! empty($this->basedir) ? realpath($this->basedir.DS.$path) : realpath($path) )
  122. ?: ( ! empty($this->basedir) ? $this->basedir.DS.str_replace('..', '', $path) : $path);
  123. // basedir prefix is required when it is set (may cause unexpected errors when realpath doesn't work)
  124. if ( ! empty($this->basedir) && substr($path, 0, strlen($this->basedir)) != $this->basedir)
  125. {
  126. throw new \OutsideAreaException('File operation not allowed: given path is outside the basedir for this area.');
  127. }
  128. // check file extension
  129. $info = pathinfo($path);
  130. if ( ! empty(static::$extensions) && array_key_exists($info['extension'], static::$extensions))
  131. {
  132. throw new \FileAccessException('File operation not allowed: disallowed file extension.');
  133. }
  134. return $path;
  135. }
  136. /**
  137. * Translate relative path to accessible path, throws error when operation is not allowed
  138. *
  139. * @param string
  140. * @return string
  141. * @throws LogicException when no url is set or no basedir is set and file is outside DOCROOT
  142. */
  143. public function get_url($path)
  144. {
  145. if(empty($this->url))
  146. {
  147. throw new \LogicException('File operation now allowed: cannot create a file url without an area url.');
  148. }
  149. $path = $this->get_path($path);
  150. $basedir = $this->basedir;
  151. empty($basedir) and $basedir = DOCROOT;
  152. if(stripos($path, $basedir) !== 0)
  153. {
  154. throw new \LogicException('File operation not allowed: cannot create file url whithout a basedir and file outside DOCROOT.');
  155. }
  156. return rtrim($this->url, '/').'/'.ltrim(substr($path, strlen($basedir)),'/');
  157. }
  158. /* -------------------------------------------------------------------------------------
  159. * Allow all File methods to be used from an area directly
  160. * ------------------------------------------------------------------------------------- */
  161. public function create($basepath, $name, $contents = null)
  162. {
  163. return \File::create($basepath, $name, $contents, $this);
  164. }
  165. public function create_dir($basepath, $name, $chmod = 0777)
  166. {
  167. return \File::create_dir($basepath, $name, $chmod, $this);
  168. }
  169. public function read($path, $as_string = false)
  170. {
  171. return \File::read($path, $as_string, $this);
  172. }
  173. public function read_dir($path, $depth = 0, $filter = null)
  174. {
  175. $content = \File::read_dir($path, $depth, $filter, $this);
  176. return $this->get_handler($path, array(), $content);
  177. }
  178. public function rename($path, $new_path)
  179. {
  180. return \File::rename($path, $new_path, $this);
  181. }
  182. public function rename_dir($path, $new_path)
  183. {
  184. return \File::rename_dir($path, $new_path, $this);
  185. }
  186. public function copy($path, $new_path)
  187. {
  188. return \File::copy($path, $new_path, $this);
  189. }
  190. public function copy_dir($path, $new_path)
  191. {
  192. return \File::copy_dir($path, $new_path, $this);
  193. }
  194. public function delete($path)
  195. {
  196. return \File::delete($path, $this);
  197. }
  198. public function delete_dir($path, $recursive = true, $delete_top = true)
  199. {
  200. return \File::delete($path, $recursive, $delete_top, $this);
  201. }
  202. public function update($basepath, $name, $new_content)
  203. {
  204. return \File::update($basepath, $name, $new_content, $this);
  205. }
  206. public function get_permissions($path)
  207. {
  208. return \File::get_permissions($path, $this);
  209. }
  210. public function get_time($path, $type)
  211. {
  212. return \File::get_time($path, $type, $this);
  213. }
  214. public function get_size($path)
  215. {
  216. return \File::get_size($path, $this);
  217. }
  218. }
  219. /* End of file area.php */