From: Michael M Slusarz Date: Sun, 7 Mar 2010 08:06:17 +0000 (-0700) Subject: Convert VFS to PHP 5. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=079bd8d84c09d7fbef27cdf291f3d94ed203b5d7;p=horde.git Convert VFS to PHP 5. I realize there is a H4-Vfs stub lying around, but it looks like zero work has been done on it for awhile. So, in the meanwhile, update VFS - mostly to eliminate the boatload of PEAR_Error usage. --- diff --git a/framework/VFS/lib/VFS.php b/framework/VFS/lib/VFS.php index 45fa4ff62..a04b993db 100644 --- a/framework/VFS/lib/VFS.php +++ b/framework/VFS/lib/VFS.php @@ -1,11 +1,7 @@ * @package VFS */ -class VFS { +class VFS +{ + /* Quota constants. */ + const QUOTA_METRIC_BYTE = 1; + const QUOTA_METRIC_KB = 2; + const QUOTA_METRIC_MB = 3; + const QUOTA_METRIC_GB = 4; + + /** + * Singleton instances. + * + * @var array + */ + static protected $_instances = array(); /** * Hash containing connection parameters. * * @var array */ - var $_params = array(); + protected $_params = array(); /** * List of additional credentials required for this VFS backend (example: @@ -33,17 +42,30 @@ class VFS { * * @var array */ - var $_credentials = array(); + protected $_credentials = array(); /** * List of permissions and if they can be changed in this VFS backend. * * @var array */ - var $_permissions = array( - 'owner' => array('read' => false, 'write' => false, 'execute' => false), - 'group' => array('read' => false, 'write' => false, 'execute' => false), - 'all' => array('read' => false, 'write' => false, 'execute' => false)); + protected $_permissions = array( + 'owner' => array( + 'read' => false, + 'write' => false, + 'execute' => false + ), + 'group' => array( + 'read' => false, + 'write' => false, + 'execute' => false + ), + 'all' => array( + 'read' => false, + 'write' => false, + 'execute' => false + ) + ); /** * A PEAR Log object. If present, will be used to log errors and @@ -51,7 +73,7 @@ class VFS { * * @var Log */ - var $_logger = null; + protected $_logger = null; /** * The log level to use - messages with a higher log level than configured @@ -59,56 +81,115 @@ class VFS { * * @var integer */ - var $_logLevel = PEAR_LOG_ERR; + protected $_logLevel = PEAR_LOG_ERR; /** * The current size, in bytes, of the VFS item. * * @var integer */ - var $_vfsSize = null; + protected $_vfsSize = null; /** - * Constructor. + * Attempts to return a reference to a concrete instance based on + * $driver. It will only create a new instance if no instance with the + * same parameters currently exists. * - * @param array $params A hash containing connection parameters. + * This should be used if multiple types of file backends (and, thus, + * multiple VFS instances) are required. + * + * This method must be invoked as: $var = VFS::singleton(); + * + * @param mixed $driver The type of concrete subclass to return. This + * is based on the storage driver ($driver). The + * code is dynamically included. + * @param array $params A hash containing any additional configuration or + * connection parameters a subclass might need. + * + * @return VFS The concrete VFS reference. + * @throws VFS_Exception */ - function VFS($params = array()) + static public function singleton($driver, $params = array()) { - if (empty($params['user'])) { - $params['user'] = ''; - } - if (empty($params['vfs_quotalimit'])) { - $params['vfs_quotalimit'] = -1; + ksort($params); + $signature = serialize(array($driver, $params)); + if (!isset(self::$_instances[$signature])) { + self::$_instances[$signature] = self::factory($driver, $params); } - if (empty($params['vfs_quotaroot'])) { - $params['vfs_quotaroot'] = '/'; + + return self::$_instances[$signature]; + } + + /** + * Attempts to return a concrete instance based on $driver. + * + * @param mixed $driver The type of concrete subclass to return. This + * is based on the storage driver ($driver). The + * code is dynamically included. + * @param array $params A hash containing any additional configuration or + * connection parameters a subclass might need. + * + * @return VFS The newly created concrete VFS instance. + * @throws VFS_Exception + */ + static public function factory($driver, $params = array()) + { + $driver = basename($driver); + $class = __CLASS__ . '_' . $driver; + if (!class_exists($class)) { + include_once 'VFS/' . $driver . '.php'; + if (!class_exists($class)) { + throw new VFS_Exception('Class definition of ' . $class . ' not found.'); + } } - $this->_params = $params; + + return new $class($params); + } + + /** + * Constructor. + * + * @param array $params A hash containing connection parameters. + */ + public function __construct($params = array()) + { + $this->setParams(array( + 'user' => '', + 'vfs_quotalimit' => -1, + 'vfs_quotaroot' => '/' + )); + $this->setParams($params); } /** * Checks the credentials that we have by calling _connect(), to see if * there is a valid login. * - * @return mixed True on success, PEAR_Error describing the problem if the - * credentials are invalid. + * @throws VFS_Exception */ - function checkCredentials() + public function checkCredentials() + { + $this->_connect(); + } + + /** + * TODO + * + * @throws VFS_Exception + */ + protected function _connect() { - return $this->_connect(); } /** * Sets configuration parameters. * - * @param array $params An associative array with parameter names as keys. + * @param array $params An associative array with parameter names as + * keys. */ - function setParams($params = array()) + public function setParams($params = array()) { - foreach ($params as $name => $value) { - $this->_params[$name] = $value; - } + $this->_params = array_merge($this->_params, $params); } /** @@ -118,9 +199,11 @@ class VFS { * * @return mixed The parameter value or null if it doesn't exist. */ - function getParam($name) + public function getParam($name) { - return isset($this->_params[$name]) ? $this->_params[$name] : null; + return isset($this->_params[$name]) + ? $this->_params[$name] + : null; } /** @@ -130,13 +213,13 @@ class VFS { * @param mixed $message The message to be logged. * @param integer $priority The message's priority. */ - function log($message, $priority = PEAR_LOG_ERR) + public function log($message, $priority = PEAR_LOG_ERR) { - if (!isset($this->_logger) || $priority > $this->_logLevel) { + if (!isset($this->_logger) || ($priority > $this->_logLevel)) { return; } - if (is_a($message, 'PEAR_Error')) { + if ($message instanceof PEAR_Error) { $userinfo = $message->getUserInfo(); $message = $message->getMessage(); if ($userinfo) { @@ -160,17 +243,15 @@ class VFS { /** * Sets the PEAR Log object used to log informational or error messages. * - * @param Log &$logger The Log object to use. + * @param Log $logger The Log object to use. */ - function setLogger(&$logger, $logLevel = null) + public function setLogger($logger, $logLevel = null) { - if (!is_callable(array($logger, 'log'))) { - return false; - } - - $this->_logger = &$logger; - if (!is_null($logLevel)) { - $this->_logLevel = $logLevel; + if (is_callable(array($logger, 'log'))) { + $this->_logger = $logger; + if (!is_null($logLevel)) { + $this->_logLevel = $logLevel; + } } } @@ -182,11 +263,12 @@ class VFS { * @param string $path The pathname to the file. * @param string $name The filename to retrieve. * - * @return integer The file size. + * @return integer The file size. + * @throws VFS_Exception */ - function size($path, $name) + public function size($path, $name) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -195,24 +277,19 @@ class VFS { * @param string $path The path to the folder. * @param string $name The name of the folder. * - * @return integer The size of the folder, in bytes, or PEAR_Error on - * failure. + * @return integer The size of the folder, in bytes. + * @throws VFS_Exception */ - function getFolderSize($path = null, $name = null) + public function getFolderSize($path = null, $name = null) { $size = 0; - $root = ((!is_null($path)) ? $path . '/' : '') . $name; + $root = (!is_null($path) ? $path . '/' : '') . $name; $object_list = $this->listFolder($root, null, true, false, true); + foreach ($object_list as $key => $val) { - if (isset($val['subdirs'])) { - $size += $this->getFolderSize($root, $key); - } else { - $filesize = $this->size($root, $key); - if (is_a($filesize, 'PEAR_Error')) { - return $filesize; - } - $size += $filesize; - } + $size += isset($val['subdirs']) + ? $this->getFolderSize($root, $key) + : $this->size($root, $key); } return $size; @@ -226,11 +303,12 @@ class VFS { * @param string $path The pathname to the file. * @param string $name The filename to retrieve. * - * @return string The file data. + * @return string The file data. + * @throws VFS_Exception */ - function read($path, $name) + public function read($path, $name) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -243,15 +321,15 @@ class VFS { * @param string $path The pathname to the file. * @param string $name The filename to retrieve. * - * @return string A local filename. + * @return string A local filename. + * @throws VFS_Exception */ - function readFile($path, $name) + public function readFile($path, $name) { // Create a temporary file and register it for deletion at the // end of this request. - $localFile = $this->_getTempFile(); - if (!$localFile) { - return PEAR::raiseError(_("Unable to create temporary file.")); + if (!($localFile = tempnam(null, 'vfs'))) { + throw new VFS_Exception('Unable to create temporary file.'); } register_shutdown_function(create_function('', 'unlink(\'' . addslashes($localFile) . '\');')); @@ -259,48 +337,16 @@ class VFS { // Use a stream from the VFS if possible, to avoid reading all data // into memory. $stream = $this->readStream($path, $name); - if (is_a($stream, 'PEAR_Error')) { - return $stream; - } - - $localStream = fopen($localFile, 'w'); - if (!$localStream) { - return PEAR::raiseError(_("Unable to open temporary file.")); - } - if (is_callable('stream_copy_to_stream')) { - // If we have stream_copy_to_stream, it can do the data transfer - // in one go. - stream_copy_to_stream($stream, $localStream); - } else { - // Otherwise loop through in chunks. - while ($buffer = fread($stream, 8192)) { - fwrite($localStream, $buffer); - } + if (!($localStream = fopen($localFile, 'w'))) { + throw new VFS_Exception('Unable to open temporary file.'); } - + stream_copy_to_stream($stream, $localStream); fclose($localStream); } else { // We have to read all of the data in one shot. $data = $this->read($path, $name); - if (is_a($data, 'PEAR_Error')) { - return $data; - } - - if (is_callable('file_put_contents')) { - // file_put_contents is more efficient if we have it. - file_put_contents($localFile, $data); - } else { - // Open the local file and write to it. - $localStream = fopen($localFile, 'w'); - if (!$localStream) { - return PEAR::raiseError(_("Unable to open temporary file.")); - } - if (!fwrite($localStream, $data)) { - return PEAR::raiseError(_("Unable to write temporary file.")); - } - fclose($localStream); - } + file_put_contents($localFile, $data); } // $localFile now has $path/$name's data in it. @@ -326,11 +372,13 @@ class VFS { * @param integer $remaining The bytes that are left, after the part that * is retrieved. * - * @return string The file data. + * @return string The file data. + * @throws VFS_Exception */ - function readByteRange($path, $name, &$offset, $length = -1, &$remaining) + public function readByteRange($path, $name, &$offset, $length = -1, + &$remaining) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -344,11 +392,11 @@ class VFS { * be stored. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function write($path, $name, $tmpFile, $autocreate = false) + public function write($path, $name, $tmpFile, $autocreate = false) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -361,11 +409,11 @@ class VFS { * @param string $data The file data. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function writeData($path, $name, $data, $autocreate = false) + public function writeData($path, $name, $data, $autocreate = false) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -376,14 +424,12 @@ class VFS { * @param string $dest The destination file name. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function move($path, $name, $dest, $autocreate = false) + public function move($path, $name, $dest, $autocreate = false) { - if (is_a($result = $this->copy($path, $name, $dest, $autocreate), 'PEAR_Error')) { - return $result; - } - return $this->deleteFile($path, $name); + $this->copy($path, $name, $dest, $autocreate); + $this->deleteFile($path, $name); } /** @@ -394,68 +440,49 @@ class VFS { * @param string $dest The name of the destination directory. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function copy($path, $name, $dest, $autocreate = false) + public function copy($path, $name, $dest, $autocreate = false) { $orig = $this->_getPath($path, $name); if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { - return PEAR::raiseError(_("Cannot copy file(s) - source and destination are the same.")); + throw new VFS_Exception('Cannot copy file(s) - source and destination are the same.'); } if ($autocreate) { - $result = $this->autocreatePath($dest); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($dest); } + if ($this->isFolder($path, $name)) { - if (is_a($result = $this->_copyRecursive($path, $name, $dest), 'PEAR_Error')) { - return $result; - } + $this->_copyRecursive($path, $name, $dest); } else { - $data = $this->read($path, $name); - if (is_a($data, 'PEAR_Error')) { - return $data; - } - return $this->writeData($dest, $name, $data, $autocreate); + return $this->writeData($dest, $name, $this->read($path, $name), $autocreate); } - return true; } /** * Recursively copies a directory through the backend. * - * @access protected + * @param string $path The path of the original file. + * @param string $name The name of the original file. + * @param string $dest The name of the destination directory. * - * @param string $path The path of the original file. - * @param string $name The name of the original file. - * @param string $dest The name of the destination directory. + * @throws VFS_Exception */ - function _copyRecursive($path, $name, $dest) + protected function _copyRecursive($path, $name, $dest) { - if (is_a($result = $this->createFolder($dest, $name), 'PEAR_Error')) { - return $result; - } - - if (is_a($file_list = $this->listFolder($this->_getPath($path, $name)), 'PEAR_Error')) { - return $file_list; - } + $this->createFolder($dest, $name); + $file_list = $this->listFolder($this->_getPath($path, $name)); foreach ($file_list as $file) { - $result = $this->copy($this->_getPath($path, $name), - $file['name'], - $this->_getPath($dest, $name)); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->copy($this->_getPath($path, $name), $file['name'], $this->_getPath($dest, $name)); } } /** * Alias to deleteFile() */ - function delete($path, $name) + public function delete($path, $name) { return $this->deleteFile($path, $name); } @@ -468,11 +495,11 @@ class VFS { * @param string $path The path to delete the file from. * @param string $name The filename to delete. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFile($path, $name) + public function deleteFile($path, $name) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -485,11 +512,11 @@ class VFS { * @param string $newpath The new path of the file. * @param string $newname The new filename. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function rename($oldpath, $oldname, $newpath, $newname) + public function rename($oldpath, $oldname, $newpath, $newname) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -500,13 +527,13 @@ class VFS { * * @return boolean True if it exists, false otherwise. */ - function exists($path, $name) + public function exists($path, $name) { - $list = $this->listFolder($path); - if (is_a($list, 'PEAR_Error')) { - return false; - } else { + try { + $list = $this->listFolder($path); return isset($list[$name]); + } catch (VFS_Exception $e) { + return false; } } @@ -518,11 +545,11 @@ class VFS { * @param string $path The parent folder. * @param string $name The name of the new folder. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function createFolder($path, $name) + public function createFolder($path, $name) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -530,8 +557,10 @@ class VFS { * $path. * * @param string $path The VFS path to autocreate. + * + * @throws VFS_Exception */ - function autocreatePath($path) + public function autocreatePath($path) { $dirs = explode('/', $path); if (is_array($dirs)) { @@ -542,9 +571,6 @@ class VFS { } if (!$this->isFolder($cur, $dir)) { $result = $this->createFolder($cur, $dir); - if (is_a($result, 'PEAR_Error')) { - return $result; - } } if ($cur != '/') { $cur .= '/'; @@ -552,8 +578,6 @@ class VFS { $cur .= $dir; } } - - return true; } /** @@ -564,10 +588,14 @@ class VFS { * * @return boolean True if it is a folder, false otherwise. */ - function isFolder($path, $name) + public function isFolder($path, $name) { - $folderList = $this->listFolder($path, null, true, true); - return isset($folderList[$name]); + try { + $folderList = $this->listFolder($path, null, true, true); + return isset($folderList[$name]); + } catch (VFS_Exception $e) { + return false; + } } /** @@ -579,11 +607,11 @@ class VFS { * @param string $name The name of the folder to delete. * @param boolean $recursive Force a recursive delete? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFolder($path, $name, $recursive = false) + public function deleteFolder($path, $name, $recursive = false) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -592,34 +620,19 @@ class VFS { * * @param string $path The path of the folder to empty. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function emptyFolder($path) + public function emptyFolder($path) { // Get and delete the subfolders. - $list = $this->listFolder($path, null, true, true); - if (is_a($list, 'PEAR_Error')) { - return $list; - } - foreach ($list as $folder) { - $result = $this->deleteFolder($path, $folder['name'], true); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + foreach ($this->listFolder($path, null, true, true) as $folder) { + $this->deleteFolder($path, $folder['name'], true); } + // Only files are left, get and delete them. - $list = $this->listFolder($path); - if (is_a($list, 'PEAR_Error')) { - return $list; + foreach ($this->listFolder($path) as $file) { + $this->deleteFile($path, $file['name']); } - foreach ($list as $file) { - $result = $this->deleteFile($path, $file['name']); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - return true; } /** @@ -631,13 +644,14 @@ class VFS { * @param boolean $dironly Show only directories? * @param boolean $recursive Return all directory levels recursively? * - * @return array File list on success or PEAR_Error on failure. + * @return array File list. + * @throws VFS_Exception */ - function listFolder($path, $filter = null, $dotfiles = true, - $dironly = false, $recursive = false) + public function listFolder($path, $filter = null, $dotfiles = true, + $dironly = false, $recursive = false) { $list = $this->_listFolder($path, $filter, $dotfiles, $dironly); - if (!$recursive || is_a($list, 'PEAR_Error')) { + if (!$recursive) { return $list; } @@ -660,12 +674,13 @@ class VFS { * @param boolean $dotfiles Show dotfiles? * @param boolean $dironly Show only directories? * - * @return array File list on success or PEAR_Error on failure. + * @return array File list. + * @throws VFS_Exception */ - function _listFolder($path, $filter = null, $dotfiles = true, - $dironly = false) + protected function _listFolder($path, $filter = null, $dotfiles = true, + $dironly = false) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -673,7 +688,7 @@ class VFS { * * @return string The current working directory. */ - function getCurrentDirectory() + public function getCurrentDirectory() { return ''; } @@ -681,31 +696,28 @@ class VFS { /** * Returns whether or not a filename matches any filter element. * - * @access private - * * @param mixed $filter String/hash to build the regular expression * from. * @param string $filename String containing the filename to match. * * @return boolean True on match, false on no match. */ - function _filterMatch($filter, $filename) + protected function _filterMatch($filter, $filename) { $namefilter = null; // Build a regexp based on $filter. - if ($filter !== null) { + if (!is_null($filter)) { $namefilter = '/'; if (is_array($filter)) { $once = false; foreach ($filter as $item) { if ($once !== true) { - $namefilter .= '('; $once = true; } else { - $namefilter .= '|('; + $namefilter .= '|'; } - $namefilter .= $item . ')'; + $namefilter .= '(' . $item . ')'; } } else { $namefilter .= '(' . $filter . ')'; @@ -714,7 +726,7 @@ class VFS { } $match = false; - if ($namefilter !== null) { + if (!is_null($namefilter)) { $match = preg_match($namefilter, $filename); } @@ -730,11 +742,11 @@ class VFS { * @param string $name The name of the item. * @param string $permission The permission to set. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function changePermissions($path, $name, $permission) + public function changePermissions($path, $name, $permission) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -747,11 +759,12 @@ class VFS { * @param mixed $filter Hash of items to filter based on folderlist. * @param boolean $dotfolders Include dotfolders? * - * @return mixed Folder list on success or a PEAR_Error object on failure. + * @return array Folder list. + * @throws VFS_Exception */ - function listFolders($path = '', $filter = null, $dotfolders = true) + public function listFolders($path = '', $filter = null, $dotfolders = true) { - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -759,7 +772,7 @@ class VFS { * * @return array Credential list. */ - function getRequiredCredentials() + public function getRequiredCredentials() { return array_diff($this->_credentials, array_keys($this->_params)); } @@ -770,57 +783,17 @@ class VFS { * * @return array Changeable permisions. */ - function getModifiablePermissions() + public function getModifiablePermissions() { return $this->_permissions; } /** - * Converts a string to all lowercase characters ignoring the current - * locale. - * - * @param string $string The string to be lowercased - * - * @return string The string with lowercase characters - */ - function strtolower($string) - { - $language = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, 'C'); - $string = strtolower($string); - setlocale(LC_CTYPE, $language); - return $string; - } - - /** - * Returns the character (not byte) length of a string. - * - * @param string $string The string to return the length of. - * @param string $charset The charset to use when calculating the - * string's length. - * - * @return string The string's length. - */ - function strlen($string, $charset = null) - { - if (extension_loaded('mbstring')) { - if (is_null($charset)) { - $charset = 'ISO-8859-1'; - } - $result = @mb_strlen($string, $charset); - if (!empty($result)) { - return $result; - } - } - return strlen($string); - } - - /** * Returns the size of the VFS item. * * @return integer The size, in bytes, of the VFS item. */ - function getVFSSize() + public function getVFSSize() { if (is_null($this->_vfsSize)) { $this->_vfsSize = $this->getFolderSize($this->_params['vfs_quotaroot']); @@ -834,18 +807,18 @@ class VFS { * @param integer $quota The limit to apply. * @param integer $metric The metric to multiply the quota into. */ - function setQuota($quota, $metric = VFS_QUOTA_METRIC_BYTE) + public function setQuota($quota, $metric = self::QUOTA_METRIC_BYTE) { switch ($metric) { - case VFS_QUOTA_METRIC_KB: + case self::QUOTA_METRIC_KB: $quota *= pow(2, 10); break; - case VFS_QUOTA_METRIC_MB: + case self::QUOTA_METRIC_MB: $quota *= pow(2, 20); break; - case VFS_QUOTA_METRIC_GB: + case self::QUOTA_METRIC_GB: $quota *= pow(2, 30); break; } @@ -858,7 +831,7 @@ class VFS { * * @param string $dir The root directory for the quota determination. */ - function setQuotaRoot($dir) + public function setQuotaRoot($dir) { $this->_params['vfs_quotaroot'] = $dir; } @@ -867,154 +840,82 @@ class VFS { * Get quota information (used/allocated), in bytes. * * @return mixed An associative array. - * 'limit' = Maximum quota allowed - * 'usage' = Currently used portion of quota (in bytes) - * Returns PEAR_Error on failure. + *
+     * 'limit' = Maximum quota allowed
+     * 'usage' = Currently used portion of quota (in bytes)
+     * 
+ * @throws VFS_Exception */ - function getQuota() + public function getQuota() { if (empty($this->_params['vfs_quotalimit'])) { - return PEAR::raiseError(_("No quota set.")); - } - - $usage = $this->getVFSSize(); - if (is_a($usage, 'PEAR_Error')) { - return $usage; - } else { - return array('usage' => $usage, 'limit' => $this->_params['vfs_quotalimit']); + throw new VFS_Exception('No quota set.'); } - } - - /** - * Determines the location of the system temporary directory. - * - * @access protected - * - * @return string A directory name which can be used for temp files. - * Returns false if one could not be found. - */ - function _getTempDir() - { - $tmp_locations = array('/tmp', '/var/tmp', 'c:\WUTemp', 'c:\temp', - 'c:\windows\temp', 'c:\winnt\temp'); - - /* Try PHP's upload_tmp_dir directive. */ - $tmp = ini_get('upload_tmp_dir'); - - /* Otherwise, try to determine the TMPDIR environment variable. */ - if (!strlen($tmp)) { - $tmp = getenv('TMPDIR'); - } - - /* If we still cannot determine a value, then cycle through a list of - * preset possibilities. */ - while (!strlen($tmp) && count($tmp_locations)) { - $tmp_check = array_shift($tmp_locations); - if (@is_dir($tmp_check)) { - $tmp = $tmp_check; - } - } - - /* If it is still empty, we have failed, so return false; otherwise - * return the directory determined. */ - return strlen($tmp) ? $tmp : false; - } - /** - * Creates a temporary file. - * - * @access protected - * - * @return string Returns the full path-name to the temporary file or - * false if a temporary file could not be created. - */ - function _getTempFile() - { - $tmp_dir = $this->_getTempDir(); - if (!strlen($tmp_dir)) { - return false; - } - - $tmp_file = tempnam($tmp_dir, 'vfs'); - if (!strlen($tmp_file)) { - return false; - } else { - return $tmp_file; - } + return array( + 'limit' => $this->_params['vfs_quotalimit'], + 'usage' => $this->getVFSSize() + ); } /** * Checks the quota when preparing to write data. * - * @access private - * * @param string $mode Either 'string' or 'file'. If 'string', $data is * the data to be written. If 'file', $data is the * filename containing the data to be written. * @param string $data Either the data or the filename to the data. * - * @return mixed PEAR_Error on error, true on success. + * @throws VFS_Exception */ - function _checkQuotaWrite($mode, $data) + protected function _checkQuotaWrite($mode, $data) { - if ($this->_params['vfs_quotalimit'] != -1) { - if ($mode == 'file') { - $filesize = filesize($data); - if ($filesize === false) { - return PEAR::raiseError(_("Unable to read VFS file (filesize() failed).")); - } - } else { - $filesize = strlen($data); - } - $vfssize = $this->getVFSSize(); - if (is_a($vfssize, 'PEAR_Error')) { - return $vfssize; - } - if (($vfssize + $filesize) > $this->_params['vfs_quotalimit']) { - return PEAR::raiseError(_("Unable to write VFS file, quota will be exceeded.")); - } elseif ($this->_vfsSize !== 0) { - $this->_vfsSize += $filesize; + if ($this->_params['vfs_quotalimit'] == -1) { + return; + } + + if ($mode == 'file') { + $filesize = filesize($data); + if ($filesize === false) { + throw new VFS_Exception('Unable to read VFS file (filesize() failed).'); } + } else { + $filesize = strlen($data); } - return true; + $vfssize = $this->getVFSSize(); + if (($vfssize + $filesize) > $this->_params['vfs_quotalimit']) { + throw new VFS_Exception('Unable to write VFS file, quota will be exceeded.'); + } elseif ($this->_vfsSize !== 0) { + $this->_vfsSize += $filesize; + } } /** * Checks the quota when preparing to delete data. * - * @access private - * * @param string $path The path the file is located in. * @param string $name The filename. * - * @return mixed PEAR_Error on error, true on success. + * @throws VFS_Exception */ - function _checkQuotaDelete($path, $name) + protected function _checkQuotaDelete($path, $name) { if (($this->_params['vfs_quotalimit'] != -1) && !empty($this->_vfsSize)) { - $filesize = $this->size($path, $name); - if (is_a($filesize, 'PEAR_Error')) { - return PEAR::raiseError(_("Unable to read VFS file (size() failed).")); - } - $this->_vfsSize -= $filesize; + $this->_vfsSize -= $this->size($path, $name); } - - return true; } /** * Returns the full path of an item. * - * @access protected - * * @param string $path The path of directory of the item. * @param string $name The name of the item. * * @return mixed Full path when $path isset and just $name when not set. */ - function _getPath($path, $name) + protected function _getPath($path, $name) { if (strlen($path) > 0) { if (substr($path, -1) == '/') { @@ -1022,68 +923,50 @@ class VFS { } else { return $path . '/' . $name; } - } else { - return $name; } + + return $name; } /** - * Attempts to return a concrete VFS instance based on $driver. + * Converts a string to all lowercase characters ignoring the current + * locale. * - * @param mixed $driver The type of concrete VFS subclass to return. This - * is based on the storage driver ($driver). The - * code is dynamically included. - * @param array $params A hash containing any additional configuration or - * connection parameters a subclass might need. + * @param string $string The string to be lowercased * - * @return VFS The newly created concrete VFS instance, or a PEAR_Error - * on failure. + * @return string The string with lowercase characters */ - function &factory($driver, $params = array()) + public function strtolower($string) { - $driver = basename($driver); - $class = 'VFS_' . $driver; - if (!class_exists($class)) { - include_once 'VFS/' . $driver . '.php'; - } - - if (class_exists($class)) { - $vfs = new $class($params); - } else { - $vfs = PEAR::raiseError(sprintf(_("Class definition of %s not found."), $class)); - } - - return $vfs; + $language = setlocale(LC_CTYPE, 0); + setlocale(LC_CTYPE, 'C'); + $string = strtolower($string); + setlocale(LC_CTYPE, $language); + return $string; } /** - * Attempts to return a reference to a concrete VFS instance based on - * $driver. It will only create a new instance if no VFS instance with the - * same parameters currently exists. - * - * This should be used if multiple types of file backends (and, thus, - * multiple VFS instances) are required. - * - * This method must be invoked as: $var = &VFS::singleton() + * Returns the character (not byte) length of a string. * - * @param mixed $driver The type of concrete VFS subclass to return. This - * is based on the storage driver ($driver). The - * code is dynamically included. - * @param array $params A hash containing any additional configuration or - * connection parameters a subclass might need. + * @param string $string The string to return the length of. + * @param string $charset The charset to use when calculating the + * string's length. * - * @return VFS The concrete VFS reference, or a PEAR_Error on failure. + * @return string The string's length. */ - function &singleton($driver, $params = array()) + public function strlen($string, $charset = null) { - static $instances = array(); - - $signature = serialize(array($driver, $params)); - if (!isset($instances[$signature])) { - $instances[$signature] = &VFS::factory($driver, $params); + if (extension_loaded('mbstring')) { + if (is_null($charset)) { + $charset = 'ISO-8859-1'; + } + $result = @mb_strlen($string, $charset); + if (!empty($result)) { + return $result; + } } - - return $instances[$signature]; + return strlen($string); } + } diff --git a/framework/VFS/lib/VFS/Browser.php b/framework/VFS/lib/VFS/Browser.php index 019353db2..d2fa003f0 100644 --- a/framework/VFS/lib/VFS/Browser.php +++ b/framework/VFS/lib/VFS/Browser.php @@ -10,44 +10,42 @@ * @author Chuck Hagenbuch * @package VFS */ -class VFS_Browser { - +class VFS_Browser +{ /** * The VFS instance that we are browsing. * * @var VFS */ - var $_vfs; + protected $_vfs; /** * The directory where the templates to use are. * * @var string */ - var $_templates; + protected $_templates; /** * Constructor * - * @param VFS &$vfs A VFS object. - * @param string $templates TODO + * @param VFS $vfs A VFS object. + * @param string $templates Template directory. */ - function VFS_Browser(&$vfs, $templates) + public function __construct($vfs, $templates) { - if (isset($vfs)) { - $this->_vfs = $vfs; - } + $this->setVFSObject($vfs); $this->_templates = $templates; } /** * Set the VFS object in the local object. * - * @param VFS &$vfs A VFS object. + * @param VFS $vfs A VFS object. */ - function setVFSObject(&$vfs) + public function setVFSObject($vfs) { - $this->_vfs = &$vfs; + $this->_vfs = $vfs; } /** @@ -56,8 +54,10 @@ class VFS_Browser { * @param string $path TODO * @param boolean $dotfiles TODO * @param boolean $dironly TODO + * + * @throws VFS_Exception */ - function getUI($path, $dotfiles = false, $dironly = false) + public function getUI($path, $dotfiles = false, $dironly = false) { $this->_vfs->listFolder($path, $dotfiles, $dironly); } diff --git a/framework/VFS/lib/VFS/Exception.php b/framework/VFS/lib/VFS/Exception.php new file mode 100644 index 000000000..62edcc942 --- /dev/null +++ b/framework/VFS/lib/VFS/Exception.php @@ -0,0 +1,13 @@ + + * @package VFS + */ +class VFS_Exception extends Exception {} diff --git a/framework/VFS/lib/VFS/GC.php b/framework/VFS/lib/VFS/GC.php index 20449d245..5733a7e6d 100644 --- a/framework/VFS/lib/VFS/GC.php +++ b/framework/VFS/lib/VFS/GC.php @@ -10,17 +10,17 @@ * @author Michael Slusarz * @package VFS */ -class VFS_GC { - +class VFS_GC +{ /** * Garbage collect files in the VFS storage system. * - * @param VFS &$vfs The VFS object to perform garbage collection on. + * @param VFS $vfs The VFS object to perform garbage collection on. * @param string $path The VFS path to clean. * @param integer $secs The minimum amount of time (in seconds) required * before a file is removed. */ - function gc(&$vfs, $path, $secs = 345600) + public function gc($vfs, $path, $secs = 345600) { /* A 1% chance we will run garbage collection during a call. */ if (rand(0, 99) != 0) { @@ -33,15 +33,14 @@ class VFS_GC { } /* Make sure cleaning is done recursively. */ - $files = $vfs->listFolder($path, null, true, false, true); - if (!is_a($files, 'PEAR_Error') && is_array($files)) { + try { $modtime = time() - $secs; - foreach ($files as $val) { + foreach ($vfs->listFolder($path, null, true, false, true) as $val) { if ($val['date'] < $modtime) { $vfs->deleteFile($path, $val['name']); } } - } + } catch (VFS_Exception $e) {} } } diff --git a/framework/VFS/lib/VFS/ListItem.php b/framework/VFS/lib/VFS/ListItem.php index 4ecb070bf..628acf916 100644 --- a/framework/VFS/lib/VFS/ListItem.php +++ b/framework/VFS/lib/VFS/ListItem.php @@ -10,80 +10,84 @@ * @author Jon Wood * @package VFS */ -class VFS_ListItem { - +class VFS_ListItem +{ /** - * VFS path + * VFS path. * * @var string */ - var $_path; + protected $_path; /** - * Filename + * Filename. * * @var string */ - var $_name; + protected $_name; /** - * File permissions (*nix format: drwxrwxrwx) + * File permissions (*nix format: drwxrwxrwx). * * @var string */ - var $_perms; + protected $_perms; /** - * Owner user + * Owner user. * * @var string */ - var $_owner; + protected $_owner; /** - * Owner group + * Owner group. * * @var string */ - var $_group; + protected $_group; /** * Size. * * @var string */ - var $_size; + protected. $_size; /** * Last modified date. * * @var string */ - var $_date; + protected $_date; /** - * Type - * .* -- File extension - * **none -- Unrecognized type - * **sym -- Symlink - * **dir -- Directory + * Type. + *
+     * .*     - File extension
+     * **none - Unrecognized type
+     * **sym  - Symlink
+     * **dir  - Directory
+     * 
* * @var string */ - var $_type; + protected $_type; /** * Type of target if type is '**sym'. * NB. Not all backends are capable of distinguishing all of these. - * .* -- File extension - * **none -- Unrecognized type - * **sym -- Symlink to a symlink - * **dir -- Directory - * **broken -- Target not found - broken link + *
+     * .*       - File extension
+     * **none   - Unrecognized type
+     * **sym    - Symlink to a symlink
+     * **dir    - Directory
+     * **broken - Target not found - broken link
+     * 
* * @var string */ - var $_linktype; + protected $_linktype; /** * Constructor @@ -94,7 +98,7 @@ class VFS_ListItem { * @param string $path The path to the file. * @param array $fileArray An array of file properties. */ - function VFS_ListItem($path, $fileArray) + public function _-construct($path, $fileArray) { $this->_path = $path . '/' . $fileArray['name']; $this->_name = $fileArray['name']; diff --git a/framework/VFS/lib/VFS/Object.php b/framework/VFS/lib/VFS/Object.php index e5d3b9404..da25ffc3c 100644 --- a/framework/VFS/lib/VFS/Object.php +++ b/framework/VFS/lib/VFS/Object.php @@ -1,7 +1,4 @@ * @package VFS */ -class VFS_Object { - +class VFS_Object +{ /** - * The actual vfs that does the work + * The actual vfs object that does the work. * * @var VFS */ - var $_vfs; + protected $_vfs; /** - * The current path that has been passed to listFolder, if this + * The current path that has been passed to listFolder(), if this * changes, the list will be rebuilt. * * @var string */ - var $_currentPath; + protected $_currentPath; /** - * The return value from a standard VFS listFolder call, to - * be read with the Object listFolder. + * The return value from a standard VFS listFolder() call, to + * be read with the Object listFolder(). * * @var array */ - var $_folderList; + protected $_folderList; /** - * Constructor. + * Attempts to return a reference to a concrete instance + * based on $driver. It will only create a new instance if no + * VFS instance with the same parameters currently exists. * - * If you pass in an existing VFS object, it will be used as the VFS - * object for this object. + * This should be used if multiple types of file backends (and, + * thus, multiple VFS instances) are required. + * + * This method must be invoked as: $var = VFS_Object::singleton(); + * + * @param mixed $driver The type of concrete subclass to return. + * @param array $params A hash containing any additional configuration or + * connection parameters a subclass might need. * - * @param VFS &$vfs The VFS object to wrap. + * @return VFS_Object The concrete VFS_Object reference. + * @throws VFS_Exception */ - function VFS_Object(&$vfs) + static public function singleton($driver, $params = array()) { - if (isset($vfs)) { - $this->_vfs = $vfs; - } + require_once dirname(__FILE__) . '/../VFS.php'; + $classname = __CLASS__; + return new $classname(VFS::singleton($driver, $params = array())); } /** - * Attempts to return a concrete VFS_Object instance based on $driver. + * Attempts to return a concrete instance based on $driver. * - * @param mixed $driver The type of concrete VFS subclass to return. If - * $driver is an array then we will look in - * $driver[0]/lib/VFS/ for the subclass - * implementation named $driver[1].php. + * @param mixed $driver The type of concrete subclass to return. * @param array $params A hash containing any additional configuration or * connection parameters a subclass might need. * - * @return VFS_Object The newly created concrete VFS_Object instance, or - * false on an error. + * @return VFS_Object The newly created concrete VFS_Object instance. + * @throws VFS_Exception */ - function &factory($driver, $params = array()) + static public function factory($driver, $params = array()) { - $vfs = &VFS::factory($driver, $params = array()); - $vfsobject = new VFS_Object($vfs); - return $vfsobject; + return self::singleton($driver, $params); } /** - * Attempts to return a reference to a concrete VFS instance - * based on $driver. It will only create a new instance if no - * VFS instance with the same parameters currently exists. - * - * This should be used if multiple types of file backends (and, - * thus, multiple VFS instances) are required. - * - * This method must be invoked as: $var = &VFS::singleton() + * Constructor. * - * @param mixed $driver The type of concrete VFS subclass to return. If - * $driver is an array then we will look in - * $driver[0]/lib/VFS/ for the subclass - * implementation named $driver[1].php. - * @param array $params A hash containing any additional configuration or - * connection parameters a subclass might need. + * If you pass in an existing VFS object, it will be used as the VFS + * object for this object. * - * @return VFS_Object The concrete VFS_Object reference, or false on - * error. + * @param VFS $vfs The VFS object to wrap. */ - function &singleton($driver, $params = array()) + public function __construct($vfs) { - $vfs = &VFS::singleton($driver, $params = array()); - $vfsobject = new VFS_Object($vfs); - return $vfsobject; + if (isset($vfs)) { + $this->_vfs = $vfs; + } } /** * Check the credentials that we have to see if there is a valid login. * - * @return mixed True on success, PEAR_Error describing the problem - * if the credentials are invalid. + * @throws VFS_Exception; */ - function checkCredentials() + public function checkCredentials() { - return $this->_vfs->checkCredentials(); + $this->_vfs->checkCredentials(); } /** @@ -117,7 +105,7 @@ class VFS_Object { * @param array $params An associative array of parameter name/value * pairs. */ - function setParams($params = array()) + public function setParams($params = array()) { $this->_vfs->setParams($params); } @@ -128,8 +116,9 @@ class VFS_Object { * @param string $path The pathname to the file. * * @return string The file data. + * @throws VFS_Exception */ - function read($path) + public function read($path) { return $this->_vfs->read(dirname($path), basename($path)); } @@ -142,11 +131,11 @@ class VFS_Object { * stored. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function write($path, $tmpFile, $autocreate = false) + public function write($path, $tmpFile, $autocreate = false) { - return $this->_vfs->write(dirname($path), basename($path), $tmpFile, $autocreate = false); + $this->_vfs->write(dirname($path), basename($path), $tmpFile, $autocreate); } /** @@ -156,11 +145,11 @@ class VFS_Object { * @param string $data The file data. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function writeData($path, $data, $autocreate = false) + public function writeData($path, $data, $autocreate = false) { - return $this->_vfs->writeData(dirname($path), basename($path), $data, $autocreate = false); + $this->_vfs->writeData(dirname($path), basename($path), $data, $autocreate); } /** @@ -169,11 +158,11 @@ class VFS_Object { * @param string $path The path to store the file in. * @param string $name The filename to use. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFile($path) + public function deleteFile($path) { - return $this->_vfs->deleteFile(dirname($path), basename($path)); + $this->_vfs->deleteFile(dirname($path), basename($path)); } /** @@ -184,9 +173,9 @@ class VFS_Object { * @param string $newpath The new path of the file. * @param string $newname The new filename. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function rename($oldpath, $newpath) + public function rename($oldpath, $newpath) { return $this->_vfs->rename(dirname($oldpath), basename($oldpath), dirname($newpath), basename($newpath)); } @@ -196,11 +185,11 @@ class VFS_Object { * * @param string $path The path to the folder. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function createFolder($path) + public function createFolder($path) { - return $this->_vfs->createFolder(dirname($path)); + $this->_vfs->createFolder(dirname($path)); } /** @@ -208,11 +197,11 @@ class VFS_Object { * * @param string $path The path of the folder to delete. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFolder($path) + public function deleteFolder($path) { - return $this->_vfs->deleteFolder(dirname($path)); + $this->_vfs->deleteFolder(dirname($path)); } /** @@ -222,11 +211,11 @@ class VFS_Object { * * @param string $path The path of the diretory. * - * @return mixed File list (array) on success, a PEAR_Error - * object on failure, or false if the folder is + * @return mixed File list (array) on success or false if the folder is * completely read. + * @throws VFS_Exception */ - function listFolder($path) + public function listFolder($path) { if (!($path === $this->_currentPath)) { $folderList = $this->_vfs->listFolder($path); @@ -234,17 +223,15 @@ class VFS_Object { $this->_folderList = $folderList; $this->_currentPath = $path; } else { - return PEAR::raiseError(sprintf(_("Could not read %s."), $path)); + require_once dirname(__FILE__) . '/Exception.php'; + throw new VFS_Exception('Could not read ' . $path . '.'); } } require_once dirname(__FILE__) . '/ListItem.php'; - if ($file = array_shift($this->_folderList)) { - $file = new VFS_ListItem($path, $file); - return $file; - } else { - return false; - } + return ($file = array_shift($this->_folderList)) + ? new VFS_ListItem($path, $file) + : false; } /** @@ -253,11 +240,11 @@ class VFS_Object { * @param string $path Holds the path of directory of the Item. * @param string $permission TODO * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function changePermissions($path, $permission) + public function changePermissions($path, $permission) { - return $this->_vfs->changePermissions(dirname($path), basename($path), $permission); + $this->_vfs->changePermissions(dirname($path), basename($path), $permission); } /** @@ -265,7 +252,7 @@ class VFS_Object { * * @return array Credential list. */ - function getRequiredCredentials() + public function getRequiredCredentials() { return $this->_vfs->getRequiredCredentials(); } @@ -276,7 +263,7 @@ class VFS_Object { * * @return array Changeable permisions. */ - function getModifiablePermissions() + public function getModifiablePermissions() { return $this->_vfs->getModifiablePermissions(); } diff --git a/framework/VFS/lib/VFS/file.php b/framework/VFS/lib/VFS/file.php index 76d1af297..5367b974b 100644 --- a/framework/VFS/lib/VFS/file.php +++ b/framework/VFS/lib/VFS/file.php @@ -2,8 +2,10 @@ /** * VFS implementation for a standard filesystem. * - * Required parameters:
- *   'vfsroot'  The root path
+ * Required parameters: + *
+ * 'vfsroot' - (string) The root path.
+ * 
* * Note: The user that your webserver runs as (commonly 'nobody', * 'apache', or 'www-data') MUST have read/write permission to the @@ -17,18 +19,29 @@ * @author Chuck Hagenbuch * @package VFS */ -class VFS_file extends VFS { - +class VFS_file extends VFS +{ /** - * List of permissions and if they can be changed in this VFS - * backend. + * List of permissions and if they can be changed in this VFS backend. * * @var array */ - var $_permissions = array( - 'owner' => array('read' => true, 'write' => true, 'execute' => true), - 'group' => array('read' => true, 'write' => true, 'execute' => true), - 'all' => array('read' => true, 'write' => true, 'execute' => true) + protected $_permissions = array( + 'owner' => array( + 'read' => true, + 'write' => true, + 'execute' => true + ), + 'group' => array( + 'read' => true, + 'write' => true, + 'execute' => true + ), + 'all' => array( + 'read' => true, + 'write' => true, + 'execute' => true + ) ); /** @@ -36,15 +49,14 @@ class VFS_file extends VFS { * * @param array $params A hash containing connection parameters. */ - function VFS_file($params = array()) + public function __construct($params = array()) { - parent::VFS($params); + parent::__construct($params); - if (!empty($this->_params['vfsroot'])) { - if (substr($this->_params['vfsroot'], -1) == '/' || - substr($this->_params['vfsroot'], -1) == '\\') { - $this->_params['vfsroot'] = substr($this->_params['vfsroot'], 0, strlen($this->_params['vfsroot']) - 1); - } + if (!empty($this->_params['vfsroot']) && + ((substr($this->_params['vfsroot'], -1) == '/') || + (substr($this->_params['vfsroot'], -1) == '\\'))) { + $this->_params['vfsroot'] = substr($this->_params['vfsroot'], 0, strlen($this->_params['vfsroot']) - 1); } } @@ -54,14 +66,15 @@ class VFS_file extends VFS { * @param string $path The pathname to the file. * @param string $name The filename to retrieve. * - * @return integer The file size. + * @return integer The file size. + * @throws VFS_Exception */ - function size($path, $name) + public function size($path, $name) { - $size = @filesize($this->_getNativePath($path, $name)); - if ($size === false) { - return PEAR::raiseError(sprintf(_("Unable to check file size of \"%s/%s\"."), $path, $name)); + if (($size = @filesize($this->_getNativePath($path, $name))) === false) { + throw new VFS_Exception(sprintf('Unable to check file size of "%s/%s".'), $path, $name); } + return $size; } @@ -72,12 +85,12 @@ class VFS_file extends VFS { * @param string $name The filename to retrieve. * * @return string The file data. + * @throws VFS_Exception */ - function read($path, $name) + public function read($path, $name) { - $data = @file_get_contents($this->_getNativePath($path, $name)); - if ($data === false) { - return PEAR::raiseError(_("Unable to open VFS file.")); + if (($data = @file_get_contents($this->_getNativePath($path, $name))) === false) { + throw new VFS_Exception('Unable to open VFS file.'); } return $data; @@ -95,7 +108,7 @@ class VFS_file extends VFS { * * @return string A local filename. */ - function readFile($path, $name) + public function readFile($path, $name) { return $this->_getNativePath($path, $name); } @@ -107,13 +120,14 @@ class VFS_file extends VFS { * @param string $name The filename to retrieve. * * @return resource The stream. + * @throws VFS_Exception */ - function readStream($path, $name) + public function readStream($path, $name) { $mode = OS_WINDOWS ? 'rb' : 'r'; $stream = @fopen($this->_getNativePath($path, $name), $mode); if (!is_resource($stream)) { - return PEAR::raiseError(_("Unable to open VFS file.")); + throw new VFS_Exception('Unable to open VFS file.'); } return $stream; @@ -124,8 +138,6 @@ class VFS_file extends VFS { * reading large files which would exceed the PHP memory limits if they * were stored in a string. * - * @abstract - * * @param string $path The pathname to the file. * @param string $name The filename to retrieve. * @param integer $offset The offset of the part. (The new offset will @@ -138,19 +150,21 @@ class VFS_file extends VFS { * @param integer $remaining The bytes that are left, after the part that * is retrieved. * - * @return string The file data. + * @return string The file data. + * @throws VFS_Exception */ - function readByteRange($path, $name, &$offset, $length = -1, &$remaining) + public function readByteRange($path, $name, &$offset, $length = -1, + &$remaining) { if ($offset < 0) { - return PEAR::raiseError(sprintf(_("Wrong offset %d while reading a VFS file."), $offset)); + throw new VFS_Exception(sprintf('Wrong offset %d while reading a VFS file.', $offset)); } // Calculate how many bytes MUST be read, so the remainging // bytes and the new offset can be calculated correctly. $file = $this->_getNativePath($path, $name); $size = filesize ($file); - if ($length == -1 || (($length + $offset) > $size)) { + if (($length == -1) || (($length + $offset) > $size)) { $length = $size - $offset; } if ($remaining < 0) { @@ -159,7 +173,7 @@ class VFS_file extends VFS { $fp = @fopen($file, 'rb'); if (!$fp) { - return PEAR::raiseError(_("Unable to open VFS file.")); + throw new VFS_Exception('Unable to open VFS file.'); } fseek($fp, $offset); $data = fread($fp, $length); @@ -181,34 +195,26 @@ class VFS_file extends VFS { * stored. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function write($path, $name, $tmpFile, $autocreate = true) + public function write($path, $name, $tmpFile, $autocreate = true) { if (!@is_dir($this->_getNativePath($path))) { if ($autocreate) { - $res = $this->autocreatePath($path); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->autocreatePath($path); } else { - return PEAR::raiseError(_("VFS directory does not exist.")); + throw new VFS_Exception('VFS directory does not exist.'); } } - $res = $this->_checkQuotaWrite('file', $tmpFile); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_checkQuotaWrite('file', $tmpFile); // Since we already have the data in a file, don't read it // into PHP's memory at all - just copy() it to the new // location. We leave it to the caller to clean up the // temporary file, so we don't use rename(). - if (@copy($tmpFile, $this->_getNativePath($path, $name))) { - return true; - } else { - return PEAR::raiseError(_("Unable to write VFS file (copy() failed).")); + if (!@copy($tmpFile, $this->_getNativePath($path, $name))) { + throw new VFS_Exception('Unable to write VFS file (copy() failed).'); } } @@ -220,37 +226,28 @@ class VFS_file extends VFS { * @param string $dest The destination of the file. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function move($path, $name, $dest, $autocreate = false) + public function move($path, $name, $dest, $autocreate = false) { $orig = $this->_getNativePath($path, $name); if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { - return PEAR::raiseError(_("Cannot move file(s) - destination is within source.")); + throw new VFS_Exception('Cannot move file(s) - destination is within source.'); } if ($autocreate) { - $result = $this->autocreatePath($dest); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($dest); } - $fileCheck = $this->listFolder($dest, false); - if (is_a($fileCheck, 'PEAR_Error')) { - return $fileCheck; - } - foreach ($fileCheck as $file) { + foreach ($this->listFolder($dest, false) as $file) { if ($file['name'] == $name) { - return PEAR::raiseError(_("Unable to move VFS file.")); + throw new VFS_Exception('Unable to move VFS file.'); } } if (!@rename($orig, $this->_getNativePath($dest, $name))) { - return PEAR::raiseError(_("Unable to move VFS file.")); + throw new VFS_Exception('Unable to move VFS file.'); } - - return true; } /** @@ -261,42 +258,30 @@ class VFS_file extends VFS { * @param string $dest The destination of the file. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function copy($path, $name, $dest, $autocreate = false) + public function copy($path, $name, $dest, $autocreate = false) { $orig = $this->_getNativePath($path, $name); if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { - return PEAR::raiseError(_("Cannot copy file(s) - source and destination are the same.")); + throw new VFS_Exception('Cannot copy file(s) - source and destination are the same.'); } if ($autocreate) { - $result = $this->autocreatePath($dest); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($dest); } - $fileCheck = $this->listFolder($dest, false); - if (is_a($fileCheck, 'PEAR_Error')) { - return $fileCheck; - } - foreach ($fileCheck as $file) { + foreach ($this->listFolder($dest, false) as $file) { if ($file['name'] == $name) { - return PEAR::raiseError(_("Unable to copy VFS file.")); + throw new VFS_Exception('Unable to copy VFS file.'); } } - $res = $this->_checkQuotaWrite('file', $orig); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_checkQuotaWrite('file', $orig); if (!@copy($orig, $this->_getNativePath($dest, $name))) { - return PEAR::raiseError(_("Unable to copy VFS file.")); + throw new VFS_Exception('Unable to copy VFS file.'); } - - return true; } /** @@ -307,18 +292,15 @@ class VFS_file extends VFS { * @param string $data The file data. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function writeData($path, $name, $data, $autocreate = true) + public function writeData($path, $name, $data, $autocreate = true) { if (!@is_dir($this->_getNativePath($path))) { if ($autocreate) { - $res = $this->autocreatePath($path); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->autocreatePath($path); } else { - return PEAR::raiseError(_("VFS directory does not exist.")); + throw new VFS_Exception('VFS directory does not exist.'); } } @@ -326,34 +308,17 @@ class VFS_file extends VFS { // since otherwise the file will not be created at all. if (!strlen($data)) { if (@touch($this->_getNativePath($path, $name))) { - return true; - } else { - return PEAR::raiseError(_("Unable to create empty VFS file.")); + return; } + throw new VFS_Exception('Unable to create empty VFS file.'); } - $res = $this->_checkQuotaWrite('string', $data); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_checkQuotaWrite('string', $data); // Otherwise we go ahead and try to write out the file. - if (function_exists('file_put_contents')) { - if (!@file_put_contents($this->_getNativePath($path, $name), $data)) { - return PEAR::raiseError(_("Unable to write VFS file data.")); - } - } else { - $fp = @fopen($this->_getNativePath($path, $name), 'w'); - if (!$fp) { - return PEAR::raiseError(_("Unable to open VFS file for writing.")); - } - - if (!@fwrite($fp, $data)) { - return PEAR::raiseError(_("Unable to write VFS file data.")); - } + if (!@file_put_contents($this->_getNativePath($path, $name), $data)) { + throw new VFS_Exception('Unable to write VFS file data.'); } - - return true; } /** @@ -362,20 +327,15 @@ class VFS_file extends VFS { * @param string $path The path to store the file in. * @param string $name The filename to use. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFile($path, $name) + public function deleteFile($path, $name) { - $res = $this->_checkQuotaDelete($path, $name); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_checkQuotaDelete($path, $name); if (!@unlink($this->_getNativePath($path, $name))) { - return PEAR::raiseError(_("Unable to delete VFS file.")); + throw new VFS_Exception('Unable to delete VFS file.'); } - - return true; } /** @@ -385,31 +345,22 @@ class VFS_file extends VFS { * @param string $name The foldername to use. * @param boolean $recursive Force a recursive delete? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFolder($path, $name, $recursive = false) + public function deleteFolder($path, $name, $recursive = false) { if ($recursive) { - $result = $this->emptyFolder($path . '/' . $name); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->emptyFolder($path . '/' . $name); } else { $list = $this->listFolder($path . '/' . $name); - if (is_a($list, 'PEAR_Error')) { - return $list; - } if (count($list)) { - return PEAR::raiseError(sprintf(_("Unable to delete %s, the directory is not empty"), - $path . '/' . $name)); + throw new VFS_Exception(sprintf('Unable to delete %s, the directory is not empty', $path . '/' . $name)); } } if (!@rmdir($this->_getNativePath($path, $name))) { - return PEAR::raiseError(_("Unable to delete VFS directory.")); + throw new VFS_Exception('Unable to delete VFS directory.'); } - - return true; } /** @@ -418,15 +369,13 @@ class VFS_file extends VFS { * @param string $path The path to create the folder in. * @param string $name The foldername to use. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function createFolder($path, $name) + public function createFolder($path, $name) { if (!@mkdir($this->_getNativePath($path, $name))) { - return PEAR::raiseError(_("Unable to create VFS directory.")); + throw new VFS_Exception('Unable to create VFS directory.'); } - - return true; } /** @@ -437,7 +386,7 @@ class VFS_file extends VFS { * * @return boolean True if it is a folder, false otherwise. */ - function isFolder($path, $name) + public function isFolder($path, $name) { return @is_dir($this->_getNativePath($path, $name)); } @@ -449,15 +398,13 @@ class VFS_file extends VFS { * @param string $name The name of the item. * @param integer $permission The octal value of the new permission. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function changePermissions($path, $name, $permission) + public function changePermissions($path, $name, $permission) { if (!@chmod($this->_getNativePath($path, $name), $permission)) { - return PEAR::raiseError(sprintf(_("Unable to change permission for VFS file %s/%s."), $path, $name)); + throw new VFS_Exception(sprintf('Unable to change permission for VFS file %s/%s.', $path, $name)); } - - return true; } /** @@ -468,24 +415,25 @@ class VFS_file extends VFS { * @param boolean $dotfiles Show dotfiles? * @param boolean $dironly Show only directories? * - * @return array File list on success, PEAR_Error on error. + * @return array File list. + * @throws VFS_Exception */ - function _listFolder($path, $filter = null, $dotfiles = true, - $dironly = false) + protected function _listFolder($path, $filter = null, $dotfiles = true, + $dironly = false) { $files = array(); - $path = isset($path) ? $this->_getNativePath($path) : $this->_getNativePath(); + $path = $this->_getNativePath(isset($path) ? $path : ''); if (!@is_dir($path)) { - return PEAR::raiseError(_("Not a directory")); + throw new VFS_Exception('Not a directory'); } if (!@chdir($path)) { - return PEAR::raiseError(_("Unable to access VFS directory.")); + throw new VFS_Exception('Unable to access VFS directory.'); } - $handle = opendir($path); - while (($entry = readdir($handle)) !== false) { + $d = dir($path); + while (($entry = $d->read()) !== false) { // Filter out '.' and '..' entries. if ($entry == '.' || $entry == '..') { continue; @@ -511,11 +459,9 @@ class VFS_file extends VFS { // Group $file['group'] = filegroup($entry); - if (function_exists('posix_getgrgid')) { - if (PHP_VERSION != '5.2.1') { - $group = posix_getgrgid($file['group']); - $file['group'] = $group['name']; - } + if (function_exists('posix_getgrgid') && (PHP_VERSION != '5.2.1')) { + $group = posix_getgrgid($file['group']); + $file['group'] = $group['name']; } // Size @@ -542,7 +488,7 @@ class VFS_file extends VFS { } elseif (is_file($file['link'])) { $ext = explode('.', $file['link']); if (!(count($ext) == 1 || ($ext[0] === '' && count($ext) == 2))) { - $file['linktype'] = VFS::strtolower($ext[count($ext) - 1]); + $file['linktype'] = self::strtolower($ext[count($ext) - 1]); } } } else { @@ -555,7 +501,7 @@ class VFS_file extends VFS { if (count($ext) == 1 || (substr($file['name'], 0, 1) === '.' && count($ext) == 2)) { $file['type'] = '**none'; } else { - $file['type'] = VFS::strtolower($ext[count($ext) - 1]); + $file['type'] = self::strtolower($ext[count($ext) - 1]); } } else { $file['type'] = '**none'; @@ -586,6 +532,8 @@ class VFS_file extends VFS { unset($file); } + $d->close(); + return $files; } @@ -597,29 +545,27 @@ class VFS_file extends VFS { * @param mixed $filter Hash of items to filter based on folderlist. * @param boolean $dotfolders Include dotfolders? * - * @return mixed Folder list on success or a PEAR_Error object on failure. + * @return array Folder list. + * @throws VFS_Exception */ function listFolders($path = '', $filter = null, $dotfolders = true) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); $folders = array(); - $folders[dirname($path)] = array('val' => dirname($path), - 'abbrev' => '..', - 'label' => '..'); + $folders[dirname($path)] = array( + 'val' => dirname($path), + 'abbrev' => '..', + 'label' => '..' + ); $folderList = $this->listFolder($path, null, $dotfolders, true); - if (is_a($folderList, 'PEAR_Error')) { - return $folderList; - } - foreach ($folderList as $name => $files) { - $folders[$name] = array('val' => $path . '/' . $files['name'], - 'abbrev' => $files['name'], - 'label' => $path . '/' . $files['name']); + $folders[$name] = array( + 'val' => $path . '/' . $files['name'], + 'abbrev' => $files['name'], + 'label' => $path . '/' . $files['name'] + ); } ksort($folders); @@ -630,13 +576,11 @@ class VFS_file extends VFS { /** * Return Unix style perms. * - * @access private - * * @param integer $perms The permissions to set. * * @return string Unix style perms. */ - function _getUnixPerms($perms) + protected function _getUnixPerms($perms) { // Determine permissions $owner['read'] = ($perms & 00400) ? 'r' : '-'; @@ -660,11 +604,9 @@ class VFS_file extends VFS { $world['execute'] = ($world['execute'] == 'x') ? 't' : 'T'; } - $unixPerms = $owner['read'] . $owner['write'] . $owner['execute'] . - $group['read'] . $group['write'] . $group['execute'] . - $world['read'] . $world['write'] . $world['execute']; - - return $unixPerms; + return $owner['read'] . $owner['write'] . $owner['execute'] . + $group['read'] . $group['write'] . $group['execute'] . + $world['read'] . $world['write'] . $world['execute']; } /** @@ -675,22 +617,18 @@ class VFS_file extends VFS { * @param string $newpath The new path of the file. * @param string $newname The new filename. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function rename($oldpath, $oldname, $newpath, $newname) + public function rename($oldpath, $oldname, $newpath, $newname) { if (!@is_dir($this->_getNativePath($newpath))) { - if (is_a($res = $this->autocreatePath($newpath), 'PEAR_Error')) { - return $res; - } + $this->autocreatePath($newpath); } if (!@rename($this->_getNativePath($oldpath, $oldname), $this->_getNativePath($newpath, $newname))) { - return PEAR::raiseError(sprintf(_("Unable to rename VFS file %s/%s."), $oldpath, $oldname)); + throw new VFS_Exception(sprintf('Unable to rename VFS file %s/%s.', $oldpath, $oldname)); } - - return true; } /** @@ -701,7 +639,7 @@ class VFS_file extends VFS { * * @return boolean True if it exists, false otherwise. */ - function exists($path, $name) + public function exists($path, $name) { return file_exists($this->_getNativePath($path, $name)); } @@ -710,14 +648,12 @@ class VFS_file extends VFS { * Return a full filename on the native filesystem, from a VFS * path and name. * - * @access private - * * @param string $path The VFS file path. * @param string $name The VFS filename. * * @return string The full native filename. */ - function _getNativePath($path = '', $name = '') + protected function _getNativePath($path = '', $name = '') { $name = basename($name); if (strlen($name)) { @@ -739,27 +675,23 @@ class VFS_file extends VFS { } else { return $this->_params['vfsroot'] . '/' . $path . $name; } - } else { - return $this->_params['vfsroot'] . $name; } + + return $this->_params['vfsroot'] . $name; } /** * Stub to check if we have a valid connection. Makes sure that * the vfsroot is readable. * - * @access private - * - * @return mixed True if vfsroot is readable, PEAR_Error if it isn't. + * @throws VFS_Exception */ - function _connect() + protected function _connect() { - if ((@is_dir($this->_params['vfsroot']) && - is_readable($this->_params['vfsroot'])) || - @mkdir($this->_params['vfsroot'])) { - return true; - } else { - return PEAR::raiseError(_("Unable to read the vfsroot directory.")); + if (!(@is_dir($this->_params['vfsroot']) && + is_readable($this->_params['vfsroot'])) || + !@mkdir($this->_params['vfsroot'])) { + throw new VFS_Exception('Unable to read the vfsroot directory.'); } } diff --git a/framework/VFS/lib/VFS/ftp.php b/framework/VFS/lib/VFS/ftp.php index 017357245..bfdca4b77 100644 --- a/framework/VFS/lib/VFS/ftp.php +++ b/framework/VFS/lib/VFS/ftp.php @@ -3,30 +3,28 @@ * VFS implementation for an FTP server. * * Required values for $params:
- *      'username'       The username with which to connect to the ftp server.
- *      'password'       The password with which to connect to the ftp server.
- *      'hostspec'       The ftp server to connect to.
+ * username - (string) The username with which to connect to the ftp server. + * password - (string) The password with which to connect to the ftp server. + * hostspec - (string) The ftp server to connect to. * * Optional values for $params:
- *      'lsformat'       The return formatting from the 'ls' command).
+ * lsformat - (string) The return formatting from the 'ls' command).
  *                       Values: 'aix', 'standard' (default)
- *      'maplocalids'    If true and the POSIX extension is available, the
- *                       driver will map the user and group IDs returned from
- *                       the FTP server with the local IDs from the local
- *                       password file.  This is useful only if the FTP server
- *                       is running on localhost or if the local user/group
- *                       IDs are identical to the remote FTP server.
- *      'pasv'           If true, connection will be set to passive mode.
- *      'port'           The port used to connect to the ftp server if other
- *                       than 21.
- *      'ssl'            If true, and PHP had been compiled with OpenSSL
- *                       support, TLS transport-level encryption will be
- *                       negotiated with the server.
- *      'timeout'        If defined, use this value as the timeout for the
- *                       server.
- *      'type'           The type of the remote FTP server.
- *                       Possible values: 'unix', 'win', 'netware'
- *                       By default, we attempt to auto-detect type.
+ * maplocalids - (boolean) If true and the POSIX extension is available, the + * driver will map the user and group IDs returned from the FTP + * server with the local IDs from the local password file. This + * is useful only if the FTP server is running on localhost or + * if the local user/group IDs are identical to the remote FTP + * server. + * pasv - (boolean) If true, connection will be set to passive mode. + * port - (integer) The port used to connect to the ftp server if other than + * 21 (FTP default). + * ssl - (boolean) If true, and PHP had been compiled with OpenSSL support, + * TLS transport-level encryption will be negotiated with the server. + * timeout -(integer) The timeout for the server. + * type - (string) The type of the remote FTP server. + * Possible values: 'unix', 'win', 'netware' + * By default, we attempt to auto-detect type. * * Copyright 2002-2010 The Horde Project (http://www.horde.org/) * Copyright 2002-2007 Michael Varghese @@ -38,70 +36,81 @@ * @author Michael Varghese * @package VFS */ -class VFS_ftp extends VFS { - +class VFS_ftp extends VFS +{ /** * List of additional credentials required for this VFS backend. * * @var array */ - var $_credentials = array('username', 'password'); + protected $_credentials = array('username', 'password'); /** * List of permissions and if they can be changed in this VFS backend. * * @var array */ - var $_permissions = array( - 'owner' => array('read' => true, 'write' => true, 'execute' => true), - 'group' => array('read' => true, 'write' => true, 'execute' => true), - 'all' => array('read' => true, 'write' => true, 'execute' => true)); + protected $_permissions = array( + 'owner' => array( + 'read' => true, + 'write' => true, + 'execute' => true + ), + 'group' => array( + 'read' => true, + 'write' => true, + 'execute' => true + ), + 'all' => array( + 'read' => true, + 'write' => true, + 'execute' => true + ) + ); /** * Variable holding the connection to the ftp server. * * @var resource */ - var $_stream = false; + protected $_stream = false; /** * Local cache array for user IDs. * * @var array */ - var $_uids = array(); + protected $_uids = array(); /** * Local cache array for group IDs. * * @var array */ - var $_gids = array(); + protected $_gids = array(); /** + * The FTP server type. + * + * @var string */ - var $_type; + protected $_type; /** * Returns the size of a file. * - * @access public - * * @param string $path The path of the file. * @param string $name The filename. * - * @return integer The size of the file in bytes or PEAR_Error on - * failure. + * @return integer The size of the file in bytes. + * @throws VFS_Exception */ - function size($path, $name) + public function size($path, $name) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if (($size = @ftp_size($this->_stream, $this->_getPath($path, $name))) === false) { - return PEAR::raiseError(sprintf(_("Unable to check file size of \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to check file size of "%s".', $this->_getPath($path, $name))); } return $size; @@ -115,19 +124,14 @@ class VFS_ftp extends VFS { * * @return string The file data. */ - function read($path, $name) + public function read($path, $name) { $file = $this->readFile($path, $name); - if (is_a($file, 'PEAR_Error')) { - return $file; - } - $size = filesize($file); - if ($size === 0) { - return ''; - } - return file_get_contents($file); + return ($size === 0) + ? '' + : file_get_contents($file); } /** @@ -140,20 +144,17 @@ class VFS_ftp extends VFS { * @param string $path The pathname to the file. * @param string $name The filename to retrieve. * - * @return string A local filename. + * @return string A local filename. + * @throws VFS_Exception */ - function readFile($path, $name) + public function readFile($path, $name) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); // Create a temporary file and register it for deletion at the // end of this request. - $localFile = $this->_getTempFile(); - if (!$localFile) { - return PEAR::raiseError(_("Unable to create temporary file.")); + if (!($localFile = tempnam(null, 'vfs'))) { + throw new VFS_Exception('Unable to create temporary file.'); } register_shutdown_function(create_function('', '@unlink(\'' . addslashes($localFile) . '\');')); @@ -162,8 +163,9 @@ class VFS_ftp extends VFS { $localFile, $this->_getPath($path, $name), FTP_BINARY); + if ($result === false) { - return PEAR::raiseError(sprintf(_("Unable to open VFS file \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to open VFS file "%s".', $this->_getPath($path, $name))); } return $localFile; @@ -176,16 +178,11 @@ class VFS_ftp extends VFS { * @param string $name The filename to retrieve. * * @return resource The stream. + * @throws VFS_Exception */ - function readStream($path, $name) + public function readStream($path, $name) { - $file = $this->readFile($path, $name); - if (is_a($file, 'PEAR_Error')) { - return $file; - } - - $mode = OS_WINDOWS ? 'rb' : 'r'; - return fopen($file, $mode); + return fopen($this->readFile($path, $name), OS_WINDOWS ? 'rb' : 'r'); } /** @@ -197,35 +194,23 @@ class VFS_ftp extends VFS { * be stored. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function write($path, $name, $tmpFile, $autocreate = false) + public function write($path, $name, $tmpFile, $autocreate = false) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } - - $res = $this->_checkQuotaWrite('file', $tmpFile); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_connect(); + $this->_checkQuotaWrite('file', $tmpFile); if (!@ftp_put($this->_stream, $this->_getPath($path, $name), $tmpFile, FTP_BINARY)) { if ($autocreate) { - $result = $this->autocreatePath($path); - if (is_a($result, 'PEAR_Error')) { - return $result; + $this->autocreatePath($path); + if (@ftp_put($this->_stream, $this->_getPath($path, $name), $tmpFile, FTP_BINARY)) { + return; } - if (!@ftp_put($this->_stream, $this->_getPath($path, $name), $tmpFile, FTP_BINARY)) { - return PEAR::raiseError(sprintf(_("Unable to write VFS file \"%s\"."), $this->_getPath($path, $name))); - } - } else { - return PEAR::raiseError(sprintf(_("Unable to write VFS file \"%s\"."), $this->_getPath($path, $name))); } - } - return true; + throw new VFS_Exception(sprintf('Unable to write VFS file "%s".', $this->_getPath($path, $name))); + } } /** @@ -236,23 +221,19 @@ class VFS_ftp extends VFS { * @param string $data The file data. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function writeData($path, $name, $data, $autocreate = false) + public function writeData($path, $name, $data, $autocreate = false) { - $res = $this->_checkQuotaWrite('string', $data); - if (is_a($res, 'PEAR_Error')) { - return $res; + $this->_checkQuotaWrite('string', $data); + file_put_contents(tempnam('null', 'vfs'), $data); + try { + $this->write($path, $name, $tmpFile, $autocreate); + unlink($tmpFile); + } catch (VFS_Exception $e) { + unlink($tmpFile); + throw $e; } - - $tmpFile = $this->_getTempFile(); - $fp = fopen($tmpFile, 'wb'); - fwrite($fp, $data); - fclose($fp); - - $result = $this->write($path, $name, $tmpFile, $autocreate); - unlink($tmpFile); - return $result; } /** @@ -261,25 +242,16 @@ class VFS_ftp extends VFS { * @param string $path The path to delete the file from. * @param string $name The filename to delete. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFile($path, $name) + public function deleteFile($path, $name) { - $res = $this->_checkQuotaDelete($path, $name); - if (is_a($res, 'PEAR_Error')) { - return $res; - } - - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); + $this->_checkQuotaDelete($path, $name); if (!@ftp_delete($this->_stream, $this->_getPath($path, $name))) { - return PEAR::raiseError(sprintf(_("Unable to delete VFS file \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to delete VFS file "%s".', $this->_getPath($path, $name))); } - - return true; } /** @@ -290,22 +262,20 @@ class VFS_ftp extends VFS { * * @return boolean True if it is a folder, false otherwise. */ - function isFolder($path, $name) + public function isFolder($path, $name) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } - $result = false; - $olddir = $this->getCurrentDirectory(); - /* See if we can change to the given path. */ - if (@ftp_chdir($this->_stream, $this->_getPath($path, $name))) { - $result = true; - } + try { + $this->_connect(); - $this->_setPath($olddir); + $olddir = $this->getCurrentDirectory(); + + /* See if we can change to the given path. */ + $result = @ftp_chdir($this->_stream, $this->_getPath($path, $name)); + + $this->_setPath($olddir); + } catch (VFS_Exception $e) {} return $result; } @@ -317,18 +287,14 @@ class VFS_ftp extends VFS { * @param string $name The name of the folder to delete. * @param boolean $recursive Force a recursive delete? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFolder($path, $name, $recursive = false) + public function deleteFolder($path, $name, $recursive = false) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); $isDir = false; - $dirCheck = $this->listFolder($path); - foreach ($dirCheck as $file) { + foreach ($this->listFolder($path) as $file) { if ($file['name'] == $name && $file['type'] == '**dir') { $isDir = true; break; @@ -337,36 +303,24 @@ class VFS_ftp extends VFS { if ($isDir) { $file_list = $this->listFolder($this->_getPath($path, $name)); - if (is_a($file_list, 'PEAR_Error')) { - return $file_list; - } - if (count($file_list) && !$recursive) { - return PEAR::raiseError(sprintf(_("Unable to delete \"%s\", the directory is not empty."), - $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to delete "%s", as the directory is not empty.', $this->_getPath($path, $name))); } foreach ($file_list as $file) { if ($file['type'] == '**dir') { - $result = $this->deleteFolder($this->_getPath($path, $name), $file['name'], $recursive); + $this->deleteFolder($this->_getPath($path, $name), $file['name'], $recursive); } else { - $result = $this->deleteFile($this->_getPath($path, $name), $file['name']); - } - if (is_a($result, 'PEAR_Error')) { - return $result; + $this->deleteFile($this->_getPath($path, $name), $file['name']); } } if (!@ftp_rmdir($this->_stream, $this->_getPath($path, $name))) { - return PEAR::raiseError(sprintf(_("Cannot remove directory \"%s\"."), $this->_getPath($path, $name))); - } - } else { - if (!@ftp_delete($this->_stream, $this->_getPath($path, $name))) { - return PEAR::raiseError(sprintf(_("Cannot delete file \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Cannot remove directory "%s".', $this->_getPath($path, $name))); } + } elseif (!@ftp_delete($this->_stream, $this->_getPath($path, $name))) { + throw new VFS_Exception(sprintf('Cannot delete file "%s".', $this->_getPath($path, $name))); } - - return true; } /** @@ -377,23 +331,16 @@ class VFS_ftp extends VFS { * @param string $newpath The new path of the file. * @param string $newname The new filename. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function rename($oldpath, $oldname, $newpath, $newname) + public function rename($oldpath, $oldname, $newpath, $newname) { - if (is_a($conn = $this->_connect(), 'PEAR_Error')) { - return $conn; - } - - if (is_a($result = $this->autocreatePath($newpath), 'PEAR_Error')) { - return $result; - } + $this->_connect(); + $this->autocreatePath($newpath); if (!@ftp_rename($this->_stream, $this->_getPath($oldpath, $oldname), $this->_getPath($newpath, $newname))) { - return PEAR::raiseError(sprintf(_("Unable to rename VFS file \"%s\"."), $this->_getPath($oldpath, $oldname))); + throw new VFS_Exception(sprintf('Unable to rename VFS file "%s".', $this->_getPath($oldpath, $oldname))); } - - return true; } /** @@ -402,20 +349,15 @@ class VFS_ftp extends VFS { * @param string $path The parent folder. * @param string $name The name of the new folder. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function createFolder($path, $name) + public function createFolder($path, $name) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if (!@ftp_mkdir($this->_stream, $this->_getPath($path, $name))) { - return PEAR::raiseError(sprintf(_("Unable to create VFS directory \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to create VFS directory "%s".', $this->_getPath($path, $name))); } - - return true; } /** @@ -425,20 +367,15 @@ class VFS_ftp extends VFS { * @param string $name The name of the item. * @param string $permission The permission to set. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function changePermissions($path, $name, $permission) + public function changePermissions($path, $name, $permission) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if (!@ftp_site($this->_stream, 'CHMOD ' . $permission . ' ' . $this->_getPath($path, $name))) { - return PEAR::raiseError(sprintf(_("Unable to change permission for VFS file \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to change permission for VFS file "%s".', $this->_getPath($path, $name))); } - - return true; } /** @@ -449,23 +386,19 @@ class VFS_ftp extends VFS { * @param boolean $dotfiles Show dotfiles? * @param boolean $dironly Show only directories? * - * @return array File list on success or PEAR_Error on failure. + * @return array File list. + * @throws VFS_Exception */ - function _listFolder($path = '', $filter = null, $dotfiles = true, - $dironly = false) + protected function _listFolder($path = '', $filter = null, + $dotfiles = true, $dironly = false) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } - - $files = array(); + $this->_connect(); if (empty($this->_type)) { if (!empty($this->_params['type'])) { $this->_type = $this->_params['type']; } else { - $type = VFS::strtolower(@ftp_systype($this->_stream)); + $type = self::strtolower(@ftp_systype($this->_stream)); if ($type == 'unknown') { // Go with unix-style listings by default. $type = 'unix'; @@ -481,10 +414,7 @@ class VFS_ftp extends VFS { $olddir = $this->getCurrentDirectory(); if (strlen($path)) { - $res = $this->_setPath($path); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_setPath($path); } if ($this->_type == 'unix') { @@ -503,25 +433,20 @@ class VFS_ftp extends VFS { if (!is_array($list)) { if (isset($olddir)) { - $res = $this->_setPath($olddir); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_setPath($olddir); } return array(); } /* If 'maplocalids' is set, check for the POSIX extension. */ - $mapids = false; - if (!empty($this->_params['maplocalids']) && - extension_loaded('posix')) { - $mapids = true; - } + $mapids = (!empty($this->_params['maplocalids']) && extension_loaded('posix')); $currtime = time(); + $files = array(); foreach ($list as $line) { $file = array(); + $item = preg_split('/\s+/', $line); if (($this->_type == 'unix') || (($this->_type == 'win') && !preg_match('|\d\d-\d\d-\d\d|', $item[0]))) { @@ -570,16 +495,16 @@ class VFS_ftp extends VFS { $file['type'] = '**sym'; if ($this->isFolder('', $file['link'])) { - $file['linktype'] = '**dir'; - } else { - $parts = explode('/', $file['link']); - $name = explode('.', array_pop($parts)); - if (count($name) == 1 || ($name[0] === '' && count($name) == 2)) { - $file['linktype'] = '**none'; - } else { - $file['linktype'] = VFS::strtolower(array_pop($name)); - } - } + $file['linktype'] = '**dir'; + } else { + $parts = explode('/', $file['link']); + $name = explode('.', array_pop($parts)); + if (count($name) == 1 || ($name[0] === '' && count($name) == 2)) { + $file['linktype'] = '**none'; + } else { + $file['linktype'] = VFS::strtolower(array_pop($name)); + } + } } elseif ($p1 === 'd') { $file['type'] = '**dir'; } else { @@ -587,7 +512,7 @@ class VFS_ftp extends VFS { if (count($name) == 1 || (substr($file['name'], 0, 1) === '.' && count($name) == 2)) { $file['type'] = '**none'; } else { - $file['type'] = VFS::strtolower($name[count($name) - 1]); + $file['type'] = self::strtolower($name[count($name) - 1]); } } if ($file['type'] == '**dir') { @@ -659,7 +584,7 @@ class VFS_ftp extends VFS { if (count($name) == 1 || (substr($file['name'], 0, 1) === '.' && count($name) == 2)) { $file['type'] = '**none'; } else { - $file['type'] = VFS::strtolower($name[count($name) - 1]); + $file['type'] = self::strtolower($name[count($name) - 1]); } } } @@ -679,11 +604,9 @@ class VFS_ftp extends VFS { } if (isset($olddir)) { - $res = $this->_setPath($olddir); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_setPath($olddir); } + return $files; } @@ -695,38 +618,31 @@ class VFS_ftp extends VFS { * @param mixed $filter Hash of items to filter based on folderlist. * @param boolean $dotfolders Include dotfolders? * - * @return mixed Folder list on success or a PEAR_Error object on failure. + * @return array Folder list. + * @throws VFS_Exception */ - function listFolders($path = '', $filter = null, $dotfolders = true) + public function listFolders($path = '', $filter = null, $dotfolders = true) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); - $folders = array(); - $folder = array(); + $folder = array( + 'abbrev' => '..', + 'label' => '..', + 'val' => $this->_parentDir($path) + ); + $folders = array($folder['val'] => $folder); $folderList = $this->listFolder($path, null, $dotfolders, true); - if (is_a($folderList, 'PEAR_Error')) { - return $folderList; - } - - $folder['val'] = $this->_parentDir($path); - $folder['abbrev'] = '..'; - $folder['label'] = '..'; - - $folders[$folder['val']] = $folder; - foreach ($folderList as $files) { - $folder['val'] = $this->_getPath($path, $files['name']); - $folder['abbrev'] = $files['name']; - $folder['label'] = $folder['val']; - - $folders[$folder['val']] = $folder; + $folders[$folder['val']] = array( + 'abbrev' => $files['name'], + 'label' => $folder['val'], + 'val' => $this->_getPath($path, $files['name']) + ); } ksort($folders); + return $folders; } @@ -738,63 +654,46 @@ class VFS_ftp extends VFS { * @param string $dest The name of the destination directory. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function copy($path, $name, $dest, $autocreate = false) + public function copy($path, $name, $dest, $autocreate = false) { $orig = $this->_getPath($path, $name); if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { - return PEAR::raiseError(_("Cannot copy file(s) - source and destination are the same.")); + throw new VFS_Exception('Cannot copy file(s) - source and destination are the same.'); } - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if ($autocreate) { - $result = $this->autocreatePath($dest); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($dest); } - $fileCheck = $this->listFolder($dest, null, true); - if (is_a($fileCheck, 'PEAR_Error')) { - return $fileCheck; - } - foreach ($fileCheck as $file) { + foreach ($this->listFolder($dest, null, true) as $file) { if ($file['name'] == $name) { - return PEAR::raiseError(sprintf(_("%s already exists."), $this->_getPath($dest, $name))); + throw new VFS_Exception(sprintf('%s already exists.'), $this->_getPath($dest, $name)); } } if ($this->isFolder($path, $name)) { - if (is_a($result = $this->_copyRecursive($path, $name, $dest), 'PEAR_Error')) { - return $result; - } + $this->_copyRecursive($path, $name, $dest); } else { - $tmpFile = $this->_getTempFile(); + $tmpFile = tempnam(null, 'vfs'); $fetch = @ftp_get($this->_stream, $tmpFile, $orig, FTP_BINARY); if (!$fetch) { unlink($tmpFile); - return PEAR::raiseError(sprintf(_("Failed to copy from \"%s\"."), $orig)); + throw new VFS_Exception(sprintf('Failed to copy from "%s".', $orig)); } - $res = $this->_checkQuotaWrite('file', $tmpFile); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_checkQuotaWrite('file', $tmpFile); if (!@ftp_put($this->_stream, $this->_getPath($dest, $name), $tmpFile, FTP_BINARY)) { unlink($tmpFile); - return PEAR::raiseError(sprintf(_("Failed to copy to \"%s\"."), $this->_getPath($dest, $name))); + throw new VFS_Exception(sprintf('Failed to copy to "%s".', $this->_getPath($dest, $name))); } unlink($tmpFile); } - - return true; } /** @@ -805,90 +704,69 @@ class VFS_ftp extends VFS { * @param string $dest The destination file name. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function move($path, $name, $dest, $autocreate = false) + public function move($path, $name, $dest, $autocreate = false) { $orig = $this->_getPath($path, $name); if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { - return PEAR::raiseError(_("Cannot move file(s) - destination is within source.")); + throw new VFS_Exception('Cannot move file(s) - destination is within source.'); } - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if ($autocreate) { - $result = $this->autocreatePath($dest); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($dest); } - $fileCheck = $this->listFolder($dest, null, true); - if (is_a($fileCheck, 'PEAR_Error')) { - return $fileCheck; - } - foreach ($fileCheck as $file) { + foreach ($this->listFolder($dest, null, true) as $file) { if ($file['name'] == $name) { - return PEAR::raiseError(sprintf(_("%s already exists."), $this->_getPath($dest, $name))); + throw new VFS_Exception(sprintf('%s already exists.', $this->_getPath($dest, $name))); } } if (!@ftp_rename($this->_stream, $orig, $this->_getPath($dest, $name))) { - return PEAR::raiseError(sprintf(_("Failed to move to \"%s\"."), $this->_getPath($dest, $name))); + throw new VFS_Exception(sprintf('Failed to move to "%s".', $this->_getPath($dest, $name))); } - - return true; } /** * Returns the current working directory on the FTP server. * * @return string The current working directory. + * @throws VFS_Exception */ - function getCurrentDirectory() + public function getCurrentDirectory() { - if (is_a($connected = $this->_connect(), 'PEAR_Error')) { - return $connected; - } + $this->_connect(); return @ftp_pwd($this->_stream); } /** * Changes the current directory on the server. * - * @access private - * * @param string $path The path to change to. * - * @return mixed True on success, or a PEAR_Error on failure. + * @throws VFS_Exception */ - function _setPath($path) + protected function _setPath($path) { if (!@ftp_chdir($this->_stream, $path)) { - return PEAR::raiseError(sprintf(_("Unable to change to %s."), $path)); + throw new VFS_Exception(sprintf('Unable to change to %s.', $path)); } - return true; } /** * Returns the parent directory of the specified path. * - * @access private - * * @param string $path The path to get the parent of. * - * @return string The parent directory (string) on success or a PEAR_Error - * object on failure. + * @return string The parent directory. + * @throws VFS_Exception */ - function _parentDir($path) + protected function _parentDir($path) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); $olddir = $this->getCurrentDirectory(); @ftp_cdup($this->_stream); @@ -897,7 +775,7 @@ class VFS_ftp extends VFS { $this->_setPath($olddir); if (!$parent) { - return PEAR::raiseError(_("Unable to determine current directory.")); + throw new VFS_Exception('Unable to determine current directory.'); } return $parent; @@ -906,59 +784,57 @@ class VFS_ftp extends VFS { /** * Attempts to open a connection to the FTP server. * - * @access private - * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function _connect() + protected function _connect() { - if ($this->_stream === false) { - if (!extension_loaded('ftp')) { - return PEAR::raiseError(_("The FTP extension is not available.")); - } + if ($this->_stream !== false) { + return; + } - if (!is_array($this->_params)) { - return PEAR::raiseError(_("No configuration information specified for FTP VFS.")); - } + if (!extension_loaded('ftp')) { + throw new VFS_Exception('The FTP extension is not available.'); + } - $required = array('hostspec', 'username', 'password'); - foreach ($required as $val) { - if (!isset($this->_params[$val])) { - return PEAR::raiseError(sprintf(_("Required \"%s\" not specified in VFS configuration."), $val)); - } + if (!is_array($this->_params)) { + throw new VFS_Exception('No configuration information specified for FTP VFS.'); + } + + $required = array('hostspec', 'username', 'password'); + foreach ($required as $val) { + if (!isset($this->_params[$val])) { + throw new VFS_Exception(sprintf('Required "%s" not specified in VFS configuration.', $val)); } + } - /* Connect to the ftp server using the supplied parameters. */ - if (!empty($this->_params['ssl'])) { - if (function_exists('ftp_ssl_connect')) { - $this->_stream = @ftp_ssl_connect($this->_params['hostspec'], $this->_params['port']); - } else { - return PEAR::raiseError(_("Unable to connect with SSL.")); - } + /* Connect to the ftp server using the supplied parameters. */ + if (!empty($this->_params['ssl'])) { + if (function_exists('ftp_ssl_connect')) { + $this->_stream = @ftp_ssl_connect($this->_params['hostspec'], $this->_params['port']); } else { - $this->_stream = @ftp_connect($this->_params['hostspec'], $this->_params['port']); - } - if (!$this->_stream) { - return PEAR::raiseError(_("Connection to FTP server failed.")); + throw new VFS_Exception('Unable to connect with SSL.'); } + } else { + $this->_stream = @ftp_connect($this->_params['hostspec'], $this->_params['port']); + } - $connected = @ftp_login($this->_stream, $this->_params['username'], $this->_params['password']); - if (!$connected) { - @ftp_quit($this->_stream); - $this->_stream = false; - return PEAR::raiseError(_("Authentication to FTP server failed.")); - } + if (!$this->_stream) { + throw new VFS_Exception('Connection to FTP server failed.'); + } - if (!empty($this->_params['pasv'])) { - @ftp_pasv($this->_stream, true); - } + if (!@ftp_login($this->_stream, $this->_params['username'], $this->_params['password'])) { + @ftp_quit($this->_stream); + $this->_stream = false; + throw new VFS_Exception('Authentication to FTP server failed.'); + } - if (!empty($this->_params['timeout'])) { - ftp_set_option($this->_stream, FTP_TIMEOUT_SEC, $this->_params['timeout']); - } + if (!empty($this->_params['pasv'])) { + @ftp_pasv($this->_stream, true); } - return true; + if (!empty($this->_params['timeout'])) { + ftp_set_option($this->_stream, FTP_TIMEOUT_SEC, $this->_params['timeout']); + } } } diff --git a/framework/VFS/lib/VFS/horde.php b/framework/VFS/lib/VFS/horde.php index 487d0814d..afef8890f 100644 --- a/framework/VFS/lib/VFS/horde.php +++ b/framework/VFS/lib/VFS/horde.php @@ -17,26 +17,27 @@ * @author Jan Schneider * @package VFS */ -class VFS_horde extends VFS { - +class VFS_horde extends VFS +{ /** * Reference to a Horde Registry instance. * - * @var Registry + * @var Horde_Registry */ - var $_registry; + protected $_registry; /** * Constructor. * * @param array $params A hash containing connection parameters. + * @throws VFS_Exception */ - function VFS_horde($params = array()) + public function __construct($params = array()) { - parent::VFS($params); + parent::__construct($params); + if (!isset($this->_params['horde_base'])) { - $this->_registry = PEAR::raiseError(sprintf(_("Required \"%s\" not specified in VFS configuration."), 'horde_base')); - return; + throw new VFS_Exception('Required "horde_base" not specified in VFS configuration.'); } require_once $this->_params['horde_base'] . '/lib/Application.php'; @@ -46,41 +47,25 @@ class VFS_horde extends VFS { $this->_registry = $GLOBALS['registry']; } - function _connect() + /** + */ + protected function _connect() { if (!empty($this->_params['user']) && !empty($this->_params['password'])) { - Horde_Auth::setAuth($this->_params['user'], - array('password' => $this->_params['password'])); + Horde_Auth::setAuth($this->_params['user'], array('password' => $this->_params['password'])); } } /** - * Retrieves the size of a file from the VFS. - * - * @abstract - * - * @param string $path The pathname to the file. - * @param string $name The filename to retrieve. - * - * @return integer The file size. - */ - function size($path, $name) - { - return PEAR::raiseError(_("Not supported.")); - } - - /** * Retrieves a file from the VFS. * - * @abstract - * * @param string $path The pathname to the file. * @param string $name The filename to retrieve. * - * @return string The file data. + * @return string The file data. */ - function read($path, $name) + public function read($path, $name) { if (substr($path, 0, 1) == '/') { $path = substr($path, 1); @@ -97,125 +82,27 @@ class VFS_horde extends VFS { } /** - * Stores a file in the VFS. - * - * @abstract - * - * @param string $path The path to store the file in. - * @param string $name The filename to use. - * @param string $tmpFile The temporary file containing the data to - * be stored. - * @param boolean $autocreate Automatically create directories? - * - * @return mixed True on success or a PEAR_Error object on failure. - */ - function write($path, $name, $tmpFile, $autocreate = false) - { - return PEAR::raiseError(_("Not supported.")); - } - - /** - * Stores a file in the VFS from raw data. - * - * @abstract - * - * @param string $path The path to store the file in. - * @param string $name The filename to use. - * @param string $data The file data. - * @param boolean $autocreate Automatically create directories? - * - * @return mixed True on success or a PEAR_Error object on failure. - */ - function writeData($path, $name, $data, $autocreate = false) - { - return PEAR::raiseError(_("Not supported.")); - } - - /** - * Moves a file through the backend. - * - * @abstract - * - * @param string $path The path of the original file. - * @param string $name The name of the original file. - * @param string $dest The destination file name. - * - * @return mixed True on success or a PEAR_Error object on failure. - */ - function move($path, $name, $dest) - { - return PEAR::raiseError(_("Not supported.")); - } - - /** - * Copies a file through the backend. - * - * @abstract - * - * @param string $path The path of the original file. - * @param string $name The name of the original file. - * @param string $dest The name of the destination directory. - * - * @return mixed True on success or a PEAR_Error object on failure. - */ - function copy($path, $name, $dest) - { - return PEAR::raiseError(_("Not supported.")); - } - - /** - * Deletes a file from the VFS. - * - * @abstract - * - * @param string $path The path to delete the file from. - * @param string $name The filename to delete. - * - * @return mixed True on success or a PEAR_Error object on failure. - */ - function deleteFile($path, $name) - { - return PEAR::raiseError(_("Not supported.")); - } - - /** - * Renames a file in the VFS. - * - * @abstract - * - * @param string $oldpath The old path to the file. - * @param string $oldname The old filename. - * @param string $newpath The new path of the file. - * @param string $newname The new filename. - * - * @return mixed True on success or a PEAR_Error object on failure. - */ - function rename($oldpath, $oldname, $newpath, $newname) - { - return PEAR::raiseError(_("Not supported.")); - } - - /** * Returns an an unsorted file list of the specified directory. * - * @abstract - * * @param string $path The path of the directory. * @param mixed $filter String/hash to filter file/dirname on. * @param boolean $dotfiles Show dotfiles? * @param boolean $dironly Show only directories? * - * @return array File list on success or PEAR_Error on failure. + * @return array File list. + * @throws VFS_Exception */ - function _listFolder($path, $filter = null, $dotfiles = true, - $dironly = false) + protected function _listFolder($path, $filter = null, $dotfiles = true, + $dironly = false) { $list = array(); if ($path == '/') { - $apps = $this->_registry->listApps(null, false, Horde_Perms::READ); - if (is_a($apps, 'PEAR_Error')) { - return $apps; + try { + $apps = $this->_registry->listApps(null, false, Horde_Perms::READ); + } catch (Horde_Exception $e) { + throw new VFS_Exception($e->getMessage()); } + foreach ($apps as $app) { if ($this->_registry->hasMethod('browse', $app)) { $file = array( @@ -239,15 +126,16 @@ class VFS_horde extends VFS { try { $items = $this->_registry->callByPackage($pieces[0], 'browse', array('path' => $path, 'properties' => array('name', 'browseable', 'contenttype', 'contentlength', 'modified'))); } catch (Horde_Exception $e) { - return PEAR::raiserError($e->getMessage(), $e->getCode()); + throw new VFS_Exception($e->getMessage()); } if (!is_array(reset($items))) { /* We return an object's content. */ - return PEAR::raiseError(_("unknown error")); + throw new VFS_Exception('Unknown error'); } - include_once 'Horde/MIME/Magic.php'; + @include_once 'Horde/Mime/Magic.php'; + foreach ($items as $sub_path => $i) { if ($dironly && !$i['browseable']) { continue; @@ -258,12 +146,9 @@ class VFS_horde extends VFS { continue; } - if (class_exists('MIME_Magic')) { - $type = empty($i['contenttype']) ? 'application/octet-stream' : $i['contenttype']; - $type = MIME_Magic::MIMEToExt($type); - } else { - $type = '**none'; - } + $type = class_exists('Horde_Mime_Magic') + ? Horde_Mime_Magic::mimeToExt(empty($i['contenttype']) ? 'application/octet-stream' : $i['contenttype']) + : '**none'; $file = array( //'name' => $i['name'], @@ -278,21 +163,4 @@ class VFS_horde extends VFS { return $list; } - /** - * Returns a sorted list of folders in the specified directory. - * - * @abstract - * - * @param string $path The path of the directory to get the - * directory list for. - * @param mixed $filter Hash of items to filter based on folderlist. - * @param boolean $dotfolders Include dotfolders? - * - * @return mixed Folder list on success or a PEAR_Error object on failure. - */ - function listFolders($path = '', $filter = null, $dotfolders = true) - { - return PEAR::raiseError(_("Not supported.")); - } - } diff --git a/framework/VFS/lib/VFS/kolab.php b/framework/VFS/lib/VFS/kolab.php index 7df4840b5..ad3d99592 100644 --- a/framework/VFS/lib/VFS/kolab.php +++ b/framework/VFS/lib/VFS/kolab.php @@ -14,21 +14,21 @@ require_once 'Horde/Kolab/Storage/List.php'; * @author Gunnar Wrobel * @package VFS */ -class VFS_kolab extends VFS { - +class VFS_kolab extends VFS +{ /** * Variable holding the connection to the Kolab storage system. * * @var Horde_Kolab_IMAP */ - var $_imap = false; + protected $_imap = false; /** * Cache for the list of folders. * * @var array */ - var $_folders; + protected $_folders; /** * Retrieves a file from the VFS. @@ -37,15 +37,13 @@ class VFS_kolab extends VFS { * @param string $name The filename to retrieve. * * @return string The file data. + * @throws VFS_Exception */ - function read($path, $name) + public function read($path, $name) { list($app, $uid) = $this->_getAppUid($path); if ($app && $uid) { - $handler = &$this->_getAppHandler($app, $uid); - if (is_a($handler, 'PEAR_Error')) { - return $handler; - } + $handler = $this->_getAppHandler($app, $uid); $object = $handler->getObject($uid); if (isset($object['_attachments'][$name])) { @@ -55,18 +53,19 @@ class VFS_kolab extends VFS { //FIXME if ($this->isFolder(dirname($path), basename($path))) { - $session = &Horde_Kolab_Session::singleton(); - $imap = &$session->getImap(); + $session = Horde_Kolab_Session::singleton(); + $imap = $session->getImap(); $result = $imap->select(substr($path,1)); - if (is_a($result, 'PEAR_Error')) { - return $result; + if ($result instanceof PEAR_Error) { + throw new VFS_Exception($result->getMessage()); } $file = explode('/', $name); return $this->_getFile($imap, $file[0], $file[1]); } + return ''; } @@ -79,16 +78,13 @@ class VFS_kolab extends VFS { * be stored. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function write($path, $name, $tmpFile, $autocreate = false) + public function write($path, $name, $tmpFile, $autocreate = false) { list($app, $uid) = $this->_getAppUid($path); if ($app) { - $handler = &$this->_getAppHandler($app, $uid); - if (is_a($handler, 'PEAR_Error')) { - return $handler; - } + $handler = $this->_getAppHandler($app, $uid); $object = $handler->getObject($uid); $object['_attachments'][$name]['path'] = $tmpFile; if (empty($object['link-attachment'])) { @@ -101,37 +97,29 @@ class VFS_kolab extends VFS { } if ($autocreate && !$this->isFolder(dirname($path), basename($path))) { - $result = $this->autocreatePath($path); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($path); } //FIXME - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** * Deletes a file from the VFS. * - * @abstract - * * @param string $path The path to delete the file from. * @param string $name The filename to delete. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFile($path, $name) + public function deleteFile($path, $name) { list($app, $uid) = $this->_getAppUid($path); if ($app) { - $handler = &$this->_getAppHandler($app, $uid); - if (is_a($handler, 'PEAR_Error')) { - return $handler; - } + $handler = $this->_getAppHandler($app, $uid); $object = $handler->getObject($uid); if (!isset($object['_attachments'][$name])) { - return PEAR::raiseError(_("Unable to delete VFS file.")); + throw new VFS_Exception('Unable to delete VFS file.'); } unset($object['_attachments'][$name]); $object['link-attachment'] = array_values(array_diff($object['link-attachment'], array($name))); @@ -140,7 +128,7 @@ class VFS_kolab extends VFS { } //FIXME - return PEAR::raiseError(_("Not supported.")); + throw new VFS_Exception('Not supported.'); } /** @@ -149,9 +137,9 @@ class VFS_kolab extends VFS { * @param string $path The parent folder. * @param string $name The name of the new folder. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function createFolder($path, $name) + public function createFolder($path, $name) { $list = Kolab_List::singleton(); $folder = $this->_getFolder($path, $name); @@ -159,9 +147,9 @@ class VFS_kolab extends VFS { $object = $list->getNewFolder(); $object->setName($folder); - $result = $object->save(array('type' => 'h-file')); - if (is_a($result, 'PEAR_Error')) { - return $result; + $object->save(array('type' => 'h-file')); + if ($result instanceof PEAR_Error) { + throw new VFS_Exception($result->getMessage()); } $this->_folders = null; @@ -174,23 +162,16 @@ class VFS_kolab extends VFS { * @param string $name The name of the folder to delete. * @param boolean $recursive Force a recursive delete? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFolder($path, $name, $recursive = false) + public function deleteFolder($path, $name, $recursive = false) { if ($recursive) { - $result = $this->emptyFolder($path . '/' . $name); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->emptyFolder($path . '/' . $name); } else { $list = $this->listFolder($path . '/' . $name, null, false); - if (is_a($list, 'PEAR_Error')) { - return $list; - } if (count($list)) { - return PEAR::raiseError(sprintf(_("Unable to delete %s, the directory is not empty"), - $path . '/' . $name)); + throw new VFS_Exception(sprintf('Unable to delete %s, the directory is not empty', $path . '/' . $name)); } } @@ -199,26 +180,19 @@ class VFS_kolab extends VFS { /** * Objects provide no real folders and we don't delete them. */ - return true; + return; } $folders = $this->_getFolders(); - if (is_a($folders, 'PEAR_Error')) { - return $folders; - } $folder = $this->_getFolder($path, $name); if (!empty($folders['/' . $folder])) { - $result = $folders['/' . $folder]->delete(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - + $folders['/' . $folder]->delete(); $this->_folders = null; - - return true; + return; } - return PEAR::raiseError(sprintf('No such folder %s!', '/' . $folder)); + + throw new VFS_Exception(sprintf('No such folder %s!', '/' . $folder)); } /** @@ -227,34 +201,21 @@ class VFS_kolab extends VFS { * * @param string $path The path of the folder to empty. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function emptyFolder($path) + public function emptyFolder($path) { // Get and delete the subfolders. $list = $this->listFolder($path, null, false, true); - if (is_a($list, 'PEAR_Error')) { - return $list; - } foreach ($list as $folder) { - $result = $this->deleteFolder($path, $folder['name'], true); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->deleteFolder($path, $folder['name'], true); } + // Only files are left, get and delete them. $list = $this->listFolder($path, null, false); - if (is_a($list, 'PEAR_Error')) { - return $list; - } foreach ($list as $file) { - $result = $this->deleteFile($path, $file['name']); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->deleteFile($path, $file['name']); } - - return true; } /** @@ -265,45 +226,44 @@ class VFS_kolab extends VFS { * @param boolean $dotfiles Show dotfiles? * @param boolean $dironly Show only directories? * - * @return array File list on success or PEAR_Error on failure. + * @return array File list. + * @throws VFS_Exception */ - function _listFolder($path = '', $filter = null, $dotfiles = true, - $dironly = false) + protected function _listFolder($path = '', $filter = null, $dotfiles = true, + $dironly = false) { list($app, $uid) = $this->_getAppUid($path); if ($app) { if ($dironly) { - /** + /** * Objects dont support directories. */ return array(); } if ($uid) { - $handler = &$this->_getAppHandler($app, $uid); - if (is_a($handler, 'PEAR_Error')) { - return $handler; - } + $handler = $this->_getAppHandler($app, $uid); $object = $handler->getObject($uid); - if (is_a($object, 'PEAR_Error')) { - return $object; + if ($object instanceof PEAR_Error) { + throw new VFS_Exception($object->getMessage()); } - $filenames = isset($object['_attachments']) ? array_keys($object['_attachments']) : array(); + $filenames = isset($object['_attachments']) + ? array_keys($object['_attachments']) + : array(); } else { $filenames = $this->_getAppUids($app); } $owner = Horde_Auth::getAuth(); - $files = array(); - $file = array(); - foreach($filenames as $filename) { + $file = $files = array(); + foreach ($filenames as $filename) { $name = explode('.', $filename); if (count($name) == 1) { $file['type'] = '**none'; } else { - $file['type'] = VFS::strtolower($name[count($name) - 1]); + $file['type'] = self::strtolower($name[count($name) - 1]); } $file['size'] = '-1'; @@ -315,21 +275,17 @@ class VFS_kolab extends VFS { $files[$file['name']] = $file; } + return $files; } $owner = Horde_Auth::getAuth(); - $files = array(); + $file = $files = array(); $folders = $this->listFolders($path, $filter, $dotfiles); - if (is_a($folders, 'PEAR_Error')) { - return $folders; - } - $list = $this->_getFolders(); - $file = array(); foreach ($folders as $folder) { $file['type'] = '**dir'; $file['size'] = -1; @@ -346,29 +302,24 @@ class VFS_kolab extends VFS { $files[$file['name']] = $file; } - if (!$dironly - && $this->isFolder(basename($path), basename($path)) - && !empty($list[$path])) { - - $session = &Horde_Kolab_Session::singleton(); - $imap = &$session->getImap(); + if (!$dironly && + $this->isFolder(basename($path), basename($path)) && + !empty($list[$path])) { + $session = Horde_Kolab_Session::singleton(); + $imap = $session->getImap(); $result = $imap->select(substr($path, 1)); - if (is_a($result, 'PEAR_Error')) { - return $result; + if ($result instanceof PEAR_Error) { + throw new VFS_Exception($result->getMessage()); } $uids = $imap->getUids(); - if (is_a($uids, 'PEAR_Error')) { - return $uids; + if ($uids instanceof PEAR_Error) { + throw new VFS_Exception($uids->getMessage()); } foreach ($uids as $uid) { - $mFiles = $this->_parseMessage($imap, $uid); - if (is_a($mFiles, 'PEAR_Error')) { - return $mFiles; - } - $result = array_merge($files, $mFiles); + $result = array_merge($files, $this->_parseMessage($imap, $uid)); $files = $result; } } @@ -376,29 +327,30 @@ class VFS_kolab extends VFS { return $files; } - function _parseMessage($imap, $uid) + /** + */ + protected function _parseMessage($imap, $uid) { $result = $imap->getMessageHeader($uid); - if (is_a($result, 'PEAR_Error')) { - return $result; + if ($result instanceof PEAR_Error) { + throw new VFS_Exception($result->getMessage()); } $raw_headers = $result; $body = $imap->getMessageBody($uid); - if (is_a($body, 'PEAR_Error')) { - return $body; + if ($body instanceof PEAR_Error) { + throw new VFS_Exception($body->getMessage()); } $raw_message = $raw_headers . $body; - $mime_message = &MIME_Structure::parseTextMIMEMessage($raw_message); + $mime_message = Horde_Mime_Part::parseMessage($raw_message); $parts = $mime_message->contentTypeMap(); $owner = Horde_Auth::getAuth(); - $files = array(); - $file = array(); + $file = $files = array(); foreach ($parts as $part_id => $disposition) { $part = $mime_message->getPart($part_id); @@ -426,44 +378,41 @@ class VFS_kolab extends VFS { return $files; } - - function _getFile($imap, $uid, $filename) + /** + */ + protected function _getFile($imap, $uid, $filename) { $result = $imap->getMessageHeader($uid); - if (is_a($result, 'PEAR_Error')) { - return $result; + if ($result instanceof PEAR_Error) { + throw new VFS_Exception($result->getMessage()); } $raw_headers = $result; $body = $imap->getMessageBody($uid); - if (is_a($body, 'PEAR_Error')) { - return $body; + if ($body instanceof PEAR_Error) { + throw new VFS_Exception($body->getMessage()); } $raw_message = $raw_headers . $body; - $mime_message = &MIME_Structure::parseTextMIMEMessage($raw_message); + $mime_message = Horde_Mime_Part::parseMessage($raw_message); $parts = $mime_message->contentTypeMap(); $owner = Horde_Auth::getAuth(); - $files = array(); - $file = array(); - foreach ($parts as $part_id => $disposition) { $part = $mime_message->getPart($part_id); - $f= $part->getDispositionParameter('filename'); - - if ($f && $f == $filename ) { + $f = $part->getDispositionParameter('filename'); + if ($f && $f == $filename) { return $part->transferDecode(); } } + return ''; } - /** * Returns a sorted list of folders in the specified directory. * @@ -472,16 +421,16 @@ class VFS_kolab extends VFS { * @param mixed $filter Hash of items to filter based on folderlist. * @param boolean $dotfolders Include dotfolders? * - * @return mixed Folder list on success or a PEAR_Error object on failure. + * @return array Folder list. + * @throws VFS_Exception */ - function listFolders($path = '', $filter = null, $dotfolders = true) + public function listFolders($path = '', $filter = null, $dotfolders = true) { if (substr($path, -1) != '/') { $path .= '/'; } - $aFolders = array(); - $aFolder = array(); + $aFolder = $aFolders = array(); if ($dotfolders && $path != '/') { $aFolder['val'] = dirname($path); @@ -510,7 +459,9 @@ class VFS_kolab extends VFS { return $aFolders; } - function _getFolder($path, $name) + /** + */ + protected function _getFolder($path, $name) { $folder = $path . '/' . $name; @@ -525,11 +476,11 @@ class VFS_kolab extends VFS { return $folder; } - - function _getFolders() + /** + */ + protected function _getFolders() { if (!isset($this->_folders)) { - $vfs_folders = array(); $list = Kolab_List::singleton(); @@ -540,8 +491,8 @@ class VFS_kolab extends VFS { $folders = $list->getByType('h-file'); } - if (is_a($folders, 'PEAR_Error')) { - return $folders; + if ($folders instanceof PEAR_Error) { + throw new VFS_Exception($folders->getMessage()); } foreach ($folders as $folder) { @@ -559,19 +510,25 @@ class VFS_kolab extends VFS { } $this->_folders = $vfs_folders; } + return $this->_folders; } - function _getAppUid($path) + /** + */ + protected function _getAppUid($path) { - if (defined('TURBA_VFS_PATH') - && substr($path, 0, strlen(TURBA_VFS_PATH)) == TURBA_VFS_PATH) { + if (defined('TURBA_VFS_PATH') && + substr($path, 0, strlen(TURBA_VFS_PATH)) == TURBA_VFS_PATH) { return array('turba', substr($path, strlen(TURBA_VFS_PATH) + 1)); } + return array(false, false); } - function &_getAppHandler($app, $uid) + /** + */ + protected function _getAppHandler($app, $uid) { global $registry; @@ -588,18 +545,20 @@ class VFS_kolab extends VFS { 'sources' => array_keys($sources), 'fields' => $fields)); if (!isset($result[$uid])) { - return PEAR::raiseError('No such contact!'); + throw new VFS_Exception('No such contact!'); } $list = Kolab_List::singleton(); - $share = &$list->getByShare($result[$uid][0]['source'], 'contact'); - if (is_a($share, 'PEAR_Error')) { - return $share; + $share = $list->getByShare($result[$uid][0]['source'], 'contact'); + if ($share instanceof PEAR_Error) { + throw new VFS_Exception($share->getMessage()); } return $share->getData(); } } - function _getAppUids($app) + /** + */ + protected function _getAppUids($app) { global $registry; @@ -621,14 +580,4 @@ class VFS_kolab extends VFS { } } - /** - * Connecting is not required for this driver. - * - * @access private - * - * @return NULL - */ - function _connect() - { - } } diff --git a/framework/VFS/lib/VFS/musql.php b/framework/VFS/lib/VFS/musql.php index efa59ea70..8df5d260d 100644 --- a/framework/VFS/lib/VFS/musql.php +++ b/framework/VFS/lib/VFS/musql.php @@ -3,16 +3,6 @@ require_once dirname(__FILE__) . '/sql.php'; /** - * Permission for read access. - */ -define('VFS_FLAG_READ', 1); - -/** - * Permission for read access. - */ -define('VFS_FLAG_WRITE', 2); - -/** * Multi User VFS implementation for PHP's PEAR database * abstraction layer. * @@ -64,17 +54,35 @@ define('VFS_FLAG_WRITE', 2); * @author Mike Cochrane * @package VFS */ -class VFS_musql extends VFS_sql { +class VFS_musql extends VFS_sql +{ + /* Permission for read access. */ + const FLAG_READ = 1; + + /* Permission for read access. */ + const FLAG_WRITE = 2; /** * List of permissions and if they can be changed in this VFS * * @var array */ - var $_permissions = array( - 'owner' => array('read' => false, 'write' => false, 'execute' => false), - 'group' => array('read' => false, 'write' => false, 'execute' => false), - 'all' => array('read' => true, 'write' => true, 'execute' => false) + protected $_permissions = array( + 'owner' => array( + 'read' => false, + 'write' => false, + 'execute' => false + ), + 'group' => array( + 'read' => false, + 'write' => false, + 'execute' => false + ), + 'all' => array( + 'read' => true, + 'write' => true, + 'execute' => false + ) ); /** @@ -85,14 +93,11 @@ class VFS_musql extends VFS_sql { * @param string $data The file data. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function writeData($path, $name, $data, $autocreate = false) + public function writeData($path, $name, $data, $autocreate = false) { - $conn = $this->_connect(); - if (PEAR::isError($conn)) { - return $conn; - } + $this->_connect(); /* Make sure we have write access to this and all parent paths. */ if ($path != '') { @@ -100,14 +105,9 @@ class VFS_musql extends VFS_sql { $path_name = array_pop($paths); if (!$this->isFolder(implode('/', $paths), $path_name)) { if (!$autocreate) { - return PEAR::raiseError( - sprintf(_("Folder \"%s\" does not exist"), $path), - 'horde.error'); + throw new VFS_Exception(sprintf('Folder "%s" does not exist'), $path); } else { - $result = $this->autocreatePath($path); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($path); } } $paths[] = $path_name; @@ -119,25 +119,25 @@ class VFS_musql extends VFS_sql { $this->_params['table']); $this->log($sql, PEAR_LOG_DEBUG); $results = $this->_db->getAll($sql, array($previous, $thispath)); - if (is_a($results, 'PEAR_Error')) { + if ($results instanceof PEAR_Error) { $this->log($results, PEAR_LOG_ERR); - return $results; + throw new VFS_Exception($results->getMessage()); } if (!is_array($results) || count($results) < 1) { - return PEAR::raiseError(_("Unable to create VFS file.")); + throw new VFS_Exception('Unable to create VFS file.'); } $allowed = false; foreach ($results as $result) { if ($result[0] == $this->_params['user'] || - $result[1] & VFS_FLAG_WRITE) { + $result[1] & self::FLAG_WRITE) { $allowed = true; break; } } if (!$allowed) { - return PEAR::raiseError(_("Access denied creating VFS file.")); + throw new VFS_Exception('Access denied creating VFS file.'); } $previous = $thispath; @@ -153,27 +153,24 @@ class VFS_musql extends VFS_sql { * @param string $path The path to store the file in. * @param string $name The filename to use. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFile($path, $name) + public function deleteFile($path, $name) { - $conn = $this->_connect(); - if (PEAR::isError($conn)) { - return $conn; - } + $this->_connect(); $sql = sprintf('SELECT vfs_id, vfs_owner, vfs_perms FROM %s WHERE vfs_path = ? AND vfs_name= ? AND vfs_type = ?', $this->_params['table']); $this->log($sql, PEAR_LOG_DEBUG); - $fileList = $this->_db->getAll($sql, array($path, $name, VFS_FILE)); + $fileList = $this->_db->getAll($sql, array($path, $name, self::FILE)); - if (is_a($fileList, 'PEAR_Error')) { + if ($fileList instanceof PEAR_Error) { $this->log($fileList, PEAR_LOG_ERR); - return $fileList; + throw new VFS_Exception($fileList->getMessage()); } if (!is_array($fileList) || count($fileList) < 1) { - return PEAR::raiseError(_("Unable to delete VFS file.")); + throw new VFS_Exception('Unable to delete VFS file.'); } /* There may be one or more files with the same name but the user may @@ -181,25 +178,25 @@ class VFS_musql extends VFS_sql { * delete the one they have access to. */ foreach ($fileList as $file) { if ($file[1] == $this->_params['user'] || - $file[2] & VFS_FLAG_WRITE) { + $file[2] & self::FLAG_WRITE) { $sql = sprintf('DELETE FROM %s WHERE vfs_id = ?', $this->_params['table']); $this->log($sql, PEAR_LOG_DEBUG); $result = $this->_db->query($sql, array($file[0])); - if (is_a($result, 'PEAR_Error')) { + if ($result instanceof PEAR_Error) { $this->log($result, PEAR_LOG_ERR); - return $result; + throw new VFS_Exception($result->getMessage()); } if ($this->_db->affectedRows() == 0) { - return PEAR::raiseError(_("Unable to delete VFS file.")); + throw new VFS_Exception('Unable to delete VFS file.'); } return $result; } } // FIXME: 'Access Denied deleting file %s/%s' - return PEAR::raiseError(_("Unable to delete VFS file.")); + throw new VFS_Exception('Unable to delete VFS file.'); } /** @@ -210,14 +207,11 @@ class VFS_musql extends VFS_sql { * @param string $newpath The new path of the file. * @param string $newname The new filename. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function rename($oldpath, $oldname, $newpath, $newname) + public function rename($oldpath, $oldname, $newpath, $newname) { - $conn = $this->_connect(); - if (PEAR::isError($conn)) { - return $conn; - } + $this->_connect(); $sql = sprintf('SELECT vfs_id, vfs_owner, vfs_perms FROM %s WHERE vfs_path = ? AND vfs_name= ?', @@ -225,12 +219,12 @@ class VFS_musql extends VFS_sql { $this->log($sql, PEAR_LOG_DEBUG); $fileList = $this->_db->getAll($sql, array($oldpath, $oldname)); - if (is_a($fileList, 'PEAR_Error')) { + if ($fileList instanceof PEAR_Error) { $this->log($fileList, PEAR_LOG_ERR); - return $fileList; + throw new VFS_Exception($fileList); } if (!is_array($fileList) || count($fileList) < 1) { - return PEAR::raiseError(_("Unable to rename VFS file.")); + throw new VFS_Exception('Unable to rename VFS file.'); } if (strpos($newpath, '/') === false) { @@ -240,9 +234,7 @@ class VFS_musql extends VFS_sql { list($parent, $path) = explode('/', $newpath, 2); } if (!$this->isFolder($parent, $path)) { - if (is_a($result = $this->autocreatePath($newpath), 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($newpath); } /* There may be one or more files with the same name but the user may @@ -250,7 +242,7 @@ class VFS_musql extends VFS_sql { * rename the one they have access to. */ foreach ($fileList as $file) { if ($file[1] == $this->_params['user'] || - $file[2] & VFS_FLAG_WRITE) { + $file[2] & self::FLAG_WRITE) { $sql = sprintf('UPDATE %s SET vfs_path = ?, vfs_name = ?, vfs_modified = ? WHERE vfs_id = ?', $this->_params['table']); @@ -258,16 +250,15 @@ class VFS_musql extends VFS_sql { $result = $this->_db->query( $sql, array($newpath, $newname, time(), $file[0])); - if (is_a($result, 'PEAR_Error')) { + if ($result instanceof PEAR_Error) { $this->log($result, PEAR_LOG_ERR); - return $result; + throw new VFS_Exception($result->getMessage()); } return $result; } } - return PEAR::raiseError(sprintf(_("Unable to rename VFS file %s/%s."), - $oldpath, $oldname)); + throw new VFS_Exception(sprintf('Unable to rename VFS file %s/%s.', $oldpath, $oldname)); } /** @@ -276,14 +267,11 @@ class VFS_musql extends VFS_sql { * @param string $path Holds the path of directory to create folder. * @param string $name Holds the name of the new folder. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function createFolder($path, $name) + public function createFolder($path, $name) { - $conn = $this->_connect(); - if (PEAR::isError($conn)) { - return $conn; - } + $this->_connect(); /* Make sure we have write access to this and all parent paths. */ if (strlen($path)) { @@ -296,25 +284,25 @@ class VFS_musql extends VFS_sql { $this->_params['table']); $this->log($sql, PEAR_LOG_DEBUG); $results = $this->_db->getAll($sql, array($previous, $thispath)); - if (is_a($results, 'PEAR_Error')) { + if ($results instanceof PEAR_Error) { $this->log($results, PEAR_LOG_ERR); - return $results; + throw new VFS_Exception($results->getMessage()); } if (!is_array($results) || count($results) < 1) { - return PEAR::raiseError(_("Unable to create VFS directory.")); + throw new VFS_Exception('Unable to create VFS directory.'); } $allowed = false; foreach ($results as $result) { if ($result[0] == $this->_params['user'] || - $result[1] & VFS_FLAG_WRITE) { + $result[1] & self::FLAG_WRITE) { $allowed = true; break; } } if (!$allowed) { - return PEAR::raiseError(_("Access denied creating VFS directory.")); + throw new VFS_Exception('Access denied creating VFS directory.'); } $previous = $thispath; @@ -330,9 +318,9 @@ class VFS_musql extends VFS_sql { $result = $this->_db->query( $sql, array($id, VFS_FOLDER, $path, $name, time(), $this->_params['user'], 0)); - var_dump($this->_db->last_query); - if (is_a($result, 'PEAR_Error')) { + if ($result instanceof PEAR_Error) { $this->log($result, PEAR_LOG_ERR); + throw new VFS_Exception($result->getMessage()); } return $result; @@ -345,29 +333,18 @@ class VFS_musql extends VFS_sql { * @param string $name The foldername to use. * @param boolean $recursive Force a recursive delete? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFolder($path, $name, $recursive = false) + public function deleteFolder($path, $name, $recursive = false) { - $conn = $this->_connect(); - if (PEAR::isError($conn)) { - return $conn; - } + $this->_connect(); if ($recursive) { - $result = $this->emptyFolder($path . '/' . $name); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->emptyFolder($path . '/' . $name); } else { $list = $this->listFolder($path . '/' . $name); - if (is_a($list, 'PEAR_Error')) { - return $list; - } if (count($list)) { - return PEAR::raiseError( - sprintf(_("Unable to delete %s, the directory is not empty"), - $path . '/' . $name)); + throw new VFS_Exception(sprintf('Unable to delete %s, the directory is not empty', $path . '/' . $name)); } } @@ -377,12 +354,12 @@ class VFS_musql extends VFS_sql { $this->log($sql, PEAR_LOG_DEBUG); $fileList = $this->_db->getAll($sql, array($path, $name, VFS_FOLDER)); - if (is_a($fileList, 'PEAR_Error')) { + if ($fileList instanceof PEAR_Error) { $this->log($fileList, PEAR_LOG_ERR); - return $fileList; + throw new VFS_Exception($fileList->getMessage()); } if (!is_array($fileList) || count($fileList) < 1) { - return PEAR::raiseError(_("Unable to delete VFS directory.")); + throw new VFS_Exception('Unable to delete VFS directory.'); } /* There may be one or more folders with the same name but as the user @@ -390,18 +367,18 @@ class VFS_musql extends VFS_sql { * to delete the one they have access to */ foreach ($fileList as $file) { if ($file[1] == $this->_params['user'] || - $file[2] & VFS_FLAG_WRITE) { + $file[2] & self::FLAG_WRITE) { $sql = sprintf('DELETE FROM %s WHERE vfs_id = ?', $this->_params['table']); $this->log($sql, PEAR_LOG_DEBUG); $result = $this->_db->query($sql, array($file[0])); - if (is_a($result, 'PEAR_Error')) { + if ($result instanceof PEAR_Error) { $this->log($result, PEAR_LOG_ERR); - return $result; + throw new VFS_Exception($result->getMessage()); } if ($this->_db->affectedRows() == 0) { - return PEAR::raiseError(_("Unable to delete VFS directory.")); + throw new VFS_Exception('Unable to delete VFS directory.'); } return $result; @@ -409,7 +386,7 @@ class VFS_musql extends VFS_sql { } // FIXME: 'Access Denied deleting folder %s/%s' - return PEAR::raiseError(_("Unable to delete VFS directory.")); + throw new VFS_Exception('Unable to delete VFS directory.'); } /** @@ -420,15 +397,13 @@ class VFS_musql extends VFS_sql { * @param boolean $dotfiles Show dotfiles? * @param boolean $dironly Show only directories? * - * @return mixed File list on success or false on failure. + * @return array File list. + * @throws VFS_Exception */ - function _listFolder($path, $filter = null, $dotfiles = true, - $dironly = false) + protected function _listFolder($path, $filter = null, $dotfiles = true, + $dironly = false) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); $length_op = $this->_getFileSizeOp(); $sql = sprintf('SELECT vfs_name, vfs_type, vfs_modified, vfs_owner, vfs_perms, %s(vfs_data) FROM %s @@ -437,10 +412,10 @@ class VFS_musql extends VFS_sql { $this->log($sql, PEAR_LOG_DEBUG); $fileList = $this->_db->getAll( $sql, - array($path, $this->_params['user'], VFS_FLAG_READ)); - if (is_a($fileList, 'PEAR_Error')) { + array($path, $this->_params['user'], self::FLAG_READ)); + if ($fileList instanceof PEAR_Error) { $this->log($fileList, PEAR_LOG_ERR); - return $fileList; + throw new VFS_Exception($fileList->getMessage()); } $files = array(); @@ -452,17 +427,17 @@ class VFS_musql extends VFS_sql { $file['name'] = stripslashes($line[0]); - if ($line[1] == VFS_FILE) { + if ($line[1] == self::FILE) { $name = explode('.', $line[0]); if (count($name) == 1) { $file['type'] = '**none'; } else { - $file['type'] = VFS::strtolower($name[count($name) - 1]); + $file['type'] = self::strtolower($name[count($name) - 1]); } $file['size'] = $line[5]; - } elseif ($line[1] == VFS_FOLDER) { + } elseif ($line[1] == self::FOLDER) { $file['type'] = '**dir'; $file['size'] = -1; } @@ -471,10 +446,10 @@ class VFS_musql extends VFS_sql { $file['owner'] = $line[3]; $line[4] = intval($line[4]); - $file['perms'] = ($line[1] == VFS_FOLDER) ? 'd' : '-'; + $file['perms'] = ($line[1] == self::FOLDER) ? 'd' : '-'; $file['perms'] .= 'rw-'; - $file['perms'] .= ($line[4] & VFS_FLAG_READ) ? 'r' : '-'; - $file['perms'] .= ($line[4] & VFS_FLAG_WRITE) ? 'w' : '-'; + $file['perms'] .= ($line[4] & self::FLAG_READ) ? 'r' : '-'; + $file['perms'] .= ($line[4] & self::FLAG_WRITE) ? 'w' : '-'; $file['perms'] .= '-'; $file['group'] = ''; @@ -501,19 +476,16 @@ class VFS_musql extends VFS_sql { * @param string $path Holds the path of directory of the Item. * @param string $name Holds the name of the Item. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function changePermissions($path, $name, $permission) + public function changePermissions($path, $name, $permission) { - $conn = $this->_connect(); - if (PEAR::isError($conn)) { - return $conn; - } + $this->_connect(); $val = intval(substr($permission, -1)); $perm = 0; - $perm |= ($val & 4) ? VFS_FLAG_READ : 0; - $perm |= ($val & 2) ? VFS_FLAG_WRITE : 0; + $perm |= ($val & 4) ? self::FLAG_READ : 0; + $perm |= ($val & 2) ? self::FLAG_WRITE : 0; $sql = sprintf('SELECT vfs_id, vfs_owner, vfs_perms FROM %s WHERE vfs_path = ? AND vfs_name= ?', @@ -521,12 +493,12 @@ class VFS_musql extends VFS_sql { $this->log($sql, PEAR_LOG_DEBUG); $fileList = $this->_db->getAll($sql, array($path, $name)); - if (is_a($fileList, 'PEAR_Error')) { + if ($fileList instanceof PEAR_Error) { $this->log($fileList, PEAR_LOG_ERR); - return $fileList; + throw new VFS_Exception($fileList->getMessage()); } if (!is_array($fileList) || count($fileList) < 1) { - return PEAR::raiseError(_("Unable to rename VFS file.")); + throw new VFS_Exception('Unable to rename VFS file.'); } /* There may be one or more files with the same name but the user may @@ -534,19 +506,20 @@ class VFS_musql extends VFS_sql { * chmod the one they have access to. */ foreach ($fileList as $file) { if ($file[1] == $this->_params['user'] || - $file[2] & VFS_FLAG_WRITE) { + $file[2] & self::FLAG_WRITE) { $sql = sprintf('UPDATE %s SET vfs_perms = ? WHERE vfs_id = ?', $this->_params['table']); $this->log($sql, PEAR_LOG_DEBUG); $result = $this->_db->query($sql, array($perm, $file[0])); + if ($result instanceof PEAR_Error) { + throw new VFS_Exception($result->getMessage()); + } return $result; } } - return PEAR::raiseError( - sprintf(_("Unable to change permission for VFS file %s/%s."), - $path, $name)); + throw new VFS_Exception(sprintf('Unable to change permission for VFS file %s/%s.', $path, $name)); } } diff --git a/framework/VFS/lib/VFS/smb.php b/framework/VFS/lib/VFS/smb.php index af2c11ebe..f326c29f0 100644 --- a/framework/VFS/lib/VFS/smb.php +++ b/framework/VFS/lib/VFS/smb.php @@ -4,22 +4,22 @@ * * Required values for $params: *
- *   'username'  - The username with which to connect to the SMB server.
- *   'password'  - The password with which to connect to the SMB server.
- *   'hostspec'  - The SMB server to connect to.
- *   'port'      - The SMB port number to connect to.
- *   'share'     - The share to access on the SMB server.
- *   'smbclient' - The path to the 'smbclient' executable.
+ * username - (string)The username with which to connect to the SMB server.
+ * password - (string) The password with which to connect to the SMB server.
+ * hostspec - (string) The SMB server to connect to.
+ * port' - (integer) The SMB port number to connect to.
+ * share - (string) The share to access on the SMB server.
+ * smbclient - (string) The path to the 'smbclient' executable.
  * 
* * Optional values for $params: *
- *   'ipaddress' - The address of the server to connect to.
+ * ipaddress - (string) The address of the server to connect to.
  * 
* * Functions not implemented: - * - changePermissions(): The SMB permission style does not fit with the - * module. + * - changePermissions(): The SMB permission style does not fit with the + * module. * * Codebase copyright 2002 Paul Gareau . Adapted with * permission by Patrice Levesque from phpsmb-0.8 code, and @@ -33,40 +33,27 @@ * @author Patrice Levesque * @package VFS */ -class VFS_smb extends VFS { - +class VFS_smb extends VFS +{ /** * List of additional credentials required for this VFS backend. * * @var array */ - var $_credentials = array('username', 'password'); - - /** - * List of permissions and if they can be changed in this VFS backend. - * - * @var array - */ - var $_permissions = array( - 'owner' => array('read' => false, 'write' => false, 'execute' => false), - 'group' => array('read' => false, 'write' => false, 'execute' => false), - 'all' => array('read' => false, 'write' => false, 'execute' => false)); + protected $_credentials = array('username', 'password'); /** * Authenticates a user on the SMB server and share. * - * @access private - * - * @return boolean|PEAR_Error True on success or a PEAR_Error on failure. + * @throws VFS_Exception */ - function _connect() + protected function _connect() { - $cmd = array('quit'); - $err = $this->_command('', $cmd); - if (is_a($err, 'PEAR_Error')) { - return PEAR::raiseError(_("Authentication to the SMB server failed.")); + try { + $this->_command('', array('quit')); + } catch (VFS_Exception $e) { + throw new VFS_Exception('Authentication to the SMB server failed.'); } - return true; } /** @@ -77,19 +64,13 @@ class VFS_smb extends VFS { * * @return string The file data. */ - function read($path, $name) + public function read($path, $name) { $file = $this->readFile($path, $name); - if (is_a($file, 'PEAR_Error')) { - return $file; - } - $size = filesize($file); - if ($size === 0) { - return ''; - } - - return file_get_contents($file); + return ($size === 0) + ? '' + : file_get_contents($file); } /** @@ -102,26 +83,22 @@ class VFS_smb extends VFS { * @param string $path The pathname to the file. * @param string $name The filename to retrieve. * - * @return string A local filename. + * @return string A local filename. */ - function readFile($path, $name) + public function readFile($path, $name) { // Create a temporary file and register it for deletion at the // end of this request. - $localFile = $this->_getTempFile(); - if (!$localFile) { - return PEAR::raiseError(_("Unable to create temporary file.")); + if (!($localFile = tempnam(null, 'vfs'))) { + throw new VFS_Exception('Unable to create temporary file.'); } - register_shutdown_function(create_function('', 'unlink(\'' . addslashes($localFile) . '\');')); + register_shutdown_function(create_function('', '@unlink(\'' . addslashes($localFile) . '\');')); list($path, $name) = $this->_escapeShellCommand($path, $name); $cmd = array('get \"' . $name . '\" ' . $localFile); - $result = $this->_command($path, $cmd); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_command($path, $cmd); if (!file_exists($localFile)) { - return PEAR::raiseError(sprintf(_("Unable to open VFS file \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to open VFS file "%s".', $this->_getPath($path, $name))); } return $localFile; @@ -135,15 +112,9 @@ class VFS_smb extends VFS { * * @return resource The stream. */ - function readStream($path, $name) + public function readStream($path, $name) { - $file = $this->readFile($path, $name); - if (is_a($file, 'PEAR_Error')) { - return $file; - } - - $mode = OS_WINDOWS ? 'rb' : 'r'; - return fopen($file, $mode); + return fopen($this->readFile($path, $name),OS_WINDOWS ? 'rb' : 'r'); } /** @@ -155,9 +126,9 @@ class VFS_smb extends VFS { * stored. * @param boolean $autocreate Automatically create directories? * - * @return boolean|PEAR_Error True on success or a PEAR_Error on failure. + * @throws VFS_Exception */ - function write($path, $name, $tmpFile, $autocreate = false) + public function write($path, $name, $tmpFile, $autocreate = false) { // Double quotes not allowed in SMB filename. $name = str_replace('"', "'", $name); @@ -166,16 +137,10 @@ class VFS_smb extends VFS { $cmd = array('put \"' . $tmpFile . '\" \"' . $name . '\"'); // do we need to first autocreate the directory? if ($autocreate) { - $result = $this->autocreatePath($path); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - $err = $this->_command($path, $cmd); - if (is_a($err, 'PEAR_Error')) { - return $err; + $this->autocreatePath($path); } - return true; + + $this->_command($path, $cmd); } /** @@ -186,17 +151,19 @@ class VFS_smb extends VFS { * @param string $data The file data. * @param boolean $autocreate Automatically create directories? * - * @return boolean|PEAR_Error True on success or a PEAR_Error on failure. + * @throws VFS_Exception */ - function writeData($path, $name, $data, $autocreate = false) + public function writeData($path, $name, $data, $autocreate = false) { - $tmpFile = $this->_getTempFile(); - $fp = fopen($tmpFile, 'wb'); - fwrite($fp, $data); - fclose($fp); - $result = $this->write($path, $name, $tmpFile, $autocreate); - unlink($tmpFile); - return $result; + $tmpFile = tempnam(null, 'vfs'); + file_put_contents($tmpFile, $data); + try { + $this->write($path, $name, $tmpFile, $autocreate); + unlink($tmpFile); + } catch (VFS_Exception $e) { + unlink($tmpFile); + throw $e; + } } /** @@ -205,9 +172,9 @@ class VFS_smb extends VFS { * @param string $path The path to delete the file from. * @param string $name The filename to use. * - * @return boolean|PEAR_Error True on success or a PEAR_Error on failure. + * @throws VFS_Exception */ - function deleteFile($path, $name) + public function deleteFile($path, $name) { // In some samba versions after samba-3.0.25-pre2, $path must // end in a trailing slash. @@ -217,11 +184,7 @@ class VFS_smb extends VFS { list($path, $name) = $this->_escapeShellCommand($path, $name); $cmd = array('del \"' . $name . '\"'); - $err = $this->_command($path, $cmd); - if (is_a($err, 'PEAR_Error')) { - return $err; - } - return true; + $this->_command($path, $cmd); } /** @@ -232,15 +195,16 @@ class VFS_smb extends VFS { * * @return boolean True if it is a folder, false otherwise. */ - function isFolder($path, $name) + public function isFolder($path, $name) { list($path, $name) = $this->_escapeShellCommand($path, $name); $cmd = array('quit'); - $err = $this->_command($this->_getPath($path, $name), $cmd); - if (is_a($err, 'PEAR_Error')) { + try { + $this->_command($this->_getPath($path, $name), array('quit')); + return true; + } catch (VFS_Exception $e) { return false; } - return true; } /** @@ -250,9 +214,9 @@ class VFS_smb extends VFS { * @param string $name The name of the folder to delete. * @param boolean $recursive Force a recursive delete? * - * @return boolean|PEAR_Error True on success or a PEAR_Error on failure. + * @throws VFS_Exception */ - function deleteFolder($path, $name, $recursive = false) + public function deleteFolder($path, $name, $recursive = false) { // In some samba versions after samba-3.0.25-pre2, $path must // end in a trailing slash. @@ -261,38 +225,31 @@ class VFS_smb extends VFS { } if (!$this->isFolder($path, $name)) { - return PEAR::raiseError(sprintf(_("\"%s\" is not a directory."), $path . '/' . $name)); + throw new VFS_Exception(sprintf('"%s" is not a directory.', $path . '/' . $name)); } $file_list = $this->listFolder($this->_getPath($path, $name)); - if (is_a($file_list, 'PEAR_Error')) { - return $file_list; - } if ($file_list && !$recursive) { - return PEAR::raiseError(sprintf(_("Unable to delete \"%s\", the directory is not empty."), - $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to delete "%s", the directory is not empty.', $this->_getPath($path, $name))); } foreach ($file_list as $file) { if ($file['type'] == '**dir') { - $result = $this->deleteFolder($this->_getPath($path, $name), $file['name'], $recursive); + $this->deleteFolder($this->_getPath($path, $name), $file['name'], $recursive); } else { - $result = $this->deleteFile($this->_getPath($path, $name), $file['name']); - } - if (is_a($result, 'PEAR_Error')) { - return $result; + $this->deleteFile($this->_getPath($path, $name), $file['name']); } } // Really delete the folder. list($path, $name) = $this->_escapeShellCommand($path, $name); $cmd = array('rmdir \"' . $name . '\"'); - $err = $this->_command($path, $cmd); - if (is_a($err, 'PEAR_Error')) { - return PEAR::raiseError(sprintf(_("Unable to delete VFS folder \"%s\"."), $this->_getPath($path, $name))); - } else { - return true; + + try { + $this->_command($path, $cmd); + } catch (VFS_Exception $e) { + throw new VFS_Exception(sprintf('Unable to delete VFS folder "%s".', $this->_getPath($path, $name))); } } @@ -304,13 +261,11 @@ class VFS_smb extends VFS { * @param string $newpath The new path of the file. * @param string $newname The new filename. * - * @return boolean|PEAR_Error True on success or a PEAR_Error on failure. + * @throws VFS_Exception */ - function rename($oldpath, $oldname, $newpath, $newname) + public function rename($oldpath, $oldname, $newpath, $newname) { - if (is_a($result = $this->autocreatePath($newpath), 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($newpath); // Double quotes not allowed in SMB filename. The '/' character should // also be removed from the beginning/end of the names. @@ -318,7 +273,7 @@ class VFS_smb extends VFS { $newname = str_replace('"', "'", trim($newname, '/')); if (empty($oldname)) { - return PEAR::raiseError(_("Unable to rename VFS file to same name.")); + throw new VFS_Exception('Unable to rename VFS file to same name.'); } /* If the path was not empty (i.e. the path is not the root path), @@ -333,11 +288,12 @@ class VFS_smb extends VFS { list($file, $name) = $this->_escapeShellCommand($oldname, $newname); $cmd = array('rename \"' . str_replace('/', '\\\\', $oldpath) . $file . '\" \"' . str_replace('/', '\\\\', $newpath) . $name . '\"'); - if (is_a($err = $this->_command('', $cmd), 'PEAR_Error')) { - return PEAR::raiseError(sprintf(_("Unable to rename VFS file \"%s\"."), $this->_getPath($path, $name))); - } - return true; + try { + $this->_command('', $cmd); + } catch (VFS_Exception $e) { + throw new VFS_Exception(sprintf('Unable to rename VFS file "%s".', $this->_getPath($path, $name))); + } } /** @@ -346,9 +302,9 @@ class VFS_smb extends VFS { * @param string $path The path of directory to create folder. * @param string $name The name of the new folder. * - * @return boolean|PEAR_Error True on success or a PEAR_Error on failure. + * @throws VFS_Exception */ - function createFolder($path, $name) + public function createFolder($path, $name) { // In some samba versions after samba-3.0.25-pre2, $path must // end in a trailing slash. @@ -361,11 +317,12 @@ class VFS_smb extends VFS { list($dir, $mkdir) = $this->_escapeShellCommand($path, $name); $cmd = array('mkdir \"' . $mkdir . '\"'); - $err = $this->_command($dir, $cmd); - if (is_a($err, 'PEAR_Error')) { - return PEAR::raiseError(sprintf(_("Unable to create VFS folder \"%s\"."), $this->_getPath($path, $name))); + + try { + $this->_command($dir, $cmd); + } catch (VFS_Exception $e) { + throw new VFS_Exception(sprintf('Unable to create VFS folder "%s".', $this->_getPath($path, $name))); } - return true; } /** @@ -378,21 +335,19 @@ class VFS_smb extends VFS { * smbclient. * @param boolean $dironly Show directories only? * - * @return boolean|PEAR_Error File list on success or a PEAR_Error on - * failure. + * @return array File list. + * @throws VFS_Exception */ - function listFolder($path = '', $filter = null, $dotfiles = true, $dironly = false) + public function listFolder($path = '', $filter = null, $dotfiles = true, + $dironly = false) { list($path) = $this->_escapeShellCommand($path); - $cmd = array('ls'); - $res = $this->_command($path, $cmd); - if (is_a($res, 'PEAR_Error')) { - return $res; - } - return $this->parseListing($res, $filter, $dotfiles, $dironly); + return $this->parseListing($this->_command($path, array('ls'), $filter, $dotfiles, $dironly); } - function parseListing($res, $filter, $dotfiles, $dironly) + /** + */ + public function parseListing($res, $filter, $dotfiles, $dironly) { $num_lines = count($res); $files = array(); @@ -434,7 +389,7 @@ class VFS_smb extends VFS { $my_type = '**dir'; $my_size = -1; } else { - $my_type = VFS::strtolower($ext_name[count($ext_name) - 1]); + $my_type = self::strtolower($ext_name[count($ext_name) - 1]); } $my_date = strtotime($split2[4] . ' ' . $split2[3] . ' ' . $split2[6] . ' ' . $split2[5]); @@ -457,6 +412,7 @@ class VFS_smb extends VFS { $files[$filedata['name']] = $filedata; } + return $files; } @@ -468,32 +424,26 @@ class VFS_smb extends VFS { * @param mixed $filter Hash of items to filter based on folderlist. * @param boolean $dotfolders Include dotfolders? Irrelevant for SMB. * - * @return boolean|PEAR_Error Folder list on success or a PEAR_Error on - * failure. + * @return array Folder list. + * @throws VFS_Exception */ - function listFolders($path = '', $filter = null, $dotfolders = true) + public function listFolders($path = '', $filter = null, $dotfolders = true) { - $folders = array(); - $folder = array(); - - $folderList = $this->listFolder($path, null, $dotfolders, true); - if (is_a($folderList, 'PEAR_Error')) { - return $folderList; - } - // dirname will strip last component from path, even on a directory - $folder['val'] = dirname($path); - $folder['abbrev'] = '..'; - $folder['label'] = '..'; - - $folders[$folder['val']] = $folder; + $folder = array( + ['val'] = dirname($path), + $folder['abbrev'] = '..', + $folder['label'] = '..' + ); + $folders = array($folder['val'] => $folder); + $folderList = $this->listFolder($path, null, $dotfolders, true); foreach ($folderList as $files) { - $folder['val'] = $this->_getPath($path, $files['name']); - $folder['abbrev'] = $files['name']; - $folder['label'] = $folder['val']; - - $folders[$folder['val']] = $folder; + $folders[$folder['val']] = array( + 'val' => $this->_getPath($path, $files['name']), + 'abbrev' => $files['name'], + 'label' => $folder['val'] + ); } ksort($folders); @@ -508,51 +458,34 @@ class VFS_smb extends VFS { * @param string $dest The destination of the file. * @param boolean $autocreate Automatically create directories? * - * @return boolean|PEAR_Error True on success or a PEAR_Error on failure. + * @throws VFS_Exception */ - function copy($path, $name, $dest, $autocreate = false) + public function copy($path, $name, $dest, $autocreate = false) { $orig = $this->_getPath($path, $name); if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { - return PEAR::raiseError(_("Cannot copy file(s) - source and destination are the same.")); + throw new VFS_Exception('Cannot copy file(s) - source and destination are the same.'); } if ($autocreate) { - $result = $this->autocreatePath($dest); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($dest); } - $fileCheck = $this->listFolder($dest, null, true); - if (is_a($fileCheck, 'PEAR_Error')) { - return $fileCheck; - } - foreach ($fileCheck as $file) { + foreach ($this->listFolder($dest, null, true) as $file) { if ($file['name'] == $name) { - return PEAR::raiseError(sprintf(_("%s already exists."), - $this->_getPath($dest, $name))); + throw new VFS_Exception(sprintf('%s already exists.', $this->_getPath($dest, $name))); } } if ($this->isFolder($path, $name)) { - if (is_a($result = $this->_copyRecursive($path, $name, $dest), 'PEAR_Error')) { - return $result; - } + $this->_copyRecursive($path, $name, $dest); } else { - $tmpFile = $this->readFile($path, $name); - if (is_a($tmpFile, 'PEAR_Error')) { - return PEAR::raiseError(sprintf(_("Failed to retrieve: %s"), $orig)); - } - - $result = $this->write($dest, $name, $tmpFile); - if (is_a($result, 'PEAR_Error')) { - return PEAR::raiseError(sprintf(_("Copy failed: %s"), - $this->_getPath($dest, $name))); + try { + $this->write($dest, $name, $this->readFile($path, $name)); + } catch (VFS_Exception $e) { + throw new VFS_Exception(sprintf('Copy failed: %s', $this->_getPath($dest, $name))); } } - - return true; } /** @@ -563,52 +496,41 @@ class VFS_smb extends VFS { * @param string $dest The destination of the file. * @param boolean $autocreate Automatically create directories? * - * @return boolean|PEAR_Error True on success or a PEAR_Error on failure. + * @throws VFS_Exception */ - function move($path, $name, $dest, $autocreate = false) + public function move($path, $name, $dest, $autocreate = false) { $orig = $this->_getPath($path, $name); if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { - return PEAR::raiseError(_("Cannot move file(s) - destination is within source.")); + throw new VFS_Exception('Cannot copy file(s) - destination is within source.'); } if ($autocreate) { - $result = $this->autocreatePath($dest); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($dest); } - $fileCheck = $this->listFolder($dest, null, true); - if (is_a($fileCheck, 'PEAR_Error')) { - return $fileCheck; - } - foreach ($fileCheck as $file) { + foreach ($this->listFolder($dest, null, true) as $file) { if ($file['name'] == $name) { - return PEAR::raiseError(sprintf(_("%s already exists."), - $this->_getPath($dest, $name))); + throw new VFS_Exception(sprintf('%s already exists.', $this->_getPath($dest, $name))); } } - $err = $this->rename($path, $name, $dest, $name); - if (is_a($err, 'PEAR_Error')) { - return PEAR::raiseError(sprintf(_("Failed to move to \"%s\"."), - $this->_getPath($dest, $name))); + try { + $this->rename($path, $name, $dest, $name); + } catch (VFS_Exception $e) { + throw new VFS_Exception(sprintf('Failed to move to "%s".', $this->_getPath($dest, $name))); } - return true; } /** * Replacement for escapeshellcmd(), variable length args, as we only want * certain characters escaped. * - * @access private - * * @param array $array Strings to escape. * - * @return array + * @return array TODO */ - function _escapeShellCommand() + protected function _escapeShellCommand() { $ret = array(); $args = func_get_args(); @@ -621,13 +543,12 @@ class VFS_smb extends VFS { /** * Executes a command and returns output lines in array. * - * @access private - * - * @param string $cmd Command to be executed + * @param string $cmd Command to be executed. * - * @return mixed Array on success, false on failure. + * @return array Array on success. + * @throws VFS_Exception */ - function _execute($cmd) + protected function _execute($cmd) { $cmd = str_replace('"-U%"', '-N', $cmd); exec($cmd, $out, $ret); @@ -654,7 +575,8 @@ class VFS_smb extends VFS { if (!$err) { $err = $out ? $out[count($out) - 1] : $ret; } - return PEAR::raiseError($err); + + throw new VFS_Exception($err); } // Check for errors even on success. @@ -671,7 +593,7 @@ class VFS_smb extends VFS { } if ($err) { - return PEAR::raiseError($err); + throw new VFS_Exception($err); } return $out; @@ -681,14 +603,13 @@ class VFS_smb extends VFS { * Executes SMB commands - without authentication - and returns output * lines in array. * - * @access private - * * @param array $path Base path for command. * @param array $cmd Commands to be executed. * - * @return mixed Array on success, false on failure. + * @return array Array on success. + * @throws VFS_Exception */ - function _command($path, $cmd) + protected function _command($path, $cmd) { list($share) = $this->_escapeShellCommand($this->_params['share']); putenv('PASSWD=' . $this->_params['password']); @@ -704,6 +625,7 @@ class VFS_smb extends VFS { $fullcmd .= $c . ";"; } $fullcmd .= '"'; + return $this->_execute($fullcmd); } diff --git a/framework/VFS/lib/VFS/sql.php b/framework/VFS/lib/VFS/sql.php index 395c5e042..fdb374f51 100644 --- a/framework/VFS/lib/VFS/sql.php +++ b/framework/VFS/lib/VFS/sql.php @@ -1,41 +1,30 @@ - * 'phptype' The database type (ie. 'pgsql', 'mysql', etc.). + * phptype - (string) The database type (ie. 'pgsql', 'mysql', etc.). * * Optional values:
- *   'table'          The name of the vfs table in 'database'. Defaults to
- *                    'horde_vfs'.
+ * table - (string) The name of the vfs table in 'database'. Defaults to + * 'horde_vfs'. * * Required by some database implementations:
- *   'hostspec'     The hostname of the database server.
- *   'protocol'     The communication protocol ('tcp', 'unix', etc.).
- *   'database'     The name of the database.
- *   'username'     The username with which to connect to the database.
- *   'password'     The password associated with 'username'.
- *   'options'      Additional options to pass to the database.
- *   'tty'          The TTY on which to connect to the database.
- *   'port'         The port on which to connect to the database.
+ * hostspec - (string) The hostname of the database server. + * protocol - (string) The communication protocol ('tcp', 'unix', etc.). + * database - (string) The name of the database. + * username - (string) The username with which to connect to the database. + * password - (string) The password associated with 'username'. + * options - (array) Additional options to pass to the database. + * tty - (string) The TTY on which to connect to the database. + * port - (integer) The port on which to connect to the database. * * Optional values when using separate reading and writing servers, for example * in replication settings:
- *   'splitread'   Boolean, whether to implement the separation or not.
- *   'read'        Array containing the parameters which are different for
- *                 the read database connection, currently supported
- *                 only 'hostspec' and 'port' parameters.
+ * splitread - (boolean) Whether to implement the separation or not. + * read - (array) Parameters which are different for the read database + * connection, currently supported only 'hostspec' and 'port' + * parameters. * * The table structure for the VFS can be found in data/vfs.sql. * @@ -60,14 +49,20 @@ define('VFS_FOLDER', 2); * @author Chuck Hagenbuch * @package VFS */ -class VFS_sql extends VFS { +class VFS_sql extends VFS +{ + /* File value for vfs_type column. */ + const FILE = 1; + + /* Folder value for vfs_type column. */ + const FOLDER = 2; /** * Handle for the current database connection. * * @var DB */ - var $_db = false; + protected $_db = false; /** * Handle for the current database connection, used for writing. Defaults @@ -75,7 +70,7 @@ class VFS_sql extends VFS { * * @var DB */ - var $_write_db; + protected $_write_db; /** * Boolean indicating whether or not we're connected to the SQL @@ -83,7 +78,7 @@ class VFS_sql extends VFS { * * @var boolean */ - var $_connected = false; + protected $_connected = false; /** * Retrieves the filesize from the VFS. @@ -91,14 +86,12 @@ class VFS_sql extends VFS { * @param string $path The pathname to the file. * @param string $name The filename to retrieve. * - * @return int The file size. + * @return integer The file size. + * @throws VFS_Exception */ - function size($path, $name) + public function size($path, $name) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); $length_op = $this->_getFileSizeOp(); $sql = sprintf( @@ -111,7 +104,7 @@ class VFS_sql extends VFS { $size = $this->_db->getOne($sql, $values); if (is_null($size)) { - return PEAR::raiseError(sprintf(_("Unable to check file size of \"%s/%s\"."), $path, $name)); + throw new VFS_Exception(sprintf('Unable to check file size of "%s/%s".', $path, $name)); } return $size; @@ -120,22 +113,19 @@ class VFS_sql extends VFS { /** * Returns the size of a file. * - * @access public - * * @param string $path The path of the file. * @param string $name The filename. * - * @return integer The size of the folder in bytes or PEAR_Error on - * failure. + * @return integer The size of the folder in bytes. + * @throws VFS_Exception */ - function getFolderSize($path = null, $name = null) + public function getFolderSize($path = null, $name = null) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); - $where = (is_null($path)) ? null : sprintf('WHERE vfs_path LIKE %s', ((!strlen($path)) ? '""' : $this->_db->quote($this->_convertPath($path) . '%'))); + $where = is_null($path) + ? null + : sprintf('WHERE vfs_path LIKE %s', ((!strlen($path)) ? '""' : $this->_db->quote($this->_convertPath($path) . '%'))); $length_op = $this->_getFileSizeOp(); $sql = sprintf( 'SELECT SUM(%s(vfs_data)) FROM %s %s', @@ -146,7 +136,7 @@ class VFS_sql extends VFS { $this->log($sql, PEAR_LOG_DEBUG); $size = $this->_db->getOne($sql); - return $size !== null ? $size : 0; + return is_null($size) ? $size : 0; } /** @@ -156,17 +146,15 @@ class VFS_sql extends VFS { * @param string $name The filename to retrieve. * * @return string The file data. + * @throws VFS_Exception */ - function read($path, $name) + public function read($path, $name) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - return $this->_readBlob($this->_params['table'], 'vfs_data', - array('vfs_path' => $this->_convertPath($path), - 'vfs_name' => $name)); + $this->_connect(); + return $this->_readBlob($this->_params['table'], 'vfs_data', array( + 'vfs_path' => $this->_convertPath($path), + 'vfs_name' => $name + )); } /** @@ -176,27 +164,28 @@ class VFS_sql extends VFS { * * @param string $path The pathname to the file. * @param string $name The filename to retrieve. - * @param integer $offset The offset of the part. (The new offset will be - * stored in here). - * @param integer $length The length of the part. If the length = -1, the - * whole part after the offset is retrieved. If - * more bytes are given as exists after the given - * offset. Only the available bytes are read. - * @param integer $remaining The bytes that are left, after the part that is - * retrieved. + * @param integer $offset The offset of the part. (The new offset will + * be stored in here). + * @param integer $length The length of the part. If the length = -1, + * the whole part after the offset is + * retrieved. If more bytes are given as exists + * after the given offset. Only the available + * bytes are read. + * @param integer $remaining The bytes that are left, after the part that + * is retrieved. * - * @return string The file data. + * @return string The file data. + * @throws VFS_Exception */ - function readByteRange($path, $name, &$offset, $length = -1, &$remaining) + public function readByteRange($path, $name, &$offset, $length = -1, + &$remaining) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); - $data = $this->_readBlob($this->_params['table'], 'vfs_data', - array('vfs_path' => $this->_convertPath($path), - 'vfs_name' => $name)); + $data = $this->_readBlob($this->_params['table'], 'vfs_data', array( + 'vfs_path' => $this->_convertPath($path), + 'vfs_name' => $name + )); // Calculate how many bytes MUST be read, so the remainging // bytes and the new offset can be calculated correctly. @@ -224,9 +213,9 @@ class VFS_sql extends VFS { * be stored. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function write($path, $name, $tmpFile, $autocreate = false) + public function write($path, $name, $tmpFile, $autocreate = false) { /* Don't need to check quota here since it will be checked when * writeData() is called. */ @@ -244,19 +233,12 @@ class VFS_sql extends VFS { * @param string $data The file data. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function writeData($path, $name, $data, $autocreate = false) + public function writeData($path, $name, $data, $autocreate = false) { - $result = $this->_checkQuotaWrite('string', $data); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_checkQuotaWrite('string', $data); + $this->_connect(); $path = $this->_convertPath($path); @@ -268,9 +250,9 @@ class VFS_sql extends VFS { $this->log($sql, PEAR_LOG_DEBUG); $id = $this->_db->getOne($sql, $values); - if (is_a($id, 'PEAR_Error')) { + if ($id instanceof PEAR_Error) { $this->log($id, PEAR_LOG_ERR); - return $id; + throw new VFS_Exception($id->getMessage()); } if (!is_null($id)) { @@ -284,28 +266,26 @@ class VFS_sql extends VFS { $parent = implode('/', $dirs); if (!$this->isFolder($parent, $path_name)) { if (!$autocreate) { - return PEAR::raiseError(sprintf(_("Folder \"%s\" does not exist"), $path), 'horde.error'); - } else { - $result = $this->autocreatePath($path); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + throw new VFS_Exception(sprintf('Folder "%s" does not exist', $path)); } + + $this->autocreatePath($path); } $id = $this->_write_db->nextId($this->_params['table']); - if (is_a($id, 'PEAR_Error')) { + if ($id instanceof PEAR_Error) { $this->log($id, PEAR_LOG_ERR); - return $id; + throw new VFS_Exception($id->getMessage()); } - return $this->_insertBlob($this->_params['table'], 'vfs_data', - $data, array('vfs_id' => $id, - 'vfs_type' => VFS_FILE, - 'vfs_path' => $path, - 'vfs_name' => $name, - 'vfs_modified' => time(), - 'vfs_owner' => $this->_params['user'])); + return $this->_insertBlob($this->_params['table'], 'vfs_data', $data, array( + 'vfs_id' => $id, + 'vfs_type' => self::FILE, + 'vfs_path' => $path, + 'vfs_name' => $name, + 'vfs_modified' => time(), + 'vfs_owner' => $this->_params['user'] + )); } } @@ -315,31 +295,24 @@ class VFS_sql extends VFS { * @param string $path The path to store the file in. * @param string $name The filename to use. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFile($path, $name) + public function deleteFile($path, $name) { - $result = $this->_checkQuotaDelete($path, $name); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_checkQuotaDelete($path, $name); + $this->_connect(); $path = $this->_convertPath($path); $sql = sprintf('DELETE FROM %s WHERE vfs_type = ? AND vfs_path %s AND vfs_name = ?', $this->_params['table'], (!strlen($path) && $this->_db->dbsyntax == 'oci8') ? ' IS NULL' : ' = ' . $this->_db->quote($path)); - $values = array(VFS_FILE, $name); + $values = array(self::FILE, $name); $this->log($sql, PEAR_LOG_DEBUG); $result = $this->_db->query($sql, $values); if ($this->_db->affectedRows() == 0) { - return PEAR::raiseError(_("Unable to delete VFS file.")); + throw new VFS_Exception('Unable to delete VFS file.'); } return $result; @@ -353,14 +326,11 @@ class VFS_sql extends VFS { * @param string $newpath The new path of the file. * @param string $newname The new filename. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function rename($oldpath, $oldname, $newpath, $newname) + public function rename($oldpath, $oldname, $newpath, $newname) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); if (strpos($newpath, '/') === false) { $parent = ''; @@ -368,10 +338,9 @@ class VFS_sql extends VFS { } else { list($parent, $path) = explode('/', $newpath, 2); } + if (!$this->isFolder($parent, $path)) { - if (is_a($result = $this->autocreatePath($newpath), 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($newpath); } $oldpath = $this->_convertPath($oldpath); @@ -386,13 +355,13 @@ class VFS_sql extends VFS { $result = $this->_write_db->query($sql, $values); if ($this->_write_db->affectedRows() == 0) { - return PEAR::raiseError(_("Unable to rename VFS file.")); + throw new VFS_Exception('Unable to rename VFS file.'); } $rename = $this->_recursiveRename($oldpath, $oldname, $newpath, $newname); - if (is_a($rename, 'PEAR_Error')) { + if ($rename instanceof PEAR_Error) { $this->log($rename, PEAR_LOG_ERR); - return PEAR::raiseError(sprintf(_("Unable to rename VFS directory: %s."), $rename->getMessage())); + throw new VFS_Exception(sprintf('Unable to rename VFS directory: %s.', $rename->getMessage())); } return $result; @@ -404,26 +373,23 @@ class VFS_sql extends VFS { * @param string $path Holds the path of directory to create folder. * @param string $name Holds the name of the new folder. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function createFolder($path, $name) + public function createFolder($path, $name) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); $id = $this->_write_db->nextId($this->_params['table']); - if (is_a($id, 'PEAR_Error')) { + if ($id instanceof PEAR_Error) { $this->log($id, PEAR_LOG_ERR); - return $id; + throw new VFS_Exception($id->getMessage()); } - $sql = 'INSERT INTO ' . $this->_params['table']; - $sql .= ' (vfs_id, vfs_type, vfs_path, vfs_name, vfs_modified, vfs_owner) VALUES (?, ?, ?, ?, ?, ?)'; + $sql = 'INSERT INTO ' . $this->_params['table'] . + ' (vfs_id, vfs_type, vfs_path, vfs_name, vfs_modified, vfs_owner) VALUES (?, ?, ?, ?, ?, ?)'; $this->log($sql, PEAR_LOG_DEBUG); - $values = array($id, VFS_FOLDER, $this->_convertPath($path), $name, time(), $this->_params['user']); + $values = array($id, self::FOLDER, $this->_convertPath($path), $name, time(), $this->_params['user']); return $this->_db->query($sql, $values); } @@ -435,28 +401,20 @@ class VFS_sql extends VFS { * @param string $name The folder name to use. * @param boolean $recursive Force a recursive delete? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFolder($path, $name, $recursive = false) + public function deleteFolder($path, $name, $recursive = false) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); $path = $this->_convertPath($path); - $folderPath = $this->_getNativePath($path, $name); /* Check if not recursive and fail if directory not empty */ if (!$recursive) { $folderList = $this->listFolder($folderPath, null, true); - if (is_a($folderList, 'PEAR_Error')) { - $this->log($folderList, PEAR_LOG_ERR); - return $folderList; - } elseif (!empty($folderList)) { - return PEAR::raiseError(sprintf(_("Unable to delete %s, the directory is not empty"), - $path . '/' . $name)); + if (!empty($folderList)) { + throw new VFS_Exception(sprintf('Unable to delete %s, the directory is not empty', $path . '/' . $name)); } } @@ -467,9 +425,9 @@ class VFS_sql extends VFS { (!strlen($folderPath) && $this->_write_db->dbsyntax == 'oci8') ? ' IS NULL' : ' LIKE ' . $this->_write_db->quote($this->_getNativePath($folderPath, '%'))); $this->log($sql, PEAR_LOG_DEBUG); $deleteContents = $this->_write_db->query($sql); - if (is_a($deleteContents, 'PEAR_Error')) { + if ($deleteContents instanceof PEAR_Error) { $this->log($deleteContents, PEAR_LOG_ERR); - return PEAR::raiseError(sprintf(_("Unable to delete VFS recursively: %s."), $deleteContents->getMessage())); + throw new VFS_Exception(sprintf('Unable to delete VFS recursively: %s.', $deleteContents->getMessage())); } /* Now delete everything inside the folder. */ @@ -478,9 +436,9 @@ class VFS_sql extends VFS { (!strlen($path) && $this->_write_db->dbsyntax == 'oci8') ? ' IS NULL' : ' = ' . $this->_write_db->quote($folderPath)); $this->log($sql, PEAR_LOG_DEBUG); $delete = $this->_write_db->query($sql); - if (is_a($delete, 'PEAR_Error')) { + if ($delete instanceof PEAR_Error) { $this->log($delete, PEAR_LOG_ERR); - return PEAR::raiseError(sprintf(_("Unable to delete VFS directory: %s."), $delete->getMessage())); + throw new VFS_Exception(sprintf('Unable to delete VFS directory: %s.', $delete->getMessage())); } /* All ok now delete the actual folder */ @@ -490,12 +448,10 @@ class VFS_sql extends VFS { $values = array($name); $this->log($sql, PEAR_LOG_DEBUG); $delete = $this->_write_db->query($sql, $values); - if (is_a($delete, 'PEAR_Error')) { + if ($delete instanceof PEAR_Error) { $this->log($delete, PEAR_LOG_ERR); - return PEAR::raiseError(sprintf(_("Unable to delete VFS directory: %s."), $delete->getMessage())); + throw new VFS_Exception(sprintf('Unable to delete VFS directory: %s.', $delete->getMessage())); } - - return $delete; } /** @@ -507,15 +463,13 @@ class VFS_sql extends VFS { * @param boolean $dotfiles Show dotfiles? * @param boolean $dironly Show directories only? * - * @return mixed File list on success or false on failure. + * @return array File list. + * @throws VFS_Exception */ - function _listFolder($path, $filter = null, $dotfiles = true, - $dironly = false) + protected function _listFolder($path, $filter = null, $dotfiles = true, + $dironly = false) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); $path = $this->_convertPath($path); @@ -533,8 +487,8 @@ class VFS_sql extends VFS { $where); $this->log($sql, PEAR_LOG_DEBUG); $fileList = $this->_db->getAll($sql); - if (is_a($fileList, 'PEAR_Error')) { - return $fileList; + if ($fileList instanceof PEAR_Error) { + throw new VFS_Exception($fileList->getMessage()); } $files = array(); @@ -546,17 +500,17 @@ class VFS_sql extends VFS { $file['name'] = $line[0]; - if ($line[1] == VFS_FILE) { + if ($line[1] == self::FILE) { $name = explode('.', $line[0]); if (count($name) == 1) { $file['type'] = '**none'; } else { - $file['type'] = VFS::strtolower($name[count($name) - 1]); + $file['type'] = self::strtolower($name[count($name) - 1]); } $file['size'] = $line[2]; - } elseif ($line[1] == VFS_FOLDER) { + } elseif ($line[1] == self::FOLDER) { $file['type'] = '**dir'; $file['size'] = -1; } @@ -592,14 +546,13 @@ class VFS_sql extends VFS { * folderlist. * @param boolean $dotfolders Include dotfolders? * - * @return mixed Folder list on success or PEAR_Error object on failure. + * @return array Folder list. + * @throws VFS_Exception */ - function listFolders($path = '', $filter = array(), $dotfolders = true) + public function listFolders($path = '', $filter = array(), + $dotfolders = true) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); $path = $this->_convertPath($path); @@ -607,11 +560,11 @@ class VFS_sql extends VFS { $sql .= ' WHERE vfs_path = ? AND vfs_type = ?'; $this->log($sql, PEAR_LOG_DEBUG); - $values = array($path, VFS_FOLDER); + $values = array($path, self::FOLDER); $folderList = $this->_db->getAll($sql, $values); - if (is_a($folderList, 'PEAR_Error')) { - return $folderList; + if ($folderList instanceof PEAR_Error) { + throw new VFS_Exception($folderList->getMessage()); } $folders = array(); @@ -663,37 +616,36 @@ class VFS_sql extends VFS { * @param string $path The VFS path to clean. * @param integer $secs The minimum amount of time (in seconds) required * before a file is removed. + * + * @throws VFS_Exception */ - function gc($path, $secs = 345600) + public function gc($path, $secs = 345600) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); $sql = 'DELETE FROM ' . $this->_params['table'] . ' WHERE vfs_type = ? AND vfs_modified < ? AND (vfs_path = ? OR vfs_path LIKE ?)'; $this->log($sql, PEAR_LOG_DEBUG); - $values = array(VFS_FILE, - time() - $secs, - $this->_convertPath($path), - $this->_convertPath($path) . '/%'); + $values = array( + self::FILE, + time() - $secs, + $this->_convertPath($path), + $this->_convertPath($path) . '/%' + ); - return $this->_write_db->query($sql, $values); + $this->_write_db->query($sql, $values); } /** * Renames all child paths. * - * @access private - * * @param string $path The path of the folder to rename. * @param string $name The foldername to use. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function _recursiveRename($oldpath, $oldname, $newpath, $newname) + protected function _recursiveRename($oldpath, $oldname, $newpath, $newname) { $oldpath = $this->_convertPath($oldpath); $newpath = $this->_convertPath($newpath); @@ -702,7 +654,7 @@ class VFS_sql extends VFS { $sql .= ' WHERE vfs_type = ? AND vfs_path = ?'; $this->log($sql, PEAR_LOG_DEBUG); - $values = array(VFS_FOLDER, $this->_getNativePath($oldpath, $oldname)); + $values = array(self::FOLDER, $this->_getNativePath($oldpath, $oldname)); $folderList = $this->_db->getCol($sql, 0, $values); @@ -715,21 +667,19 @@ class VFS_sql extends VFS { $values = array($this->_getNativePath($newpath, $newname), $this->_getNativePath($oldpath, $oldname)); - return $this->_write_db->query($sql, $values); + $this->_write_db->query($sql, $values); } /** * Return a full filename on the native filesystem, from a VFS * path and name. * - * @access private - * * @param string $path The VFS file path. * @param string $name The VFS filename. * * @return string The full native filename. */ - function _getNativePath($path, $name) + protected function _getNativePath($path, $name) { if (!strlen($path)) { return $name; @@ -746,50 +696,47 @@ class VFS_sql extends VFS { /** * Attempts to open a persistent connection to the SQL server. * - * @access private - * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function _connect() + protected function _connect() { if ($this->_connected) { return true; } if (!is_array($this->_params)) { - return PEAR::raiseError(_("No configuration information specified for SQL VFS.")); + throw new VFS_Exception('No configuration information specified for SQL VFS.'); } $required = array('phptype'); foreach ($required as $val) { if (!isset($this->_params[$val])) { - return PEAR::raiseError(sprintf(_("Required \"%s\" not specified in VFS configuration."), $val)); + throw new VFS_Exception(sprintf('Required "%s" not specified in VFS configuration.', $val)); } } - if (!isset($this->_params['database'])) { - $this->_params['database'] = ''; - } - if (!isset($this->_params['username'])) { - $this->_params['username'] = ''; - } - if (!isset($this->_params['hostspec'])) { - $this->_params['hostspec'] = ''; - } - if (!isset($this->_params['table'])) { - $this->_params['table'] = 'horde_vfs'; - } + $this->_params = array_merge(array( + 'database' => '', + 'hostspec' => '', + 'table' => 'horde_vfs', + 'username' => '' + ), $this->_params); /* Connect to the SQL server using the supplied parameters. */ require_once 'DB.php'; - $this->_write_db = &DB::connect($this->_params, - array('persistent' => !empty($this->_params['persistent']), - 'ssl' => !empty($this->_params['ssl']))); - if (is_a($this->_write_db, 'PEAR_Error')) { + $this->_write_db = DB::connect( + $this->_params, + array( + 'persistent' => !empty($this->_params['persistent']), + 'ssl' => !empty($this->_params['ssl'] + ) + )); + + if ($this->_write_db instanceof PEAR_Error) { $this->log($this->_write_db, PEAR_LOG_ERR); - $error = $this->_write_db; + $error = new VFS_Exception($this->_write_db->getMessage()); $this->_write_db = false; - return $error; + throw $error; } // Set DB portability options. @@ -805,11 +752,16 @@ class VFS_sql extends VFS { * seperately. */ if (!empty($this->_params['splitread'])) { $params = array_merge($this->_params, $this->_params['read']); - $this->_db = &DB::connect($params, - array('persistent' => !empty($params['persistent']), - 'ssl' => !empty($params['ssl']))); - if (is_a($this->_db, 'PEAR_Error')) { - return $this->_db; + $this->_db = DB::connect( + $params, + array( + 'persistent' => !empty($params['persistent']), + 'ssl' => !empty($params['ssl'] + ) + )); + + if ($this->_db instanceof PEAR_Error) { + throw new VFS_Exception($this->_db->getMessage()); } // Set DB portability options. @@ -827,24 +779,22 @@ class VFS_sql extends VFS { } $this->_connected = true; - return true; } /** * Read file data from the SQL VFS backend. * - * @access private - * * @param string $table The VFS table name. * @param string $field TODO * @param array $criteria TODO * * @return mixed TODO + * @throws VFS_Exception */ - function _readBlob($table, $field, $criteria) + protected function _readBlob($table, $field, $criteria) { if (!count($criteria)) { - return PEAR::raiseError('You must specify the fetch criteria'); + throw new VFS_Exception('You must specify the fetch criteria'); } $where = ''; @@ -869,10 +819,11 @@ class VFS_sql extends VFS { if (OCIFetchInto($statement, $lob)) { $result = $lob[0]->load(); if (is_null($result)) { - $result = PEAR::raiseError('Unable to load SQL data.'); + throw new VFS_Exception('Unable to load SQL data.'); } } else { - $result = PEAR::raiseError('Unable to load SQL data.'); + OCIFreeStatement($statement); + throw new VFS_Exception('Unable to load SQL data.'); } OCIFreeStatement($statement); break; @@ -891,7 +842,7 @@ class VFS_sql extends VFS { $result = $this->_db->getOne($sql); if (is_null($result)) { - $result = PEAR::raiseError('Unable to load SQL data.'); + throw new VFS_Exception('Unable to load SQL data.'); } else { switch ($this->_db->dbsyntax) { case 'pgsql': @@ -907,19 +858,17 @@ class VFS_sql extends VFS { /** * TODO * - * @access private - * * @param string $table TODO * @param string $field TODO * @param string $data TODO * @param string $attributes TODO * * @return mixed TODO + * @throws VFS_Exception */ - function _insertBlob($table, $field, $data, $attributes) + protected function _insertBlob($table, $field, $data, $attributes) { - $fields = array(); - $values = array(); + $fields = $values = array(); switch ($this->_write_db->dbsyntax) { case 'oci8': @@ -944,7 +893,10 @@ class VFS_sql extends VFS { $result = OCICommit($this->_write_db->connection); $lob->free(); OCIFreeStatement($statement); - return $result ? true : PEAR::raiseError('Unknown Error'); + if ($result) { + return true; + } + throw new VFS_Exception('Unknown Error'); default: foreach ($attributes as $key => $value) { @@ -978,8 +930,6 @@ class VFS_sql extends VFS { /** * TODO * - * @access private - * * @param string $table TODO * @param string $field TODO * @param string $data TODO @@ -987,11 +937,11 @@ class VFS_sql extends VFS { * @param array $alsoupdate TODO * * @return mixed TODO + * @throws VFS_Exception */ - function _updateBlob($table, $field, $data, $where, $alsoupdate) + protected function _updateBlob($table, $field, $data, $where, $alsoupdate) { - $fields = array(); - $values = array(); + $fields = $values = array(); switch ($this->_write_db->dbsyntax) { case 'oci8': @@ -1015,7 +965,10 @@ class VFS_sql extends VFS { $result = OCICommit($this->_write_db->connection); $lob[0]->free(); OCIFreeStatement($statement); - return $result ? true : PEAR::raiseError('Unknown Error'); + if ($result) { + return true; + } + throw new VFS_Exception('Unknown Error'); default: $updatestring = ''; @@ -1063,21 +1016,21 @@ class VFS_sql extends VFS { * Namely, we will treat '/' as a base directory as this is pretty much * the standard way to access base directories over most filesystems. * - * @access private - * * @param string $path A VFS path. * * @return string The path with any surrouding slashes stripped off. */ - function _convertPath($path) + protected function _convertPath($path) { return trim($path, '/'); } /** * TODO + * + * @return string TODO */ - function _getFileSizeOp() + protected function _getFileSizeOp() { switch ($this->_db->dbsyntax) { case 'mysql': @@ -1102,15 +1055,14 @@ class VFS_sql extends VFS { * @param string $path Path to possible folder * @param string $name Name of possible folder * - * @return boolean True if $path/$name is a folder + * @return boolean True if $path/$name is a folder */ - function isFolder($path, $name) + public function isFolder($path, $name) { - if ($path == '' && $name == '') { + return (($path == '') && ($name == '')) // The root of VFS is always a folder. - return true; - } - return parent::isFolder($path, $name); + ? true + : parent::isFolder($path, $name); } } diff --git a/framework/VFS/lib/VFS/sql_file.php b/framework/VFS/lib/VFS/sql_file.php index 0325b5610..8143a015a 100644 --- a/framework/VFS/lib/VFS/sql_file.php +++ b/framework/VFS/lib/VFS/sql_file.php @@ -4,16 +4,6 @@ */ /** - * File value for vfs_type column. - */ -define('VFS_FILE', 1); - -/** - * Folder value for vfs_type column. - */ -define('VFS_FOLDER', 2); - -/** * VFS_file parent class. */ include_once 'VFS/file.php'; @@ -23,23 +13,23 @@ include_once 'VFS/file.php'; * layer and local file system for file storage. * * Required values for $params:
- *      'phptype'       The database type (ie. 'pgsql', 'mysql', etc.).
- *      'vfsroot'       The root directory of where the files should be
- *                      actually stored.
+ * phptype - (string) The database type (ie. 'pgsql', 'mysql', etc.). + * vfsroot - (string) The root directory of where the files should be + * actually stored. * * Optional values:
- *      'table'         The name of the vfs table in 'database'. Defaults to
- *                      'horde_vfs'.
+ * table - (string) The name of the vfs table in 'database'. Defaults to + * 'horde_vfs'. * * Required by some database implementations:
- *      'hostspec'      The hostname of the database server.
- *      'protocol'      The communication protocol ('tcp', 'unix', etc.).
- *      'database'      The name of the database.
- *      'username'      The username with which to connect to the database.
- *      'password'      The password associated with 'username'.
- *      'options'       Additional options to pass to the database.
- *      'tty'           The TTY on which to connect to the database.
- *      'port'          The port on which to connect to the database.
+ * hostspec - (string) The hostname of the database server. + * protocol - (string) The communication protocol ('tcp', 'unix', etc.). + * database - (string) The name of the database. + * username - (string) The username with which to connect to the database. + * password - (string) The password associated with 'username'. + * options - (array) Additional options to pass to the database. + * tty - (string) The TTY on which to connect to the database. + * port - (integer) The port on which to connect to the database. * * The table structure for the VFS can be found in * data/vfs.sql. @@ -47,14 +37,20 @@ include_once 'VFS/file.php'; * @author Michael Varghese * @package VFS */ -class VFS_sql_file extends VFS_file { +class VFS_sql_file extends VFS_file +{ + /* File value for vfs_type column. */ + const FILE = 1; + + /* Folder value for vfs_type column. */ + const FOLDER = 2; /** * Handle for the current database connection. * * @var DB */ - var $_db = false; + protected $_db = false; /** * Store a file in the VFS, with the data copied from a temporary @@ -66,9 +62,9 @@ class VFS_sql_file extends VFS_file { * stored. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function write($path, $name, $tmpFile, $autocreate = false) + public function write($path, $name, $tmpFile, $autocreate = false) { /* No need to check quota here as we will check it when we call * writeData(). */ @@ -84,38 +80,32 @@ class VFS_sql_file extends VFS_file { * @param string $data The file data. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function writeData($path, $name, $data, $autocreate = false) + public function writeData($path, $name, $data, $autocreate = false) { - $res = $this->_checkQuotaWrite('string', $data); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_checkQuotaWrite('string', $data); $fp = @fopen($this->_getNativePath($path, $name), 'w'); if (!$fp) { if ($autocreate) { - $result = $this->autocreatePath($path); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($path); $fp = @fopen($this->_getNativePath($path, $name), 'w'); if (!$fp) { - return PEAR::raiseError(_("Unable to open VFS file for writing.")); + throw new VFS_Exception('Unable to open VFS file for writing.'); } } else { - return PEAR::raiseError(_("Unable to open VFS file for writing.")); + throw new VFS_Exception('Unable to open VFS file for writing.'); } } if (!@fwrite($fp, $data)) { - return PEAR::raiseError(_("Unable to write VFS file data.")); + throw new VFS_Exception('Unable to write VFS file data.'); } - if (is_a($this->_writeSQLData($path, $name, $autocreate), 'PEAR_Error')) { + if ($this->_writeSQLData($path, $name, $autocreate) instanceof PEAR_Error) { @unlink($this->_getNativePath($path, $name)); - return PEAR::raiseError(_("Unable to write VFS file data.")); + throw new VFS_Exception('Unable to write VFS file data.'); } } @@ -127,37 +117,30 @@ class VFS_sql_file extends VFS_file { * @param string $dest The new filename. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function move($path, $name, $dest, $autocreate = false) + public function move($path, $name, $dest, $autocreate = false) { $orig = $this->_getNativePath($path, $name); if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { - return PEAR::raiseError(_("Cannot move file(s) - destination is within source.")); + throw new VFS_Exception('Cannot move file(s) - destination is within source.'); } if ($autocreate) { - $result = $this->autocreatePath($dest); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($dest); } - $fileCheck = $this->listFolder($dest, null, false); - if (is_a($fileCheck, 'PEAR_Error')) { - return $fileCheck; - } - foreach ($fileCheck as $file) { + foreach ($this->listFolder($dest, null, false) as $file) { if ($file['name'] == $name) { - return PEAR::raiseError(_("Unable to move VFS file.")); + throw new VFS_Exception('Unable to move VFS file.'); } } if (strpos($dest, $this->_getSQLNativePath($path, $name)) !== false) { - return PEAR::raiseError(_("Unable to move VFS file.")); + throw new VFS_Exception('Unable to move VFS file.'); } - return $this->rename($path, $name, $dest, $name); + $this->rename($path, $name, $dest, $name); } /** @@ -168,68 +151,53 @@ class VFS_sql_file extends VFS_file { * @param string $dest The destination of the file. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function copy($path, $name, $dest, $autocreate = false) + public function copy($path, $name, $dest, $autocreate = false) { $orig = $this->_getNativePath($path, $name); if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { - return PEAR::raiseError(_("Cannot copy file(s) - source and destination are the same.")); + throw new VFS_Exception('Cannot copy file(s) - source and destination are the same.'); } - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if ($autocreate) { - $result = $this->autocreatePath($dest); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($dest); } - $fileCheck = $this->listFolder($dest, null, false); - if (is_a($fileCheck, 'PEAR_Error')) { - return $fileCheck; - } - foreach ($fileCheck as $file) { + foreach ($this->listFolder($dest, null, false) as $file) { if ($file['name'] == $name) { - return PEAR::raiseError(_("Unable to copy VFS file.")); + throw new VFS_Exception('Unable to copy VFS file.'); } } if (strpos($dest, $this->_getSQLNativePath($path, $name)) !== false) { - return PEAR::raiseError(_("Unable to copy VFS file.")); + throw new VFS_Exception('Unable to copy VFS file.'); } if (is_dir($orig)) { return $this->_recursiveCopy($path, $name, $dest); } - $res = $this->_checkQuotaWrite('file', $orig); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_checkQuotaWrite('file', $orig); if (!@copy($orig, $this->_getNativePath($dest, $name))) { - return PEAR::raiseError(_("Unable to copy VFS file.")); + throw new VFS_Exception('Unable to copy VFS file.'); } $id = $this->_db->nextId($this->_params['table']); $query = sprintf('INSERT INTO %s (vfs_id, vfs_type, vfs_path, vfs_name, vfs_modified, vfs_owner) VALUES (?, ?, ?, ?, ?, ?)', $this->_params['table']); - $values = array($id, VFS_FILE, $dest, $name, time(), $this->_params['user']); + $values = array($id, self::FILE, $dest, $name, time(), $this->_params['user']); $result = $this->_db->query($query, $values); - if (is_a($result, 'PEAR_Error')) { + if ($result instanceof PEAR_Error) { unlink($this->_getNativePath($dest, $name)); - return $result; + throw new VFS_Exception($result->getMessage()); } - - return true; } /** @@ -238,32 +206,27 @@ class VFS_sql_file extends VFS_file { * @param string $path Holds the path of directory to create folder. * @param string $name Holds the name of the new folder. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function createFolder($path, $name) + public function createFolder($path, $name) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); $id = $this->_db->nextId($this->_params['table']); $result = $this->_db->query(sprintf('INSERT INTO %s (vfs_id, vfs_type, vfs_path, vfs_name, vfs_modified, vfs_owner) VALUES (?, ?, ?, ?, ?, ?)', $this->_params['table']), - array($id, VFS_FOLDER, $path, $name, time(), $this->_params['user'])); - if (is_a($result, 'PEAR_Error')) { - return $result; + array($id, self::FOLDER, $path, $name, time(), $this->_params['user'])); + if ($result instanceof PEAR_Error) { + throw new VFS_Exception($result->getMessage()); } if (!@mkdir($this->_getNativePath($path, $name))) { $result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_id = ?', $this->_params['table']), array($id)); - return PEAR::raiseError(_("Unable to create VFS directory.")); + throw new VFS_Exception('Unable to create VFS directory.'); } - - return true; } /** @@ -274,14 +237,11 @@ class VFS_sql_file extends VFS_file { * @param string $newpath The new path of the file. * @param string $newname The new filename. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function rename($oldpath, $oldname, $newpath, $newname) + public function rename($oldpath, $oldname, $newpath, $newname) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if (strpos($newpath, '/') === false) { $parent = ''; @@ -289,44 +249,30 @@ class VFS_sql_file extends VFS_file { } else { list($parent, $path) = explode('/', $newpath, 2); } + if (!$this->isFolder($parent, $path)) { - if (is_a($result = $this->autocreatePath($newpath), 'PEAR_Error')) { - return $result; - } + $this->autocreatePath($newpath); } - $result = $this->_db->query(sprintf('UPDATE %s SET vfs_path = ?, vfs_name = ?, vfs_modified = ? - WHERE vfs_path = ? AND vfs_name = ?', - $this->_params['table']), - array($newpath, $newname, time(), $oldpath, $oldname)); + $this->_db->query(sprintf('UPDATE %s SET vfs_path = ?, vfs_name = ?, vfs_modified = ? WHERE vfs_path = ? AND vfs_name = ?', $this->_params['table']), array($newpath, $newname, time(), $oldpath, $oldname)); if ($this->_db->affectedRows() == 0) { - return PEAR::raiseError(_("Unable to rename VFS file.")); + throw new VFS_Exception('Unable to rename VFS file.'); } if (is_a($this->_recursiveSQLRename($oldpath, $oldname, $newpath, $newname), 'PEAR_Error')) { - $result = $this->_db->query(sprintf('UPDATE %s SET vfs_path = ?, vfs_name = ? - WHERE vfs_path = ? AND vfs_name = ?', - $this->_params['table']), - array($oldpath, $oldname, $newpath, $newname)); - return PEAR::raiseError(_("Unable to rename VFS directory.")); + $this->_db->query(sprintf('UPDATE %s SET vfs_path = ?, vfs_name = ? WHERE vfs_path = ? AND vfs_name = ?', $this->_params['table']), array($oldpath, $oldname, $newpath, $newname)); + throw new VFS_Exception('Unable to rename VFS directory.'); } if (!@is_dir($this->_getNativePath($newpath))) { - if (is_a($res = $this->autocreatePath($newpath), 'PEAR_Error')) { - return $res; - } + $this->autocreatePath($newpath); } if (!@rename($this->_getNativePath($oldpath, $oldname), $this->_getNativePath($newpath, $newname))) { - $result = $this->_db->query(sprintf('UPDATE %s SET vfs_path = ?, vfs_name = ? - WHERE vfs_path = ? AND vfs_name = ?', - $this->_params['table']), - array($oldpath, $oldname, $newpath, $newname)); + $this->_db->query(sprintf('UPDATE %s SET vfs_path = ?, vfs_name = ? WHERE vfs_path = ? AND vfs_name = ?', $this->_params['table']), array($oldpath, $oldname, $newpath, $newname)); return PEAR::raiseError(_("Unable to rename VFS file.")); } - - return true; } /** @@ -336,48 +282,31 @@ class VFS_sql_file extends VFS_file { * @param string $name The foldername to use. * @param boolean $recursive Force a recursive delete? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFolder($path, $name, $recursive = false) + public function deleteFolder($path, $name, $recursive = false) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if ($recursive) { - $result = $this->emptyFolder($path . '/' . $name); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->emptyFolder($path . '/' . $name); } else { $list = $this->listFolder($path . '/' . $name); - if (is_a($list, 'PEAR_Error')) { - return $list; - } if (count($list)) { - return PEAR::raiseError(sprintf(_("Unable to delete %s, the directory is not empty"), - $path . '/' . $name)); + throw new VFS_Exception(sprintf('Unable to delete %s, the directory is not empty', $path . '/' . $name)); } } - $result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_type = ? AND vfs_path = ? AND vfs_name = ?', - $this->_params['table']), - array(VFS_FOLDER, $path, $name)); + $result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_type = ? AND vfs_path = ? AND vfs_name = ?', $this->_params['table']), array(self::FOLDER, $path, $name)); - if ($this->_db->affectedRows() == 0 || is_a($result, 'PEAR_Error')) { - return PEAR::raiseError(_("Unable to delete VFS directory.")); + if ($this->_db->affectedRows() == 0 || ($result instanceof PEAR_Error)) { + throw new VFS_Exception('Unable to delete VFS directory.'); } - if (is_a($this->_recursiveSQLDelete($path, $name), 'PEAR_Error')) { - return PEAR::raiseError(_("Unable to delete VFS directory recursively.")); + if ($this->_recursiveSQLDelete($path, $name) instanceof PEAR_Error || + $this->_recursiveLFSDelete($path, $name) instanceof PEAR_Error) { + throw new VFS_Exception('Unable to delete VFS directory recursively.'); } - - if (is_a($this->_recursiveLFSDelete($path, $name), 'PEAR_Error')) { - return PEAR::raiseError(_("Unable to delete VFS directory recursively.")); - } - - return $result; } /** @@ -386,37 +315,28 @@ class VFS_sql_file extends VFS_file { * @param string $path The path to store the file in. * @param string $name The filename to use. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFile($path, $name) + public function deleteFile($path, $name) { - $res = $this->_checkQuotaDelete($path, $name); - if (is_a($res, 'PEAR_Error')) { - return $res; - } - - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_checkQuotaDelete($path, $name); + $this->_connect(); $result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_type = ? AND vfs_path = ? AND vfs_name = ?', $this->_params['table']), - array(VFS_FILE, $path, $name)); + array(self::FILE, $path, $name)); if ($this->_db->affectedRows() == 0) { - return PEAR::raiseError(_("Unable to delete VFS file.")); + throw new VFS_Exception('Unable to delete VFS file.'); } - if (is_a($result, 'PEAR_Error')) { - return $result; + if ($result instanceof PEAR_Error) { + throw new VFS_Exception($result->getMessage()); } if (!@unlink($this->_getNativePath($path, $name))) { - return PEAR::raiseError(_("Unable to delete VFS file.")); + throw new VFS_Exception('Unable to delete VFS file.'); } - - return true; } /** @@ -428,25 +348,22 @@ class VFS_sql_file extends VFS_file { * @param boolean $dotfiles Show dotfiles? * @param boolean $dironly Show directories only? * - * @return mixed File list on success or false on failure. + * @return array File list. + * @throws VFS_Exception */ - function _listFolder($path, $filter = null, $dotfiles = true, - $dironly = false) + protected function _listFolder($path, $filter = null, $dotfiles = true, + $dironly = false) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); $files = array(); - $fileList = array(); $fileList = $this->_db->getAll(sprintf('SELECT vfs_name, vfs_type, vfs_modified, vfs_owner FROM %s WHERE vfs_path = ?', $this->_params['table']), array($path)); - if (is_a($fileList, 'PEAR_Error')) { - return $fileList; + if ($fileList instanceof PEAR_Error) { + throw new VFS_Exception($fileList->getMessage()); } foreach ($fileList as $line) { @@ -457,17 +374,17 @@ class VFS_sql_file extends VFS_file { $file['name'] = $line[0]; - if ($line[1] == VFS_FILE) { + if ($line[1] == self::FILE) { $name = explode('.', $line[0]); if (count($name) == 1) { $file['type'] = '**none'; } else { - $file['type'] = VFS::strtolower($name[count($name) - 1]); + $file['type'] = self::strtolower($name[count($name) - 1]); } $file['size'] = filesize($this->_getNativePath($path, $line[0])); - } elseif ($line[1] == VFS_FOLDER) { + } elseif ($line[1] == self::FOLDER) { $file['type'] = '**dir'; $file['size'] = -1; } @@ -503,21 +420,20 @@ class VFS_sql_file extends VFS_file { * folderlist. * @param boolean $dotfolders Include dotfolders? * - * @return mixed Folder list on success or a PEAR_Error object on failure. + * @return array Folder list. + * @throws VFS_Exception */ - function listFolders($path = '', $filter = array(), $dotfolders = true) + public function listFolders($path = '', $filter = array(), + $dotfolders = true) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); $sql = sprintf('SELECT vfs_name, vfs_path FROM %s WHERE vfs_path = ? AND vfs_type = ?', $this->_params['table']); - $folderList = $this->_db->getAll($sql, array($path, $VFS_FOLDER)); - if (is_a($folderList, 'PEAR_Error')) { - return $folderList; + $folderList = $this->_db->getAll($sql, array($path, self::FOLDER)); + if ($folderList instanceof PEAR_Error) { + throw new VFS_Exception($folderList->getMessage()); } $folders = array(); @@ -538,7 +454,7 @@ class VFS_sql_file extends VFS_file { $folder['abbrev'] .= $line[0]; $folder['label'] .= $line[0]; - $strlen = VFS::strlen($folder['label']); + $strlen = self::strlen($folder['label']); if ($strlen > 26) { $folder['abbrev'] = substr($folder['label'], 0, ($count * 4)); $length = (29 - ($count * 4)) / 2; @@ -566,49 +482,34 @@ class VFS_sql_file extends VFS_file { /** * Recursively copies the contents of a folder to a destination. * - * @access private - * * @param string $path The path to store the directory in. * @param string $name The name of the directory. * @param string $dest The destination of the directory. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ function _recursiveCopy($path, $name, $dest) { - $result = $this->createFolder($dest, $name); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->createFolder($dest, $name); $file_list = $this->listFolder($this->_getSQLNativePath($path, $name)); foreach ($file_list as $file) { - $result = $this->copy($this->_getSQLNativePath($path, $name), $file['name'], $this->_getSQLNativePath($dest, $name)); - - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->copy($this->_getSQLNativePath($path, $name), $file['name'], $this->_getSQLNativePath($dest, $name)); } - return true; } /** * Store a files information within the database. * - * @access private - * * @param string $path The path to store the file in. * @param string $name The filename to use. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function _writeSQLData($path, $name, $autocreate = false) + protected function _writeSQLData($path, $name, $autocreate = false) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); // File already exists in database if ($this->exists($path, $name)) { @@ -622,7 +523,7 @@ class VFS_sql_file extends VFS_file { $query = 'INSERT INTO ' . $this->_params['table'] . ' (vfs_id, vfs_type, vfs_path, vfs_name, vfs_modified,' . ' vfs_owner) VALUES (?, ?, ?, ?, ?, ?)'; - $values = array($id, VFS_FILE, $path, $name, time(), + $values = array($id, self::FILE, $path, $name, time(), $this->_params['user']); } return $this->_db->query($query, $values); @@ -631,21 +532,20 @@ class VFS_sql_file extends VFS_file { /** * Renames all child paths. * - * @access private - * * @param string $oldpath The old path of the folder to rename. * @param string $oldname The old name. * @param string $newpath The new path of the folder to rename. * @param string $newname The new name. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function _recursiveSQLRename($oldpath, $oldname, $newpath, $newname) + protected function _recursiveSQLRename($oldpath, $oldname, $newpath, + $newname) { $folderList = $this->_db->getCol(sprintf('SELECT vfs_name FROM %s WHERE vfs_type = ? AND vfs_path = ?', $this->_params['table']), 0, - array(VFS_FOLDER, $this->_getSQLNativePath($oldpath, $oldname))); + array(self::FOLDER, $this->_getSQLNativePath($oldpath, $oldname))); foreach ($folderList as $folder) { $this->_recursiveSQLRename($this->_getSQLNativePath($oldpath, $oldname), $folder, $this->_getSQLNativePath($newpath, $newname), $folder); @@ -656,8 +556,8 @@ class VFS_sql_file extends VFS_file { array($this->_getSQLNativePath($newpath, $newname), $this->_getSQLNativePath($oldpath, $oldname))); - if (is_a($result, 'PEAR_Error')) { - return $result; + if ($result instanceof PEAR_Error) { + throw new VFS_Exception($result->getMessage()); } } @@ -665,49 +565,36 @@ class VFS_sql_file extends VFS_file { * Delete a folders contents from the VFS in the SQL database, * recursively. * - * @access private - * * @param string $path The path of the folder. * @param string $name The foldername to use. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function _recursiveSQLDelete($path, $name) + protected function _recursiveSQLDelete($path, $name) { - $result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_type = ? AND vfs_path = ?', - $this->_params['table']), - array(VFS_FILE, $this->_getSQLNativePath($path, $name))); - if (is_a($result, 'PEAR_Error')) { - return $result; + $result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_type = ? AND vfs_path = ?', $this->_params['table']), array(self::FILE, $this->_getSQLNativePath($path, $name))); + if ($result instanceof PEAR_Error) { + throw new VFS_Exception($result->getMessage()); } - $folderList = $this->_db->getCol(sprintf('SELECT vfs_name FROM %s WHERE vfs_type = ? AND vfs_path = ?', - $this->_params['table']), - 0, - array(VFS_FOLDER, $this->_getSQLNativePath($path, $name))); + $folderList = $this->_db->getCol(sprintf('SELECT vfs_name FROM %s WHERE vfs_type = ? AND vfs_path = ?', $this->_params['table']), 0, array(self::FOLDER, $this->_getSQLNativePath($path, $name))); foreach ($folderList as $folder) { $this->_recursiveSQLDelete($this->_getSQLNativePath($path, $name), $folder); } - $result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_type = ? AND vfs_name = ? AND vfs_path = ?', - $this->_params['table']), - array(VFS_FOLDER, $name, $path)); - - return $result; + $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_type = ? AND vfs_name = ? AND vfs_path = ?', $this->_params['table']), array(self::FOLDER, $name, $path)); } /** * Delete a folders contents from the VFS, recursively. * - * @access private - * * @param string $path The path of the folder. * @param string $name The foldername to use. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function _recursiveLFSDelete($path, $name) + protected function _recursiveLFSDelete($path, $name) { $dir = $this->_getNativePath($path, $name); $dh = @opendir($dir); @@ -723,58 +610,51 @@ class VFS_sql_file extends VFS_file { } @closedir($dh); - return rmdir($dir); + rmdir($dir); } /** * Attempts to open a persistent connection to the SQL server. * - * @access private - * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function _connect() + protected function _connect() { if ($this->_db !== false) { - return true; + return; } if (!is_array($this->_params)) { - return PEAR::raiseError(_("No configuration information specified for SQL-File VFS.")); + throw new VFS_Exception('No configuration information specified for SQL-File VFS.'); } $required = array('phptype', 'vfsroot'); foreach ($required as $val) { if (!isset($this->_params[$val])) { - return PEAR::raiseError(sprintf(_("Required \"%s\" not specified in VFS configuration."), $val)); + throw new VFS_Exception(sprintf('Required "%s" not specified in VFS configuration.', $val)); } } - if (!isset($this->_params['database'])) { - $this->_params['database'] = ''; - } - - if (!isset($this->_params['username'])) { - $this->_params['username'] = ''; - } - - if (!isset($this->_params['hostspec'])) { - $this->_params['hostspec'] = ''; - } - - if (!isset($this->_params['table'])) { - $this->_params['table'] = 'horde_vfs'; - } + $this->_params = array_merge(array( + 'database' => '', + 'hostspec' => '', + 'table' => 'horde_vfs', + 'username' => '' + ), $this->_params); /* Connect to the SQL server using the supplied parameters. */ require_once 'DB.php'; - $this->_db = &DB::connect($this->_params, - array('persistent' => !empty($this->_params['persistent']), - 'ssl' => !empty($this->_params['ssl']))); - if (is_a($this->_db, 'PEAR_Error')) { - $error = $this->_db; + $this->_db = DB::connect( + $this->_params, + array( + 'persistent' => !empty($this->_params['persistent']), + 'ssl' => !empty($this->_params['ssl'] + ) + )); + if ($this->_db instanceof PEAR_Error) { + $error = new VFS_Exception($this->_db->getMessage()); $this->_db = false; - return $error; + throw $error; } // Set DB portability options. @@ -786,26 +666,23 @@ class VFS_sql_file extends VFS_file { default: $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS); } - - return true; } /** * Return a full filename on the native filesystem, from a VFS * path and name. * - * @access private - * * @param string $path The VFS file path. * @param string $name The VFS filename. * * @return string The full native filename. */ - function _getNativePath($path, $name) + protected function _getNativePath($path, $name) { if (strlen($name)) { $name = '/' . $name; } + if (strlen($path)) { if (isset($this->_params['home']) && preg_match('|^~/?(.*)$|', $path, $matches)) { @@ -813,29 +690,25 @@ class VFS_sql_file extends VFS_file { } return $this->_params['vfsroot'] . '/' . $path . $name; - } else { - return $this->_params['vfsroot'] . $name; } + + return $this->_params['vfsroot'] . $name; } /** * Return a full SQL filename on the native filesystem, from a VFS * path and name. * - * @access private - * * @param string $path The VFS file path. * @param string $name The VFS filename. * * @return string The full native filename. */ - function _getSQLNativePath($path, $name) + protected function _getSQLNativePath($path, $name) { - if (!strlen($path)) { - return $name; - } - - return $path . '/' . $name; + return strlen($path) + ? $path . '/' . $name + : $name; } } diff --git a/framework/VFS/lib/VFS/ssh2.php b/framework/VFS/lib/VFS/ssh2.php index 3c3beda9e..00e512981 100644 --- a/framework/VFS/lib/VFS/ssh2.php +++ b/framework/VFS/lib/VFS/ssh2.php @@ -4,13 +4,13 @@ * This module requires the SSH2 (version 0.10+) PECL package. * * Required values for $params:
- *      'username'       The username with which to connect to the ssh2 server.
- *      'password'       The password with which to connect to the ssh2 server.
- *      'hostspec'       The ssh2 server to connect to.
+ * username - (string) The username with which to connect to the ssh2 server. + * password - (string) The password with which to connect to the ssh2 server. + * hostspec - (string) The ssh2 server to connect to. * * Optional values for $params:
- *      'port'           The port used to connect to the ssh2 server if other
- *                       than 22.
+ * port - (integer) The port used to connect to the ssh2 server if other than + * 22. * * Copyright 2006-2010 The Horde Project (http://www.horde.org/) * @@ -20,14 +20,14 @@ * @editor Cliff Green * @package VFS */ -class VFS_ssh2 extends VFS { - +class VFS_ssh2 extends VFS +{ /** * List of additional credentials required for this VFS backend. * * @var array */ - var $_credentials = array('username', 'password'); + protected $_credentials = array('username', 'password'); /** * List of permissions and if they can be changed in this VFS backend. @@ -35,66 +35,74 @@ class VFS_ssh2 extends VFS { * @var array */ var $_permissions = array( - 'owner' => array('read' => true, 'write' => true, 'execute' => true), - 'group' => array('read' => true, 'write' => true, 'execute' => true), - 'all' => array('read' => true, 'write' => true, 'execute' => true)); + 'owner' => array( + 'read' => true, + 'write' => true, + 'execute' => true + ), + 'group' => array( + 'read' => true, + 'write' => true, + 'execute' => true + ), + 'all' => array( + 'read' => true, + 'write' => true, + 'execute' => true + ) + ); /** * Variable holding the connection to the ssh2 server. * * @var resource */ - var $_stream = false; + protected $_stream = false; /** * The SFTP resource stream. * * @var resource */ - var $_sftp; + protected $_sftp; /** * The current working directory. * * @var string */ - var $_cwd; + protected $_cwd; /** * Local cache array for user IDs. * * @var array */ - var $_uids = array(); + protected $_uids = array(); /** * Local cache array for group IDs. * * @var array */ - var $_gids = array(); + protected $_gids = array(); /** * Returns the size of a file. * - * @access public - * * @param string $path The path of the file. * @param string $name The filename. * - * @return integer The size of the file in bytes or PEAR_Error on - * failure. + * @return integer The size of the file in bytes. + * @throws VFS_Exception */ - function size($path, $name) + public function size($path, $name) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); $statinfo = @ssh2_sftp_stat($this->_sftp, $this->_getPath($path, $name)); if (($size = $statinfo['size']) === false) { - return PEAR::raiseError(sprintf(_("Unable to check file size of \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to check file size of "%s".', $this->_getPath($path, $name))); } return $size; @@ -107,21 +115,16 @@ class VFS_ssh2 extends VFS { * @param string $name The filename to retrieve. * * @return string The file data. + * @throws VFS_Exception */ - function read($path, $name) + public function read($path, $name) { $file = $this->readFile($path, $name); - if (is_a($file, 'PEAR_Error')) { - return $file; - } - clearstatcache(); - $size = filesize($file); - if ($size === 0) { - return ''; - } - return file_get_contents($file); + return (filesize($file) === 0) + ? '' + : file_get_contents($file); } /** @@ -134,25 +137,22 @@ class VFS_ssh2 extends VFS { * @param string $path The pathname to the file. * @param string $name The filename to retrieve. * - * @return string A local filename. + * @return string A local filename. + * @throws VFS_Exception */ - function readFile($path, $name) + public function readFile($path, $name) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); // Create a temporary file and register it for deletion at the // end of this request. - $localFile = $this->_getTempFile(); - if (!$localFile) { - return PEAR::raiseError(_("Unable to create temporary file.")); + if (!($localFile = tempnam(null, 'vfs'))) { + throw new VFS_Exception('Unable to create temporary file.'); } - register_shutdown_function(create_function('', 'unlink(\'' . addslashes($localFile) . '\');')); + register_shutdown_function(create_function('', '@unlink(\'' . addslashes($localFile) . '\');')); if (!$this->_recv($this->_getPath($path, $name), $localFile)) { - return PEAR::raiseError(sprintf(_("Unable to open VFS file \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to open VFS file "%s".', $this->_getPath($path, $name))); } return $localFile; @@ -165,16 +165,11 @@ class VFS_ssh2 extends VFS { * @param string $name The filename to retrieve. * * @return resource The stream. + * @throws VFS_Exception */ - function readStream($path, $name) + public function readStream($path, $name) { - $file = $this->readFile($path, $name); - if (is_a($file, 'PEAR_Error')) { - return $file; - } - - $mode = OS_WINDOWS ? 'rb' : 'r'; - return fopen($file, $mode); + return fopen($this->readFile($path, $name), OS_WINDOWS ? 'rb' : 'r'); } /** @@ -186,35 +181,23 @@ class VFS_ssh2 extends VFS { * be stored. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function write($path, $name, $tmpFile, $autocreate = false) + public function write($path, $name, $tmpFile, $autocreate = false) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } - - $res = $this->_checkQuotaWrite('file', $tmpFile); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_connect(); + $this->_checkQuotaWrite('file', $tmpFile); if (!$this->_send($tmpFile, $this->_getPath($path, $name))) { if ($autocreate) { - $result = $this->autocreatePath($path); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - if (!$this->_send($tmpFile, $this->_getPath($path, $name))) { - return PEAR::raiseError(sprintf(_("Unable to write VFS file \"%s\"."), $this->_getPath($path, $name))); + $this->autocreatePath($path); + if ($this->_send($tmpFile, $this->_getPath($path, $name))) { + return; } - } else { - return PEAR::raiseError(sprintf(_("Unable to write VFS file \"%s\"."), $this->_getPath($path, $name))); } - } - return true; + throw new VFS_Exception(sprintf('Unable to write VFS file "%s".', $this->_getPath($path, $name))); + } } /** @@ -225,27 +208,22 @@ class VFS_ssh2 extends VFS { * @param string $data The file data. * @param boolean $autocreate Automatically create directories? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function writeData($path, $name, $data, $autocreate = false) + public function writeData($path, $name, $data, $autocreate = false) { - $res = $this->_checkQuotaWrite('string', $data); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_checkQuotaWrite('string', $data); - $tmpFile = $this->_getTempFile(); - if (function_exists('file_put_contents')) { - file_put_contents($tmpFile, $data); - } else { - $fp = fopen($tmpFile, 'wb'); - fwrite($fp, $data); - fclose($fp); - } + $tmpFile = tempnam(null, 'vfs'); + file_put_contents($tmpFile, $data); - $result = $this->write($path, $name, $tmpFile, $autocreate); - unlink($tmpFile); - return $result; + try { + $this->write($path, $name, $tmpFile, $autocreate); + unlink($tmpFile); + } catch (VFS_Exception $e) { + unlink($tmpFile); + throw $e; + } } /** @@ -254,25 +232,16 @@ class VFS_ssh2 extends VFS { * @param string $path The path to delete the file from. * @param string $name The filename to delete. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFile($path, $name) + public function deleteFile($path, $name) { - $res = $this->_checkQuotaDelete($path, $name); - if (is_a($res, 'PEAR_Error')) { - return $res; - } - - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_checkQuotaDelete($path, $name); + $this->_connect(); if (!@ssh2_sftp_unlink($this->_sftp, $this->_getPath($path, $name))) { - return PEAR::raiseError(sprintf(_("Unable to delete VFS file \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to delete VFS file "%s".', $this->_getPath($path, $name))); } - - return true; } /** @@ -283,11 +252,12 @@ class VFS_ssh2 extends VFS { * * @return boolean True if it is a folder, false otherwise. */ - function isFolder($path, $name) + public function isFolder($path, $name) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; + try { + $this->_connect(); + } catch (VFS_Exception $e) { + return false; } /* See if we can stat the remote filename. ANDed with 040000 is true @@ -303,18 +273,14 @@ class VFS_ssh2 extends VFS { * @param string $name The name of the folder to delete. * @param boolean $recursive Force a recursive delete? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function deleteFolder($path, $name, $recursive = false) + public function deleteFolder($path, $name, $recursive = false) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); $isDir = false; - $dirCheck = $this->listFolder($path); - foreach ($dirCheck as $file) { + foreach ($this->listFolder($path) as $file) { if ($file['name'] == $name && $file['type'] == '**dir') { $isDir = true; break; @@ -323,35 +289,25 @@ class VFS_ssh2 extends VFS { if ($isDir) { $file_list = $this->listFolder($this->_getPath($path, $name)); - if (is_a($file_list, 'PEAR_Error')) { - return $file_list; - } - if (count($file_list) && !$recursive) { - return PEAR::raiseError(sprintf(_("Unable to delete \"%s\", the directory is not empty."), - $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to delete "%s", the directory is not empty.', $this->_getPath($path, $name))); } foreach ($file_list as $file) { if ($file['type'] == '**dir') { - $result = $this->deleteFolder($this->_getPath($path, $name), $file['name'], $recursive); + $this->deleteFolder($this->_getPath($path, $name), $file['name'], $recursive); } else { - $result = $this->deleteFile($this->_getPath($path, $name), $file['name']); - } - if (is_a($result, 'PEAR_Error')) { - return $result; + $this->deleteFile($this->_getPath($path, $name), $file['name']); } } if (!@ssh2_sftp_rmdir($this->_sftp, $this->_getPath($path, $name))) { - return PEAR::raiseError(sprintf(_("Cannot remove directory \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Cannot remove directory "%s".', $this->_getPath($path, $name))); } } else { if (!@ssh2_sftp_unlink($this->_sftp, $this->_getPath($path, $name))) { - return PEAR::raiseError(sprintf(_("Cannot delete file \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Cannot delete file "%s".', $this->_getPath($path, $name))); } } - - return true; } /** @@ -362,24 +318,16 @@ class VFS_ssh2 extends VFS { * @param string $newpath The new path of the file. * @param string $newname The new filename. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function rename($oldpath, $oldname, $newpath, $newname) + public function rename($oldpath, $oldname, $newpath, $newname) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } - - if (is_a($res = $this->autocreatePath($newpath), 'PEAR_Error')) { - return $res; - } + $this->_connect(); + $this->autocreatePath($newpath); if (!@ssh2_sftp_rename($this->_sftp, $this->_getPath($oldpath, $oldname), $this->_getPath($newpath, $newname))) { - return PEAR::raiseError(sprintf(_("Unable to rename VFS file \"%s\"."), $this->_getPath($oldpath, $oldname))); + throw new VFS_Exception(sprintf('Unable to rename VFS file "%s".', $this->_getPath($oldpath, $oldname))); } - - return true; } /** @@ -388,20 +336,15 @@ class VFS_ssh2 extends VFS { * @param string $path The parent folder. * @param string $name The name of the new folder. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function createFolder($path, $name) + public function createFolder($path, $name) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if (!@ssh2_sftp_mkdir($this->_sftp, $this->_getPath($path, $name))) { - return PEAR::raiseError(sprintf(_("Unable to create VFS directory \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to create VFS directory "%s".', $this->_getPath($path, $name))); } - - return true; } /** @@ -411,20 +354,15 @@ class VFS_ssh2 extends VFS { * @param string $name The name of the item. * @param string $permission The permission to set. * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function changePermissions($path, $name, $permission) + public function changePermissions($path, $name, $permission) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if (!@ssh2_exec($this->_stream, 'chmod ' . escapeshellarg($permission) . ' ' . escapeshellarg($this->_getPath($path, $name)))) { - return PEAR::raiseError(sprintf(_("Unable to change permission for VFS file \"%s\"."), $this->_getPath($path, $name))); + throw new VFS_Exception(sprintf('Unable to change permission for VFS file "%s".', $this->_getPath($path, $name))); } - - return true; } /** @@ -435,24 +373,18 @@ class VFS_ssh2 extends VFS { * @param boolean $dotfiles Show dotfiles? * @param boolean $dironly Show only directories? * - * @return array File list on success or PEAR_Error on failure. + * @return array File list. + * @throws VFS_Exception */ - function _listFolder($path = '', $filter = null, $dotfiles = true, - $dironly = false) + protected function _listFolder($path = '', $filter = null, + $dotfiles = true, $dironly = false) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); $files = array(); /* If 'maplocalids' is set, check for the POSIX extension. */ - $mapids = false; - if (!empty($this->_params['maplocalids']) && - extension_loaded('posix')) { - $mapids = true; - } + $mapids = (!empty($this->_params['maplocalids']) && extension_loaded('posix')); // THIS IS A PROBLEM.... there is no builtin systype() fn for SSH2. // Go with unix-style listings for now... @@ -460,10 +392,7 @@ class VFS_ssh2 extends VFS { $olddir = $this->getCurrentDirectory(); if (strlen($path)) { - $res = $this->_setPath($path); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_setPath($path); } if ($type == 'unix') { @@ -501,10 +430,7 @@ class VFS_ssh2 extends VFS { if (!is_array($list)) { if (isset($olddir)) { - $res = $this->_setPath($olddir); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_setPath($olddir); } return array(); } @@ -564,7 +490,7 @@ class VFS_ssh2 extends VFS { (($name[0] === '') && (count($name) == 2))) { $file['linktype'] = '**none'; } else { - $file['linktype'] = VFS::strtolower(array_pop($name)); + $file['linktype'] = self::strtolower(array_pop($name)); } } } elseif ($p1 === 'd') { @@ -576,7 +502,7 @@ class VFS_ssh2 extends VFS { (count($name) == 2))) { $file['type'] = '**none'; } else { - $file['type'] = VFS::strtolower($name[count($name) - 1]); + $file['type'] = self::strtolower($name[count($name) - 1]); } } if ($file['type'] == '**dir') { @@ -638,7 +564,7 @@ class VFS_ssh2 extends VFS { (count($name) == 2))) { $file['type'] = '**none'; } else { - $file['type'] = VFS::strtolower($name[count($name) - 1]); + $file['type'] = self::strtolower($name[count($name) - 1]); } } } @@ -675,34 +601,27 @@ class VFS_ssh2 extends VFS { * @param mixed $filter Hash of items to filter based on folderlist. * @param boolean $dotfolders Include dotfolders? * - * @return mixed Folder list on success or a PEAR_Error object on failure. + * @return array Folder list. + * @throws VFS_Exception */ - function listFolders($path = '', $filter = null, $dotfolders = true) + public function listFolders($path = '', $filter = null, $dotfolders = true) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } - - $folders = array(); - $folder = array(); - - $folderList = $this->listFolder($path, null, $dotfolders, true); - if (is_a($folderList, 'PEAR_Error')) { - return $folderList; - } - - $folder['val'] = $this->_parentDir($path); - $folder['abbrev'] = $folder['label'] = '..'; + $this->_connect(); + $folder = array( + 'abbrev' => '..', + 'val' => $this->_parentDir($path), + 'label' => '..' + ); $folders[$folder['val']] = $folder; + $folderList = $this->listFolder($path, null, $dotfolders, true); foreach ($folderList as $files) { - $folder['val'] = $this->_getPath($path, $files['name']); - $folder['abbrev'] = $files['name']; - $folder['label'] = $folder['val']; - - $folders[$folder['val']] = $folder; + $folders[$folder['val']] = array( + 'val' => $this->_getPath($path, $files['name']), + 'abbrev' => $files['name'], + 'label' => $folder['val'] + ); } ksort($folders); @@ -718,64 +637,45 @@ class VFS_ssh2 extends VFS { * @param boolean $autocreate Auto-create the directory if it doesn't * exist? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function copy($path, $name, $dest, $autocreate = false) + public function copy($path, $name, $dest, $autocreate = false) { $orig = $this->_getPath($path, $name); if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { - return PEAR::raiseError(_("Cannot copy file(s) - source and destination are the same.")); + throw new VFS_Exception('Cannot copy file(s) - source and destination are the same.'); } - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if ($autocreate) { - $res = $this->autocreatePath($dest); - if (is_a($res, 'PEAR_Error')) { - return $res; - } - } - $fileCheck = $this->listFolder($dest, null, true); - if (is_a($fileCheck, 'PEAR_Error')) { - return $fileCheck; + $this->autocreatePath($dest); } - foreach ($fileCheck as $file) { + foreach ($this->listFolder($dest, null, true) as $file) { if ($file['name'] == $name) { - return PEAR::raiseError(sprintf(_("%s already exists."), $this->_getPath($dest, $name))); + throw new VFS_Exception(sprintf('%s already exists.', $this->_getPath($dest, $name))); } } if ($this->isFolder($path, $name)) { - $result = $this->_copyRecursive($path, $name, $dest); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_copyRecursive($path, $name, $dest); } else { - $tmpFile = $this->_getTempFile(); - $fetch = $this->_recv($orig, $tmpFile); - if (!$fetch) { + $tmpFile = tempnam(null, 'vfs'); + if (!$this->_recv($orig, $tmpFile)) { unlink($tmpFile); - return PEAR::raiseError(sprintf(_("Failed to copy from \"%s\"."), $orig)); + throw new VFS_Exception(sprintf('Failed to copy from "%s".', $orig)); } - $res = $this->_checkQuotaWrite('file', $tmpFile); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_checkQuotaWrite('file', $tmpFile); if (!$this->_send($tmpFile, $this->_getPath($dest, $name))) { unlink($tmpFile); - return PEAR::raiseError(sprintf(_("Failed to copy to \"%s\"."), $this->_getPath($dest, $name))); + throw new VFS_Exception(sprintf('Failed to copy to "%s".', $this->_getPath($dest, $name))); } unlink($tmpFile); } - - return true; } /** @@ -787,200 +687,174 @@ class VFS_ssh2 extends VFS { * @param boolean $autocreate Auto-create the directory if it doesn't * exist? * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function move($path, $name, $dest, $autocreate = false) + public function move($path, $name, $dest, $autocreate = false) { $orig = $this->_getPath($path, $name); if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { - return PEAR::raiseError(_("Cannot move file(s) - destination is within source.")); + throw new VFS_Exception('Cannot move file(s) - destination is within source.'); } - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } + $this->_connect(); if ($autocreate) { - $res = $this->autocreatePath($dest); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->autocreatePath($dest); } - $fileCheck = $this->listFolder($dest, null, true); - if (is_a($fileCheck, 'PEAR_Error')) { - return $fileCheck; - } - - foreach ($fileCheck as $file) { + foreach ($this->listFolder($dest, null, true) as $file) { if ($file['name'] == $name) { - return PEAR::raiseError(sprintf(_("%s already exists."), $this->_getPath($dest, $name))); + throw new VFS_Exception(sprintf('%s already exists.', $this->_getPath($dest, $name))); } } if (!@ssh2_sftp_rename($this->_sftp, $orig, $this->_getPath($dest, $name))) { - return PEAR::raiseError(sprintf(_("Failed to move to \"%s\"."), $this->_getPath($dest, $name))); + throw new VFS_Exception(sprintf('Failed to move to "%s".', $this->_getPath($dest, $name))); } - - return true; } /** * Returns the current working directory on the SSH2 server. * * @return string The current working directory. + * @throws VFS_Exception */ - function getCurrentDirectory() + public function getCurrentDirectory() { - if (is_a($res = $this->_connect(), 'PEAR_Error')) { - return $res; - } + $this->_connect(); + if (!strlen($this->_cwd)) { $stream = @ssh2_exec($this->_stream, 'pwd'); stream_set_blocking($stream, true); $this->_cwd = trim(fgets($stream)); } + return $this->_cwd; } /** * Changes the current directory on the server. * - * @access private - * * @param string $path The path to change to. * - * @return boolean True on success, or a PEAR_Error on failure. + * @throws VFS_Exception */ - function _setPath($path) + protected function _setPath($path) { - if ($stream = @ssh2_exec($this->_stream, 'cd ' . escapeshellarg($path) . '; pwd')) { - stream_set_blocking($stream, true); - $this->_cwd = trim(fgets($stream)); - fclose($stream); - return true; - } else { - return PEAR::raiseError(sprintf(_("Unable to change to %s."), $path)); + if (!($stream = @ssh2_exec($this->_stream, 'cd ' . escapeshellarg($path) . '; pwd'))) { + throw new VFS_Exception(sprintf('Unable to change to %s.', $path)); } + + stream_set_blocking($stream, true); + $this->_cwd = trim(fgets($stream)); + fclose($stream); } /** * Returns the full path of an item. * - * @access private - * * @param string $path The directory of the item. * @param string $name The name of the item. * * @return mixed Full path to the file when $path is not empty and just * $name when not set. */ - function _getPath($path, $name) + protected function _getPath($path, $name) { - if ($path !== '') { - return ($path . '/' . $name); - } - return $name; + return ($path !== '') + ? ($path . '/' . $name) + : $name; } /** * Returns the parent directory of the specified path. * - * @access private - * * @param string $path The path to get the parent of. * - * @return string The parent directory (string) on success or a PEAR_Error - * object on failure. + * @return string The parent directory. + * @throws VFS_Exception */ - function _parentDir($path) + protected function _parentDir($path) { - $conn = $this->_connect(); - if (is_a($conn, 'PEAR_Error')) { - return $conn; - } - + $this->_connect(); $this->_setPath('cd ' . $path . '/..'); + return $this->getCurrentDirectory(); } /** * Attempts to open a connection to the SSH2 server. * - * @access private - * - * @return mixed True on success or a PEAR_Error object on failure. + * @throws VFS_Exception */ - function _connect() + protected function _connect() { - if ($this->_stream === false) { - if (!extension_loaded('ssh2')) { - return PEAR::raiseError(_("The SSH2 PECL extension is not available.")); - } + if ($this->_stream !== false) { + return; + } - if (!is_array($this->_params)) { - return PEAR::raiseError(_("No configuration information specified for SSH2 VFS.")); - } + if (!extension_loaded('ssh2')) { + throw new VFS_Exception('The SSH2 PECL extension is not available.'); + } - $required = array('hostspec', 'username', 'password'); - foreach ($required as $val) { - if (!isset($this->_params[$val])) { - return PEAR::raiseError(sprintf(_("Required \"%s\" not specified in VFS configuration."), $val)); - } - } + if (!is_array($this->_params)) { + throw new VFS_Exception('No configuration information specified for SSH2 VFS.'); + } - /* Connect to the ssh2 server using the supplied parameters. */ - if (empty($this->_params['port'])) { - $this->_stream = @ssh2_connect($this->_params['hostspec']); - } else { - $this->_stream = @ssh2_connect($this->_params['hostspec'], $this->_params['port']); - } - if (!$this->_stream) { - return PEAR::raiseError(_("Connection to SSH2 server failed.")); + $required = array('hostspec', 'username', 'password'); + foreach ($required as $val) { + if (!isset($this->_params[$val])) { + throw new VFS_Exception(sprintf('Required "%s" not specified in VFS configuration.', $val)); } + } - $connected = @ssh2_auth_password($this->_stream, $this->_params['username'], $this->_params['password']); - if (!$connected) { - $this->_stream = false; - return PEAR::raiseError(_("Authentication to SSH2 server failed.")); - } + /* Connect to the ssh2 server using the supplied parameters. */ + if (empty($this->_params['port'])) { + $this->_stream = @ssh2_connect($this->_params['hostspec']); + } else { + $this->_stream = @ssh2_connect($this->_params['hostspec'], $this->_params['port']); + } - /* Create sftp resource. */ - $this->_sftp = @ssh2_sftp($this->_stream); + if (!$this->_stream) { + $this->_stream = false; + throw new VFS_Exception('Connection to SSH2 server failed.'); } - return true; + if (!@ssh2_auth_password($this->_stream, $this->_params['username'], $this->_params['password'])) { + $this->_stream = false; + throw new VFS_Exception('Authentication to SSH2 server failed.'); + } + + /* Create sftp resource. */ + $this->_sftp = @ssh2_sftp($this->_stream); } /** * Sends local file to remote host. - * This function exists because the php_scp_* functions doesn't seem to work on some hosts. - * - * @access private + * This function exists because the php_scp_* functions doesn't seem to + * work on some hosts. * * @param string $local Full path to the local file. * @param string $remote Full path to the remote location. * - * @return boolean TRUE on success, FALSE on failure. + * @return boolean Success. */ - function _send($local, $remote) + protected function _send($local, $remote) { return @copy($local, $this->_wrap($remote)); } /** * Receives file from remote host. - * This function exists because the php_scp_* functions doesn't seem to work on some hosts. - * - * @access private + * This function exists because the php_scp_* functions doesn't seem to + * work on some hosts. * - * @param string $local Full path to the local file. - * @param string $remote Full path to the remote location. + * @param string $local Full path to the local file. + * @param string $remote Full path to the remote location. * - * @return boolean TRUE on success, FALSE on failure. + * @return boolean Success. */ - function _recv($remote, $local) + protected function _recv($remote, $local) { return @copy($this->_wrap($remote), $local); } @@ -988,16 +862,15 @@ class VFS_ssh2 extends VFS { /** * Generate a stream wrapper file spec for a remote file path * - * @access private - * * @param string $remote Full path to the remote location * * @return string A full stream wrapper path to the remote location */ - function _wrap($remote) + protected function _wrap($remote) { - return 'ssh2.sftp://' . $this->_params['username'] . ':' . $this->_params['password'] - . '@' . $this->_params['hostspec'] . ':' . $this->_params['port'] . $remote; + return 'ssh2.sftp://' . $this->_params['username'] . ':' . + $this->_params['password'] . '@' . $this->_params['hostspec'] . + ':' . $this->_params['port'] . $remote; } } diff --git a/framework/VFS/package.xml b/framework/VFS/package.xml index 2501cdd0f..1d75c957a 100644 --- a/framework/VFS/package.xml +++ b/framework/VFS/package.xml @@ -34,14 +34,14 @@ Reading, writing and listing of files are all supported, and there are both obje 2009-12-31 0.4.0 - 0.3.0 + 0.4.0 beta beta LGPL - * TODO + * Now throws exceptions instead of returning PEAR_Errors. Package now requires PHP 5. @@ -62,6 +62,7 @@ Reading, writing and listing of files are all supported, and there are both obje + @@ -82,7 +83,7 @@ Reading, writing and listing of files are all supported, and there are both obje - 4.3.0 + 5.0.0 1.4.0b1 @@ -100,6 +101,7 @@ Reading, writing and listing of files are all supported, and there are both obje + @@ -185,7 +187,6 @@ Reading, writing and listing of files are all supported, and there are both obje * Add SSH2/SFTP driver (Cliff Green <green@umdnj.edu>). * Let rename() automatically create the destination path. * Make sure copy/move doesn't result in infinite recursion (Horde Bug #3680). - diff --git a/framework/VFS/scripts/VFS/vfs.php b/framework/VFS/scripts/VFS/vfs.php index a2069c912..87ad04c1e 100644 --- a/framework/VFS/scripts/VFS/vfs.php +++ b/framework/VFS/scripts/VFS/vfs.php @@ -86,12 +86,13 @@ function ls($url, $argv, $filter) $params = url2params($url); $recursive = in_array('R', $argv); - $vfs = &vfs($params); - $list = $vfs->listFolder($params['path'], - count($filter) ? $filter[0] : null, - in_array('a', $argv)); - if (is_a($list, 'PEAR_Error')) { - usage($list); + $vfs = vfs($params); + try { + $list = $vfs->listFolder($params['path'], + count($filter) ? $filter[0] : null, + in_array('a', $argv)); + } catch (VFS_Exception $e) { + usage($e); } if (in_array('a', $argv)) { $list = array_merge(array('.' => array('name' => '.'), @@ -208,9 +209,10 @@ function _cp(&$source_vfs, &$target_vfs, $source_path, $target_path, $argv, return; } - $data = &$source_vfs->read($source_parent_path, $source_object); - if (is_a($data, 'PEAR_Error')) { - usage($data); + try { + $data = &$source_vfs->read($source_parent_path, $source_object); + } catch (VFS_Exception $e) { + usage($e); } if ($target_vfs->isFolder($target_parent_path, $target_object)) { @@ -218,24 +220,25 @@ function _cp(&$source_vfs, &$target_vfs, $source_path, $target_path, $argv, echo '`' . $source_path . '\' -> `' . $target_path . '/' . $source_object . "'\n"; } - $result = $target_vfs->writeData($target_path, $source_object, - $data, true); - if (is_a($result, 'PEAR_Error')) { - usage($result); + + try { + $target_vfs->writeData($target_path, $source_object, $data, true); + } catch (VFS_Exception $e) { + usage($e); } } elseif ($target_vfs->isFolder(dirname($target_parent_path), basename($target_parent_path))) { if (in_array('v', $argv)) { echo '`' . $source_path . '\' -> `' . $target_path . "'\n"; } - $result = $target_vfs->writeData($target_parent_path, $target_object, - $data, true); - if (is_a($result, 'PEAR_Error')) { - usage($result); + + try { + $target_vfs->writeData($target_parent_path, $target_object, $data, true); + } catch (VFS_Exception $e) { + usage($e); } } else { - usage(PEAR::raiseError('"' . $target_parent_path . - '" does not exist or is not a folder.')); + usage(new VFS_Exception('"' . $target_parent_path . '" does not exist or is not a folder.')); } } @@ -246,9 +249,8 @@ function _cp(&$source_vfs, &$target_vfs, $source_path, $target_path, $argv, */ function usage($error = null) { - if (is_a($error, 'PEAR_Error')) { + if ($error instanceof VFS_Exception) { echo $error->getMessage() . "\n"; - echo $error->getUserinfo() . "\n\n"; } else { switch ($error) { case 'ls': @@ -290,7 +292,7 @@ USAGE; * * @return VFS An instance of the requested VFS backend. */ -function &vfs($params) +function vfs($params) { return VFS::singleton($params['driver'], $params); }