You've already forked joomla_test
first commit
This commit is contained in:
543
libraries/joomla/filesystem/file.php
Normal file
543
libraries/joomla/filesystem/file.php
Normal file
@ -0,0 +1,543 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.filesystem.path');
|
||||
|
||||
/**
|
||||
* A File handling class
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
* @since 11.1
|
||||
*/
|
||||
class JFile
|
||||
{
|
||||
/**
|
||||
* Gets the extension of a file name
|
||||
*
|
||||
* @param string $file The file name
|
||||
*
|
||||
* @return string The file extension
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function getExt($file)
|
||||
{
|
||||
$dot = strrpos($file, '.') + 1;
|
||||
|
||||
return substr($file, $dot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips the last extension off of a file name
|
||||
*
|
||||
* @param string $file The file name
|
||||
*
|
||||
* @return string The file name without the extension
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
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 11.1
|
||||
*/
|
||||
public static function makeSafe($file)
|
||||
{
|
||||
// Remove any trailing dots, as those aren't ever valid file names.
|
||||
$file = rtrim($file, '.');
|
||||
|
||||
$regex = array('#(\.){2,}#', '#[^A-Za-z0-9\.\_\- ]#', '#^\.#');
|
||||
|
||||
return 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 $use_streams True to use streams
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function copy($src, $dest, $path = null, $use_streams = false)
|
||||
{
|
||||
// Prepend a base path if it exists
|
||||
if ($path)
|
||||
{
|
||||
$src = JPath::clean($path . '/' . $src);
|
||||
$dest = JPath::clean($path . '/' . $dest);
|
||||
}
|
||||
|
||||
// Check src path
|
||||
if (!is_readable($src))
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_FILESYSTEM_ERROR_JFILE_FIND_COPY', $src), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($use_streams)
|
||||
{
|
||||
$stream = JFactory::getStream();
|
||||
|
||||
if (!$stream->copy($src, $dest))
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_FILESYSTEM_ERROR_JFILE_STREAMS', $src, $dest, $stream->getError()), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$FTPOptions = JClientHelper::getCredentials('ftp');
|
||||
|
||||
if ($FTPOptions['enabled'] == 1)
|
||||
{
|
||||
// Connect the FTP client
|
||||
$ftp = JClientFtp::getInstance($FTPOptions['host'], $FTPOptions['port'], array(), $FTPOptions['user'], $FTPOptions['pass']);
|
||||
|
||||
// If the parent folder doesn't exist we must create it
|
||||
if (!file_exists(dirname($dest)))
|
||||
{
|
||||
jimport('joomla.filesystem.folder');
|
||||
JFolder::create(dirname($dest));
|
||||
}
|
||||
|
||||
// Translate the destination path for the FTP account
|
||||
$dest = JPath::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))
|
||||
{
|
||||
JLog::add(JText::_('JLIB_FILESYSTEM_ERROR_COPY_FAILED'), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
$ret = true;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 11.1
|
||||
*/
|
||||
public static function delete($file)
|
||||
{
|
||||
$FTPOptions = JClientHelper::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 = JClientFtp::getInstance($FTPOptions['host'], $FTPOptions['port'], array(), $FTPOptions['user'], $FTPOptions['pass']);
|
||||
}
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
$file = JPath::clean($file);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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 (@unlink($file))
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
elseif ($FTPOptions['enabled'] == 1)
|
||||
{
|
||||
$file = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $file), '/');
|
||||
if (!$ftp->delete($file))
|
||||
{
|
||||
// FTP connector throws an error
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$filename = basename($file);
|
||||
JLog::add(JText::sprintf('JLIB_FILESYSTEM_DELETE_FAILED', $filename), JLog::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 $use_streams True to use streams
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function move($src, $dest, $path = '', $use_streams = false)
|
||||
{
|
||||
if ($path)
|
||||
{
|
||||
$src = JPath::clean($path . '/' . $src);
|
||||
$dest = JPath::clean($path . '/' . $dest);
|
||||
}
|
||||
|
||||
// Check src path
|
||||
if (!is_readable($src))
|
||||
{
|
||||
|
||||
return JText::_('JLIB_FILESYSTEM_CANNOT_FIND_SOURCE_FILE');
|
||||
}
|
||||
|
||||
if ($use_streams)
|
||||
{
|
||||
$stream = JFactory::getStream();
|
||||
|
||||
if (!$stream->move($src, $dest))
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_FILESYSTEM_ERROR_JFILE_MOVE_STREAMS', $stream->getError()), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$FTPOptions = JClientHelper::getCredentials('ftp');
|
||||
|
||||
if ($FTPOptions['enabled'] == 1)
|
||||
{
|
||||
// Connect the FTP client
|
||||
$ftp = JClientFtp::getInstance($FTPOptions['host'], $FTPOptions['port'], array(), $FTPOptions['user'], $FTPOptions['pass']);
|
||||
|
||||
// Translate path for the FTP account
|
||||
$src = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $src), '/');
|
||||
$dest = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dest), '/');
|
||||
|
||||
// Use FTP rename to simulate move
|
||||
if (!$ftp->rename($src, $dest))
|
||||
{
|
||||
JLog::add(JText::_('JLIB_FILESYSTEM_ERROR_RENAME_FILE'), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!@ rename($src, $dest))
|
||||
{
|
||||
JLog::add(JText::_('JLIB_FILESYSTEM_ERROR_RENAME_FILE'), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the contents of a file
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @since 11.1
|
||||
* @deprecated 13.3 (Platform) & 4.0 (CMS) - Use the native file_get_contents() instead.
|
||||
*/
|
||||
public static function read($filename, $incpath = false, $amount = 0, $chunksize = 8192, $offset = 0)
|
||||
{
|
||||
JLog::add(__METHOD__ . ' is deprecated. Use native file_get_contents() syntax.', JLog::WARNING, 'deprecated');
|
||||
|
||||
$data = null;
|
||||
if ($amount && $chunksize > $amount)
|
||||
{
|
||||
$chunksize = $amount;
|
||||
}
|
||||
|
||||
if (false === $fh = fopen($filename, 'rb', $incpath))
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_FILESYSTEM_ERROR_READ_UNABLE_TO_OPEN_FILE', $filename), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
clearstatcache();
|
||||
|
||||
if ($offset)
|
||||
{
|
||||
fseek($fh, $offset);
|
||||
}
|
||||
|
||||
if ($fsize = @ filesize($filename))
|
||||
{
|
||||
if ($amount && $fsize > $amount)
|
||||
{
|
||||
$data = fread($fh, $amount);
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = fread($fh, $fsize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = '';
|
||||
|
||||
/*
|
||||
* While it's:
|
||||
* 1: Not the end of the file AND
|
||||
* 2a: No Max Amount set OR
|
||||
* 2b: The length of the data is less than the max amount we want
|
||||
*/
|
||||
while (!feof($fh) && (!$amount || strlen($data) < $amount))
|
||||
{
|
||||
$data .= fread($fh, $chunksize);
|
||||
}
|
||||
}
|
||||
fclose($fh);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write contents to a file
|
||||
*
|
||||
* @param string $file The full file path
|
||||
* @param string &$buffer The buffer to write
|
||||
* @param boolean $use_streams Use streams
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function write($file, &$buffer, $use_streams = false)
|
||||
{
|
||||
@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)))
|
||||
{
|
||||
jimport('joomla.filesystem.folder');
|
||||
JFolder::create(dirname($file));
|
||||
}
|
||||
|
||||
if ($use_streams)
|
||||
{
|
||||
$stream = JFactory::getStream();
|
||||
|
||||
// Beef up the chunk size to a meg
|
||||
$stream->set('chunksize', (1024 * 1024 * 1024));
|
||||
|
||||
if (!$stream->writeFile($file, $buffer))
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_FILESYSTEM_ERROR_WRITE_STREAMS', $file, $stream->getError()), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$FTPOptions = JClientHelper::getCredentials('ftp');
|
||||
|
||||
if ($FTPOptions['enabled'] == 1)
|
||||
{
|
||||
// Connect the FTP client
|
||||
$ftp = JClientFtp::getInstance($FTPOptions['host'], $FTPOptions['port'], array(), $FTPOptions['user'], $FTPOptions['pass']);
|
||||
|
||||
// Translate path for the FTP account and use FTP write buffer to file
|
||||
$file = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $file), '/');
|
||||
$ret = $ftp->write($file, $buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = JPath::clean($file);
|
||||
$ret = is_int(file_put_contents($file, $buffer)) ? true : false;
|
||||
}
|
||||
|
||||
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 $use_streams True to use streams
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function upload($src, $dest, $use_streams = false)
|
||||
{
|
||||
// Ensure that the path is valid and clean
|
||||
$dest = JPath::clean($dest);
|
||||
|
||||
// Create the destination directory if it does not exist
|
||||
$baseDir = dirname($dest);
|
||||
|
||||
if (!file_exists($baseDir))
|
||||
{
|
||||
jimport('joomla.filesystem.folder');
|
||||
JFolder::create($baseDir);
|
||||
}
|
||||
|
||||
if ($use_streams)
|
||||
{
|
||||
$stream = JFactory::getStream();
|
||||
|
||||
if (!$stream->upload($src, $dest))
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_FILESYSTEM_ERROR_UPLOAD', $stream->getError()), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$FTPOptions = JClientHelper::getCredentials('ftp');
|
||||
$ret = false;
|
||||
|
||||
if ($FTPOptions['enabled'] == 1)
|
||||
{
|
||||
// Connect the FTP client
|
||||
$ftp = JClientFtp::getInstance($FTPOptions['host'], $FTPOptions['port'], array(), $FTPOptions['user'], $FTPOptions['pass']);
|
||||
|
||||
// Translate path for the FTP account
|
||||
$dest = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dest), '/');
|
||||
|
||||
// Copy the file to the destination directory
|
||||
if (is_uploaded_file($src) && $ftp->store($src, $dest))
|
||||
{
|
||||
unlink($src);
|
||||
$ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_FILESYSTEM_ERROR_WARNFS_ERR02'), JLog::WARNING, 'jerror');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_writeable($baseDir) && move_uploaded_file($src, $dest))
|
||||
{
|
||||
// Short circuit to prevent file permission errors
|
||||
if (JPath::setPermissions($dest))
|
||||
{
|
||||
$ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_FILESYSTEM_ERROR_WARNFS_ERR01'), JLog::WARNING, 'jerror');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_FILESYSTEM_ERROR_WARNFS_ERR02'), JLog::WARNING, 'jerror');
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for the standard file_exists function
|
||||
*
|
||||
* @param string $file File path
|
||||
*
|
||||
* @return boolean True if path is a file
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function exists($file)
|
||||
{
|
||||
return is_file(JPath::clean($file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name, without any path.
|
||||
*
|
||||
* @param string $file File path
|
||||
*
|
||||
* @return string filename
|
||||
*
|
||||
* @since 11.1
|
||||
* @deprecated 13.3 (Platform) & 4.0 (CMS) - Use basename() instead.
|
||||
*/
|
||||
public static function getName($file)
|
||||
{
|
||||
JLog::add(__METHOD__ . ' is deprecated. Use native basename() syntax.', JLog::WARNING, 'deprecated');
|
||||
|
||||
// Convert back slashes to forward slashes
|
||||
$file = str_replace('\\', '/', $file);
|
||||
$slash = strrpos($file, '/');
|
||||
if ($slash !== false)
|
||||
{
|
||||
|
||||
return substr($file, $slash + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
676
libraries/joomla/filesystem/folder.php
Normal file
676
libraries/joomla/filesystem/folder.php
Normal file
@ -0,0 +1,676 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.filesystem.path');
|
||||
|
||||
/**
|
||||
* A Folder handling class
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
* @since 11.1
|
||||
*/
|
||||
abstract class JFolder
|
||||
{
|
||||
/**
|
||||
* 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 string $force Force copy.
|
||||
* @param boolean $use_streams Optionally force folder/file overwrites.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 11.1
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public static function copy($src, $dest, $path = '', $force = false, $use_streams = false)
|
||||
{
|
||||
@set_time_limit(ini_get('max_execution_time'));
|
||||
|
||||
$FTPOptions = JClientHelper::getCredentials('ftp');
|
||||
|
||||
if ($path)
|
||||
{
|
||||
$src = JPath::clean($path . '/' . $src);
|
||||
$dest = JPath::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 not found', -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 && !$use_streams)
|
||||
{
|
||||
// Connect the FTP client
|
||||
$ftp = JClientFtp::getInstance($FTPOptions['host'], $FTPOptions['port'], array(), $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 = JPath::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, $use_streams);
|
||||
if ($ret !== true)
|
||||
{
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'file':
|
||||
if ($use_streams)
|
||||
{
|
||||
$stream = JFactory::getStream();
|
||||
if (!$stream->copy($sfid, $dfid))
|
||||
{
|
||||
throw new RuntimeException('Cannot copy file: ' . $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 11.1
|
||||
*/
|
||||
public static function create($path = '', $mode = 0755)
|
||||
{
|
||||
$FTPOptions = JClientHelper::getCredentials('ftp');
|
||||
static $nested = 0;
|
||||
|
||||
// Check to make sure the path valid and clean
|
||||
$path = JPath::clean($path);
|
||||
|
||||
// Check if parent dir exists
|
||||
$parent = dirname($path);
|
||||
if (!self::exists($parent))
|
||||
{
|
||||
// Prevent infinite loops!
|
||||
$nested++;
|
||||
if (($nested > 20) || ($parent == $path))
|
||||
{
|
||||
JLog::add(__METHOD__ . ': ' . JText::_('JLIB_FILESYSTEM_ERROR_FOLDER_LOOP'), JLog::WARNING, 'jerror');
|
||||
$nested--;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the parent directory
|
||||
if (self::create($parent, $mode) !== true)
|
||||
{
|
||||
// JFolder::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 = JClientFtp::getInstance($FTPOptions['host'], $FTPOptions['port'], array(), $FTPOptions['user'], $FTPOptions['pass']);
|
||||
|
||||
// Translate path to FTP path
|
||||
$path = JPath::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 = JPath::clean($test);
|
||||
if (strpos($path, $test) === 0)
|
||||
{
|
||||
$inBaseDir = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($inBaseDir == false)
|
||||
{
|
||||
// Return false for JFolder::create because the path to be created is not in open_basedir
|
||||
JLog::add(__METHOD__ . ': ' . JText::_('JLIB_FILESYSTEM_ERROR_FOLDER_PATH'), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// First set umask
|
||||
$origmask = @umask(0);
|
||||
|
||||
// Create the path
|
||||
if (!$ret = @mkdir($path, $mode))
|
||||
{
|
||||
@umask($origmask);
|
||||
JLog::add(
|
||||
__METHOD__ . ': ' . JText::_('JLIB_FILESYSTEM_ERROR_COULD_NOT_CREATE_DIRECTORY') . ' Path: ' . $path, JLog::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 11.1
|
||||
*/
|
||||
public static function delete($path)
|
||||
{
|
||||
@set_time_limit(ini_get('max_execution_time'));
|
||||
|
||||
// Sanity check
|
||||
if (!$path)
|
||||
{
|
||||
// Bad programmer! Bad Bad programmer!
|
||||
JLog::add(__METHOD__ . ': ' . JText::_('JLIB_FILESYSTEM_ERROR_DELETE_BASE_DIRECTORY'), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
$FTPOptions = JClientHelper::getCredentials('ftp');
|
||||
|
||||
try
|
||||
{
|
||||
// Check to make sure the path valid and clean
|
||||
$path = JPath::clean($path);
|
||||
}
|
||||
catch (UnexpectedValueException $e)
|
||||
{
|
||||
throw new UnexpectedValueException($e);
|
||||
}
|
||||
|
||||
// Is this really a folder?
|
||||
if (!is_dir($path))
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER', $path), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove all the files in folder if they exist; disable all filtering
|
||||
$files = self::files($path, '.', false, true, array(), array());
|
||||
if (!empty($files))
|
||||
{
|
||||
jimport('joomla.filesystem.file');
|
||||
if (JFile::delete($files) !== true)
|
||||
{
|
||||
// JFile::delete throws an error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove sub-folders of folder; disable all filtering
|
||||
$folders = self::folders($path, '.', false, true, array(), array());
|
||||
foreach ($folders as $folder)
|
||||
{
|
||||
if (is_link($folder))
|
||||
{
|
||||
// Don't descend into linked directories, just delete the link.
|
||||
jimport('joomla.filesystem.file');
|
||||
if (JFile::delete($folder) !== true)
|
||||
{
|
||||
// JFile::delete throws an error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
elseif (self::delete($folder) !== true)
|
||||
{
|
||||
// JFolder::delete throws an error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($FTPOptions['enabled'] == 1)
|
||||
{
|
||||
// Connect the FTP client
|
||||
$ftp = JClientFtp::getInstance($FTPOptions['host'], $FTPOptions['port'], array(), $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 = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $path), '/');
|
||||
|
||||
// FTP connector throws an error
|
||||
$ret = $ftp->delete($path);
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_FILESYSTEM_ERROR_FOLDER_DELETE', $path), JLog::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 $use_streams Optionally use streams.
|
||||
*
|
||||
* @return mixed Error message on false or boolean true on success.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function move($src, $dest, $path = '', $use_streams = false)
|
||||
{
|
||||
$FTPOptions = JClientHelper::getCredentials('ftp');
|
||||
|
||||
if ($path)
|
||||
{
|
||||
$src = JPath::clean($path . '/' . $src);
|
||||
$dest = JPath::clean($path . '/' . $dest);
|
||||
}
|
||||
|
||||
if (!self::exists($src))
|
||||
{
|
||||
return JText::_('JLIB_FILESYSTEM_ERROR_FIND_SOURCE_FOLDER');
|
||||
}
|
||||
if (self::exists($dest))
|
||||
{
|
||||
return JText::_('JLIB_FILESYSTEM_ERROR_FOLDER_EXISTS');
|
||||
}
|
||||
if ($use_streams)
|
||||
{
|
||||
$stream = JFactory::getStream();
|
||||
if (!$stream->move($src, $dest))
|
||||
{
|
||||
return JText::sprintf('JLIB_FILESYSTEM_ERROR_FOLDER_RENAME', $stream->getError());
|
||||
}
|
||||
$ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($FTPOptions['enabled'] == 1)
|
||||
{
|
||||
// Connect the FTP client
|
||||
$ftp = JClientFtp::getInstance($FTPOptions['host'], $FTPOptions['port'], array(), $FTPOptions['user'], $FTPOptions['pass']);
|
||||
|
||||
// Translate path for the FTP account
|
||||
$src = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $src), '/');
|
||||
$dest = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dest), '/');
|
||||
|
||||
// Use FTP rename to simulate move
|
||||
if (!$ftp->rename($src, $dest))
|
||||
{
|
||||
return JText::_('Rename failed');
|
||||
}
|
||||
$ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!@rename($src, $dest))
|
||||
{
|
||||
return JText::_('Rename failed');
|
||||
}
|
||||
$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 11.1
|
||||
*/
|
||||
public static function exists($path)
|
||||
{
|
||||
return is_dir(JPath::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 Files in the given folder.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function files($path, $filter = '.', $recurse = false, $full = false, $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'),
|
||||
$excludefilter = array('^\..*', '.*~'), $naturalSort = false)
|
||||
{
|
||||
// Check to make sure the path valid and clean
|
||||
$path = JPath::clean($path);
|
||||
|
||||
// Is the path a folder?
|
||||
if (!is_dir($path))
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER_FILES', $path), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute the excludefilter string
|
||||
if (count($excludefilter))
|
||||
{
|
||||
$excludefilter_string = '/(' . implode('|', $excludefilter) . ')/';
|
||||
}
|
||||
else
|
||||
{
|
||||
$excludefilter_string = '';
|
||||
}
|
||||
|
||||
// Get the files
|
||||
$arr = self::_items($path, $filter, $recurse, $full, $exclude, $excludefilter_string, 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 11.1
|
||||
*/
|
||||
public static function folders($path, $filter = '.', $recurse = false, $full = false, $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'),
|
||||
$excludefilter = array('^\..*'))
|
||||
{
|
||||
// Check to make sure the path valid and clean
|
||||
$path = JPath::clean($path);
|
||||
|
||||
// Is the path a folder?
|
||||
if (!is_dir($path))
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER_FOLDER', $path), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute the excludefilter string
|
||||
if (count($excludefilter))
|
||||
{
|
||||
$excludefilter_string = '/(' . implode('|', $excludefilter) . ')/';
|
||||
}
|
||||
else
|
||||
{
|
||||
$excludefilter_string = '';
|
||||
}
|
||||
|
||||
// Get the folders
|
||||
$arr = self::_items($path, $filter, $recurse, $full, $exclude, $excludefilter_string, 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 $excludefilter_string Regexp of files to exclude
|
||||
* @param boolean $findfiles True to read the files, false to read the folders
|
||||
*
|
||||
* @return array Files.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected static function _items($path, $filter, $recurse, $full, $exclude, $excludefilter_string, $findfiles)
|
||||
{
|
||||
@set_time_limit(ini_get('max_execution_time'));
|
||||
|
||||
$arr = array();
|
||||
|
||||
// Read the source directory
|
||||
if (!($handle = @opendir($path)))
|
||||
{
|
||||
return $arr;
|
||||
}
|
||||
|
||||
while (($file = readdir($handle)) !== false)
|
||||
{
|
||||
if ($file != '.' && $file != '..' && !in_array($file, $exclude)
|
||||
&& (empty($excludefilter_string) || !preg_match($excludefilter_string, $file)))
|
||||
{
|
||||
// Compute the fullpath
|
||||
$fullpath = $path . DIRECTORY_SEPARATOR . $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, $excludefilter_string, $findfiles));
|
||||
}
|
||||
else
|
||||
{
|
||||
$arr = array_merge($arr, self::_items($fullpath, $filter, $recurse, $full, $exclude, $excludefilter_string, $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 11.1
|
||||
*/
|
||||
public static function listFolderTree($path, $filter, $maxLevel = 3, $level = 0, $parent = 0)
|
||||
{
|
||||
$dirs = array();
|
||||
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 = JPath::clean($path . '/' . $name);
|
||||
$dirs[] = array('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 11.1
|
||||
*/
|
||||
public static function makeSafe($path)
|
||||
{
|
||||
$regex = array('#[^A-Za-z0-9:_\\\/-]#');
|
||||
return preg_replace($regex, '', $path);
|
||||
}
|
||||
}
|
300
libraries/joomla/filesystem/helper.php
Normal file
300
libraries/joomla/filesystem/helper.php
Normal file
@ -0,0 +1,300 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* File system helper
|
||||
*
|
||||
* Holds support functions for the filesystem, particularly the stream
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
* @since 11.1
|
||||
*/
|
||||
class JFilesystemHelper
|
||||
{
|
||||
/**
|
||||
* Remote file size function for streams that don't support it
|
||||
*
|
||||
* @param string $url TODO Add text
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @see http://www.php.net/manual/en/function.filesize.php#71098
|
||||
* @since 11.1
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @see http://www.php.net/manual/en/function.ftp-chmod.php
|
||||
* @since 11.1
|
||||
*/
|
||||
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 11.1
|
||||
*/
|
||||
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 11.1
|
||||
*/
|
||||
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 11.1
|
||||
*/
|
||||
public static function getTransports()
|
||||
{
|
||||
// Is this overkill?
|
||||
return stream_get_transports();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of filters
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
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 11.1
|
||||
*/
|
||||
public static function getJStreams()
|
||||
{
|
||||
static $streams = array();
|
||||
|
||||
if (!$streams)
|
||||
{
|
||||
$files = new DirectoryIterator(__DIR__ . '/streams');
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
$filename = $file->getFilename();
|
||||
|
||||
// Only load for php files.
|
||||
// Note: DirectoryIterator::getExtension only available PHP >= 5.3.6
|
||||
if (!$file->isFile() || substr($filename, strrpos($filename, '.') + 1) != 'php')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$streams[] = $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 11.1
|
||||
*/
|
||||
public static function isJoomlaStream($streamname)
|
||||
{
|
||||
return in_array($streamname, self::getJStreams());
|
||||
}
|
||||
}
|
1
libraries/joomla/filesystem/index.html
Normal file
1
libraries/joomla/filesystem/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
1
libraries/joomla/filesystem/meta/index.html
Normal file
1
libraries/joomla/filesystem/meta/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
@ -0,0 +1,13 @@
|
||||
; Joomla! Project
|
||||
; Copyright (C) 2005 - 2013 Open Source Matters. All rights reserved.
|
||||
; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
|
||||
; Note : All ini files need to be saved as UTF-8 - No BOM
|
||||
|
||||
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_UNEXISING_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"
|
||||
|
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
1
libraries/joomla/filesystem/meta/language/index.html
Normal file
1
libraries/joomla/filesystem/meta/language/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
522
libraries/joomla/filesystem/patcher.php
Normal file
522
libraries/joomla/filesystem/patcher.php
Normal file
@ -0,0 +1,522 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.filesystem.file');
|
||||
|
||||
/**
|
||||
* A Unified Diff Format Patcher class
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
*
|
||||
* @link http://sourceforge.net/projects/phppatcher/ This has been derived from the PhpPatcher version 0.1.1 written by Giuseppe Mazzotta
|
||||
* @since 12.1
|
||||
*/
|
||||
class JFilesystemPatcher
|
||||
{
|
||||
/**
|
||||
* 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 12.1
|
||||
*/
|
||||
protected $sources = array();
|
||||
|
||||
/**
|
||||
* @var array destination files
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $destinations = array();
|
||||
|
||||
/**
|
||||
* @var array removal files
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $removals = array();
|
||||
|
||||
/**
|
||||
* @var array patches
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $patches = array();
|
||||
|
||||
/**
|
||||
* @var array instance of this class
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* The constructor is protected to force the use of JFilesystemPatcher::getInstance()
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a patcher
|
||||
*
|
||||
* @return JFilesystemPatcher an instance of the patcher
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!isset(static::$instance))
|
||||
{
|
||||
static::$instance = new static;
|
||||
}
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the pacher
|
||||
*
|
||||
* @return JFilesystemPatcher This object for chaining
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->sources = array();
|
||||
$this->destinations = array();
|
||||
$this->removals = array();
|
||||
$this->patches = array();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the patches
|
||||
*
|
||||
* @throw RuntimeException
|
||||
*
|
||||
* @return integer the number of files patched
|
||||
*/
|
||||
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;
|
||||
|
||||
if ($patch['strip'] === null)
|
||||
{
|
||||
$src = $patch['root'] . preg_replace('#^([^/]*/)*#', '', $src);
|
||||
$dst = $patch['root'] . preg_replace('#^([^/]*/)*#', '', $dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
$src = $patch['root'] . preg_replace('#^([^/]*/){' . (int) $patch['strip'] . '}#', '', $src);
|
||||
$dst = $patch['root'] . preg_replace('#^([^/]*/){' . (int) $patch['strip'] . '}#', '', $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)
|
||||
{
|
||||
if (JFile::write($file, implode("\n", $content)))
|
||||
{
|
||||
if (isset($this->sources[$file]))
|
||||
{
|
||||
$this->sources[$file] = $content;
|
||||
}
|
||||
$done++;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove each removed file
|
||||
foreach ($this->removals as $file)
|
||||
{
|
||||
if (JFile::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 JFilesystemPatch $this for chaining
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
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 JFilesystemPatch $this for chaining
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
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 12.1
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @throw 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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 &$src_line The beginning of the patch for the source file
|
||||
* @param string &$src_size The size of the patch for the source file
|
||||
* @param string &$dst_line The beginning of the patch for the destination file
|
||||
* @param string &$dst_size The size of the patch for the destination file
|
||||
*
|
||||
* @return boolean TRUE in case of success, false in case of failure
|
||||
*
|
||||
* @throw RuntimeException
|
||||
*/
|
||||
protected static function findHunk(&$lines, &$src_line, &$src_size, &$dst_line, &$dst_size)
|
||||
{
|
||||
$line = current($lines);
|
||||
if (preg_match(self::HUNK, $line, $m))
|
||||
{
|
||||
$src_line = (int) $m[1];
|
||||
if ($m[3] === '')
|
||||
{
|
||||
$src_size = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$src_size = (int) $m[3];
|
||||
}
|
||||
|
||||
$dst_line = (int) $m[4];
|
||||
if ($m[6] === '')
|
||||
{
|
||||
$dst_size = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$dst_size = (int) $m[6];
|
||||
}
|
||||
|
||||
if (next($lines) === false)
|
||||
{
|
||||
throw new RuntimeException('Unexpected EOF');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 $src_line The beginning of the patch for the source file
|
||||
* @param string $src_size The size of the patch for the source file
|
||||
* @param string $dst_line The beginning of the patch for the destination file
|
||||
* @param string $dst_size The size of the patch for the destination file
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throw RuntimeException
|
||||
*/
|
||||
protected function applyHunk(&$lines, $src, $dst, $src_line, $src_size, $dst_line, $dst_size)
|
||||
{
|
||||
$src_line--;
|
||||
$dst_line--;
|
||||
$line = current($lines);
|
||||
|
||||
// Source lines (old file)
|
||||
$source = array();
|
||||
|
||||
// New lines (new file)
|
||||
$destin = array();
|
||||
$src_left = $src_size;
|
||||
$dst_left = $dst_size;
|
||||
do
|
||||
{
|
||||
if (!isset($line[0]))
|
||||
{
|
||||
$source[] = '';
|
||||
$destin[] = '';
|
||||
$src_left--;
|
||||
$dst_left--;
|
||||
}
|
||||
elseif ($line[0] == '-')
|
||||
{
|
||||
if ($src_left == 0)
|
||||
{
|
||||
throw new RuntimeException(JText::sprintf('JLIB_FILESYSTEM_PATCHER_REMOVE_LINE', key($lines)));
|
||||
}
|
||||
$source[] = substr($line, 1);
|
||||
$src_left--;
|
||||
}
|
||||
elseif ($line[0] == '+')
|
||||
{
|
||||
if ($dst_left == 0)
|
||||
{
|
||||
throw new RuntimeException(JText::sprintf('JLIB_FILESYSTEM_PATCHER_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 ($src_size > 0)
|
||||
{
|
||||
$src_lines = & $this->getSource($src);
|
||||
if (!isset($src_lines))
|
||||
{
|
||||
throw new RuntimeException(JText::sprintf('JLIB_FILESYSTEM_PATCHER_UNEXISING_SOURCE', $src));
|
||||
}
|
||||
}
|
||||
if ($dst_size > 0)
|
||||
{
|
||||
if ($src_size > 0)
|
||||
{
|
||||
$dst_lines = & $this->getDestination($dst, $src);
|
||||
$src_bottom = $src_line + count($source);
|
||||
for ($l = $src_line;$l < $src_bottom;$l++)
|
||||
{
|
||||
if ($src_lines[$l] != $source[$l - $src_line])
|
||||
{
|
||||
throw new RuntimeException(JText::sprintf('JLIB_FILESYSTEM_PATCHER_FAILED_VERIFY', $src, $l));
|
||||
}
|
||||
}
|
||||
array_splice($dst_lines, $dst_line, 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 12.1
|
||||
*/
|
||||
protected function &getSource($src)
|
||||
{
|
||||
if (!isset($this->sources[$src]))
|
||||
{
|
||||
if (is_readable($src))
|
||||
{
|
||||
$this->sources[$src] = self::splitLines(file_get_contents($src));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->sources[$src] = null;
|
||||
}
|
||||
}
|
||||
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 12.1
|
||||
*/
|
||||
protected function &getDestination($dst, $src)
|
||||
{
|
||||
if (!isset($this->destinations[$dst]))
|
||||
{
|
||||
$this->destinations[$dst] = $this->getSource($src);
|
||||
}
|
||||
return $this->destinations[$dst];
|
||||
}
|
||||
}
|
308
libraries/joomla/filesystem/path.php
Normal file
308
libraries/joomla/filesystem/path.php
Normal file
@ -0,0 +1,308 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
if (!defined('JPATH_ROOT'))
|
||||
{
|
||||
// Define a string constant for the root directory of the file system in native format
|
||||
define('JPATH_ROOT', JPath::clean(JPATH_SITE));
|
||||
}
|
||||
|
||||
/**
|
||||
* A Path handling class
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
* @since 11.1
|
||||
*/
|
||||
class JPath
|
||||
{
|
||||
/**
|
||||
* 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 11.1
|
||||
*/
|
||||
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 11.1
|
||||
*/
|
||||
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 give path.
|
||||
*
|
||||
* @param string $path The path of a file/folder.
|
||||
*
|
||||
* @return string Filesystem permissions.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
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.
|
||||
* @param string $ds Directory separator (optional).
|
||||
*
|
||||
* @return string A cleaned version of the path or exit on error.
|
||||
*
|
||||
* @since 11.1
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function check($path, $ds = DIRECTORY_SEPARATOR)
|
||||
{
|
||||
if (strpos($path, '..') !== false)
|
||||
{
|
||||
// Don't translate
|
||||
throw new Exception('JPath::check Use of relative paths not permitted', 20);
|
||||
}
|
||||
|
||||
$path = self::clean($path);
|
||||
if ((JPATH_ROOT != '') && strpos($path, self::clean(JPATH_ROOT)) !== 0)
|
||||
{
|
||||
throw new Exception('JPath::check Snooping out of bounds @ ' . $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 11.1
|
||||
* @throws UnexpectedValueException
|
||||
*/
|
||||
public static function clean($path, $ds = DIRECTORY_SEPARATOR)
|
||||
{
|
||||
if (!is_string($path) && !empty($path))
|
||||
{
|
||||
throw new UnexpectedValueException('JPath::clean: $path is not a string.');
|
||||
}
|
||||
|
||||
$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 == '\\') && ($path[0] == '\\' ) && ( $path[1] == '\\' ))
|
||||
{
|
||||
$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 11.1
|
||||
*/
|
||||
public static function isOwner($path)
|
||||
{
|
||||
jimport('joomla.filesystem.file');
|
||||
|
||||
$tmp = md5(mt_rand());
|
||||
$ssp = ini_get('session.save_path');
|
||||
$jtp = JPATH_SITE . '/tmp';
|
||||
|
||||
// Try to find a writable directory
|
||||
$dir = is_writable('/tmp') ? '/tmp' : false;
|
||||
$dir = (!$dir && is_writable($ssp)) ? $ssp : false;
|
||||
$dir = (!$dir && is_writable($jtp)) ? $jtp : false;
|
||||
|
||||
if ($dir)
|
||||
{
|
||||
$test = $dir . '/' . $tmp;
|
||||
|
||||
// Create the test file
|
||||
$blank = '';
|
||||
JFile::write($test, $blank, false);
|
||||
|
||||
// Test ownership
|
||||
$return = (fileowner($test) == fileowner($path));
|
||||
|
||||
// Delete the test file
|
||||
JFile::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 11.1
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
1413
libraries/joomla/filesystem/stream.php
Normal file
1413
libraries/joomla/filesystem/stream.php
Normal file
File diff suppressed because it is too large
Load Diff
1
libraries/joomla/filesystem/streams/index.html
Normal file
1
libraries/joomla/filesystem/streams/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
298
libraries/joomla/filesystem/streams/string.php
Normal file
298
libraries/joomla/filesystem/streams/string.php
Normal file
@ -0,0 +1,298 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.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
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
* @since 11.1
|
||||
*/
|
||||
class JStreamString
|
||||
{
|
||||
/**
|
||||
* The current string
|
||||
*
|
||||
* @var string
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $currentString;
|
||||
|
||||
/**
|
||||
*
|
||||
* The path
|
||||
*
|
||||
* @var string
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
*
|
||||
* The mode
|
||||
*
|
||||
* @var string
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $mode;
|
||||
|
||||
/**
|
||||
*
|
||||
* Enter description here ...
|
||||
* @var string
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
*
|
||||
* Enter description here ...
|
||||
* @var string
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $openedPath;
|
||||
|
||||
/**
|
||||
* Current position
|
||||
*
|
||||
* @var integer
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $pos;
|
||||
|
||||
/**
|
||||
* Length of the string
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $len;
|
||||
|
||||
/**
|
||||
* Statistics for a file
|
||||
*
|
||||
* @var array
|
||||
* @since 12.1
|
||||
*
|
||||
* @see 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 &$opened_path Not used.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
$this->currentString = &JStringController::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
|
||||
*
|
||||
* @see http://www.php.net/manual/en/streamwrapper.stream-stat.php
|
||||
* @since 11.1
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.url-stat.php
|
||||
* @since 11.1
|
||||
*/
|
||||
public function url_stat($path, $flags = 0)
|
||||
{
|
||||
$now = time();
|
||||
$string = &JStringController::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 11.1
|
||||
*
|
||||
* @see http://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 11.1
|
||||
* @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 11.1
|
||||
*/
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of field check
|
||||
*
|
||||
* @return boolean True if at end of field.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
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 11.1
|
||||
*/
|
||||
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 11.1
|
||||
* @note Data storage is not supported
|
||||
*/
|
||||
public function stream_flush()
|
||||
{
|
||||
// We don't store data.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
stream_wrapper_register('string', 'JStreamString') or die('JStreamString Wrapper Registration Failed');
|
1
libraries/joomla/filesystem/support/index.html
Normal file
1
libraries/joomla/filesystem/support/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
71
libraries/joomla/filesystem/support/stringcontroller.php
Normal file
71
libraries/joomla/filesystem/support/stringcontroller.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* String Controller
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage FileSystem
|
||||
* @since 11.1
|
||||
*/
|
||||
class JStringController
|
||||
{
|
||||
/**
|
||||
* Defines a variable as an array
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function _getArray()
|
||||
{
|
||||
static $strings = array();
|
||||
return $strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a reference
|
||||
*
|
||||
* @param string $reference The key
|
||||
* @param string &$string The value
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
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 it exists
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function getRef($reference)
|
||||
{
|
||||
$ref = &self::_getArray();
|
||||
if (isset($ref[$reference]))
|
||||
{
|
||||
return $ref[$reference];
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user