Joomla Platform  13.1
Documentation des API du framework Joomla Platform
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
path.php
Aller à la documentation de ce fichier.
1 <?php
2 /**
3  * @package Joomla.Platform
4  * @subpackage FileSystem
5  *
6  * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
7  * @license GNU General Public License version 2 or later; see LICENSE
8  */
9 
10 defined('JPATH_PLATFORM') or die;
11 
12 if (!defined('JPATH_ROOT'))
13 {
14  // Define a string constant for the root directory of the file system in native format
15  define('JPATH_ROOT', JPath::clean(JPATH_SITE));
16 }
17 
18 /**
19  * A Path handling class
20  *
21  * @package Joomla.Platform
22  * @subpackage FileSystem
23  * @since 11.1
24  */
25 class JPath
26 {
27  /**
28  * Checks if a path's permissions can be changed.
29  *
30  * @param string $path Path to check.
31  *
32  * @return boolean True if path can have mode changed.
33  *
34  * @since 11.1
35  */
36  public static function canChmod($path)
37  {
38  $perms = fileperms($path);
39 
40  if ($perms !== false)
41  {
42  if (@chmod($path, $perms ^ 0001))
43  {
44  @chmod($path, $perms);
45 
46  return true;
47  }
48  }
49 
50  return false;
51  }
52 
53  /**
54  * Chmods files and directories recursively to given permissions.
55  *
56  * @param string $path Root path to begin changing mode [without trailing slash].
57  * @param string $filemode Octal representation of the value to change file mode to [null = no change].
58  * @param string $foldermode Octal representation of the value to change folder mode to [null = no change].
59  *
60  * @return boolean True if successful [one fail means the whole operation failed].
61  *
62  * @since 11.1
63  */
64  public static function setPermissions($path, $filemode = '0644', $foldermode = '0755')
65  {
66  // Initialise return value
67  $ret = true;
68 
69  if (is_dir($path))
70  {
71  $dh = opendir($path);
72 
73  while ($file = readdir($dh))
74  {
75  if ($file != '.' && $file != '..')
76  {
77  $fullpath = $path . '/' . $file;
78 
79  if (is_dir($fullpath))
80  {
81  if (!self::setPermissions($fullpath, $filemode, $foldermode))
82  {
83  $ret = false;
84  }
85  }
86  else
87  {
88  if (isset($filemode))
89  {
90  if (!@ chmod($fullpath, octdec($filemode)))
91  {
92  $ret = false;
93  }
94  }
95  }
96  }
97  }
98 
99  closedir($dh);
100 
101  if (isset($foldermode))
102  {
103  if (!@ chmod($path, octdec($foldermode)))
104  {
105  $ret = false;
106  }
107  }
108  }
109  else
110  {
111  if (isset($filemode))
112  {
113  $ret = @ chmod($path, octdec($filemode));
114  }
115  }
116 
117  return $ret;
118  }
119 
120  /**
121  * Get the permissions of the file/folder at a given path.
122  *
123  * @param string $path The path of a file/folder.
124  *
125  * @return string Filesystem permissions.
126  *
127  * @since 11.1
128  */
129  public static function getPermissions($path)
130  {
131  $path = self::clean($path);
132  $mode = @ decoct(@ fileperms($path) & 0777);
133 
134  if (strlen($mode) < 3)
135  {
136  return '---------';
137  }
138 
139  $parsed_mode = '';
140 
141  for ($i = 0; $i < 3; $i++)
142  {
143  // Read
144  $parsed_mode .= ($mode{$i} & 04) ? "r" : "-";
145 
146  // Write
147  $parsed_mode .= ($mode{$i} & 02) ? "w" : "-";
148 
149  // Execute
150  $parsed_mode .= ($mode{$i} & 01) ? "x" : "-";
151  }
152 
153  return $parsed_mode;
154  }
155 
156  /**
157  * Checks for snooping outside of the file system root.
158  *
159  * @param string $path A file system path to check.
160  *
161  * @return string A cleaned version of the path or exit on error.
162  *
163  * @since 11.1
164  * @throws Exception
165  */
166  public static function check($path)
167  {
168  if (strpos($path, '..') !== false)
169  {
170  // Don't translate
171  throw new Exception('JPath::check Use of relative paths not permitted', 20);
172  }
173 
174  $path = self::clean($path);
175 
176  if ((JPATH_ROOT != '') && strpos($path, self::clean(JPATH_ROOT)) !== 0)
177  {
178  throw new Exception('JPath::check Snooping out of bounds @ ' . $path, 20);
179  }
180 
181  return $path;
182  }
183 
184  /**
185  * Function to strip additional / or \ in a path name.
186  *
187  * @param string $path The path to clean.
188  * @param string $ds Directory separator (optional).
189  *
190  * @return string The cleaned path.
191  *
192  * @since 11.1
193  * @throws UnexpectedValueException
194  */
195  public static function clean($path, $ds = DIRECTORY_SEPARATOR)
196  {
197  if (!is_string($path))
198  {
199  throw new UnexpectedValueException('JPath::clean: $path is not a string.');
200  }
201 
202  $path = trim($path);
203 
204  if (empty($path))
205  {
206  $path = JPATH_ROOT;
207  }
208  // Remove double slashes and backslashes and convert all slashes and backslashes to DIRECTORY_SEPARATOR
209  // If dealing with a UNC path don't forget to prepend the path with a backslash.
210  elseif (($ds == '\\') && ($path[0] == '\\' ) && ( $path[1] == '\\' ))
211  {
212  $path = "\\" . preg_replace('#[/\\\\]+#', $ds, $path);
213  }
214  else
215  {
216  $path = preg_replace('#[/\\\\]+#', $ds, $path);
217  }
218 
219  return $path;
220  }
221 
222  /**
223  * Method to determine if script owns the path.
224  *
225  * @param string $path Path to check ownership.
226  *
227  * @return boolean True if the php script owns the path passed.
228  *
229  * @since 11.1
230  */
231  public static function isOwner($path)
232  {
233  jimport('joomla.filesystem.file');
234 
235  $tmp = md5(mt_rand());
236  $ssp = ini_get('session.save_path');
237  $jtp = JPATH_SITE . '/tmp';
238 
239  // Try to find a writable directory
240  $dir = is_writable('/tmp') ? '/tmp' : false;
241  $dir = (!$dir && is_writable($ssp)) ? $ssp : false;
242  $dir = (!$dir && is_writable($jtp)) ? $jtp : false;
243 
244  if ($dir)
245  {
246  $test = $dir . '/' . $tmp;
247 
248  // Create the test file
249  $blank = '';
250  JFile::write($test, $blank, false);
251 
252  // Test ownership
253  $return = (fileowner($test) == fileowner($path));
254 
255  // Delete the test file
256  JFile::delete($test);
257 
258  return $return;
259  }
260 
261  return false;
262  }
263 
264  /**
265  * Searches the directory paths for a given file.
266  *
267  * @param mixed $paths An path string or array of path strings to search in
268  * @param string $file The file name to look for.
269  *
270  * @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.
271  *
272  * @since 11.1
273  */
274  public static function find($paths, $file)
275  {
276  // Force to array
277  if (!is_array($paths) && !($paths instanceof Iterator))
278  {
279  settype($paths, 'array');
280  }
281 
282  // Start looping through the path set
283  foreach ($paths as $path)
284  {
285  // Get the path to the file
286  $fullname = $path . '/' . $file;
287 
288  // Is the path based on a stream?
289  if (strpos($path, '://') === false)
290  {
291  // Not a stream, so do a realpath() to avoid directory
292  // traversal attempts on the local file system.
293 
294  // Needed for substr() later
295  $path = realpath($path);
296  $fullname = realpath($fullname);
297  }
298 
299  /*
300  * The substr() check added to make sure that the realpath()
301  * results in a directory registered so that
302  * non-registered directories are not accessible via directory
303  * traversal attempts.
304  */
305  if (file_exists($fullname) && substr($fullname, 0, strlen($path)) == $path)
306  {
307  return $fullname;
308  }
309  }
310 
311  // Could not find the file in the set of paths
312  return false;
313  }
314 }