[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/joomla/filesystem/src/ -> Path.php (source)

   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  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer