Файловый менеджер - Редактировать - /home/wuectly/www/03cbe/Filesystem.zip
Назад
PK �X!]���� � Streams/StreamString.phpnu &1i� <?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 */ 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 */ 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 */ 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 */ public function url_stat($path, $flags = 0) { $now = time(); $string = &StringController::getRef(str_replace('string://', '', $path)); $stat = array( '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 void * * @since 1.7.0 * * @link https://www.php.net/manual/en/streamwrapper.stream-read.php */ 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. */ 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 */ public function stream_tell() { return $this->pos; } /** * End of field check * * @return boolean True if at end of field. * * @since 1.7.0 */ 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 */ 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 */ 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'); PK �X!]* � Support/StringController.phpnu &1i� <?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; defined('JPATH_PLATFORM') or die; /** * String Controller * * @since 1.7.0 */ class StringController { /** * Defines a variable as an array * * @return array * * @since 1.7.0 */ public function _getArray() { static $strings = array(); return $strings; } /** * Create a reference * * @param string $reference The key * @param string &$string The value * * @return void * * @since 1.7.0 */ 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 */ public function getRef($reference) { $ref = &self::_getArray(); if (isset($ref[$reference])) { return $ref[$reference]; } else { return false; } } } PK �X!]��K=y =y Stream.phpnu &1i� <?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; defined('JPATH_PLATFORM') or die; use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Language\Text; /** * 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 */ 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 = array(); /** * 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 */ public function __construct($writeprefix = '', $readprefix = '', $context = array()) { $this->writeprefix = $writeprefix; $this->readprefix = $readprefix; $this->contextOptions = $context; $this->_buildContext(); } /** * Destructor * * @since 1.7.0 */ 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 */ 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); } // One provided at initialisation elseif ($this->context) { $this->fh = fopen($filename, $mode, $useIncludePath, $this->context); } // No context; all defaults else { $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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 header/metadata * * @link https://www.php.net/manual/en/function.stream-get-meta-data.php * @since 1.7.0 */ 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 mixed * * @since 1.7.0 */ 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 */ 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 */ 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 */ 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 */ 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 */ public function appendFilter($filterName, $readWrite = STREAM_FILTER_READ, $params = array()) { $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 */ public function prependFilter($filterName, $readWrite = STREAM_FILTER_READ, $params = array()) { $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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ public function getFileHandle() { return $this->fh; } } PK �X!]���7 7 Wrapper/FileWrapper.phpnu &1i� <?php /** * Joomla! Content Management System * * @copyright (C) 2014 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Filesystem\Wrapper; use Joomla\Filesystem\File; defined('JPATH_PLATFORM') or die; /** * Wrapper class for File * * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ class FileWrapper { /** * Helper wrapper method for getExt * * @param string $file The file name. * * @return string The file extension. * * @see File::getExt() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ public function getExt($file) { return File::getExt($file); } /** * Helper wrapper method for stripExt * * @param string $file The file name. * * @return string The file name without the extension. * * @see File::stripExt() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ public function stripExt($file) { return File::stripExt($file); } /** * Helper wrapper method for makeSafe * * @param string $file The name of the file [not full path]. * * @return string The sanitised string. * * @see File::makeSafe() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ public function makeSafe($file) { return File::makeSafe($file); } /** * Helper wrapper method for copy * * @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. * * @see File::copy() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ public function copy($src, $dest, $path = null, $useStreams = false) { return File::copy($src, $dest, $path, $useStreams); } /** * Helper wrapper method for delete * * @param mixed $file The file name or an array of file names * * @return boolean True on success. * * @see File::delete() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ public function delete($file) { return File::delete($file); } /** * Helper wrapper method for move * * @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. * * @see File::move() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ public function move($src, $dest, $path = '', $useStreams = false) { return File::move($src, $dest, $path, $useStreams); } /** * Helper wrapper method for read * * @param string $filename The full file path. * @param boolean $incpath Use include path. * @param integer $amount Amount of file to read. * @param integer $chunksize Size of chunks to read. * @param integer $offset Offset of the file. * * @return mixed Returns file contents or boolean False if failed. * * @see File::read() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ public function read($filename, $incpath = false, $amount = 0, $chunksize = 8192, $offset = 0) { return File::read($filename, $incpath, $amount, $chunksize, $offset); } /** * Helper wrapper method for write * * @param string $file The full file path. * @param string &$buffer The buffer to write. * @param boolean $useStreams Use streams. * * @return boolean True on success. * * @see File::write() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ public function write($file, &$buffer, $useStreams = false) { return File::write($file, $buffer, $useStreams); } /** * Helper wrapper method for upload * * @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. * * @return boolean True on success. * * @see File::upload() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ public function upload($src, $dest, $useStreams = false) { return File::upload($src, $dest, $useStreams); } /** * Helper wrapper method for exists * * @param string $file File path. * * @return boolean True if path is a file. * * @see File::exists() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ public function exists($file) { return File::exists($file); } /** * Helper wrapper method for getName * * @param string $file File path. * * @return string filename. * * @see File::getName() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\File instead */ public function getName($file) { return File::getName($file); } } PK �X!]�A Wrapper/FolderWrapper.phpnu &1i� <?php /** * Joomla! Content Management System * * @copyright (C) 2014 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Filesystem\Wrapper; use Joomla\CMS\Filesystem\Folder; defined('JPATH_PLATFORM') or die; /** * Wrapper class for Folder * * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Folder instead */ class FolderWrapper { /** * Helper wrapper method for copy * * @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. * * @see Folder::copy() * @since 3.4 * @throws RuntimeException * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Folder instead */ public function copy($src, $dest, $path = '', $force = false, $useStreams = false) { return Folder::copy($src, $dest, $path, $force, $useStreams); } /** * Helper wrapper method for create * * @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. * * @see Folder::create() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Folder instead */ public function create($path = '', $mode = 493) { return Folder::create($path, $mode); } /** * Helper wrapper method for delete * * @param string $path The path to the folder to delete. * * @return boolean True on success. * * @see Folder::delete() * @since 3.4 * @throws UnexpectedValueException * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Folder instead */ public function delete($path) { return Folder::delete($path); } /** * Helper wrapper method for move * * @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. * * @see Folder::move() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Folder instead */ public function move($src, $dest, $path = '', $useStreams = false) { return Folder::move($src, $dest, $path, $useStreams); } /** * Helper wrapper method for exists * * @param string $path Folder name relative to installation dir. * * @return boolean True if path is a folder. * * @see Folder::exists() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Folder instead */ public function exists($path) { return Folder::exists($path); } /** * Helper wrapper method for files * * @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 Files in the given folder. * * @see Folder::files() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Folder instead */ public function files($path, $filter = '.', $recurse = false, $full = false, $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'), $excludefilter = array('^\..*', '.*~'), $naturalSort = false) { return Folder::files($path, $filter, $recurse, $full, $exclude, $excludefilter, $naturalSort); } /** * Helper wrapper method for folders * * @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. * * @see Folder::folders() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Folder instead */ public function folders($path, $filter = '.', $recurse = false, $full = false, $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'), $excludefilter = array('^\..*')) { return Folder::folders($path, $filter, $recurse, $full, $exclude, $excludefilter); } /** * Helper wrapper method for listFolderTree * * @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. * * @see Folder::listFolderTree() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Folder instead */ public function listFolderTree($path, $filter, $maxLevel = 3, $level = 0, $parent = 0) { return Folder::listFolderTree($path, $filter, $maxLevel, $level, $parent); } /** * Helper wrapper method for makeSafe * * @param string $path The full path to sanitise. * * @return string The sanitised string * * @see Folder::makeSafe() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Folder instead */ public function makeSafe($path) { return Folder::makeSafe($path); } } PK �X!];�b C C Wrapper/PathWrapper.phpnu &1i� <?php /** * Joomla! Content Management System * * @copyright (C) 2014 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Filesystem\Wrapper; use Joomla\CMS\Filesystem\Path; defined('JPATH_PLATFORM') or die; /** * Wrapper class for Path * * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Path instead */ class PathWrapper { /** * Helper wrapper method for canChmod * * @param string $path Path to check. * * @return boolean True if path can have mode changed. * * @see Path::canChmod() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Path instead */ public function canChmod($path) { return Path::canChmod($path); } /** * Helper wrapper method for setPermissions * * @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]. * * @see Path::setPermissions() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Path instead */ public function setPermissions($path, $filemode = '0644', $foldermode = '0755') { return Path::setPermissions($path, $filemode, $foldermode); } /** * Helper wrapper method for getPermissions * * @param string $path The path of a file/folder. * * @return string Filesystem permissions. * * @see Path::getPermissions() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Path instead */ public function getPermissions($path) { return Path::getPermissions($path); } /** * Helper wrapper method for check * * @param string $path A file system path to check. * * @return string A cleaned version of the path or exit on error. * * @see Path::check() * @since 3.4 * @throws Exception * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Path instead */ public function check($path) { return Path::check($path); } /** * Helper wrapper method for clean * * @param string $path The path to clean. * @param string $ds Directory separator (optional). * * @return string The cleaned path. * * @see Path::clean() * @since 3.4 * @throws UnexpectedValueException * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Path instead */ public function clean($path, $ds = DIRECTORY_SEPARATOR) { return Path::clean($path, $ds); } /** * Helper wrapper method for isOwner * * @param string $path Path to check ownership. * * @return boolean True if the php script owns the path passed. * * @see Path::isOwner() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Path instead */ public function isOwner($path) { return Path::isOwner($path); } /** * Helper wrapper method for find * * @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. * * @see Path::find() * @since 3.4 * @deprecated 4.0 Use \Joomla\CMS\Filesystem\Path instead */ public function find($paths, $file) { return Path::find($paths, $file); } } PK �X!]�'�p# p# Path.phpnu &1i� <?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\Filesystem\Wrapper\PathWrapper; use Joomla\CMS\Filesystem\Wrapper\FileWrapper; use Joomla\CMS\Crypt\Crypt; if (!defined('JPATH_ROOT')) { // Define a string constant for the root directory of the file system in native format $pathHelper = new PathWrapper; define('JPATH_ROOT', $pathHelper->clean(JPATH_SITE)); } /** * A Path handling class * * @since 1.7.0 */ 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 */ 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 */ 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 */ 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. * * @since 1.7.0 * @throws Exception */ public static function check($path) { if (strpos($path, '..') !== false) { // Don't translate throw new \Exception( sprintf( '%s() - Use of relative paths not permitted', __METHOD__ ), 20 ); } $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) ), 20 ); } 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. * * @since 1.7.0 * @throws UnexpectedValueException */ 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__ ), 20 ); } $path = trim($path); if (empty($path)) { $path = JPATH_ROOT; } // 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. elseif (($ds == '\\') && substr($path, 0, 2) == '\\\\') { $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 */ 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 (array($jtp, $ssp, '/tmp') as $currentDir) { if (is_writable($currentDir)) { $dir = $currentDir; break; } } if ($dir) { $fileObject = new FileWrapper; $test = $dir . '/' . $tmp; // Create the test file $blank = ''; $fileObject->write($test, $blank, false); // Test ownership $return = (fileowner($test) == fileowner($path)); // Delete the test file $fileObject->delete($test); return $return; } return false; } /** * Searches the directory paths for a given file. * * @param mixed $paths An 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 */ 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 */ public static function resolve($path) { $path = static::clean($path); // Save start character for absolute path $startCharacter = ($path[0] === DIRECTORY_SEPARATOR) ? DIRECTORY_SEPARATOR : ''; $parts = array(); 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 */ public static function removeRoot($message, $rootDirectory = null) { if (empty($rootDirectory)) { $rootDirectory = JPATH_ROOT; } $replacements = array( self::makePattern(static::clean($rootDirectory)) => '[ROOT]', self::makePattern(sys_get_temp_dir()) => '[TMP]', ); return preg_replace(array_keys($replacements), array_values($replacements), $message); } /** * Turn directory separators into match classes * * @param string $dir A directory name * * @return string * * @since 3.10.7 */ private static function makePattern($dir) { return '~' . str_replace('~', '\\~', preg_replace('~[/\\\\]+~', '[/\\\\\\\\]+', $dir)) . '~'; } } PK �X!]D�%�- - Patcher.phpnu &1i� <?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; defined('JPATH_PLATFORM') or die; use Joomla\CMS\Log\Log; use Joomla\CMS\Language\Text; /** * 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 */ class Patcher { /** * Regular expression for searching source files */ 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 */ 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 */ const HUNK = '/@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@($)/A'; /** * Regular expression for splitting lines */ const SPLIT = '/(\r\n)|(\r)|(\n)/'; /** * @var array sources files * @since 3.0.0 */ protected $sources = array(); /** * @var array destination files * @since 3.0.0 */ protected $destinations = array(); /** * @var array removal files * @since 3.0.0 */ protected $removals = array(); /** * @var array patches * @since 3.0.0 */ protected $patches = array(); /** * @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 */ protected function __construct() { } /** * Method to get a patcher * * @return FilesystemPatcher an instance of the patcher * * @since 3.0.0 */ public static function getInstance() { if (!isset(static::$instance)) { static::$instance = new static; } return static::$instance; } /** * Reset the pacher * * @return FilesystemPatcher This object for chaining * * @since 3.0.0 */ public function reset() { $this->sources = array(); $this->destinations = array(); $this->removals = array(); $this->patches = array(); return $this; } /** * Apply the patches * * @return integer The number of files patched * * @since 3.0.0 * @throws \RuntimeException */ 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 = array(); // Clear the removals $this->removals = array(); // Clear the patches $this->patches = array(); 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 string $strip The number of '/' to strip * * @return FilesystemPatcher $this for chaining * * @since 3.0.0 */ 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 string $strip The number of '/' to strip * * @return FilesystemPatcher $this for chaining * * @since 3.0.0 */ public function add($udiff, $root = JPATH_BASE, $strip = 0) { $this->patches[] = array( '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 */ 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 */ 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 */ 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 */ protected function applyHunk(&$lines, $src, $dst, $srcLine, $srcSize, $dstLine, $dstSize) { $srcLine--; $dstLine--; $line = current($lines); // Source lines (old file) $source = array(); // New lines (new file) $destin = array(); $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_UNEXISING_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 */ 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 */ protected function &getDestination($dst, $src) { if (!isset($this->destinations[$dst])) { $this->destinations[$dst] = $this->getSource($src); } return $this->destinations[$dst]; } } PK �X!] >�s FilesystemHelper.phpnu &1i� <?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; defined('JPATH_PLATFORM') or die; /** * File system helper * * Holds support functions for the filesystem, particularly the stream * * @since 1.7.0 */ class FilesystemHelper { /** * Remote file size function for streams that don't support it * * @param string $url TODO Add text * * @return mixed * * @link https://www.php.net/manual/en/function.filesize.php * @since 1.7.0 */ 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 */ 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 */ public static function getWriteModes() { return array('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 */ 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 */ public static function getTransports() { // Is this overkill? return stream_get_transports(); } /** * Returns a list of filters * * @return array * * @since 1.7.0 */ 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 */ public static function getJStreams() { static $streams = array(); if (!$streams) { $files = new \DirectoryIterator(__DIR__ . '/Streams'); /* @type $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 */ 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 = array('', 'k', 'M', 'G', 'T'); return round(pow(1024, $base - floor($base)), 0) . $suffixes[floor($base)]; } } PK �X!]�H�|>