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