[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Part of the Joomla Framework Filesystem Package 4 * 5 * @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved. 6 * @license GNU General Public License version 2 or later; see LICENSE 7 */ 8 9 namespace Joomla\Filesystem; 10 11 use Joomla\Filesystem\Exception\FilesystemException; 12 13 /** 14 * A Path handling class 15 * 16 * @since 1.0 17 */ 18 class Path 19 { 20 /** 21 * Checks if a path's permissions can be changed. 22 * 23 * @param string $path Path to check. 24 * 25 * @return boolean True if path can have mode changed. 26 * 27 * @since 1.0 28 */ 29 public static function canChmod($path) 30 { 31 if (!file_exists($path)) 32 { 33 return false; 34 } 35 36 $perms = @fileperms($path); 37 38 if ($perms !== false) 39 { 40 if (@chmod($path, $perms ^ 0001)) 41 { 42 @chmod($path, $perms); 43 44 return true; 45 } 46 } 47 48 return false; 49 } 50 51 /** 52 * Chmods files and directories recursively to given permissions. 53 * 54 * @param string $path Root path to begin changing mode [without trailing slash]. 55 * @param string $filemode Octal representation of the value to change file mode to [null = no change]. 56 * @param string $foldermode Octal representation of the value to change folder mode to [null = no change]. 57 * 58 * @return boolean True if successful [one fail means the whole operation failed]. 59 * 60 * @since 1.0 61 */ 62 public static function setPermissions($path, $filemode = '0644', $foldermode = '0755') 63 { 64 // Initialise return value 65 $ret = true; 66 67 if (is_dir($path)) 68 { 69 $dh = @opendir($path); 70 71 if ($dh) 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 (!static::setPermissions($fullpath, $filemode, $foldermode)) 82 { 83 $ret = false; 84 } 85 } 86 else 87 { 88 if (isset($filemode)) 89 { 90 if (!static::canChmod($fullpath) || !@ chmod($fullpath, octdec($filemode))) 91 { 92 $ret = false; 93 } 94 } 95 } 96 } 97 } 98 99 closedir($dh); 100 } 101 102 if (isset($foldermode)) 103 { 104 if (!static::canChmod($path) || !@ chmod($path, octdec($foldermode))) 105 { 106 $ret = false; 107 } 108 } 109 } 110 else 111 { 112 if (isset($filemode)) 113 { 114 if (!static::canChmod($path) || !@ chmod($path, octdec($filemode))) 115 { 116 $ret = false; 117 } 118 } 119 } 120 121 return $ret; 122 } 123 124 /** 125 * Get the permissions of the file/folder at a give path. 126 * 127 * @param string $path The path of a file/folder. 128 * 129 * @return string Filesystem permissions. 130 * 131 * @since 1.0 132 */ 133 public static function getPermissions($path) 134 { 135 $path = self::clean($path); 136 $mode = @ decoct(@ fileperms($path) & 0777); 137 138 if (\strlen($mode) < 3) 139 { 140 return '---------'; 141 } 142 143 $parsedMode = ''; 144 145 for ($i = 0; $i < 3; $i++) 146 { 147 // Read 148 $parsedMode .= ($mode[$i] & 04) ? 'r' : '-'; 149 150 // Write 151 $parsedMode .= ($mode[$i] & 02) ? 'w' : '-'; 152 153 // Execute 154 $parsedMode .= ($mode[$i] & 01) ? 'x' : '-'; 155 } 156 157 return $parsedMode; 158 } 159 160 /** 161 * Checks for snooping outside of the file system root. 162 * 163 * @param string $path A file system path to check. 164 * @param string $basePath The base path of the system 165 * 166 * @return string A cleaned version of the path or exit on error. 167 * 168 * @since 1.0 169 * @throws FilesystemException 170 */ 171 public static function check($path, $basePath = '') 172 { 173 if (strpos($path, '..') !== false) 174 { 175 throw new FilesystemException( 176 sprintf( 177 '%s() - Use of relative paths not permitted', 178 __METHOD__ 179 ), 180 20 181 ); 182 } 183 184 $path = static::clean($path); 185 186 // If a base path is defined then check the cleaned path is not outside of root 187 if (($basePath != '') && strpos($path, static::clean($basePath)) !== 0) 188 { 189 throw new FilesystemException( 190 sprintf( 191 '%1$s() - Snooping out of bounds @ %2$s', 192 __METHOD__, 193 $path 194 ), 195 20 196 ); 197 } 198 199 return $path; 200 } 201 202 /** 203 * Function to strip additional / or \ in a path name. 204 * 205 * @param string $path The path to clean. 206 * @param string $ds Directory separator (optional). 207 * 208 * @return string The cleaned path. 209 * 210 * @since 1.0 211 * @throws \UnexpectedValueException If $path is not a string. 212 */ 213 public static function clean($path, $ds = \DIRECTORY_SEPARATOR) 214 { 215 if (!\is_string($path)) 216 { 217 throw new \InvalidArgumentException('You must specify a non-empty path to clean'); 218 } 219 220 $stream = explode('://', $path, 2); 221 $scheme = ''; 222 $path = $stream[0]; 223 224 if (\count($stream) >= 2) 225 { 226 $scheme = $stream[0] . '://'; 227 $path = $stream[1]; 228 } 229 230 $path = trim($path); 231 232 // Remove double slashes and backslashes and convert all slashes and backslashes to DIRECTORY_SEPARATOR 233 // If dealing with a UNC path don't forget to prepend the path with a backslash. 234 if (($ds == '\\') && ($path[0] == '\\') && ($path[1] == '\\')) 235 { 236 $path = '\\' . preg_replace('#[/\\\\]+#', $ds, $path); 237 } 238 else 239 { 240 $path = preg_replace('#[/\\\\]+#', $ds, $path); 241 } 242 243 return $scheme . $path; 244 } 245 246 /** 247 * Method to determine if script owns the path. 248 * 249 * @param string $path Path to check ownership. 250 * 251 * @return boolean True if the php script owns the path passed. 252 * 253 * @since 1.0 254 */ 255 public static function isOwner($path) 256 { 257 $tmp = md5(random_bytes(16)); 258 $ssp = ini_get('session.save_path'); 259 260 // Try to find a writable directory 261 $dir = is_writable('/tmp') ? '/tmp' : false; 262 $dir = !$dir && is_writable('.') ? '.' : $dir; 263 $dir = !$dir && is_writable($ssp) ? $ssp : $dir; 264 265 if ($dir) 266 { 267 $test = $dir . '/' . $tmp; 268 269 // Create the test file 270 $blank = ''; 271 File::write($test, $blank, false); 272 273 // Test ownership 274 $return = fileowner($test) === fileowner($path); 275 276 // Delete the test file 277 File::delete($test); 278 279 return $return; 280 } 281 282 return false; 283 } 284 285 /** 286 * Searches the directory paths for a given file. 287 * 288 * @param mixed $paths A path string or array of path strings to search in 289 * @param string $file The file name to look for. 290 * 291 * @return string|boolean The full path and file name for the target file, or boolean false if the file is not found in any of the paths. 292 * 293 * @since 1.0 294 */ 295 public static function find($paths, $file) 296 { 297 // Force to array 298 if (!\is_array($paths) && !($paths instanceof \Iterator)) 299 { 300 settype($paths, 'array'); 301 } 302 303 // Start looping through the path set 304 foreach ($paths as $path) 305 { 306 // Get the path to the file 307 $fullname = $path . '/' . $file; 308 309 // Is the path based on a stream? 310 if (strpos($path, '://') === false) 311 { 312 // Not a stream, so do a realpath() to avoid directory 313 // traversal attempts on the local file system. 314 315 // Needed for substr() later 316 $path = realpath($path); 317 $fullname = realpath($fullname); 318 } 319 320 /* 321 * The substr() check added to make sure that the realpath() 322 * results in a directory registered so that 323 * non-registered directories are not accessible via directory 324 * traversal attempts. 325 */ 326 if (file_exists($fullname) && substr($fullname, 0, \strlen($path)) == $path) 327 { 328 return $fullname; 329 } 330 } 331 332 // Could not find the file in the set of paths 333 return false; 334 } 335 336 /** 337 * Resolves /./, /../ and multiple / in a string and returns the resulting absolute path, inspired by Flysystem 338 * Removes trailing slashes 339 * 340 * @param string $path A path to resolve 341 * 342 * @return string The resolved path 343 * 344 * @since 1.6.0 345 */ 346 public static function resolve($path) 347 { 348 $path = static::clean($path); 349 350 // Save start character for absolute path 351 $startCharacter = ($path[0] === DIRECTORY_SEPARATOR) ? DIRECTORY_SEPARATOR : ''; 352 353 $parts = array(); 354 355 foreach (explode(DIRECTORY_SEPARATOR, $path) as $part) 356 { 357 switch ($part) 358 { 359 case '': 360 case '.': 361 break; 362 363 case '..': 364 if (empty($parts)) 365 { 366 throw new FilesystemException('Path is outside of the defined root'); 367 } 368 369 array_pop($parts); 370 break; 371 372 default: 373 $parts[] = $part; 374 break; 375 } 376 } 377 378 return $startCharacter . implode(DIRECTORY_SEPARATOR, $parts); 379 } 380 381 /** 382 * Remove all references to root directory path and the system tmp path from a message 383 * 384 * @param string $message The message to be cleaned 385 * @param string $rootDirectory Optional root directory, defaults to JPATH_ROOT 386 * 387 * @return string 388 * @since 2.0.1 389 */ 390 public static function removeRoot($message, $rootDirectory = null) 391 { 392 if (empty($rootDirectory)) 393 { 394 $rootDirectory = JPATH_ROOT; 395 } 396 397 $makePattern = static function ($dir) { 398 return '~' . str_replace('~', '\\~', preg_replace('~[/\\\\]+~', '.',$dir)) . '~'; 399 }; 400 401 $replacements = [ 402 $makePattern(static::clean($rootDirectory)) => '[ROOT]', 403 $makePattern(sys_get_temp_dir()) => '[TMP]', 404 ]; 405 406 return preg_replace(array_keys($replacements), array_values($replacements), $message); 407 } 408 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |