PageRenderTime 39ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/filesystem/path.php

https://bitbucket.org/joomla/joomla-platform/
PHP | 257 lines | 131 code | 35 blank | 91 comment | 33 complexity | a218c49f0264809027569b338c631397 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage FileSystem
  5. *
  6. * @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. /** boolean True if a Windows based host */
  11. define('JPATH_ISWIN', (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'));
  12. /** boolean True if a Mac based host */
  13. define('JPATH_ISMAC', (strtoupper(substr(PHP_OS, 0, 3)) === 'MAC'));
  14. if (!defined('DS')) {
  15. /** string Shortcut for the DIRECTORY_SEPARATOR define */
  16. define('DS', DIRECTORY_SEPARATOR);
  17. }
  18. if (!defined('JPATH_ROOT')) {
  19. /** string The root directory of the file system in native format */
  20. define('JPATH_ROOT', JPath::clean(JPATH_SITE));
  21. }
  22. /**
  23. * A Path handling class
  24. *
  25. * @package Joomla.Platform
  26. * @subpackage FileSystem
  27. * @since 11.1
  28. */
  29. class JPath
  30. {
  31. /**
  32. * Checks if a path's permissions can be changed
  33. *
  34. * @param string Path to check
  35. * @return boolean True if path can have mode changed
  36. * @since 11.1
  37. */
  38. public static function canChmod($path)
  39. {
  40. $perms = fileperms($path);
  41. if ($perms !== false) {
  42. if (@chmod($path, $perms ^ 0001)) {
  43. @chmod($path, $perms);
  44. return true;
  45. }
  46. }
  47. return false;
  48. }
  49. /**
  50. * Chmods files and directories recursivly to given permissions
  51. *
  52. * @param string Root path to begin changing mode [without trailing slash]
  53. * @param string Octal representation of the value to change file mode to [null = no change]
  54. * @param string Octal representation of the value to change folder mode to [null = no change]
  55. * @return boolean True if successful [one fail means the whole operation failed]
  56. * @since 11.1
  57. */
  58. public static function setPermissions($path, $filemode = '0644', $foldermode = '0755')
  59. {
  60. // Initialise return value
  61. $ret = true;
  62. if (is_dir($path)) {
  63. $dh = opendir($path);
  64. while ($file = readdir($dh)) {
  65. if ($file != '.' && $file != '..') {
  66. $fullpath = $path.'/'.$file;
  67. if (is_dir($fullpath)) {
  68. if (!JPath::setPermissions($fullpath, $filemode, $foldermode)) {
  69. $ret = false;
  70. }
  71. } else {
  72. if (isset ($filemode)) {
  73. if (!@ chmod($fullpath, octdec($filemode))) {
  74. $ret = false;
  75. }
  76. }
  77. }
  78. }
  79. }
  80. closedir($dh);
  81. if (isset ($foldermode)) {
  82. if (!@ chmod($path, octdec($foldermode))) {
  83. $ret = false;
  84. }
  85. }
  86. } else {
  87. if (isset ($filemode)) {
  88. $ret = @ chmod($path, octdec($filemode));
  89. }
  90. }
  91. return $ret;
  92. }
  93. /**
  94. * Get the permissions of the file/folder at a give path
  95. *
  96. * @param string The path of a file/folder
  97. * @return string Filesystem permissions
  98. * @since 11.1
  99. */
  100. public static function getPermissions($path)
  101. {
  102. $path = JPath::clean($path);
  103. $mode = @ decoct(@ fileperms($path) & 0777);
  104. if (strlen($mode) < 3) {
  105. return '---------';
  106. }
  107. $parsed_mode = '';
  108. for ($i = 0; $i < 3; $i ++) {
  109. // read
  110. $parsed_mode .= ($mode { $i } & 04) ? "r" : "-";
  111. // write
  112. $parsed_mode .= ($mode { $i } & 02) ? "w" : "-";
  113. // execute
  114. $parsed_mode .= ($mode { $i } & 01) ? "x" : "-";
  115. }
  116. return $parsed_mode;
  117. }
  118. /**
  119. * Checks for snooping outside of the file system root
  120. *
  121. * @param string A file system path to check
  122. * @param string Directory separator (optional)
  123. * @return string A cleaned version of the path
  124. * @since 11.1
  125. */
  126. public static function check($path, $ds = DIRECTORY_SEPARATOR)
  127. {
  128. if (strpos($path, '..') !== false) {
  129. JError::raiseError(20, 'JPath::check Use of relative paths not permitted'); // don't translate
  130. jexit();
  131. }
  132. $path = JPath::clean($path);
  133. if (strpos($path, JPath::clean(JPATH_ROOT)) !== 0) {
  134. JError::raiseError(20, 'JPath::check Snooping out of bounds @ '.$path); // don't translate
  135. jexit();
  136. }
  137. return $path;
  138. }
  139. /**
  140. * Function to strip additional / or \ in a path name
  141. *
  142. * @param string The path to clean
  143. * @param string Directory separator (optional)
  144. * @return string The cleaned path
  145. * @since 11.1
  146. */
  147. public static function clean($path, $ds = DIRECTORY_SEPARATOR)
  148. {
  149. $path = trim($path);
  150. if (empty($path)) {
  151. $path = JPATH_ROOT;
  152. } else {
  153. // Remove double slashes and backslahses and convert all slashes and backslashes to DS
  154. $path = preg_replace('#[/\\\\]+#', $ds, $path);
  155. }
  156. return $path;
  157. }
  158. /**
  159. * Method to determine if script owns the path
  160. *
  161. * @param string Path to check ownership
  162. * @return boolean True if the php script owns the path passed
  163. * @since 11.1
  164. */
  165. public static function isOwner($path)
  166. {
  167. jimport('joomla.filesystem.file');
  168. jimport('joomla.user.helper');
  169. $tmp = md5(JUserHelper::genRandomPassword(16));
  170. $ssp = ini_get('session.save_path');
  171. $jtp = JPATH_SITE.DS.'tmp';
  172. // Try to find a writable directory
  173. $dir = is_writable('/tmp') ? '/tmp' : false;
  174. $dir = (!$dir && is_writable($ssp)) ? $ssp : false;
  175. $dir = (!$dir && is_writable($jtp)) ? $jtp : false;
  176. if ($dir) {
  177. $test = $dir.DS.$tmp;
  178. // Create the test file
  179. $blank = '';
  180. JFile::write($test, $blank, false);
  181. // Test ownership
  182. $return = (fileowner($test) == fileowner($path));
  183. // Delete the test file
  184. JFile::delete($test);
  185. return $return;
  186. }
  187. return false;
  188. }
  189. /**
  190. * Searches the directory paths for a given file.
  191. *
  192. * @param array|string An path or array of path to search in
  193. * @param string The file name to look for.
  194. * @return mixed The full path and file name for the target file, or boolean false if the file is not found in any of the paths.
  195. * @since 11.1
  196. */
  197. public static function find($paths, $file)
  198. {
  199. settype($paths, 'array'); //force to array
  200. // start looping through the path set
  201. foreach ($paths as $path) {
  202. // get the path to the file
  203. $fullname = $path.'/'.$file;
  204. // is the path based on a stream?
  205. if (strpos($path, '://') === false) {
  206. // not a stream, so do a realpath() to avoid directory
  207. // traversal attempts on the local file system.
  208. $path = realpath($path); // needed for substr() later
  209. $fullname = realpath($fullname);
  210. }
  211. // the substr() check added to make sure that the realpath()
  212. // results in a directory registered so that
  213. // non-registered directores are not accessible via directory
  214. // traversal attempts.
  215. if (file_exists($fullname) && substr($fullname, 0, strlen($path)) == $path) {
  216. return $fullname;
  217. }
  218. }
  219. // could not find the file in the set of paths
  220. return false;
  221. }
  222. }