File manager - Edit - /home/opticamezl/www/newok/Filesystem.tar
Back
Meta/language/en-GB/en-GB.lib_joomla_filesystem_patcher.ini 0000644 00000001300 15172625747 0017570 0 ustar 00 ; Joomla! Project ; (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 JLIB_FILESYSTEM_PATCHER_FAILED_VERIFY="Failed source verification of file %s at line %d" JLIB_FILESYSTEM_PATCHER_INVALID_DIFF="Invalid unified diff block" JLIB_FILESYSTEM_PATCHER_INVALID_INPUT="Invalid input" JLIB_FILESYSTEM_PATCHER_UNEXISTING_SOURCE="Unexisting source file" JLIB_FILESYSTEM_PATCHER_UNEXPECTED_ADD_LINE="Unexpected add line at line %d'" JLIB_FILESYSTEM_PATCHER_UNEXPECTED_EOF="Unexpected end of file" JLIB_FILESYSTEM_PATCHER_UNEXPECTED_REMOVE_LINE="Unexpected remove line at line %d" FilesystemHelper.php 0000644 00000023147 15172625747 0010570 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Filesystem; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * File system helper * * Holds support functions for the filesystem, particularly the stream * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Helper instead. */ class FilesystemHelper { /** * Remote file size function for streams that don't support it * * @param string $url Link identifier * * @return mixed * * @link https://www.php.net/manual/en/function.filesize.php * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Helper::remotefsize() instead. */ public static function remotefsize($url) { $sch = parse_url($url, PHP_URL_SCHEME); if (($sch !== 'http') && ($sch !== 'https') && ($sch !== 'ftp') && ($sch !== 'ftps')) { return false; } if (($sch === 'http') || ($sch === 'https')) { $headers = get_headers($url, 1); if ((!\array_key_exists('Content-Length', $headers))) { return false; } return $headers['Content-Length']; } if (($sch === 'ftp') || ($sch === 'ftps')) { $server = parse_url($url, PHP_URL_HOST); $port = parse_url($url, PHP_URL_PORT); $path = parse_url($url, PHP_URL_PATH); $user = parse_url($url, PHP_URL_USER); $pass = parse_url($url, PHP_URL_PASS); if ((!$server) || (!$path)) { return false; } if (!$port) { $port = 21; } if (!$user) { $user = 'anonymous'; } if (!$pass) { $pass = ''; } switch ($sch) { case 'ftp': $ftpid = ftp_connect($server, $port); break; case 'ftps': $ftpid = ftp_ssl_connect($server, $port); break; } if (!$ftpid) { return false; } $login = ftp_login($ftpid, $user, $pass); if (!$login) { return false; } $ftpsize = ftp_size($ftpid, $path); ftp_close($ftpid); if ($ftpsize == -1) { return false; } return $ftpsize; } } /** * Quick FTP chmod * * @param string $url Link identifier * @param integer $mode The new permissions, given as an octal value. * * @return mixed * * @link https://www.php.net/manual/en/function.ftp-chmod.php * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Helper::ftpChmod() instead. */ public static function ftpChmod($url, $mode) { $sch = parse_url($url, PHP_URL_SCHEME); if (($sch !== 'ftp') && ($sch !== 'ftps')) { return false; } $server = parse_url($url, PHP_URL_HOST); $port = parse_url($url, PHP_URL_PORT); $path = parse_url($url, PHP_URL_PATH); $user = parse_url($url, PHP_URL_USER); $pass = parse_url($url, PHP_URL_PASS); if ((!$server) || (!$path)) { return false; } if (!$port) { $port = 21; } if (!$user) { $user = 'anonymous'; } if (!$pass) { $pass = ''; } switch ($sch) { case 'ftp': $ftpid = ftp_connect($server, $port); break; case 'ftps': $ftpid = ftp_ssl_connect($server, $port); break; } if (!$ftpid) { return false; } $login = ftp_login($ftpid, $user, $pass); if (!$login) { return false; } $res = ftp_chmod($ftpid, $mode, $path); ftp_close($ftpid); return $res; } /** * Modes that require a write operation * * @return array * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Helper::getWriteModes() instead. */ public static function getWriteModes() { return ['w', 'w+', 'a', 'a+', 'r+', 'x', 'x+']; } /** * Stream and Filter Support Operations * * Returns the supported streams, in addition to direct file access * Also includes Joomla! streams as well as PHP streams * * @return array Streams * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Helper::getSupported() instead. */ public static function getSupported() { // Really quite cool what php can do with arrays when you let it... static $streams; if (!$streams) { $streams = array_merge(stream_get_wrappers(), self::getJStreams()); } return $streams; } /** * Returns a list of transports * * @return array * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Helper::getTransports() instead. */ public static function getTransports() { // Is this overkill? return stream_get_transports(); } /** * Returns a list of filters * * @return array * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Helper::getFilters() instead. */ public static function getFilters() { // Note: This will look like the getSupported() function with J! filters. // @todo: add user space filter loading like user space stream loading return stream_get_filters(); } /** * Returns a list of J! streams * * @return array * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Helper::getJStreams() instead. */ public static function getJStreams() { static $streams = []; if (!$streams) { $files = new \DirectoryIterator(__DIR__ . '/Streams'); /** @var $file \DirectoryIterator */ foreach ($files as $file) { // Only load for php files. if (!$file->isFile() || $file->getExtension() !== 'php') { continue; } $streams[] = str_replace('stream', '', strtolower($file->getBasename('.php'))); } } return $streams; } /** * Determine if a stream is a Joomla stream. * * @param string $streamname The name of a stream * * @return boolean True for a Joomla Stream * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Helper::isJoomlaStream() instead. */ public static function isJoomlaStream($streamname) { return \in_array($streamname, self::getJStreams()); } /** * Calculates the maximum upload file size and returns string with unit or the size in bytes * * Call it with JFilesystemHelper::fileUploadMaxSize(); * * @param bool $unitOutput This parameter determines whether the return value should be a string with a unit * * @return float|string The maximum upload size of files with the appropriate unit or in bytes * * @since 3.4 */ public static function fileUploadMaxSize($unitOutput = true) { static $max_size = false; static $output_type = true; if ($max_size === false || $output_type != $unitOutput) { $max_size = self::parseSize(ini_get('post_max_size')); $upload_max = self::parseSize(ini_get('upload_max_filesize')); if ($upload_max > 0 && ($upload_max < $max_size || $max_size == 0)) { $max_size = $upload_max; } if ($unitOutput == true) { $max_size = self::parseSizeUnit($max_size); } $output_type = $unitOutput; } return $max_size; } /** * Returns the size in bytes without the unit for the comparison * * @param string $size The size which is received from the PHP settings * * @return float The size in bytes without the unit * * @since 3.4 */ private static function parseSize($size) { $unit = preg_replace('/[^bkmgtpezy]/i', '', $size); $size = preg_replace('/[^0-9\.]/', '', $size); $return = round($size); if ($unit) { $return = round($size * pow(1024, stripos('bkmgtpezy', $unit[0]))); } return $return; } /** * Creates the rounded size of the size with the appropriate unit * * @param float $maxSize The maximum size which is allowed for the uploads * * @return string String with the size and the appropriate unit * * @since 3.4 */ private static function parseSizeUnit($maxSize) { $base = log($maxSize) / log(1024); $suffixes = ['', 'k', 'M', 'G', 'T']; return round(pow(1024, $base - floor($base)), 0) . $suffixes[floor($base)]; } } Stream.php 0000644 00000123167 15172625747 0006542 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Filesystem; use Joomla\CMS\Language\Text; use Joomla\CMS\Object\CMSObject; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Joomla! Stream Interface * * The Joomla! stream interface is designed to handle files as streams * where as the legacy File static class treated files in a rather * atomic manner. * * @note This class adheres to the stream wrapper operations: * @link https://www.php.net/manual/en/function.stream-get-wrappers.php * @link https://www.php.net/manual/en/intro.stream.php PHP Stream Manual * @link https://www.php.net/manual/en/wrappers.php Stream Wrappers * @link https://www.php.net/manual/en/filters.php Stream Filters * @link https://www.php.net/manual/en/transports.php Socket Transports (used by some options, particularly HTTP proxy) * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream instead. */ class Stream extends CMSObject { /** * File Mode * * @var integer * @since 1.7.0 */ protected $filemode = 0644; /** * Directory Mode * * @var integer * @since 1.7.0 */ protected $dirmode = 0755; /** * Default Chunk Size * * @var integer * @since 1.7.0 */ protected $chunksize = 8192; /** * Filename * * @var string * @since 1.7.0 */ protected $filename; /** * Prefix of the connection for writing * * @var string * @since 1.7.0 */ protected $writeprefix; /** * Prefix of the connection for reading * * @var string * @since 1.7.0 */ protected $readprefix; /** * Read Processing method * @var string gz, bz, f * If a scheme is detected, fopen will be defaulted * To use compression with a network stream use a filter * @since 1.7.0 */ protected $processingmethod = 'f'; /** * Filters applied to the current stream * * @var array * @since 1.7.0 */ protected $filters = []; /** * File Handle * * @var resource * @since 3.0.0 */ protected $fh; /** * File size * * @var integer * @since 3.0.0 */ protected $filesize; /** * Context to use when opening the connection * * @var resource * @since 3.0.0 */ protected $context = null; /** * Context options; used to rebuild the context * * @var array * @since 3.0.0 */ protected $contextOptions; /** * The mode under which the file was opened * * @var string * @since 3.0.0 */ protected $openmode; /** * Constructor * * @param string $writeprefix Prefix of the stream (optional). Unlike the JPATH_*, this has a final path separator! * @param string $readprefix The read prefix (optional). * @param array $context The context options (optional). * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::__construct() instead. */ public function __construct($writeprefix = '', $readprefix = '', $context = []) { $this->writeprefix = $writeprefix; $this->readprefix = $readprefix; $this->contextOptions = $context; $this->_buildContext(); } /** * Destructor * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::__destruct() instead. */ public function __destruct() { // Attempt to close on destruction if there is a file handle if ($this->fh) { @$this->close(); } } /** * Generic File Operations * * Open a stream with some lazy loading smarts * * @param string $filename Filename * @param string $mode Mode string to use * @param boolean $useIncludePath Use the PHP include path * @param resource $context Context to use when opening * @param boolean $usePrefix Use a prefix to open the file * @param boolean $relative Filename is a relative path (if false, strips JPATH_ROOT to make it relative) * @param boolean $detectProcessingMode Detect the processing method for the file and use the appropriate function * to handle output automatically * * @return boolean * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::open() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function open( $filename, $mode = 'r', $useIncludePath = false, $context = null, $usePrefix = false, $relative = false, $detectProcessingMode = false ) { $filename = $this->_getFilename($filename, $mode, $usePrefix, $relative); if (!$filename) { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILENAME')); return false; } $this->filename = $filename; $this->openmode = $mode; $url = parse_url($filename); $retval = false; if (isset($url['scheme'])) { // If we're dealing with a Joomla! stream, load it if (FilesystemHelper::isJoomlaStream($url['scheme'])) { require_once __DIR__ . '/streams/' . $url['scheme'] . '.php'; } // We have a scheme! force the method to be f $this->processingmethod = 'f'; } elseif ($detectProcessingMode) { $ext = strtolower(File::getExt($this->filename)); switch ($ext) { case 'tgz': case 'gz': case 'gzip': $this->processingmethod = 'gz'; break; case 'tbz2': case 'bz2': case 'bzip2': $this->processingmethod = 'bz'; break; default: $this->processingmethod = 'f'; break; } } // Capture PHP errors $php_errormsg = 'Error Unknown whilst opening a file'; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); // Decide which context to use: switch ($this->processingmethod) { // Gzip doesn't support contexts or streams case 'gz': $this->fh = gzopen($filename, $mode, $useIncludePath); break; // Bzip2 is much like gzip except it doesn't use the include path case 'bz': $this->fh = bzopen($filename, $mode); break; // Fopen can handle streams case 'f': default: // One supplied at open; overrides everything if ($context) { $this->fh = fopen($filename, $mode, $useIncludePath, $context); } elseif ($this->context) { // One provided at initialisation $this->fh = fopen($filename, $mode, $useIncludePath, $this->context); } else { // No context; all defaults $this->fh = fopen($filename, $mode, $useIncludePath); } break; } if (!$this->fh) { $this->setError($php_errormsg); } else { $retval = true; } // Restore error tracking to what it was before ini_set('track_errors', $track_errors); // Return the result return $retval; } /** * Attempt to close a file handle * * Will return false if it failed and true on success * If the file is not open the system will return true, this function destroys the file handle as well * * @return boolean * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::close() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function close() { if (!$this->fh) { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); return true; } $retval = false; // Capture PHP errors $php_errormsg = 'Error Unknown'; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); switch ($this->processingmethod) { case 'gz': $res = gzclose($this->fh); break; case 'bz': $res = bzclose($this->fh); break; case 'f': default: $res = fclose($this->fh); break; } if (!$res) { $this->setError($php_errormsg); } else { // Reset this $this->fh = null; $retval = true; } // If we wrote, chmod the file after it's closed if ($this->openmode[0] == 'w') { $this->chmod(); } // Restore error tracking to what it was before ini_set('track_errors', $track_errors); // Return the result return $retval; } /** * Work out if we're at the end of the file for a stream * * @return boolean * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::eof() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function eof() { if (!$this->fh) { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); return false; } // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); switch ($this->processingmethod) { case 'gz': $res = gzeof($this->fh); break; case 'bz': case 'f': default: $res = feof($this->fh); break; } if ($php_errormsg) { $this->setError($php_errormsg); } // Restore error tracking to what it was before ini_set('track_errors', $track_errors); // Return the result return $res; } /** * Retrieve the file size of the path * * @return mixed * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::filesize() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function filesize() { if (!$this->filename) { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); return false; } $retval = false; // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); $res = @filesize($this->filename); if (!$res) { $tmp_error = ''; if ($php_errormsg) { // Something went wrong. // Store the error in case we need it. $tmp_error = $php_errormsg; } $res = FilesystemHelper::remotefsize($this->filename); if (!$res) { if ($tmp_error) { // Use the php_errormsg from before $this->setError($tmp_error); } else { // Error but nothing from php? How strange! Create our own $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_SIZE')); } } else { $this->filesize = $res; $retval = $res; } } else { $this->filesize = $res; $retval = $res; } // Restore error tracking to what it was before. ini_set('track_errors', $track_errors); // Return the result return $retval; } /** * Get a line from the stream source. * * @param integer $length The number of bytes (optional) to read. * * @return mixed * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::gets() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function gets($length = 0) { if (!$this->fh) { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); return false; } $retval = false; // Capture PHP errors $php_errormsg = 'Error Unknown'; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); switch ($this->processingmethod) { case 'gz': $res = $length ? gzgets($this->fh, $length) : gzgets($this->fh); break; case 'bz': case 'f': default: $res = $length ? fgets($this->fh, $length) : fgets($this->fh); break; } if (!$res) { $this->setError($php_errormsg); } else { $retval = $res; } // Restore error tracking to what it was before ini_set('track_errors', $track_errors); // Return the result return $retval; } /** * Read a file * * Handles user space streams appropriately otherwise any read will return 8192 * * @param integer $length Length of data to read * * @return mixed * * @link https://www.php.net/manual/en/function.fread.php * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::read() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function read($length = 0) { if (!$this->filesize && !$length) { // Get the filesize $this->filesize(); if (!$this->filesize) { // Set it to the biggest and then wait until eof $length = -1; } else { $length = $this->filesize; } } if (!$this->fh) { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); return false; } $retval = false; // Capture PHP errors $php_errormsg = 'Error Unknown'; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); $remaining = $length; do { // Do chunked reads where relevant switch ($this->processingmethod) { case 'bz': $res = ($remaining > 0) ? bzread($this->fh, $remaining) : bzread($this->fh, $this->chunksize); break; case 'gz': $res = ($remaining > 0) ? gzread($this->fh, $remaining) : gzread($this->fh, $this->chunksize); break; case 'f': default: $res = ($remaining > 0) ? fread($this->fh, $remaining) : fread($this->fh, $this->chunksize); break; } if (!$res) { $this->setError($php_errormsg); // Jump from the loop $remaining = 0; } else { if (!$retval) { $retval = ''; } $retval .= $res; if (!$this->eof()) { $len = \strlen($res); $remaining -= $len; } else { // If it's the end of the file then we've nothing left to read; reset remaining and len $remaining = 0; $length = \strlen($retval); } } } while ($remaining || !$length); // Restore error tracking to what it was before ini_set('track_errors', $track_errors); // Return the result return $retval; } /** * Seek the file * * Note: the return value is different to that of fseek * * @param integer $offset Offset to use when seeking. * @param integer $whence Seek mode to use. * * @return boolean True on success, false on failure * * @link https://www.php.net/manual/en/function.fseek.php * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::seek() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function seek($offset, $whence = SEEK_SET) { if (!$this->fh) { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); return false; } $retval = false; // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); switch ($this->processingmethod) { case 'gz': $res = gzseek($this->fh, $offset, $whence); break; case 'bz': case 'f': default: $res = fseek($this->fh, $offset, $whence); break; } // Seek, interestingly, returns 0 on success or -1 on failure. if ($res == -1) { $this->setError($php_errormsg); } else { $retval = true; } // Restore error tracking to what it was before ini_set('track_errors', $track_errors); // Return the result return $retval; } /** * Returns the current position of the file read/write pointer. * * @return mixed * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::tell() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function tell() { if (!$this->fh) { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); return false; } // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); switch ($this->processingmethod) { case 'gz': $res = gztell($this->fh); break; case 'bz': case 'f': default: $res = ftell($this->fh); break; } // May return 0 so check if it's really false if ($res === false) { $this->setError($php_errormsg); } // Restore error tracking to what it was before ini_set('track_errors', $track_errors); // Return the result return $res; } /** * File write * * Whilst this function accepts a reference, the underlying fwrite * will do a copy! This will roughly double the memory allocation for * any write you do. Specifying chunked will get around this by only * writing in specific chunk sizes. This defaults to 8192 which is a * sane number to use most of the time (change the default with * JStream::set('chunksize', newsize);) * Note: This doesn't support gzip/bzip2 writing like reading does * * @param string $string Reference to the string to write. * @param integer $length Length of the string to write. * @param integer $chunk Size of chunks to write in. * * @return boolean * * @link https://www.php.net/manual/en/function.fwrite.php * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::write() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function write(&$string, $length = 0, $chunk = 0) { if (!$this->fh) { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); return false; } // If the length isn't set, set it to the length of the string. if (!$length) { $length = \strlen($string); } // If the chunk isn't set, set it to the default. if (!$chunk) { $chunk = $this->chunksize; } $retval = true; // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); $remaining = $length; $start = 0; do { // If the amount remaining is greater than the chunk size, then use the chunk $amount = ($remaining > $chunk) ? $chunk : $remaining; $res = fwrite($this->fh, substr($string, $start), $amount); // Returns false on error or the number of bytes written if ($res === false) { // Returned error $this->setError($php_errormsg); $retval = false; $remaining = 0; } elseif ($res === 0) { // Wrote nothing? $remaining = 0; $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_NO_DATA_WRITTEN')); } else { // Wrote something $start += $amount; $remaining -= $res; } } while ($remaining); // Restore error tracking to what it was before. ini_set('track_errors', $track_errors); // Return the result return $retval; } /** * Chmod wrapper * * @param string $filename File name. * @param mixed $mode Mode to use. * * @return boolean * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::chmod() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function chmod($filename = '', $mode = 0) { if (!$filename) { if (!isset($this->filename) || !$this->filename) { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILENAME')); return false; } $filename = $this->filename; } // If no mode is set use the default if (!$mode) { $mode = $this->filemode; } $retval = false; // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); $sch = parse_url($filename, PHP_URL_SCHEME); // Scheme specific options; ftp's chmod support is fun. switch ($sch) { case 'ftp': case 'ftps': $res = FilesystemHelper::ftpChmod($filename, $mode); break; default: $res = chmod($filename, $mode); break; } // Seek, interestingly, returns 0 on success or -1 on failure if (!$res) { $this->setError($php_errormsg); } else { $retval = true; } // Restore error tracking to what it was before. ini_set('track_errors', $track_errors); // Return the result return $retval; } /** * Get the stream metadata * * @return array|boolean header/metadata * * @link https://www.php.net/manual/en/function.stream-get-meta-data.php * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::get_meta_data() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function get_meta_data() { if (!$this->fh) { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); return false; } return stream_get_meta_data($this->fh); } /** * Stream contexts * Builds the context from the array * * @return void * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::_buildContext() instead. */ public function _buildContext() { // According to the manual this always works! if (\count($this->contextOptions)) { $this->context = @stream_context_create($this->contextOptions); } else { $this->context = null; } } /** * Updates the context to the array * * Format is the same as the options for stream_context_create * * @param array $context Options to create the context with * * @return void * * @link https://www.php.net/stream_context_create * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::setContextOptions() instead. */ public function setContextOptions($context) { $this->contextOptions = $context; $this->_buildContext(); } /** * Adds a particular options to the context * * @param string $wrapper The wrapper to use * @param string $name The option to set * @param string $value The value of the option * * @return void * * @link https://www.php.net/stream_context_create Stream Context Creation * @link https://www.php.net/manual/en/context.php Context Options for various streams * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::addContextEntry() instead. */ public function addContextEntry($wrapper, $name, $value) { $this->contextOptions[$wrapper][$name] = $value; $this->_buildContext(); } /** * Deletes a particular setting from a context * * @param string $wrapper The wrapper to use * @param string $name The option to unset * * @return void * * @link https://www.php.net/stream_context_create * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::deleteContextEntry() instead. */ public function deleteContextEntry($wrapper, $name) { // Check whether the wrapper is set if (isset($this->contextOptions[$wrapper])) { // Check that entry is set for that wrapper if (isset($this->contextOptions[$wrapper][$name])) { // Unset the item unset($this->contextOptions[$wrapper][$name]); // Check that there are still items there if (!\count($this->contextOptions[$wrapper])) { // Clean up an empty wrapper context option unset($this->contextOptions[$wrapper]); } } } // Rebuild the context and apply it to the stream $this->_buildContext(); } /** * Applies the current context to the stream * * Use this to change the values of the context after you've opened a stream * * @return mixed * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::applyContextToStream() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function applyContextToStream() { $retval = false; if ($this->fh) { // Capture PHP errors $php_errormsg = 'Unknown error setting context option'; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); $retval = @stream_context_set_option($this->fh, $this->contextOptions); if (!$retval) { $this->setError($php_errormsg); } // Restore error tracking to what it was before ini_set('track_errors', $track_errors); } return $retval; } /** * Stream filters * Append a filter to the chain * * @param string $filterName The key name of the filter. * @param integer $readWrite Optional. Defaults to STREAM_FILTER_READ. * @param array $params An array of params for the stream_filter_append call. * * @return mixed * * @link https://www.php.net/manual/en/function.stream-filter-append.php * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::appendFilter() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function appendFilter($filterName, $readWrite = STREAM_FILTER_READ, $params = []) { $res = false; if ($this->fh) { // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); $res = @stream_filter_append($this->fh, $filterName, $readWrite, $params); if (!$res && $php_errormsg) { $this->setError($php_errormsg); } else { $this->filters[] = &$res; } // Restore error tracking to what it was before. ini_set('track_errors', $track_errors); } return $res; } /** * Prepend a filter to the chain * * @param string $filterName The key name of the filter. * @param integer $readWrite Optional. Defaults to STREAM_FILTER_READ. * @param array $params An array of params for the stream_filter_prepend call. * * @return mixed * * @link https://www.php.net/manual/en/function.stream-filter-prepend.php * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::prependFilter() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function prependFilter($filterName, $readWrite = STREAM_FILTER_READ, $params = []) { $res = false; if ($this->fh) { // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); $res = @stream_filter_prepend($this->fh, $filterName, $readWrite, $params); if (!$res && $php_errormsg) { // Set the error msg $this->setError($php_errormsg); } else { array_unshift($res, ''); $res[0] = &$this->filters; } // Restore error tracking to what it was before. ini_set('track_errors', $track_errors); } return $res; } /** * Remove a filter, either by resource (handed out from the append or prepend function) * or via getting the filter list) * * @param resource $resource The resource. * @param boolean $byindex The index of the filter. * * @return boolean Result of operation * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::removeFilter() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function removeFilter(&$resource, $byindex = false) { // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); if ($byindex) { $res = stream_filter_remove($this->filters[$resource]); } else { $res = stream_filter_remove($resource); } if ($res && $php_errormsg) { $this->setError($php_errormsg); } // Restore error tracking to what it was before. ini_set('track_errors', $track_errors); return $res; } /** * Copy a file from src to dest * * @param string $src The file path to copy from. * @param string $dest The file path to copy to. * @param resource $context A valid context resource (optional) created with stream_context_create. * @param boolean $usePrefix Controls the use of a prefix (optional). * @param boolean $relative Determines if the filename given is relative. Relative paths do not have JPATH_ROOT stripped. * * @return mixed * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::copy() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function copy($src, $dest, $context = null, $usePrefix = true, $relative = false) { // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); $chmodDest = $this->_getFilename($dest, 'w', $usePrefix, $relative); // Since we're going to open the file directly we need to get the filename. // We need to use the same prefix so force everything to write. $src = $this->_getFilename($src, 'w', $usePrefix, $relative); $dest = $this->_getFilename($dest, 'w', $usePrefix, $relative); if ($context) { // Use the provided context $res = @copy($src, $dest, $context); } elseif ($this->context) { // Use the objects context $res = @copy($src, $dest, $this->context); } else { // Don't use any context $res = @copy($src, $dest); } if (!$res && $php_errormsg) { $this->setError($php_errormsg); } else { $this->chmod($chmodDest); } // Restore error tracking to what it was before ini_set('track_errors', $track_errors); return $res; } /** * Moves a file * * @param string $src The file path to move from. * @param string $dest The file path to move to. * @param resource $context A valid context resource (optional) created with stream_context_create. * @param boolean $usePrefix Controls the use of a prefix (optional). * @param boolean $relative Determines if the filename given is relative. Relative paths do not have JPATH_ROOT stripped. * * @return mixed * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::move() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function move($src, $dest, $context = null, $usePrefix = true, $relative = false) { // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); $src = $this->_getFilename($src, 'w', $usePrefix, $relative); $dest = $this->_getFilename($dest, 'w', $usePrefix, $relative); if ($context) { // Use the provided context $res = @rename($src, $dest, $context); } elseif ($this->context) { // Use the object's context $res = @rename($src, $dest, $this->context); } else { // Don't use any context $res = @rename($src, $dest); } if (!$res && $php_errormsg) { $this->setError($php_errormsg()); } $this->chmod($dest); // Restore error tracking to what it was before ini_set('track_errors', $track_errors); return $res; } /** * Delete a file * * @param string $filename The file path to delete. * @param resource $context A valid context resource (optional) created with stream_context_create. * @param boolean $usePrefix Controls the use of a prefix (optional). * @param boolean $relative Determines if the filename given is relative. Relative paths do not have JPATH_ROOT stripped. * * @return mixed * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::delete() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function delete($filename, $context = null, $usePrefix = true, $relative = false) { // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); $filename = $this->_getFilename($filename, 'w', $usePrefix, $relative); if ($context) { // Use the provided context $res = @unlink($filename, $context); } elseif ($this->context) { // Use the object's context $res = @unlink($filename, $this->context); } else { // Don't use any context $res = @unlink($filename); } if (!$res && $php_errormsg) { $this->setError($php_errormsg()); } // Restore error tracking to what it was before. ini_set('track_errors', $track_errors); return $res; } /** * Upload a file * * @param string $src The file path to copy from (usually a temp folder). * @param string $dest The file path to copy to. * @param resource $context A valid context resource (optional) created with stream_context_create. * @param boolean $usePrefix Controls the use of a prefix (optional). * @param boolean $relative Determines if the filename given is relative. Relative paths do not have JPATH_ROOT stripped. * * @return mixed * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::upload() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public function upload($src, $dest, $context = null, $usePrefix = true, $relative = false) { if (is_uploaded_file($src)) { // Make sure it's an uploaded file return $this->copy($src, $dest, $context, $usePrefix, $relative); } else { $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_NOT_UPLOADED_FILE')); return false; } } /** * Writes a chunk of data to a file. * * @param string $filename The file name. * @param string $buffer The data to write to the file. * * @return boolean * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::writeFile() instead. */ public function writeFile($filename, &$buffer) { if ($this->open($filename, 'w')) { $result = $this->write($buffer); $this->chmod(); $this->close(); return $result; } return false; } /** * Determine the appropriate 'filename' of a file * * @param string $filename Original filename of the file * @param string $mode Mode string to retrieve the filename * @param boolean $usePrefix Controls the use of a prefix * @param boolean $relative Determines if the filename given is relative. Relative paths do not have JPATH_ROOT stripped. * * @return string * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::_getFilename() instead. */ public function _getFilename($filename, $mode, $usePrefix, $relative) { if ($usePrefix) { // Get rid of binary or t, should be at the end of the string $tmode = trim($mode, 'btf123456789'); // Check if it's a write mode then add the appropriate prefix // Get rid of JPATH_ROOT (legacy compat) along the way if (\in_array($tmode, FilesystemHelper::getWriteModes())) { if (!$relative && $this->writeprefix) { $filename = str_replace(JPATH_ROOT, '', $filename); } $filename = $this->writeprefix . $filename; } else { if (!$relative && $this->readprefix) { $filename = str_replace(JPATH_ROOT, '', $filename); } $filename = $this->readprefix . $filename; } } return $filename; } /** * Return the internal file handle * * @return resource File handler * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream::getFileHandle() instead. */ public function getFileHandle() { return $this->fh; } } Patcher.php 0000644 00000036405 15172625747 0006673 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Filesystem; use Joomla\CMS\Language\Text; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * A Unified Diff Format Patcher class * * @link http://sourceforge.net/projects/phppatcher/ This has been derived from the PhpPatcher version 0.1.1 written by Giuseppe Mazzotta * @since 3.0.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher instead. */ class Patcher { /** * Regular expression for searching source files */ public const SRC_FILE = '/^---\\s+(\\S+)\s+\\d{1,4}-\\d{1,2}-\\d{1,2}\\s+\\d{1,2}:\\d{1,2}:\\d{1,2}(\\.\\d+)?\\s+(\+|-)\\d{4}/A'; /** * Regular expression for searching destination files */ public const DST_FILE = '/^\\+\\+\\+\\s+(\\S+)\s+\\d{1,4}-\\d{1,2}-\\d{1,2}\\s+\\d{1,2}:\\d{1,2}:\\d{1,2}(\\.\\d+)?\\s+(\+|-)\\d{4}/A'; /** * Regular expression for searching hunks of differences */ public const HUNK = '/@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@($)/A'; /** * Regular expression for splitting lines */ public const SPLIT = '/(\r\n)|(\r)|(\n)/'; /** * @var array sources files * @since 3.0.0 */ protected $sources = []; /** * @var array destination files * @since 3.0.0 */ protected $destinations = []; /** * @var array removal files * @since 3.0.0 */ protected $removals = []; /** * @var array patches * @since 3.0.0 */ protected $patches = []; /** * @var array instance of this class * @since 3.0.0 */ protected static $instance; /** * Constructor * * The constructor is protected to force the use of FilesystemPatcher::getInstance() * * @since 3.0.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::__construct() instead. */ protected function __construct() { } /** * Method to get a patcher * * @return Patcher an instance of the patcher * * @since 3.0.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::getInstance() instead. */ public static function getInstance() { if (!isset(static::$instance)) { static::$instance = new static(); } return static::$instance; } /** * Reset the patcher * * @return Patcher This object for chaining * * @since 3.0.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::reset() instead. */ public function reset() { $this->sources = []; $this->destinations = []; $this->removals = []; $this->patches = []; return $this; } /** * Apply the patches * * @return integer The number of files patched * * @since 3.0.0 * @throws \RuntimeException * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::apply() instead. */ public function apply() { foreach ($this->patches as $patch) { // Separate the input into lines $lines = self::splitLines($patch['udiff']); // Loop for each header while (self::findHeader($lines, $src, $dst)) { $done = false; $regex = '#^([^/]*/)*#'; if ($patch['strip'] !== null) { $regex = '#^([^/]*/){' . (int) $patch['strip'] . '}#'; } $src = $patch['root'] . preg_replace($regex, '', $src); $dst = $patch['root'] . preg_replace($regex, '', $dst); // Loop for each hunk of differences while (self::findHunk($lines, $src_line, $src_size, $dst_line, $dst_size)) { $done = true; // Apply the hunk of differences $this->applyHunk($lines, $src, $dst, $src_line, $src_size, $dst_line, $dst_size); } // If no modifications were found, throw an exception if (!$done) { throw new \RuntimeException('Invalid Diff'); } } } // Initialize the counter $done = 0; // Patch each destination file foreach ($this->destinations as $file => $content) { $buffer = implode("\n", $content); if (File::write($file, $buffer)) { if (isset($this->sources[$file])) { $this->sources[$file] = $content; } $done++; } } // Remove each removed file foreach ($this->removals as $file) { if (File::delete($file)) { if (isset($this->sources[$file])) { unset($this->sources[$file]); } $done++; } } // Clear the destinations cache $this->destinations = []; // Clear the removals $this->removals = []; // Clear the patches $this->patches = []; return $done; } /** * Add a unified diff file to the patcher * * @param string $filename Path to the unified diff file * @param string $root The files root path * @param integer $strip The number of '/' to strip * * @return Patcher $this for chaining * * @since 3.0.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::addFile() instead. */ public function addFile($filename, $root = JPATH_BASE, $strip = 0) { return $this->add(file_get_contents($filename), $root, $strip); } /** * Add a unified diff string to the patcher * * @param string $udiff Unified diff input string * @param string $root The files root path * @param integer $strip The number of '/' to strip * * @return Patcher $this for chaining * * @since 3.0.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::add() instead. */ public function add($udiff, $root = JPATH_BASE, $strip = 0) { $this->patches[] = [ 'udiff' => $udiff, 'root' => isset($root) ? rtrim($root, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : '', 'strip' => $strip, ]; return $this; } /** * Separate CR or CRLF lines * * @param string $data Input string * * @return array The lines of the inputdestination file * * @since 3.0.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::splitLines() instead. */ protected static function splitLines($data) { return preg_split(self::SPLIT, $data); } /** * Find the diff header * * The internal array pointer of $lines is on the next line after the finding * * @param array $lines The udiff array of lines * @param string $src The source file * @param string $dst The destination file * * @return boolean TRUE in case of success, FALSE in case of failure * * @since 3.0.0 * @throws \RuntimeException * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::findHeader() instead. */ protected static function findHeader(&$lines, &$src, &$dst) { // Get the current line $line = current($lines); // Search for the header while ($line !== false && !preg_match(self::SRC_FILE, $line, $m)) { $line = next($lines); } if ($line === false) { // No header found, return false return false; } // Set the source file $src = $m[1]; // Advance to the next line $line = next($lines); if ($line === false) { throw new \RuntimeException('Unexpected EOF'); } // Search the destination file if (!preg_match(self::DST_FILE, $line, $m)) { throw new \RuntimeException('Invalid Diff file'); } // Set the destination file $dst = $m[1]; // Advance to the next line if (next($lines) === false) { throw new \RuntimeException('Unexpected EOF'); } return true; } /** * Find the next hunk of difference * * The internal array pointer of $lines is on the next line after the finding * * @param array $lines The udiff array of lines * @param string $srcLine The beginning of the patch for the source file * @param string $srcSize The size of the patch for the source file * @param string $dstLine The beginning of the patch for the destination file * @param string $dstSize The size of the patch for the destination file * * @return boolean TRUE in case of success, false in case of failure * * @since 3.0.0 * @throws \RuntimeException * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::findHunk() instead. */ protected static function findHunk(&$lines, &$srcLine, &$srcSize, &$dstLine, &$dstSize) { $line = current($lines); if (preg_match(self::HUNK, $line, $m)) { $srcLine = (int) $m[1]; $srcSize = 1; if ($m[3] !== '') { $srcSize = (int) $m[3]; } $dstLine = (int) $m[4]; $dstSize = 1; if ($m[6] !== '') { $dstSize = (int) $m[6]; } if (next($lines) === false) { throw new \RuntimeException('Unexpected EOF'); } return true; } return false; } /** * Apply the patch * * @param array $lines The udiff array of lines * @param string $src The source file * @param string $dst The destination file * @param string $srcLine The beginning of the patch for the source file * @param string $srcSize The size of the patch for the source file * @param string $dstLine The beginning of the patch for the destination file * @param string $dstSize The size of the patch for the destination file * * @return void * * @since 3.0.0 * @throws \RuntimeException * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::applyHunk() instead. */ protected function applyHunk(&$lines, $src, $dst, $srcLine, $srcSize, $dstLine, $dstSize) { $srcLine--; $dstLine--; $line = current($lines); // Source lines (old file) $source = []; // New lines (new file) $destin = []; $src_left = $srcSize; $dst_left = $dstSize; do { if (!isset($line[0])) { $source[] = ''; $destin[] = ''; $src_left--; $dst_left--; } elseif ($line[0] == '-') { if ($src_left == 0) { throw new \RuntimeException(Text::sprintf('JLIB_FILESYSTEM_PATCHER_UNEXPECTED_REMOVE_LINE', key($lines))); } $source[] = substr($line, 1); $src_left--; } elseif ($line[0] == '+') { if ($dst_left == 0) { throw new \RuntimeException(Text::sprintf('JLIB_FILESYSTEM_PATCHER_UNEXPECTED_ADD_LINE', key($lines))); } $destin[] = substr($line, 1); $dst_left--; } elseif ($line != '\\ No newline at end of file') { $line = substr($line, 1); $source[] = $line; $destin[] = $line; $src_left--; $dst_left--; } if ($src_left == 0 && $dst_left == 0) { // Now apply the patch, finally! if ($srcSize > 0) { $src_lines = & $this->getSource($src); if (!isset($src_lines)) { throw new \RuntimeException( Text::sprintf( 'JLIB_FILESYSTEM_PATCHER_UNEXISTING_SOURCE', Path::removeRoot($src) ) ); } } if ($dstSize > 0) { if ($srcSize > 0) { $dst_lines = & $this->getDestination($dst, $src); $src_bottom = $srcLine + \count($source); for ($l = $srcLine; $l < $src_bottom; $l++) { if ($src_lines[$l] != $source[$l - $srcLine]) { throw new \RuntimeException( Text::sprintf( 'JLIB_FILESYSTEM_PATCHER_FAILED_VERIFY', Path::removeRoot($src), $l ) ); } } array_splice($dst_lines, $dstLine, \count($source), $destin); } else { $this->destinations[$dst] = $destin; } } else { $this->removals[] = $src; } next($lines); return; } $line = next($lines); } while ($line !== false); throw new \RuntimeException('Unexpected EOF'); } /** * Get the lines of a source file * * @param string $src The path of a file * * @return array The lines of the source file * * @since 3.0.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::getSource() instead. */ protected function &getSource($src) { if (!isset($this->sources[$src])) { $this->sources[$src] = null; if (is_readable($src)) { $this->sources[$src] = self::splitLines(file_get_contents($src)); } } return $this->sources[$src]; } /** * Get the lines of a destination file * * @param string $dst The path of a destination file * @param string $src The path of a source file * * @return array The lines of the destination file * * @since 3.0.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Patcher::getDestination() instead. */ protected function &getDestination($dst, $src) { if (!isset($this->destinations[$dst])) { $this->destinations[$dst] = $this->getSource($src); } return $this->destinations[$dst]; } } File.php 0000644 00000052110 15172625747 0006153 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Filesystem; use Joomla\CMS\Client\ClientHelper; use Joomla\CMS\Client\FtpClient; use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * A File handling class * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\File instead. */ class File { /** * @var boolean true if OPCache enabled, and we have permission to invalidate files * @since 4.0.1 */ protected static $canFlushFileCache; /** * Gets the extension of a file name * * @param string $file The file name * * @return string The file extension * * @since 1.7.0 */ public static function getExt($file) { // String manipulation should be faster than pathinfo() on newer PHP versions. $dot = strrpos($file, '.'); if ($dot === false) { return ''; } $ext = substr($file, $dot + 1); // Extension cannot contain slashes. if (strpos($ext, '/') !== false || (DIRECTORY_SEPARATOR === '\\' && strpos($ext, '\\') !== false)) { return ''; } return $ext; } /** * Strips the last extension off of a file name * * @param string $file The file name * * @return string The file name without the extension * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\File::stripExt() instead. */ public static function stripExt($file) { return preg_replace('#\.[^.]*$#', '', $file); } /** * Makes file name safe to use * * @param string $file The name of the file [not full path] * * @return string The sanitised string * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\File::makeSafe() instead. */ public static function makeSafe($file) { // Remove any trailing dots, as those aren't ever valid file names. $file = rtrim($file, '.'); // Try transliterating the file name using the native php function if (function_exists('transliterator_transliterate') && function_exists('iconv')) { // Using iconv to ignore characters that can't be transliterated $file = iconv("UTF-8", "ASCII//TRANSLIT//IGNORE", transliterator_transliterate('Any-Latin; Latin-ASCII', $file)); } $regex = ['#(\.){2,}#', '#[^A-Za-z0-9\.\_\- ]#', '#^\.#']; return trim(preg_replace($regex, '', $file)); } /** * Copies a file * * @param string $src The path to the source file * @param string $dest The path to the destination file * @param string $path An optional base path to prefix to the file names * @param boolean $useStreams True to use streams * * @return boolean True on success * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\File::copy() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public static function copy($src, $dest, $path = null, $useStreams = false) { // Prepend a base path if it exists if ($path) { $src = Path::clean($path . '/' . $src); $dest = Path::clean($path . '/' . $dest); } // Check src path if (!is_readable($src)) { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_FILE_FIND_COPY', __METHOD__, $src), Log::WARNING, 'jerror'); return false; } if ($useStreams) { $stream = Factory::getStream(); if (!$stream->copy($src, $dest)) { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_FILE_STREAMS', __METHOD__, $src, $dest, $stream->getError()), Log::WARNING, 'jerror'); return false; } self::invalidateFileCache($dest); return true; } else { $FTPOptions = ClientHelper::getCredentials('ftp'); if ($FTPOptions['enabled'] == 1) { // Connect the FTP client $ftp = FtpClient::getInstance($FTPOptions['host'], $FTPOptions['port'], [], $FTPOptions['user'], $FTPOptions['pass']); // If the parent folder doesn't exist we must create it if (!file_exists(\dirname($dest))) { Folder::create(\dirname($dest)); } // Translate the destination path for the FTP account $dest = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dest), '/'); if (!$ftp->store($src, $dest)) { // FTP connector throws an error return false; } $ret = true; } else { if (!@ copy($src, $dest)) { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_COPY_FAILED_ERR01', $src, $dest), Log::WARNING, 'jerror'); return false; } $ret = true; } self::invalidateFileCache($dest); return $ret; } } /** * Invalidate opcache for a newly written/deleted file immediately, if opcache* functions exist and if this was a PHP file. * * @param string $filepath The path to the file just written to, to flush from opcache * @param boolean $force If set to true, the script will be invalidated regardless of whether invalidation is necessary * * @return boolean TRUE if the opcode cache for script was invalidated/nothing to invalidate, * or FALSE if the opcode cache is disabled or other conditions returning * FALSE from opcache_invalidate (like file not found). * * @since 4.0.1 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\File::invalidateFileCache() instead. */ public static function invalidateFileCache($filepath, $force = true) { if (self::canFlushFileCache() && '.php' === strtolower(substr($filepath, -4))) { return opcache_invalidate($filepath, $force); } return false; } /** * First we check if opcache is enabled * Then we check if the opcache_invalidate function is available * Lastly we check if the host has restricted which scripts can use opcache_invalidate using opcache.restrict_api. * * `$_SERVER['SCRIPT_FILENAME']` approximates the origin file's path, but `realpath()` * is necessary because `SCRIPT_FILENAME` can be a relative path when run from CLI. * If the host has this set, check whether the path in `opcache.restrict_api` matches * the beginning of the path of the origin file. * * @return boolean TRUE if we can proceed to use opcache_invalidate to flush a file from the OPCache * * @since 4.0.1 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\File::invalidateFileCache() instead. * This method will be removed without replacement. */ public static function canFlushFileCache() { if (isset(static::$canFlushFileCache)) { return static::$canFlushFileCache; } if ( ini_get('opcache.enable') && function_exists('opcache_invalidate') && (!ini_get('opcache.restrict_api') || stripos(realpath($_SERVER['SCRIPT_FILENAME']), ini_get('opcache.restrict_api')) === 0) ) { static::$canFlushFileCache = true; } else { static::$canFlushFileCache = false; } return static::$canFlushFileCache; } /** * Delete a file or array of files * * @param mixed $file The file name or an array of file names * * @return boolean True on success * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\File::delete() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public static function delete($file) { $FTPOptions = ClientHelper::getCredentials('ftp'); if (\is_array($file)) { $files = $file; } else { $files[] = $file; } // Do NOT use ftp if it is not enabled if ($FTPOptions['enabled'] == 1) { // Connect the FTP client $ftp = FtpClient::getInstance($FTPOptions['host'], $FTPOptions['port'], [], $FTPOptions['user'], $FTPOptions['pass']); } foreach ($files as $file) { $file = Path::clean($file); if (!is_file($file)) { continue; } /** * Try making the file writable first. If it's read-only, it can't be deleted * on Windows, even if the parent folder is writable */ @chmod($file, 0777); /** * Invalidate the OPCache for the file before actually deleting it * @see https://github.com/joomla/joomla-cms/pull/32915#issuecomment-812865635 * @see https://www.php.net/manual/en/function.opcache-invalidate.php#116372 */ self::invalidateFileCache($file); /** * In case of restricted permissions we delete it one way or the other * as long as the owner is either the webserver or the ftp */ if (@unlink($file)) { // Do nothing } elseif ($FTPOptions['enabled'] == 1) { $file = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $file), '/'); if (!$ftp->delete($file)) { // FTP connector throws an error return false; } } else { $filename = basename($file); Log::add(Text::sprintf('JLIB_FILESYSTEM_DELETE_FAILED', $filename), Log::WARNING, 'jerror'); return false; } } return true; } /** * Moves a file * * @param string $src The path to the source file * @param string $dest The path to the destination file * @param string $path An optional base path to prefix to the file names * @param boolean $useStreams True to use streams * * @return boolean True on success * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\File::move() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public static function move($src, $dest, $path = '', $useStreams = false) { if ($path) { $src = Path::clean($path . '/' . $src); $dest = Path::clean($path . '/' . $dest); } // Check src path if (!is_readable($src)) { Log::add(Text::_('JLIB_FILESYSTEM_CANNOT_FIND_SOURCE_FILE'), Log::WARNING, 'jerror'); return false; } if ($useStreams) { $stream = Factory::getStream(); if (!$stream->move($src, $dest)) { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_GENERIC', __METHOD__, $stream->getError()), Log::WARNING, 'jerror'); return false; } self::invalidateFileCache($dest); return true; } else { $FTPOptions = ClientHelper::getCredentials('ftp'); // Invalidate the compiled OPCache of the old file so it's no longer used. self::invalidateFileCache($src); if ($FTPOptions['enabled'] == 1) { // Connect the FTP client $ftp = FtpClient::getInstance($FTPOptions['host'], $FTPOptions['port'], [], $FTPOptions['user'], $FTPOptions['pass']); // Translate path for the FTP account $src = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $src), '/'); $dest = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dest), '/'); // Use FTP rename to simulate move if (!$ftp->rename($src, $dest)) { Log::add(Text::_('JLIB_FILESYSTEM_ERROR_RENAME_FILE'), Log::WARNING, 'jerror'); return false; } } else { if (!@ rename($src, $dest)) { Log::add(Text::_('JLIB_FILESYSTEM_ERROR_RENAME_FILE'), Log::WARNING, 'jerror'); return false; } } self::invalidateFileCache($dest); return true; } } /** * Write contents to a file * * @param string $file The full file path * @param string $buffer The buffer to write * @param boolean $useStreams Use streams * * @return boolean True on success * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\File::write() instead. */ public static function write($file, $buffer, $useStreams = false) { if (\function_exists('set_time_limit')) { set_time_limit(ini_get('max_execution_time')); } // If the destination directory doesn't exist we need to create it if (!file_exists(\dirname($file))) { if (Folder::create(\dirname($file)) == false) { return false; } } if ($useStreams) { $stream = Factory::getStream(); // Beef up the chunk size to a meg $stream->set('chunksize', (1024 * 1024)); if (!$stream->writeFile($file, $buffer)) { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_WRITE_STREAMS', __METHOD__, $file, $stream->getError()), Log::WARNING, 'jerror'); return false; } self::invalidateFileCache($file); return true; } else { $FTPOptions = ClientHelper::getCredentials('ftp'); if ($FTPOptions['enabled'] == 1) { // Connect the FTP client $ftp = FtpClient::getInstance($FTPOptions['host'], $FTPOptions['port'], [], $FTPOptions['user'], $FTPOptions['pass']); // Translate path for the FTP account and use FTP write buffer to file $file = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $file), '/'); $ret = $ftp->write($file, $buffer); } else { $file = Path::clean($file); $ret = \is_int(file_put_contents($file, $buffer)); } self::invalidateFileCache($file); return $ret; } } /** * Append contents to a file * * @param string $file The full file path * @param string $buffer The buffer to write * @param boolean $useStreams Use streams * * @return boolean True on success * * @since 3.6.0 * */ public static function append($file, $buffer, $useStreams = false) { if (\function_exists('set_time_limit')) { set_time_limit(ini_get('max_execution_time')); } // If the file doesn't exist, just write instead of append if (!file_exists($file)) { return self::write($file, $buffer, $useStreams); } if ($useStreams) { $stream = Factory::getStream(); // Beef up the chunk size to a meg $stream->set('chunksize', (1024 * 1024)); if ($stream->open($file, 'ab') && $stream->write($buffer) && $stream->close()) { self::invalidateFileCache($file); return true; } Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_WRITE_STREAMS', __METHOD__, $file, $stream->getError()), Log::WARNING, 'jerror'); return false; } else { // Initialise variables. $FTPOptions = ClientHelper::getCredentials('ftp'); if ($FTPOptions['enabled'] == 1) { // Connect the FTP client $ftp = FtpClient::getInstance($FTPOptions['host'], $FTPOptions['port'], [], $FTPOptions['user'], $FTPOptions['pass']); // Translate path for the FTP account and use FTP write buffer to file $file = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $file), '/'); $ret = $ftp->append($file, $buffer); } else { $file = Path::clean($file); $ret = \is_int(file_put_contents($file, $buffer, FILE_APPEND)); } self::invalidateFileCache($file); return $ret; } } /** * Moves an uploaded file to a destination folder * * @param string $src The name of the php (temporary) uploaded file * @param string $dest The path (including filename) to move the uploaded file to * @param boolean $useStreams True to use streams * @param boolean $allowUnsafe Allow the upload of unsafe files * @param array $safeFileOptions Options to InputFilter::isSafeFile * * @return boolean True on success * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\File::upload() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public static function upload($src, $dest, $useStreams = false, $allowUnsafe = false, $safeFileOptions = []) { if (!$allowUnsafe) { $descriptor = [ 'tmp_name' => $src, 'name' => basename($dest), 'type' => '', 'error' => '', 'size' => '', ]; $isSafe = InputFilter::isSafeFile($descriptor, $safeFileOptions); if (!$isSafe) { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_WARNFS_ERR03', $dest), Log::WARNING, 'jerror'); return false; } } // Ensure that the path is valid and clean $dest = Path::clean($dest); // Create the destination directory if it does not exist $baseDir = \dirname($dest); if (!file_exists($baseDir)) { Folder::create($baseDir); } if ($useStreams) { $stream = Factory::getStream(); if (!$stream->upload($src, $dest)) { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_GENERIC', __METHOD__, $stream->getError()), Log::WARNING, 'jerror'); return false; } return true; } else { $FTPOptions = ClientHelper::getCredentials('ftp'); $ret = false; if ($FTPOptions['enabled'] == 1) { // Connect the FTP client $ftp = FtpClient::getInstance($FTPOptions['host'], $FTPOptions['port'], [], $FTPOptions['user'], $FTPOptions['pass']); // Translate path for the FTP account $dest = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dest), '/'); // Copy the file to the destination directory if (is_uploaded_file($src) && $ftp->store($src, $dest)) { self::invalidateFileCache($src); unlink($src); $ret = true; } else { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_WARNFS_ERR04', $src, $dest), Log::WARNING, 'jerror'); } } else { self::invalidateFileCache($src); if (is_writable($baseDir) && move_uploaded_file($src, $dest)) { // Short circuit to prevent file permission errors if (Path::setPermissions($dest)) { $ret = true; } else { Log::add(Text::_('JLIB_FILESYSTEM_ERROR_WARNFS_ERR01'), Log::WARNING, 'jerror'); } } else { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_WARNFS_ERR04', $src, $dest), Log::WARNING, 'jerror'); } } self::invalidateFileCache($dest); return $ret; } } /** * Wrapper for the standard file_exists function * * @param string $file File path * * @return boolean True if path is a file * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use is_file() instead. */ public static function exists($file) { return is_file(Path::clean($file)); } } Path.php 0000644 00000027573 15172625747 0006207 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Filesystem; \defined('JPATH_PLATFORM') or die; use Joomla\CMS\Crypt\Crypt; if (!\defined('JPATH_ROOT')) { // Define a string constant for the root directory of the file system in native format \define('JPATH_ROOT', Path::clean(JPATH_SITE)); } /** * A Path handling class * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Path instead. */ class Path { /** * Checks if a path's permissions can be changed. * * @param string $path Path to check. * * @return boolean True if path can have mode changed. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Path::canChmod() instead. */ public static function canChmod($path) { $perms = fileperms($path); if ($perms !== false) { if (@chmod($path, $perms ^ 0001)) { @chmod($path, $perms); return true; } } return false; } /** * Chmods files and directories recursively to given permissions. * * @param string $path Root path to begin changing mode [without trailing slash]. * @param string $filemode Octal representation of the value to change file mode to [null = no change]. * @param string $foldermode Octal representation of the value to change folder mode to [null = no change]. * * @return boolean True if successful [one fail means the whole operation failed]. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Path::setPermissions() instead. */ public static function setPermissions($path, $filemode = '0644', $foldermode = '0755') { // Initialise return value $ret = true; if (is_dir($path)) { $dh = opendir($path); while ($file = readdir($dh)) { if ($file != '.' && $file != '..') { $fullpath = $path . '/' . $file; if (is_dir($fullpath)) { if (!self::setPermissions($fullpath, $filemode, $foldermode)) { $ret = false; } } else { if (isset($filemode)) { if (!@ chmod($fullpath, octdec($filemode))) { $ret = false; } } } } } closedir($dh); if (isset($foldermode)) { if (!@ chmod($path, octdec($foldermode))) { $ret = false; } } } else { if (isset($filemode)) { $ret = @ chmod($path, octdec($filemode)); } } return $ret; } /** * Get the permissions of the file/folder at a given path. * * @param string $path The path of a file/folder. * * @return string Filesystem permissions. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Path::getPermissions() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public static function getPermissions($path) { $path = self::clean($path); $mode = @ decoct(@ fileperms($path) & 0777); if (\strlen($mode) < 3) { return '---------'; } $parsed_mode = ''; for ($i = 0; $i < 3; $i++) { // Read $parsed_mode .= ($mode[$i] & 04) ? 'r' : '-'; // Write $parsed_mode .= ($mode[$i] & 02) ? 'w' : '-'; // Execute $parsed_mode .= ($mode[$i] & 01) ? 'x' : '-'; } return $parsed_mode; } /** * Checks for snooping outside of the file system root. * * @param string $path A file system path to check. * * @return string A cleaned version of the path or exit on error. * * @throws \Exception * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Path::check() instead. */ public static function check($path) { if (strpos($path, '..') !== false) { // Don't translate throw new \Exception( sprintf( '%s() - Use of relative paths not permitted', __METHOD__ ) ); } $path = self::clean($path); if ((JPATH_ROOT != '') && strpos($path, self::clean(JPATH_ROOT)) !== 0) { throw new \Exception( sprintf( '%1$s() - Snooping out of bounds @ %2$s', __METHOD__, self::removeRoot($path) ) ); } return $path; } /** * Function to strip additional / or \ in a path name. * * @param string $path The path to clean. * @param string $ds Directory separator (optional). * * @return string The cleaned path. * * @throws \UnexpectedValueException * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Path::clean() instead. */ public static function clean($path, $ds = DIRECTORY_SEPARATOR) { if (!\is_string($path) && !empty($path)) { throw new \UnexpectedValueException( sprintf( '%s() - $path is not a string', __METHOD__ ) ); } if ($path === null) { @trigger_error( sprintf( 'Path can not be null, in 6.0 it will throw an exception', __METHOD__ ), E_USER_DEPRECATED ); $path = ''; } $path = trim($path); if (empty($path)) { $path = JPATH_ROOT; } elseif (($ds === '\\') && substr($path, 0, 2) === '\\\\') { // Remove double slashes and backslashes and convert all slashes and backslashes to DIRECTORY_SEPARATOR // If dealing with a UNC path don't forget to prepend the path with a backslash. $path = "\\" . preg_replace('#[/\\\\]+#', $ds, $path); } else { $path = preg_replace('#[/\\\\]+#', $ds, $path); } return $path; } /** * Method to determine if script owns the path. * * @param string $path Path to check ownership. * * @return boolean True if the php script owns the path passed. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Path::isOwner() instead. */ public static function isOwner($path) { $tmp = md5(Crypt::genRandomBytes()); $ssp = ini_get('session.save_path'); $jtp = JPATH_SITE . '/tmp'; // Try to find a writable directory $dir = false; foreach ([$jtp, $ssp, '/tmp'] as $currentDir) { if (is_writable($currentDir)) { $dir = $currentDir; break; } } if ($dir) { $test = $dir . '/' . $tmp; // Create the test file $blank = ''; File::write($test, $blank, false); // Test ownership $return = (fileowner($test) == fileowner($path)); // Delete the test file File::delete($test); return $return; } return false; } /** * Searches the directory paths for a given file. * * @param mixed $paths A path string or array of path strings to search in * @param string $file The file name to look for. * * @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. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Path::find() instead. */ public static function find($paths, $file) { // Force to array if (!\is_array($paths) && !($paths instanceof \Iterator)) { settype($paths, 'array'); } // Start looping through the path set foreach ($paths as $path) { // Get the path to the file $fullname = $path . '/' . $file; // Is the path based on a stream? if (strpos($path, '://') === false) { // Not a stream, so do a realpath() to avoid directory // traversal attempts on the local file system. // Needed for substr() later $path = realpath($path); $fullname = realpath($fullname); } /* * The substr() check added to make sure that the realpath() * results in a directory registered so that * non-registered directories are not accessible via directory * traversal attempts. */ if (file_exists($fullname) && substr($fullname, 0, \strlen($path)) === $path) { return $fullname; } } // Could not find the file in the set of paths return false; } /** * Resolves /./, /../ and multiple / in a string and returns the resulting absolute path, inspired by Flysystem * Removes trailing slashes * * @param string $path A path to resolve * * @return string The resolved path * * @since 3.9.25 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Path::resolve() instead. */ public static function resolve($path) { $path = static::clean($path); // Save start character for absolute path $startCharacter = ($path[0] === DIRECTORY_SEPARATOR) ? DIRECTORY_SEPARATOR : ''; $parts = []; foreach (explode(DIRECTORY_SEPARATOR, $path) as $part) { switch ($part) { case '': case '.': break; case '..': if (empty($parts)) { throw new \Exception('Path is outside of the defined root'); } array_pop($parts); break; default: $parts[] = $part; break; } } return $startCharacter . implode(DIRECTORY_SEPARATOR, $parts); } /** * Remove all references to root directory path and the system tmp path from a message * * @param string $message The message to be cleaned * @param string $rootDirectory Optional root directory, defaults to JPATH_ROOT * * @return string * * @since 3.10.7 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Path::removeRoot() instead. */ public static function removeRoot($message, $rootDirectory = null) { if (empty($rootDirectory)) { $rootDirectory = JPATH_ROOT; } $makePattern = static function ($dir) { return '~' . str_replace('~', '\\~', preg_replace('~[/\\\\]+~', '[/\\\\\\\\]+', $dir)) . '~'; }; $replacements = [ $makePattern(static::clean($rootDirectory)) => '[ROOT]', $makePattern(sys_get_temp_dir()) => '[TMP]', ]; return preg_replace(array_keys($replacements), array_values($replacements), $message); } } Folder.php 0000644 00000057557 15172625747 0006533 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Filesystem; use Joomla\CMS\Client\ClientHelper; use Joomla\CMS\Client\FtpClient; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * A Folder handling class * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Folder instead. */ abstract class Folder { /** * Copy a folder. * * @param string $src The path to the source folder. * @param string $dest The path to the destination folder. * @param string $path An optional base path to prefix to the file names. * @param boolean $force Force copy. * @param boolean $useStreams Optionally force folder/file overwrites. * * @return boolean True on success. * * @since 1.7.0 * @throws \RuntimeException * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Folder::copy() instead. */ public static function copy($src, $dest, $path = '', $force = false, $useStreams = false) { if (\function_exists('set_time_limit')) { set_time_limit(ini_get('max_execution_time')); } $FTPOptions = ClientHelper::getCredentials('ftp'); if ($path) { $src = Path::clean($path . '/' . $src); $dest = Path::clean($path . '/' . $dest); } // Eliminate trailing directory separators, if any $src = rtrim($src, DIRECTORY_SEPARATOR); $dest = rtrim($dest, DIRECTORY_SEPARATOR); if (!self::exists($src)) { throw new \RuntimeException('Source folder not found', -1); } if (self::exists($dest) && !$force) { throw new \RuntimeException('Destination folder already exists', -1); } // Make sure the destination exists if (!self::create($dest)) { throw new \RuntimeException('Cannot create destination folder', -1); } // If we're using ftp and don't have streams enabled if ($FTPOptions['enabled'] == 1 && !$useStreams) { // Connect the FTP client $ftp = FtpClient::getInstance($FTPOptions['host'], $FTPOptions['port'], [], $FTPOptions['user'], $FTPOptions['pass']); if (!($dh = @opendir($src))) { throw new \RuntimeException('Cannot open source folder', -1); } // Walk through the directory copying files and recursing into folders. while (($file = readdir($dh)) !== false) { $sfid = $src . '/' . $file; $dfid = $dest . '/' . $file; switch (filetype($sfid)) { case 'dir': if ($file != '.' && $file != '..') { $ret = self::copy($sfid, $dfid, null, $force); if ($ret !== true) { return $ret; } } break; case 'file': // Translate path for the FTP account $dfid = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dfid), '/'); if (!$ftp->store($sfid, $dfid)) { throw new \RuntimeException('Copy file failed', -1); } break; } } } else { if (!($dh = @opendir($src))) { throw new \RuntimeException('Cannot open source folder', -1); } // Walk through the directory copying files and recursing into folders. while (($file = readdir($dh)) !== false) { $sfid = $src . '/' . $file; $dfid = $dest . '/' . $file; switch (filetype($sfid)) { case 'dir': if ($file != '.' && $file != '..') { $ret = self::copy($sfid, $dfid, null, $force, $useStreams); if ($ret !== true) { return $ret; } } break; case 'file': if ($useStreams) { $stream = Factory::getStream(); if (!$stream->copy($sfid, $dfid)) { throw new \RuntimeException( sprintf( "Cannot copy file: %s", Path::removeRoot($stream->getError()) ), -1 ); } } else { if (!@copy($sfid, $dfid)) { throw new \RuntimeException('Copy file failed', -1); } } break; } } } return true; } /** * Create a folder -- and all necessary parent folders. * * @param string $path A path to create from the base path. * @param integer $mode Directory permissions to set for folders created. 0755 by default. * * @return boolean True if successful. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Folder::create() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public static function create($path = '', $mode = 0755) { $FTPOptions = ClientHelper::getCredentials('ftp'); static $nested = 0; // Check to make sure the path valid and clean $path = Path::clean($path); // Check if parent dir exists $parent = \dirname($path); if (!self::exists($parent)) { // Prevent infinite loops! $nested++; if (($nested > 20) || ($parent == $path)) { Log::add(__METHOD__ . ': ' . Text::_('JLIB_FILESYSTEM_ERROR_FOLDER_LOOP'), Log::WARNING, 'jerror'); $nested--; return false; } // Create the parent directory if (self::create($parent, $mode) !== true) { // Folder::create throws an error $nested--; return false; } // OK, parent directory has been created $nested--; } // Check if dir already exists if (self::exists($path)) { return true; } // Check for safe mode if ($FTPOptions['enabled'] == 1) { // Connect the FTP client $ftp = FtpClient::getInstance($FTPOptions['host'], $FTPOptions['port'], [], $FTPOptions['user'], $FTPOptions['pass']); // Translate path to FTP path $path = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $path), '/'); $ret = $ftp->mkdir($path); $ftp->chmod($path, $mode); } else { // We need to get and explode the open_basedir paths $obd = ini_get('open_basedir'); // If open_basedir is set we need to get the open_basedir that the path is in if ($obd != null) { if (IS_WIN) { $obdSeparator = ';'; } else { $obdSeparator = ':'; } // Create the array of open_basedir paths $obdArray = explode($obdSeparator, $obd); $inBaseDir = false; // Iterate through open_basedir paths looking for a match foreach ($obdArray as $test) { $test = Path::clean($test); if (strpos($path, $test) === 0 || strpos($path, realpath($test)) === 0) { $inBaseDir = true; break; } } if ($inBaseDir == false) { // Return false for JFolder::create because the path to be created is not in open_basedir Log::add(__METHOD__ . ': ' . Text::_('JLIB_FILESYSTEM_ERROR_FOLDER_PATH'), Log::WARNING, 'jerror'); return false; } } // First set umask $origmask = @umask(0); // Create the path if (!$ret = @mkdir($path, $mode)) { @umask($origmask); Log::add( __METHOD__ . ': ' . Text::_('JLIB_FILESYSTEM_ERROR_COULD_NOT_CREATE_DIRECTORY') . 'Path: ' . $path, Log::WARNING, 'jerror' ); return false; } // Reset umask @umask($origmask); } return $ret; } /** * Delete a folder. * * @param string $path The path to the folder to delete. * * @return boolean True on success. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Folder::delete() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public static function delete($path) { if (\function_exists('set_time_limit')) { set_time_limit(ini_get('max_execution_time')); } // Sanity check if (!$path) { // Bad programmer! Bad Bad programmer! Log::add(__METHOD__ . ': ' . Text::_('JLIB_FILESYSTEM_ERROR_DELETE_BASE_DIRECTORY'), Log::WARNING, 'jerror'); return false; } $FTPOptions = ClientHelper::getCredentials('ftp'); // Check to make sure the path valid and clean $path = Path::clean($path); // Is this really a folder? if (!is_dir($path)) { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER', __METHOD__, $path), Log::WARNING, 'jerror'); return false; } // Remove all the files in folder if they exist; disable all filtering $files = self::files($path, '.', false, true, [], []); if (!empty($files)) { if (File::delete($files) !== true) { // File::delete throws an error return false; } } // Remove sub-folders of folder; disable all filtering $folders = self::folders($path, '.', false, true, [], []); foreach ($folders as $folder) { if (is_link($folder)) { // Don't descend into linked directories, just delete the link. if (File::delete($folder) !== true) { // File::delete throws an error return false; } } elseif (self::delete($folder) !== true) { // Folder::delete throws an error return false; } } if ($FTPOptions['enabled'] == 1) { // Connect the FTP client $ftp = FtpClient::getInstance($FTPOptions['host'], $FTPOptions['port'], [], $FTPOptions['user'], $FTPOptions['pass']); } // In case of restricted permissions we zap it one way or the other // as long as the owner is either the webserver or the ftp. if (@rmdir($path)) { $ret = true; } elseif ($FTPOptions['enabled'] == 1) { // Translate path and delete $path = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $path), '/'); // FTP connector throws an error $ret = $ftp->delete($path); } else { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_FOLDER_DELETE', $path), Log::WARNING, 'jerror'); $ret = false; } return $ret; } /** * Moves a folder. * * @param string $src The path to the source folder. * @param string $dest The path to the destination folder. * @param string $path An optional base path to prefix to the file names. * @param boolean $useStreams Optionally use streams. * * @return mixed Error message on false or boolean true on success. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Folder::move() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public static function move($src, $dest, $path = '', $useStreams = false) { $FTPOptions = ClientHelper::getCredentials('ftp'); if ($path) { $src = Path::clean($path . '/' . $src); $dest = Path::clean($path . '/' . $dest); } if (!self::exists($src)) { return Text::_('JLIB_FILESYSTEM_ERROR_FIND_SOURCE_FOLDER'); } if (self::exists($dest)) { return Text::_('JLIB_FILESYSTEM_ERROR_FOLDER_EXISTS'); } if ($useStreams) { $stream = Factory::getStream(); if (!$stream->move($src, $dest)) { return Text::sprintf('JLIB_FILESYSTEM_ERROR_FOLDER_RENAME', $stream->getError()); } $ret = true; } else { if ($FTPOptions['enabled'] == 1) { // Connect the FTP client $ftp = FtpClient::getInstance($FTPOptions['host'], $FTPOptions['port'], [], $FTPOptions['user'], $FTPOptions['pass']); // Translate path for the FTP account $src = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $src), '/'); $dest = Path::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dest), '/'); // Use FTP rename to simulate move if (!$ftp->rename($src, $dest)) { return Text::_('JLIB_FILESYSTEM_ERROR_RENAME_FILE'); } $ret = true; } else { if (!@rename($src, $dest)) { return Text::_('JLIB_FILESYSTEM_ERROR_RENAME_FILE'); } $ret = true; } } return $ret; } /** * Wrapper for the standard file_exists function * * @param string $path Folder name relative to installation dir * * @return boolean True if path is a folder * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use is_dir() instead. */ public static function exists($path) { return is_dir(Path::clean($path)); } /** * Utility function to read the files in a folder. * * @param string $path The path of the folder to read. * @param string $filter A filter for file names. * @param mixed $recurse True to recursively search into sub-folders, or an integer to specify the maximum depth. * @param boolean $full True to return the full path to the file. * @param array $exclude Array with names of files which should not be shown in the result. * @param array $excludeFilter Array of filter to exclude * @param boolean $naturalSort False for asort, true for natsort * * @return array|boolean Files in the given folder. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Folder::files() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public static function files( $path, $filter = '.', $recurse = false, $full = false, $exclude = ['.svn', 'CVS', '.DS_Store', '__MACOSX'], $excludeFilter = ['^\..*', '.*~'], $naturalSort = false ) { // Check to make sure the path valid and clean $path = Path::clean($path); // Is the path a folder? if (!is_dir($path)) { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER', __METHOD__, $path), Log::WARNING, 'jerror'); return false; } // Compute the excludefilter string if (\count($excludeFilter)) { $excludeFilterString = '/(' . implode('|', $excludeFilter) . ')/'; } else { $excludeFilterString = ''; } // Get the files $arr = self::_items($path, $filter, $recurse, $full, $exclude, $excludeFilterString, true); // Sort the files based on either natural or alpha method if ($naturalSort) { natsort($arr); } else { asort($arr); } return array_values($arr); } /** * Utility function to read the folders in a folder. * * @param string $path The path of the folder to read. * @param string $filter A filter for folder names. * @param mixed $recurse True to recursively search into sub-folders, or an integer to specify the maximum depth. * @param boolean $full True to return the full path to the folders. * @param array $exclude Array with names of folders which should not be shown in the result. * @param array $excludeFilter Array with regular expressions matching folders which should not be shown in the result. * * @return array Folders in the given folder. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Folder::folders() instead. * The framework class throws Exceptions in case of error which you have to catch. */ public static function folders( $path, $filter = '.', $recurse = false, $full = false, $exclude = ['.svn', 'CVS', '.DS_Store', '__MACOSX'], $excludeFilter = ['^\..*'] ) { // Check to make sure the path valid and clean $path = Path::clean($path); // Is the path a folder? if (!is_dir($path)) { Log::add(Text::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER', __METHOD__, $path), Log::WARNING, 'jerror'); return false; } // Compute the excludefilter string if (\count($excludeFilter)) { $excludeFilterString = '/(' . implode('|', $excludeFilter) . ')/'; } else { $excludeFilterString = ''; } // Get the folders $arr = self::_items($path, $filter, $recurse, $full, $exclude, $excludeFilterString, false); // Sort the folders asort($arr); return array_values($arr); } /** * Function to read the files/folders in a folder. * * @param string $path The path of the folder to read. * @param string $filter A filter for file names. * @param mixed $recurse True to recursively search into sub-folders, or an integer to specify the maximum depth. * @param boolean $full True to return the full path to the file. * @param array $exclude Array with names of files which should not be shown in the result. * @param string $excludeFilterString Regexp of files to exclude * @param boolean $findFiles True to read the files, false to read the folders * * @return array Files. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Folder::_items() instead. */ protected static function _items($path, $filter, $recurse, $full, $exclude, $excludeFilterString, $findFiles) { if (\function_exists('set_time_limit')) { set_time_limit(ini_get('max_execution_time')); } $arr = []; // Read the source directory if (!($handle = @opendir($path))) { return $arr; } while (($file = readdir($handle)) !== false) { if ( $file != '.' && $file != '..' && !\in_array($file, $exclude) && (empty($excludeFilterString) || !preg_match($excludeFilterString, $file)) ) { // Compute the fullpath $fullpath = $path . '/' . $file; // Compute the isDir flag $isDir = is_dir($fullpath); if (($isDir xor $findFiles) && preg_match("/$filter/", $file)) { // (fullpath is dir and folders are searched or fullpath is not dir and files are searched) and file matches the filter if ($full) { // Full path is requested $arr[] = $fullpath; } else { // Filename is requested $arr[] = $file; } } if ($isDir && $recurse) { // Search recursively if (\is_int($recurse)) { // Until depth 0 is reached $arr = array_merge($arr, self::_items($fullpath, $filter, $recurse - 1, $full, $exclude, $excludeFilterString, $findFiles)); } else { $arr = array_merge($arr, self::_items($fullpath, $filter, $recurse, $full, $exclude, $excludeFilterString, $findFiles)); } } } } closedir($handle); return $arr; } /** * Lists folder in format suitable for tree display. * * @param string $path The path of the folder to read. * @param string $filter A filter for folder names. * @param integer $maxLevel The maximum number of levels to recursively read, defaults to three. * @param integer $level The current level, optional. * @param integer $parent Unique identifier of the parent folder, if any. * * @return array Folders in the given folder. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Folder::listFolderTree() instead. */ public static function listFolderTree($path, $filter, $maxLevel = 3, $level = 0, $parent = 0) { $dirs = []; if ($level == 0) { $GLOBALS['_JFolder_folder_tree_index'] = 0; } if ($level < $maxLevel) { $folders = self::folders($path, $filter); // First path, index foldernames foreach ($folders as $name) { $id = ++$GLOBALS['_JFolder_folder_tree_index']; $fullName = Path::clean($path . '/' . $name); $dirs[] = [ 'id' => $id, 'parent' => $parent, 'name' => $name, 'fullname' => $fullName, 'relname' => str_replace(JPATH_ROOT, '', $fullName), ]; $dirs2 = self::listFolderTree($fullName, $filter, $maxLevel, $level + 1, $id); $dirs = array_merge($dirs, $dirs2); } } return $dirs; } /** * Makes path name safe to use. * * @param string $path The full path to sanitise. * * @return string The sanitised string. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Folder::makeSafe() instead. */ public static function makeSafe($path) { $regex = ['#[^A-Za-z0-9_\\\/\(\)\[\]\{\}\#\$\^\+\.\'~`!@&=;,-]#']; return preg_replace($regex, '', $path); } } Streams/StreamString.php 0000644 00000016740 15172625747 0011345 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Filesystem\Streams; \defined('JPATH_PLATFORM') or die; use Joomla\CMS\Filesystem\Support\StringController; /** * String Stream Wrapper * * This class allows you to use a PHP string in the same way that * you would normally use a regular stream wrapper * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream\StringWrapper instead. */ class StreamString { /** * The current string * * @var string * @since 3.0.0 */ protected $currentString; /** * The path * * @var string * @since 3.0.0 */ protected $path; /** * The mode * * @var string * @since 3.0.0 */ protected $mode; /** * Enter description here ... * * @var string * @since 3.0.0 */ protected $options; /** * Enter description here ... * * @var string * @since 3.0.0 */ protected $openedPath; /** * Current position * * @var integer * @since 3.0.0 */ protected $pos; /** * Length of the string * * @var string * @since 3.0.0 */ protected $len; /** * Statistics for a file * * @var array * @since 3.0.0 * * @link http://us.php.net/manual/en/function.stat.php */ protected $stat; /** * Method to open a file or URL. * * @param string $path The stream path. * @param string $mode Not used. * @param integer $options Not used. * @param string $openedPath Not used. * * @return boolean * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream\StringWrapper::stream_open() instead. */ public function stream_open($path, $mode, $options, &$openedPath) { $this->currentString = &StringController::getRef(str_replace('string://', '', $path)); if ($this->currentString) { $this->len = \strlen($this->currentString); $this->pos = 0; $this->stat = $this->url_stat($path, 0); return true; } else { return false; } } /** * Method to retrieve information from a file resource * * @return array * * @link https://www.php.net/manual/en/streamwrapper.stream-stat.php * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream\StringWrapper::stream_stat instead. */ public function stream_stat() { return $this->stat; } /** * Method to retrieve information about a file. * * @param string $path File path or URL to stat * @param integer $flags Additional flags set by the streams API * * @return array * * @link https://www.php.net/manual/en/streamwrapper.url-stat.php * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream\StringWrapper::url_stat() instead. */ public function url_stat($path, $flags = 0) { $now = time(); $string = &StringController::getRef(str_replace('string://', '', $path)); $stat = [ 'dev' => 0, 'ino' => 0, 'mode' => 0, 'nlink' => 1, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => \strlen($string), 'atime' => $now, 'mtime' => $now, 'ctime' => $now, 'blksize' => '512', 'blocks' => ceil(\strlen($string) / 512), ]; return $stat; } /** * Method to read a given number of bytes starting at the current position * and moving to the end of the string defined by the current position plus the * given number. * * @param integer $count Bytes of data from the current position should be returned. * * @return string * * @link https://www.php.net/manual/en/streamwrapper.stream-read.php * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream\StringWrapper::stream_read() instead. */ public function stream_read($count) { $result = substr($this->currentString, $this->pos, $count); $this->pos += $count; return $result; } /** * Stream write, always returning false. * * @param string $data The data to write. * * @return boolean * * @since 1.7.0 * @note Updating the string is not supported. * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream\StringWrapper::stream_write() instead. */ public function stream_write($data) { // We don't support updating the string. return false; } /** * Method to get the current position * * @return integer The position * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream\StringWrapper::stream_tell() instead. */ public function stream_tell() { return $this->pos; } /** * End of field check * * @return boolean True if at end of field. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream\StringWrapper::stream_eof() instead. */ public function stream_eof() { if ($this->pos > $this->len) { return true; } return false; } /** * Stream offset * * @param integer $offset The starting offset. * @param integer $whence SEEK_SET, SEEK_CUR, SEEK_END * * @return boolean True on success. * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream\StringWrapper::stream_seek() instead. */ public function stream_seek($offset, $whence) { // $whence: SEEK_SET, SEEK_CUR, SEEK_END if ($offset > $this->len) { // We can't seek beyond our len. return false; } switch ($whence) { case SEEK_SET: $this->pos = $offset; break; case SEEK_CUR: if (($this->pos + $offset) < $this->len) { $this->pos += $offset; } else { return false; } break; case SEEK_END: $this->pos = $this->len - $offset; break; } return true; } /** * Stream flush, always returns true. * * @return boolean * * @since 1.7.0 * @note Data storage is not supported * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Stream\StringWrapper::stream_flush() instead. */ public function stream_flush() { // We don't store data. return true; } } stream_wrapper_register('string', '\\Joomla\\CMS\\Filesystem\\Streams\\StreamString') or die('StreamString Wrapper Registration Failed'); Support/StringController.php 0000644 00000003627 15172625747 0012273 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Filesystem\Support; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * String Controller * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Support\StringController instead. */ class StringController { /** * Defines a variable as an array * * @return array * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Support\StringController::getArray() instead. */ public function _getArray() { static $strings = []; return $strings; } /** * Create a reference * * @param string $reference The key * @param string $string The value * * @return void * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Support\StringController::createRef() instead. */ public function createRef($reference, &$string) { $ref = &self::_getArray(); $ref[$reference] = & $string; } /** * Get reference * * @param string $reference The key for the reference. * * @return mixed False if not set, reference if it exists * * @since 1.7.0 * @deprecated 4.4 will be removed in 6.0 * Use Joomla\Filesystem\Support\StringController::getRef() instead. */ public function getRef($reference) { $ref = &self::_getArray(); if (isset($ref[$reference])) { return $ref[$reference]; } else { return false; } } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.23 | Generation time: 0 |
proxy
|
phpinfo
|
Settings