steffen: server/kolab-horde-framework/kolab-horde-framework/VFS/VFS Browser.php, NONE, 1.1 GC.php, NONE, 1.1 ListItem.php, NONE, 1.1 Object.php, NONE, 1.1 file.php, NONE, 1.1 ftp.php, NONE, 1.1 musql.php, NONE, 1.1 sql.php, NONE, 1.1 sql_file.php, NONE, 1.1
cvs at intevation.de
cvs at intevation.de
Fri Oct 14 16:33:17 CEST 2005
- Previous message: steffen: server/kolab-horde-framework/kolab-horde-framework/XML_WBXML/WBXML ContentHandler.php, NONE, 1.1 DTD.php, NONE, 1.1 DTDManager.php, NONE, 1.1 Decoder.php, NONE, 1.1 Encoder.php, NONE, 1.1
- Next message: steffen: server/kolab-horde-framework/kolab-horde-framework/XML_WBXML/WBXML/DTD SyncML.php, NONE, 1.1 SyncMLDevInf.php, NONE, 1.1 SyncMLMetInf.php, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Author: steffen
Update of /kolabrepository/server/kolab-horde-framework/kolab-horde-framework/VFS/VFS
In directory doto:/tmp/cvs-serv28903/kolab-horde-framework/kolab-horde-framework/VFS/VFS
Added Files:
Browser.php GC.php ListItem.php Object.php file.php ftp.php
musql.php sql.php sql_file.php
Log Message:
Separated Horde Framework from kolab-resource-handlers
--- NEW FILE: Browser.php ---
<?php
/**
* Class for providing a generic UI for any VFS instance.
*
* $Horde: framework/VFS/VFS/Browser.php,v 1.8 2004/04/08 18:33:17 slusarz Exp $
*
* Copyright 2002-2004 Chuck Hagenbuch <chuck at horde.org>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Chuck Hagenbuch <chuck at horde.org>
* @version $Revision: 1.1 $
* @since Horde 2.2
* @package VFS
*/
class VFS_Browser {
/**
* The VFS instance that we are browsing.
*
* @var object VFS $_vfs
*/
var $_vfs;
/**
* The directory where the templates to use are.
*
* @var string $_templates
*/
var $_templates;
/**
* Constructor
*
* @access public
*
* @param object VFS &$vfs A VFS object.
* @param string $templates TODO
*/
function VFS_Browser(&$vfs, $templates)
{
if (isset($vfs)) {
$this->_vfs = $vfs;
}
$this->_templates = $templates;
}
/**
* Set the VFS object in the local object.
*
* @access public
*
* @param object VFS &$vfs A VFS object.
*/
function setVFSObject(&$vfs)
{
$this->_vfs = &$vfs;
}
/**
* TODO
*
* @access public
*
* @param string $path TODO
* @param optional boolean $dotfiles TODO
* @param optional boolean $dironly TODO
*/
function getUI($path, $dotfiles = false, $dironly = false)
{
$this->_vfs->listFolder($path, $dotfiles, $dironly);
}
}
--- NEW FILE: GC.php ---
<?php
/**
* Class for providing garbage collection for any VFS instance.
*
* $Horde: framework/VFS/VFS/GC.php,v 1.4 2004/01/01 15:14:43 jan Exp $
*
* Copyright 2003-2004 Michael Slusarz <slusarz at bigworm.colorado.edu>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Michael Slusarz <slusarz at bigworm.colorado.edu>
* @version $Revision: 1.1 $
* @since Horde 3.0
* @package VFS
*/
class VFS_GC {
/**
* Garbage collect files in the VFS storage system.
*
* @access public
*
* @param object VFS &$vfs The VFS object to perform
* garbage collection on.
* @param string $path The VFS path to clean.
* @param optional integer $secs The minimum amount of time (in seconds)
* required before a file is removed.
*/
function gc(&$vfs, $path, $secs = 345600)
{
/* A 1% chance we will run garbage collection during a call. */
if (rand(0, 99) == 0) {
$files = $vfs->listFolder($path);
if (!is_a($files, 'PEAR_Error') && is_array($files)) {
$modtime = time() - $secs;
foreach ($files as $val) {
if ($val['date'] < $modtime) {
$vfs->deleteFile($path, $val['name']);
}
}
}
}
}
}
--- NEW FILE: ListItem.php ---
<?php
/**
* An item returned from a folder list.
*
* $Horde: framework/VFS/VFS/ListItem.php,v 1.11 2004/04/08 18:33:17 slusarz Exp $
*
* Copyright 2002-2004 Jon Wood <jon at jellybob.co.uk>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Jon Wood <jon at jellybob.co.uk>
* @version $Revision: 1.1 $
* @package VFS
* @since Horde 2.2
*/
class VFS_ListItem {
/**
* VFS path
*
* @var string $_path
*/
var $_path;
/**
* Filename
*
* @var string $_name
*/
var $_name;
/**
* File permissions (*nix format: drwxrwxrwx)
*
* @var string $_perms
*/
var $_perms;
/**
* Owner user
*
* @var string $_owner
*/
var $_owner;
/**
* Owner group
*
* @var string $_group
*/
var $_group;
/**
* Size.
*
* @var string $_size
*/
var $_size;
/**
* Last modified date.
*
* @var string $_date
*/
var $_date;
/**
* Type
* .* -- File extension
* **none -- Unrecognized type
* **sym -- Symlink
* **dir -- Directory
*
* @var string $_type
*/
var $_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
*
* @var string $_linktype
*/
var $_linktype;
/**
* Constructor
*
* Requires the path to the file, and it's array of properties,
* returned from a standard VFS::listFolder() call.
*
* @access public
*
* @param string $path The path to the file.
* @param array $fileArray An array of file properties.
*/
function VFS_ListItem($path, $fileArray)
{
$this->_path = $path . '/' . $fileArray['name'];
$this->_name = $fileArray['name'];
$this->_dirname = $path;
$this->_perms = $fileArray['perms'];
$this->_owner = $fileArray['owner'];
$this->_group = $fileArray['group'];
$this->_size = $fileArray['size'];
$this->_date = $fileArray['date'];
$this->_type = $fileArray['type'];
$this->_linktype = $fileArray['linktype'];
}
}
--- NEW FILE: Object.php ---
<?php
require_once dirname(__FILE__) . '/../VFS.php';
/**
* A wrapper for the VFS class to return objects, instead of arrays.
*
* $Horde: framework/VFS/VFS/Object.php,v 1.12 2004/04/08 18:33:17 slusarz Exp $
*
* Copyright 2002-2004 Jon Wood <jon at jellybob.co.uk>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Jon Wood <jon at jellybob.co.uk>
* @version $Revision: 1.1 $
* @package VFS
* @since Horde 2.2
*/
class VFS_Object {
/**
* The actual vfs that does the work
*
* @var object VFS $_vfs
*/
var $_vfs;
/**
* The current path that has been passed to listFolder, if this
* changes, the list will be rebuilt.
*
* @var string $_currentPath
*/
var $_currentPath;
/**
* The return value from a standard VFS listFolder call, to
* be read with the Object listFolder.
*
* @var array $_folderList
*/
var $_folderList;
/**
* Constructor.
*
* If you pass in an existing VFS object, it will be used as the VFS
* object for this object.
*
* @access public
*
* @param object VFS &$vfs The VFS object to wrap.
*/
function VFS_Object(&$vfs)
{
if (isset($vfs)) {
$this->_vfs = $vfs;
}
}
/**
* Attempts to return a concrete VFS_Object instance based on
* $driver.
*
* @access public
*
* @param mixed $driver The type of concrete VFS subclass to
* return. This is based on the storage
* driver ($driver). The code is
* dynamically included. If $driver is an
* array then we will look in
* $driver[0]/lib/VFS/ for the subclass
* implementation named $driver[1].php.
* @param optional array $params A hash containing any additional
* configuration or connection parameters
* a subclass might need.
*
* @return object VFS_Object The newly created concrete VFS_Object
* instance, or false on an error.
*/
function &factory($driver, $params = array())
{
$vfs = &VFS::factory($driver, $params = array());
return $ret = &new VFS_Object($vfs);
}
/**
* 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()
*
* @access public
*
* @param mixed $driver The type of concrete VFS subclass to
* return. This is based on the storage
* driver ($driver). The code is
* dynamically included. If $driver is an
* array then we will look in
* $driver[0]/lib/VFS/ for the subclass
* implementation named $driver[1].php.
* @param optional array $params A hash containing any additional
* configuration or connection parameters
* a subclass might need.
*
* @return object VFS_Object The concrete VFS_Object reference, or false
* on error.
*/
function &singleton($driver, $params = array())
{
$vfs = &VFS::singleton($driver, $params = array());
return $ret = &new VFS_Object($vfs);
}
/**
* Check the credentials that we have to see if there is a valid login.
*
* @access public
*
* @return mixed True on success, PEAR_Error describing the problem
* if the credentials are invalid.
*/
function checkCredentials()
{
return $this->_vfs->checkCredentials();
}
/**
* Set configuration parameters.
*
* @access public
*
* @param optional array $params An associative array:
* KEY: param name, VAL: param value
*/
function setParams($params = array())
{
$this->_vfs->setParams($params);
}
/**
* Retrieve a file from the VFS.
*
* @access public
*
* @param string $path The pathname to the file.
*
* @return string The file data.
*/
function read($path)
{
return $this->_vfs->read(dirname($path), basename($path));
}
/**
* Store a file in the VFS.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $tmpFile The temporary file containing the
* data to be stored.
* @param optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function write($path, $tmpFile, $autocreate = false)
{
return $this->_vfs->write(dirname($path), basename($path), $tmpFile, $autocreate = false);
}
/**
* Store a file in the VFS from raw data.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $data The file data.
* @param optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function writeData($path, $data, $autocreate = false)
{
return $this->_vfs->writeData(dirname($path), basename($path), $data, $autocreate = false);
}
/**
* Delete a file from the 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.
*/
function deleteFile($path)
{
return $this->_vfs->deleteFile(dirname($path), basename($path));
}
/**
* Rename a file in the VFS.
*
* @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, $newpath)
{
return $this->_vfs->rename(dirname($oldpath), basename($oldpath), dirname($newpath), basename($newpath));
}
/**
* Create a folder in the VFS.
*
* @access public
*
* @param string $path The path to the folder.
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function createFolder($path)
{
return $this->_vfs->createFolder(dirname($path));
}
/**
* Deletes a folder from the VFS.
*
* @access public
*
* @param string $path The path of the folder to delete.
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function deleteFolder($path)
{
return $this->_vfs->deleteFolder(dirname($path));
}
/**
* Returns a VFS_ListItem object if the folder can
* be read, or a PEAR_Error if it can't be. Returns false once
* the folder has been completely read.
*
* @access public
*
* @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
* completely read.
*/
function listFolder($path)
{
if (!($path === $this->_currentPath)) {
$folderList = $this->_vfs->listFolder($path);
if ($folderList) {
$this->_folderList = $folderList;
$this->_currentPath = $path;
} else {
return PEAR::raiseError(sprintf(_("Could not read %s."), $path));
}
}
require_once dirname(__FILE__) . '/ListItem.php';
if ($file = array_shift($this->_folderList)) {
$file = &new VFS_ListItem($path, $file);
return $file;
} else {
return false;
}
}
/**
* Changes permissions for an Item on the VFS.
*
* @access public
*
* @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.
*/
function changePermissions($path, $permission)
{
return $this->_vfs->changePermissions(dirname($path), basename($path), $permission);
}
/**
* Return the list of additional credentials required, if any.
*
* @access public
*
* @return array Credential list.
*/
function getRequiredCredentials()
{
return $this->_vfs->getRequiredCredentials();
}
/**
* Return the array specificying what permissions are
* changeable for this implementation.
*
* @access public
*
* @return array Changeable permisions.
*/
function getModifiablePermissions()
{
return $this->_vfs->getModifiablePermissions();
}
/**
* Close any resources that need to be closed.
*
* @access private
*/
function _disconnect()
{
$this->_vfs->_disconnect();
}
}
--- NEW FILE: file.php ---
<?php
/**
* VFS implementation for a standard filesystem.
*
* <pre>
* Required values for $params:
* 'vfsroot' The root path
* </pre>
*
* Note: The user that your webserver runs as (commonly 'nobody',
* 'apache', or 'www-data') MUST have read/write permission to the
* directory you specific as the 'vfsroot'.
*
* $Horde: framework/VFS/VFS/file.php,v 1.57 2004/05/27 22:06:27 jan Exp $
*
* Copyright 2002-2004 Chuck Hagenbuch <chuck at horde.org>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Chuck Hagenbuch
* @version $Revision: 1.1 $
* @since Horde 2.2
* @package VFS
*/
class VFS_file extends VFS {
/**
* List of permissions and if they can be changed in this VFS
* backend.
*
* @var array $_permissions
*/
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)
);
/**
* Constructs a new Filesystem based VFS object.
*
* @access public
*
* @param optional array $params A hash containing connection parameters.
*/
function VFS_file($params = array())
{
parent::VFS($params);
if (substr($this->_params['vfsroot'], -1) == '/' ||
substr($this->_params['vfsroot'], -1) == '\\') {
$this->_params['vfsroot'] = substr($this->_params['vfsroot'], 0, strlen($this->_params['vfsroot']) - 1);
}
}
/**
* Retrieve a file from the VFS.
*
* @access public
*
* @param string $path The pathname to the file.
* @param string $name The filename to retrieve.
*
* @return string The file data.
*/
function read($path, $name)
{
$file = $this->_getNativePath($path, $name);
$fp = @fopen($file, 'rb');
if (!$fp) {
return PEAR::raiseError(_("Unable to open VFS file."));
}
$data = fread($fp, filesize($file));
fclose($fp);
return $data;
}
/**
* Store a file in the VFS, with the data copied from a temporary
* file.
*
* @access public
*
* @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 optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
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;
}
} else {
return PEAR::raiseError(_("VFS directory does not exist."));
}
}
$fp = @fopen($this->_getNativePath($path, $name), 'w');
if (!$fp) {
return PEAR::raiseError(_("Unable to open VFS file for writing."));
}
$dataFP = @fopen($tmpFile, 'rb');
$data = @fread($dataFP, filesize($tmpFile));
fclose($dataFP);
if (!@fwrite($fp, $data)) {
return PEAR::raiseError(_("Unable to write VFS file data."));
}
return true;
}
/**
* Moves a file in the database and the file system.
*
* @access public
*
* @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.
*/
function move($path, $name, $dest)
{
$fileCheck = $this->listFolder($dest, false);
foreach ($fileCheck as $file) {
if ($file['name'] == $name) {
return PEAR::raiseError(_("Unable to move VFS file."));
}
}
if (!@rename($this->_getNativePath($path, $name), $this->_getNativePath($dest, $name))) {
return PEAR::raiseError(_("Unable to move VFS file."));
}
return true;
}
/**
* Copies a file through the backend.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $name The filename to use.
* @param string $dest The destination of the file.
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function copy($path, $name, $dest)
{
$fileCheck = $this->listFolder($dest, false);
if ($path == $dest) {
return PEAR::raiseError(_("The file can not be copied onto itself."));
}
foreach ($fileCheck as $file) {
if ($file['name'] == $name) {
return PEAR::raiseError(_("Unable to copy VFS file."));
}
}
if (!@copy($this->_getNativePath($path, $name), $this->_getNativePath($dest, $name))) {
return PEAR::raiseError(_("Unable to copy VFS file."));
}
return true;
}
/**
* Store a file in the VFS from raw data.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $name The filename to use.
* @param string $data The file data.
* @param optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
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;
}
} else {
return PEAR::raiseError(_("VFS directory does not exist."));
}
}
$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."));
}
return true;
}
/**
* Delete a file from the VFS.
*
* @access public
*
* @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.
*/
function deleteFile($path, $name)
{
if (!@unlink($this->_getNativePath($path, $name))) {
return PEAR::raiseError(_("Unable to delete VFS file."));
}
}
/**
* Delete a folder from the VFS.
*
* @access public
*
* @param string $path The path to delete the folder from.
* @param string $name The foldername to use.
* @param optional boolean $recursive Force a recursive delete?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function deleteFolder($path, $name, $recursive = false)
{
if ($recursive) {
$result = $this->emptyFolder($path . '/' . $name);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
} 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));
}
}
if (!@rmdir($this->_getNativePath($path, $name))) {
return PEAR::raiseError(_("Unable to delete VFS directory."));
}
return true;
}
/**
* Creates a folder on the VFS.
*
* @access public
*
* @param string $path The path to delete the folder from.
* @param string $name The foldername to use.
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function createFolder($path, $name)
{
if (!@mkdir($this->_getNativePath($path, $name))) {
return PEAR::raiseError(_("Unable to create VFS directory."));
}
return true;
}
/**
* Check if a given pathname is a folder.
*
* @access public
*
* @param string $path The path to the folder.
* @param string $name The file/folder name.
*
* @return boolean True if it is a folder, false otherwise.
*/
function isFolder($path, $name)
{
return @is_dir($this->_getNativePath($path, $name));
}
/**
* Changes permissions for an item in the VFS.
*
* @access public
*
* @param string $path The path of directory of the item.
* @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.
*/
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));
}
return true;
}
/**
* Return a list of the contents of a folder.
*
* @access public
*
* @param string $path The path of the directory.
* @param optional mixed $filter String/hash to filter file/dirname
* on.
* @param optional boolean $dotfiles Show dotfiles?
* @param optional boolean $dironly Show only directories?
*
* @return array File list on success, PEAR_Error on error.
*/
function listFolder($path, $filter = null, $dotfiles = true,
$dironly = false)
{
$files = array();
$path = isset($path) ? $this->_getNativePath($path) : $this->_getNativePath();
if (!@is_dir($path)) {
return PEAR::raiseError(_("Not a directory"));
}
if (!@chdir($path)) {
return PEAR::raiseError(_("Unable to access VFS directory."));
}
$handle = opendir($path);
while (($entry = readdir($handle)) !== false) {
// Filter out '.' and '..' entries.
if ($entry == '.' || $entry == '..') {
continue;
}
// Filter out dotfiles if they aren't wanted.
if (!$dotfiles && substr($entry, 0, 1) == '.') {
continue;
}
// File name
$file['name'] = $entry;
// Unix style file permissions
$file['perms'] = $this->_getUnixPerms(fileperms($entry));
// Owner
$file['owner'] = fileowner($entry);
if (function_exists('posix_getpwuid')) {
$owner = posix_getpwuid($file['owner']);
$file['owner'] = $owner['name'];
}
// Group
$file['group'] = filegroup($entry);
if (function_exists('posix_getgrgid')) {
$group = posix_getgrgid($file['group']);
$file['group'] = $group['name'];
}
// Size
$file['size'] = filesize($entry);
// Date
$file['date'] = filemtime($entry);
// Type
if (@is_dir($entry) && !is_link($entry)) {
$file['perms'] = 'd' . $file['perms'];
$file['type'] = '**dir';
$file['size'] = -1;
} elseif (is_link($entry)) {
$file['perms'] = 'l' . $file['perms'];
$file['type'] = '**sym';
$file['link'] = readlink($entry);
$file['linktype'] = '**none';
if (file_exists($file['link'])) {
if (is_dir($file['link'])) {
$file['linktype'] = '**dir';
} elseif (is_link($file['link'])) {
$file['linktype'] = '**sym';
} 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]);
}
}
} else {
$file['linktype'] = '**broken';
}
} elseif (is_file($entry)) {
$file['perms'] = '-' . $file['perms'];
$ext = explode('.', $entry);
if (count($ext) == 1 || (substr($file['name'], 0, 1) === '.' && count($ext) == 2)) {
$file['type'] = '**none';
} else {
$file['type'] = VFS::strtolower($ext[count($ext) - 1]);
}
} else {
$file['type'] = '**none';
if ((fileperms($entry) & 0xC000) == 0xC000) {
$file['perms'] = 's' . $file['perms'];
} elseif ((fileperms($entry) & 0x6000) == 0x6000) {
$file['perms'] = 'b' . $file['perms'];
} elseif ((fileperms($entry) & 0x2000) == 0x2000) {
$file['perms'] = 'c' . $file['perms'];
} elseif ((fileperms($entry) & 0x1000) == 0x1000) {
$file['perms'] = 'p' . $file['perms'];
} else {
$file['perms'] = '?' . $file['perms'];
}
}
// Filtering.
if ($this->_filterMatch($filter, $file['name'])) {
unset($file);
continue;
}
if ($dironly && $file['type'] !== '**dir') {
unset($file);
continue;
}
$files[$file['name']] = $file;
unset($file);
}
return $files;
}
/**
* Returns a sorted list of folders in specified directory.
*
* @access public
*
* @param optional string $path The path of the directory to get
* the directory list for.
* @param optional mixed $filter Hash of items to filter based on
* folderlist.
* @param optional boolean $dotfolders Include dotfolders?
*
* @return mixed Folder list on success or a PEAR_Error object on failure.
*/
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);
$folder['val'] = dirname($path);
$folder['abbrev'] = '..';
$folder['label'] = '..';
$folders[$folder['val']] = $folder;
foreach ($folderList as $files) {
$folder['val'] = $path . '/' . $files['name'];
$folder['abbrev'] = $files['name'];
$folder['label'] = $folder['val'];
$folders[$folder['val']] = $folder;
}
ksort($folders);
return $folders;
}
/**
* Return Unix style perms.
*
* @access private
*
* @param integer $perms The permissions to set.
*
* @return string Unix style perms.
*/
function _getUnixPerms($perms)
{
// Determine permissions
$owner['read'] = ($perms & 00400) ? 'r' : '-';
$owner['write'] = ($perms & 00200) ? 'w' : '-';
$owner['execute'] = ($perms & 00100) ? 'x' : '-';
$group['read'] = ($perms & 00040) ? 'r' : '-';
$group['write'] = ($perms & 00020) ? 'w' : '-';
$group['execute'] = ($perms & 00010) ? 'x' : '-';
$world['read'] = ($perms & 00004) ? 'r' : '-';
$world['write'] = ($perms & 00002) ? 'w' : '-';
$world['execute'] = ($perms & 00001) ? 'x' : '-';
// Adjust for SUID, SGID and sticky bit
if ($perms & 0x800) {
$owner['execute'] = ($owner['execute'] == 'x') ? 's' : 'S';
}
if ($perms & 0x400) {
$group['execute'] = ($group['execute'] == 'x') ? 's' : 'S';
}
if ($perms & 0x200) {
$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;
}
/**
* Rename a file or folder in the VFS.
*
* @access public
*
* @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)
{
if (!@rename($this->_getNativePath($oldpath, $oldname),
$this->_getNativePath($newpath, $newname))) {
return PEAR::raiseError(sprintf(_("Unable to rename VFS file %s/%s."), $oldpath, $oldname));
}
return true;
}
/**
* Return a full filename on the native filesystem, from a VFS
* path and name.
*
* @access private
*
* @param optional string $path The VFS file path.
* @param optional string $name The VFS filename.
*
* @return string The full native filename.
*/
function _getNativePath($path = '', $name = '')
{
$name = basename($name);
if (!empty($name)) {
if ($name == '..') {
$name = '';
} else {
if (substr($name, 0, 1) != '/') {
$name = '/' . $name;
}
}
}
if (!empty($path)) {
if (isset($this->_params['home']) &&
preg_match('|^~/?(.*)$|', $path, $matches)) {
$path = $this->_params['home'] . '/' . $matches[1];
}
$path = str_replace('..', '', $path);
if (substr($path, 0, 1) == '/') {
return $this->_params['vfsroot'] . $path . $name;
} else {
return $this->_params['vfsroot'] . '/' . $path . $name;
}
} else {
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.
*/
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."));
}
}
}
--- NEW FILE: ftp.php ---
<?php
/**
* VFS implementation for an FTP server.
*
* <pre>
* 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.
* Optional values for $params:
* '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.
* </pre>
*
* $Horde: framework/VFS/VFS/ftp.php,v 1.70 2004/04/18 13:46:15 jan Exp $
*
* Copyright 2002-2004 Chuck Hagenbuch <chuck at horde.org>
* Copyright 2002-2004 Michael Varghese <mike.varghese at ascellatech.com>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Chuck Hagenbuch <chuck at horde.org>
* @author Michael Varghese <mike.varghese at ascellatech.com>
* @version $Revision: 1.1 $
* @since Horde 2.2
* @package VFS
*/
class VFS_ftp extends VFS {
/**
* List of additional credentials required for this VFS backend.
*
* @var array $_credentials
*/
var $_credentials = array('username', 'password');
/**
* List of permissions and if they can be changed in this VFS
* backend.
*
* @var array $_permissions
*/
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));
/**
* Variable holding the connection to the ftp server.
*
* @var resource $_stream
*/
var $_stream = false;
/**
* Retrieve a file from the VFS.
*
* @access public
*
* @param string $path The pathname to the file.
* @param string $name The filename to retrieve.
*
* @return string The file data.
*/
function read($path, $name)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$tmpFile = $this->_getTempFile();
$fetch = @ftp_get($this->_stream, $tmpFile,
$this->_getPath($path, $name), FTP_BINARY);
if ($fetch === false) {
return PEAR::raiseError(sprintf(_("Unable to open VFS file \"%s\"."), $this->_getPath($path, $name)));
}
if (OS_WINDOWS) {
$mode = 'rb';
} else {
$mode = 'r';
}
$fp = fopen($tmpFile, $mode);
$data = fread($fp, filesize($tmpFile));
fclose($fp);
unlink($tmpFile);
return $data;
}
/**
* Store a file in the VFS.
*
* @access public
*
* @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 optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function write($path, $name, $tmpFile, $autocreate = false)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
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;
}
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;
}
/**
* Store a file in the VFS from raw data.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $name The filename to use.
* @param string $data The file data.
* @param optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
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;
}
/**
* Delete a file from the VFS.
*
* @access public
*
* @param string $path The path to delete the file from.
* @param string $name The filename to use.
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function deleteFile($path, $name)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
if (!@ftp_delete($this->_stream, $this->_getPath($path, $name))) {
return PEAR::raiseError(sprintf(_("Unable to delete VFS file \"%s\"."), $this->_getPath($path, $name)));
}
return true;
}
/**
* Check if a given pathname is a folder.
*
* @access public
*
* @param string $path The path to the folder.
* @param string $name The file/folder name.
*
* @return boolean True if it is a folder, false otherwise.
*/
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;
}
$this->_setPath($olddir);
return $result;
}
/**
* Delete a folder from the VFS.
*
* @access public
*
* @param string $path The path to delete the folder from.
* @param string $name The name of the folder to delete.
* @param optional boolean $recursive Force a recursive delete?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function deleteFolder($path, $name, $recursive = false)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$isDir = false;
$dirCheck = $this->listFolder($path);
foreach ($dirCheck as $file) {
if ($file['name'] == $name && $file['type'] == '**dir') {
$isDir = true;
break;
}
}
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)));
}
foreach ($file_list as $file) {
if ($file['type'] == '**dir') {
$result = $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;
}
}
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)));
}
}
return true;
}
/**
* Rename a file in the VFS.
*
* @access public
*
* @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)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
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)));
}
return true;
}
/**
* Creates a folder on the VFS.
*
* @access public
*
* @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.
*/
function createFolder($path, $name)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
if (!@ftp_mkdir($this->_stream, $this->_getPath($path, $name))) {
return PEAR::raiseError(sprintf(_("Unable to create VFS directory \"%s\"."), $this->_getPath($path, $name)));
}
return true;
}
/**
* Changes permissions for an Item on the VFS.
*
* @access public
*
* @param string $path Holds the path of directory of the Item.
* @param string $name Holds the name of the Item.
* @param string $permission TODO
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function changePermissions($path, $name, $permission)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
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)));
}
return true;
}
/**
* Returns an unsorted file list.
*
* @access public
*
* @param optional string $path The path of the directory to get the
* file list for.
* @param optional mixed $filter Hash of items to filter based on
* filename.
* @param optional boolean $dotfiles Show dotfiles?
* @param optional boolean $dironly Show directories only?
*
* @return mixed File list on success or a PEAR_Error object on failure.
*/
function listFolder($path = '', $filter = null, $dotfiles = true,
$dironly = false)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$files = array();
$type = @ftp_systype($this->_stream);
if ($type == 'UNKNOWN') {
// Go with unix-style listings by default.
$type = 'UNIX';
}
$olddir = $this->getCurrentDirectory();
if (!empty($path)) {
$res = $this->_setPath($path);
if (is_a($res, 'PEAR_Error')) {
return $res;
}
}
if ($type == 'UNIX') {
// If we don't want dotfiles, We can save work here by not
// doing an ls -a and then not doing the check later (by
// setting $dotfiles to true, the if is short-circuited).
if ($dotfiles) {
$list = ftp_rawlist($this->_stream, '-al');
$dotfiles = true;
} else {
$list = ftp_rawlist($this->_stream, '-l');
}
} else {
$list = ftp_rawlist($this->_stream, '');
}
if (!is_array($list)) {
if (isset($olddir)) {
$res = $this->_setPath($olddir);
if (is_a($res, 'PEAR_Error')) {
return $res;
}
}
return array();
}
foreach ($list as $line) {
$file = array();
$item = preg_split('/\s+/', $line);
if ($type == 'UNIX' || (stristr($type, 'win') && !preg_match('|\d\d-\d\d-\d\d|', $item[0]))) {
if (count($item) < 8 || substr($line, 0, 5) == 'total') {
continue;
}
$file['perms'] = $item[0];
$file['owner'] = $item[2];
$file['group'] = $item[3];
$file['name'] = substr($line, strpos($line, sprintf("%s %2s %5s", $item[5], $item[6], $item[7])) + 13);
// Filter out '.' and '..' entries.
if (preg_match('/^\.\.?\/?$/', $file['name'])) {
continue;
}
// Filter out dotfiles if they aren't wanted.
if (!$dotfiles && substr($file['name'], 0, 1) == '.') {
continue;
}
$p1 = substr($file['perms'], 0, 1);
if ($p1 === 'l') {
$file['link'] = substr($file['name'], strpos($file['name'], '->') + 3);
$file['name'] = substr($file['name'], 0, strpos($file['name'], '->') - 1);
$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));
}
}
} elseif ($p1 === 'd') {
$file['type'] = '**dir';
} else {
$name = explode('.', $file['name']);
if (count($name) == 1 || (substr($file['name'], 0, 1) === '.' && count($name) == 2)) {
$file['type'] = '**none';
} else {
$file['type'] = VFS::strtolower($name[count($name) - 1]);
}
}
if ($file['type'] == '**dir') {
$file['size'] = -1;
} else {
$file['size'] = $item[4];
}
if (strstr($item[7], ':')) {
$file['date'] = strtotime($item[7] . ':00' . $item[5] . ' ' . $item[6] . ' ' . date('Y', time()));
if ($file['date'] > time()) {
$file['date'] = strtotime($item[7] . ':00' . $item[5] . ' ' . $item[6] . ' ' . (date('Y', time()) - 1));
}
} else {
$file['date'] = strtotime('00:00:00' . $item[5] . ' ' . $item[6] . ' ' . $item[7]);
}
} else {
/* Handle Windows FTP servers returning DOS-style file
* listings. */
$file['perms'] = '';
$file['owner'] = '';
$file['group'] = '';
$file['name'] = $item[3];
$index = 4;
while ($index < count($item)) {
$file['name'] .= ' ' . $item[$index];
$index++;
}
$file['date'] = strtotime($item[0] . ' ' . $item[1]);
if ($item[2] == '<DIR>') {
$file['type'] = '**dir';
$file['size'] = -1;
} else {
$file['size'] = $item[2];
$name = explode('.', $file['name']);
if (count($name) == 1 || (substr($file['name'], 0, 1) === '.' && count($name) == 2)) {
$file['type'] = '**none';
} else {
$file['type'] = VFS::strtolower($name[count($name) - 1]);
}
}
}
// Filtering.
if ($this->_filterMatch($filter, $file['name'])) {
unset($file);
continue;
}
if ($dironly && $file['type'] !== '**dir') {
unset($file);
continue;
}
$files[$file['name']] = $file;
unset($file);
}
if (isset($olddir)) {
$res = $this->_setPath($olddir);
if (is_a($res, 'PEAR_Error')) {
return $res;
}
}
return $files;
}
/**
* Returns a sorted list of folders in specified directory.
*
* @access public
*
* @param optional string $path The path of the directory to get
* the directory list for.
* @param optional mixed $filter Hash of items to filter based on
* folderlist.
* @param optional boolean $dotfolders Include dotfolders?
*
* @return mixed Folder list on success or a PEAR_Error object on failure.
*/
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'] = '..';
$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;
}
ksort($folders);
return $folders;
}
/**
* Copies a file through the backend.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $name The filename to use.
* @param string $dest The destination of the file.
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function copy($path, $name, $dest)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$fileCheck = $this->listFolder($dest, null, true);
foreach ($fileCheck as $file) {
if ($file['name'] == $name) {
return PEAR::raiseError(sprintf(_("%s already exists."), $this->_getPath($dest, $name)));
}
}
$isDir = false;
$dirCheck = $this->listFolder($path, null, false);
foreach ($dirCheck as $file) {
if ($file['name'] == $name && $file['type'] == '**dir') {
$isDir = true;
break;
}
}
if ($isDir) {
$result = $this->createFolder($dest, $name);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
$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;
}
}
} else {
$tmpFile = $this->_getTempFile();
$fetch = @ftp_get($this->_stream, $tmpFile, $this->_getPath($path, $name), FTP_BINARY);
if (!$fetch) {
unlink($tmpFile);
return PEAR::raiseError(sprintf(_("Failed to copy from \"%s\"."), $this->_getPath($path, $name)));
}
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)));
}
unlink($tmpFile);
}
return true;
}
/**
* Moves a file through the backend.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $name The filename to use.
* @param string $dest The destination of the file.
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function move($path, $name, $dest)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$fileCheck = $this->listFolder($dest, null, true);
foreach ($fileCheck as $file) {
if ($file['name'] == $name) {
return PEAR::raiseError(sprintf(_("%s already exists."), $this->_getPath($dest, $name)));
}
}
if (!@ftp_rename($this->_stream, $this->_getPath($path, $name), $this->_getPath($dest, $name))) {
return PEAR::raiseError(sprintf(_("Failed to move to \"%s\"."), $this->_getPath($dest, $name)));
}
return true;
}
/**
* Return the current working directory on the FTP server.
*
* @access public
*
* @return string The current working directory.
*/
function getCurrentDirectory()
{
$this->_connect();
return ftp_pwd($this->_stream);
}
/**
* Change directories on the server.
*
* @access private
*
* @param string $path The path to change to.
*
* @return mixed True on success, or a PEAR_Error on failure.
*/
function _setPath($path)
{
if (!@ftp_chdir($this->_stream, $path)) {
return PEAR::raiseError(sprintf(_("Unable to change to %s."), $path));
}
return true;
}
/**
* Returns the full path of an item.
*
* @access private
*
* @param string $path Holds the path of directory of the Item.
* @param string $name Holds the name of the Item.
*
* @return mixed Full path when $path isset and just $name when not set.
*/
function _getPath($path, $name)
{
if ($path !== '') {
return ($path . '/' . $name);
}
return ($name);
}
/**
* Returns the parent directory of specified path.
*
* @access private
*
* @param string $path The path to get the parent of.
*
* @return mixed The parent directory (string) on success
* or a PEAR_Error object on failure.
*/
function _parentDir($path)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$olddir = $this->getCurrentDirectory();
@ftp_cdup($this->_stream);
$parent = $this->getCurrentDirectory();
$this->_setPath($olddir);
if (!$parent) {
return PEAR::raiseError(_("Unable to determine current directory."));
}
return $parent;
}
/**
* Attempts to open a connection to the FTP server.
*
* @access private
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function _connect()
{
if ($this->_stream === false) {
if (!extension_loaded('ftp')) {
return PEAR::raiseError(_("The FTP extension is not available."));
}
if (!is_array($this->_params)) {
return PEAR::raiseError(_("No configuration information specified for FTP VFS."));
}
$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));
}
}
/* 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."));
}
} else {
$this->_stream = @ftp_connect($this->_params['hostspec'], $this->_params['port']);
}
if (!$this->_stream) {
return PEAR::raiseError(_("Connection to FTP server failed."));
}
$connected = @ftp_login($this->_stream, $this->_params['username'], $this->_params['password']);
if (!$connected) {
return PEAR::raiseError(_("Authentication to FTP server failed."));
$this->_disconnect();
}
if (!empty($this->_params['pasv'])) {
@ftp_pasv($this->_stream, true);
}
}
return true;
}
/**
* Disconnect from the FTP server and clean up the connection.
*
* @access private
*/
function _disconnect()
{
@ftp_quit($this->_stream);
$this->_stream = false;
}
/**
* Determine the location of the system temporary directory. If a
* specific setting cannot be found, it defaults to /tmp
*
* @access private
*
* @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 (empty($tmp)) {
$tmp = getenv('TMPDIR');
}
/* If we still cannot determine a value, then cycle through a
* list of preset possibilities. */
while (empty($tmp) && sizeof($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 empty($tmp) ? false : $tmp;
}
/**
* Create a temporary file.
*
* @access private
*
* @return string Returns the full path-name to the temporary file.
* Returns false if a temp file could not be created.
*/
function _getTempFile()
{
$tmp_dir = $this->_getTempDir();
if (empty($tmp_dir)) {
return false;
}
$tmp_file = tempnam($tmp_dir, 'vfs');
/* If the file was created, then register it for deletion and return */
if (empty($tmp_file)) {
return false;
} else {
return $tmp_file;
}
}
}
--- NEW FILE: musql.php ---
<?php
require_once dirname(__FILE__) . '/sql.php';
/** @constant integer VFS_FLAG_READ Permission for read access. */
define('VFS_FLAG_READ', 1);
/** @constant integer VFS_FLAG_WRITE Permission for read access. */
define('VFS_FLAG_WRITE', 2);
/**
* Multi User VFS implementation for PHP's PEAR database
* abstraction layer.
*
* <pre>
* Required values for $params:
* 'phptype' The database type (ie. 'pgsql', 'mysql, etc.).
* 'hostspec' The hostname of the database server.
* 'protocol' The communication protocol ('tcp', 'unix', etc.).
* 'username' The username with which to connect to the database.
* 'password' The password associated with 'username'.
* 'database' The name of the database.
*
* Optional values:
* 'table' The name of the vfs table in 'database'. Defaults to
* 'horde_muvfs'.
*
* Required by some database implementations:
* '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.
* </pre>
*
* Known Issues:
* Delete is not recusive, so file and folders that used to be in a folder that
* gets deleted life forever in the database, or re-appear when the folder is
* recreated.
* Rename has the same issue, if files are lost if a folder is renamed.
*
* The table structure for the VFS can be found in
* horde/scripts/db/muvfs.sql.
*
* Database specific notes:
*
* MSSQL:
* - The vfs_data field must be of type IMAGE.
* - You need the following php.ini settings:
* <code>
* ; Valid range 0 - 2147483647. Default = 4096.
* mssql.textlimit = 0 ; zero to pass through
*
* ; Valid range 0 - 2147483647. Default = 4096.
* mssql.textsize = 0 ; zero to pass through
* </code>
*
* $Horde: framework/VFS/VFS/musql.php,v 1.29 2004/04/08 18:33:17 slusarz Exp $
*
* Copyright 2002-2004 Chuck Hagenbuch <chuck at horde.org>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Chuck Hagenbuch <chuck at horde.org>
* @author Mike Cochrane <mike at graftonhall.co.nz>
* @version $Revision: 1.1 $
* @since Horde 2.2
* @package VFS
*/
class VFS_musql extends VFS_sql {
/**
* List of permissions and if they can be changed in this VFS
*
* @var array $_permissions
*/
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)
);
/**
* Store a file in the VFS from raw data.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $name The filename to use.
* @param string $data The file data.
* @param optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function writeData($path, $name, $data, $autocreate = false)
{
$conn = $this->_connect();
if (PEAR::isError($conn)) {
return $conn;
}
/* Make sure we have write access to this and all parent
* paths. */
if ($path != '') {
$paths = explode('/', $path);
$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');
} else {
$result = $this->autocreatePath($path);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
}
}
$paths[] = $path_name;
$previous = '';
foreach ($paths as $thispath) {
$results = $this->_db->getAll(sprintf('SELECT vfs_owner, vfs_perms FROM %s
WHERE vfs_path = %s AND vfs_name= %s',
$this->_params['table'],
$this->_db->quote($previous),
$this->_db->quote($thispath)));
if (!is_array($results) || count($results) < 1) {
return PEAR::raiseError(_("Unable to create VFS file."));
}
$allowed = false;
foreach ($results as $result) {
if ($result[0] == $this->_params['user'] || $result[1] & VFS_FLAG_WRITE) {
$allowed = true;
break;
}
}
if (!$allowed) {
return PEAR::raiseError(_("Access denied creating VFS file."));
}
$previous = $thispath;
}
}
return parent::writeData($path, $name, $data, $autocreate);
}
/**
* Delete a file from the VFS.
*
* @access public
*
* @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.
*/
function deleteFile($path, $name)
{
$conn = $this->_connect();
if (PEAR::isError($conn)) {
return $conn;
}
$fileList = $this->_db->getAll(sprintf('SELECT vfs_id, vfs_owner, vfs_perms FROM %s
WHERE vfs_path = %s AND vfs_name= %s AND vfs_type = %s',
$this->_params['table'],
$this->_db->quote($path),
$this->_db->quote($name),
$this->_db->quote(VFS_FILE)));
if (!is_array($fileList) || count($fileList) < 1) {
return PEAR::raiseError(_("Unable to delete VFS file."));
}
/* There may be one or more files with the same name but the
user may not have read access to them, so doesn't see
them. So we have to delete the one they have access to. */
foreach ($fileList as $file) {
if ($file[1] == $this->_params['user'] || $file[2] & VFS_FLAG_WRITE) {
$result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_id = %s',
$this->_params['table'],
$this->_db->quote($file[0])));
if ($this->_db->affectedRows() == 0) {
return PEAR::raiseError(_("Unable to delete VFS file."));
}
return $result;
}
}
// FIXME: 'Access Denied deleting file %s/%s'
return PEAR::raiseError(_("Unable to delete VFS file."));
}
/**
* Rename a file or folder in the VFS.
*
* @access public
*
* @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)
{
$conn = $this->_connect();
if (PEAR::isError($conn)) {
return $conn;
}
$fileList = $this->_db->getAll(sprintf('SELECT vfs_id, vfs_owner, vfs_perms FROM %s
WHERE vfs_path = %s AND vfs_name= %s',
$this->_params['table'],
$this->_db->quote($oldpath),
$this->_db->quote($oldname)));
if (!is_array($fileList) || count($fileList) < 1) {
return PEAR::raiseError(_("Unable to rename VFS file."));
}
/* There may be one or more files with the same name but the user may
* not have read access to them, so doesn't see them. So we have to
* rename the one they have access to. */
foreach ($fileList as $file) {
if ($file[1] == $this->_params['user'] || $file[2] & VFS_FLAG_WRITE) {
$result = $this->_db->query(sprintf('UPDATE %s SET vfs_path = %s, vfs_name = %s, vfs_modified = %s
WHERE vfs_id = %s',
$this->_params['table'],
$this->_db->quote($newpath),
$this->_db->quote($newname),
$this->_db->quote(time()),
$this->_db->quote($file[0])));
return $result;
}
}
return PEAR::raiseError(sprintf(_("Unable to rename VFS file %s/%s."), $oldpath, $oldname));
}
/**
* Creates a folder on the VFS.
*
* @access public
*
* @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.
*/
function createFolder($path, $name)
{
$conn = $this->_connect();
if (PEAR::isError($conn)) {
return $conn;
}
/* make sure we have write access to this and all parent paths */
if ($path != "") {
$paths = explode('/', $path);
$previous = '';
foreach ($paths as $thispath) {
$results = $this->_db->getAll(sprintf('SELECT vfs_owner, vfs_perms FROM %s
WHERE vfs_path = %s AND vfs_name= %s',
$this->_params['table'],
$this->_db->quote($previous),
$this->_db->quote($thispath)));
if (!is_array($results) || count($results) < 1) {
return PEAR::raiseError(_("Unable to create VFS directory."));
}
$allowed = false;
foreach ($results as $result) {
if ($result[0] == $this->_params['user'] || $result[1] & VFS_FLAG_WRITE) {
$allowed = true;
break;
}
}
if (!$allowed) {
return PEAR::raiseError(_("Access denied creating VFS directory."));
}
$previous = $thispath;
}
}
$id = $this->_db->nextId($this->_params['table']);
return $this->_db->query(sprintf('INSERT INTO %s (vfs_id, vfs_type, vfs_path, vfs_name, vfs_modified, vfs_owner, vfs_perms)
VALUES (%s, %s, %s, %s, %s, %s, %s)',
$this->_params['table'],
$this->_db->quote($id),
$this->_db->quote(VFS_FOLDER),
$this->_db->quote($path),
$this->_db->quote($name),
$this->_db->quote(time()),
$this->_db->quote($this->_params['user']),
$this->_db->quote(0)
));
}
/**
* Delete a file from the VFS.
*
* @access public
*
* @param string $path The path to delete the folder from.
* @param string $name The foldername to use.
* @param optional boolean $recursive Force a recursive delete?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function deleteFolder($path, $name, $recursive = false)
{
$conn = $this->_connect();
if (PEAR::isError($conn)) {
return $conn;
}
if ($recursive) {
$result = $this->emptyFolder($path . '/' . $name);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
} 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));
}
}
$fileList = $this->_db->getAll(sprintf('SELECT vfs_id, vfs_owner, vfs_perms FROM %s
WHERE vfs_path = %s AND vfs_name= %s AND vfs_type = %s',
$this->_params['table'],
$this->_db->quote($path),
$this->_db->quote($name),
$this->_db->quote(VFS_FOLDER)));
if (!is_array($fileList) || count($fileList) < 1) {
return PEAR::raiseError(_("Unable to delete VFS directory."));
}
/* There may be one or more folders with the same name but as the user
* may not have read access to them, they don't see them. So we have to
* delete the one they have access to */
foreach ($fileList as $file) {
if ($file[1] == $this->_params['user'] || $file[2] & VFS_FLAG_WRITE) {
$result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_id = %s',
$this->_params['table'],
$this->_db->quote($file[0])));
if ($this->_db->affectedRows() == 0) {
return PEAR::raiseError(_("Unable to delete VFS directory."));
}
return $result;
}
}
// FIXME: 'Access Denied deleting folder %s/%s'
return PEAR::raiseError(_("Unable to delete VFS directory."));
}
/**
* Return a list of the contents of a folder.
*
* @param string $path The path of the directory.
* @param optional mixed $filter String/hash to filter file/dirname
* on.
* @param optional boolean $dotfiles Show dotfiles?
* @param optional boolean $dironly Show only directories?
*
* @return mixed File list on success or false on failure.
*/
function listFolder($path, $filter = null, $dotfiles = true,
$dironly = false)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$files = array();
$fileList = array();
$fileList = $this->_db->getAll(sprintf('SELECT vfs_name, vfs_type, vfs_modified, vfs_owner, vfs_perms, vfs_data FROM %s
WHERE vfs_path = %s AND (vfs_owner = %s or vfs_perms && %s)',
$this->_params['table'],
$this->_db->quote($path),
$this->_db->quote($this->_params['user']),
$this->_db->quote(VFS_FLAG_READ)
));
if (is_a($fileList, 'PEAR_Error')) {
return $fileList;
}
foreach ($fileList as $line) {
// Filter out dotfiles if they aren't wanted.
if (!$dotfiles && substr($line[0], 0, 1) == '.') {
continue;
}
$file['name'] = stripslashes($line[0]);
if ($line[1] == VFS_FILE) {
$name = explode('.', $line[0]);
if (count($name) == 1) {
$file['type'] = '**none';
} else {
$file['type'] = VFS::strtolower($name[count($name) - 1]);
}
$file['size'] = VFS::strlen($line[5]);
} elseif ($line[1] == VFS_FOLDER) {
$file['type'] = '**dir';
$file['size'] = -1;
}
$file['date'] = $line[2];
$file['owner'] = $line[3];
$line[4] = intval($line[4]);
$file['perms'] = ($line[1] == VFS_FOLDER) ? 'd' : '-';
$file['perms'] .= 'rw-';
$file['perms'] .= ($line[4] & VFS_FLAG_READ) ? 'r' : '-';
$file['perms'] .= ($line[4] & VFS_FLAG_WRITE) ? 'w' : '-';
$file['perms'] .= '-';
$file['group'] = '-';
// filtering
if ($this->_filterMatch($filter, $file['name'])) {
unset($file);
continue;
}
if ($dironly && $file['type'] !== '**dir') {
unset($file);
continue;
}
$files[$file['name']] = $file;
unset($file);
}
return $files;
}
/**
* Changes permissions for an Item on the VFS.
*
* @access public
*
* @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.
*/
function changePermissions($path, $name, $permission)
{
$conn = $this->_connect();
if (PEAR::isError($conn)) {
return $conn;
}
$val = intval(substr($permission, -1));
$perm = 0;
$perm |= ($val & 4) ? VFS_FLAG_READ : 0;
$perm |= ($val & 2) ? VFS_FLAG_WRITE : 0;
$fileList = $this->_db->getAll(sprintf('SELECT vfs_id, vfs_owner, vfs_perms FROM %s
WHERE vfs_path = %s AND vfs_name= %s',
$this->_params['table'],
$this->_db->quote($path),
$this->_db->quote($name)));
if (!is_array($fileList) || count($fileList) < 1) {
return PEAR::raiseError(_("Unable to rename VFS file."));
}
/* There may be one or more files with the same name but the user may
* not have read access to them, so doesn't see them. So we have to
* chmod the one they have access to. */
foreach ($fileList as $file) {
if ($file[1] == $this->_params['user'] || $file[2] & VFS_FLAG_WRITE) {
$result = $this->_db->query(sprintf('UPDATE %s SET vfs_perms = %s
WHERE vfs_id = %s',
$this->_params['table'],
$this->_db->quote($perm),
$this->_db->quote($file[0])));
return $result;
}
}
return PEAR::raiseError(sprintf(_("Unable to change permission for VFS file %s/%s."), $path, $name));
}
}
--- NEW FILE: sql.php ---
<?php
/** @constant integer VFS_FILE File value for vfs_type column. */
define('VFS_FILE', 1);
/** @constant integer VFS_FOLDER Folder value for vfs_type column. */
define('VFS_FOLDER', 2);
/**
* VFS implementation for PHP's PEAR database abstraction layer.
*
* <pre>
* Required values for $params:
* 'phptype' The database type (ie. 'pgsql', 'mysql, etc.).
* 'hostspec' The hostname of the database server.
* 'protocol' The communication protocol ('tcp', 'unix', etc.).
* 'username' The username with which to connect to the database.
* 'password' The password associated with 'username'.
* 'database' The name of the database.
*
* Optional values:
* 'table' The name of the vfs table in 'database'. Defaults to
* 'horde_vfs'.
*
* Required by some database implementations:
* '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.
* </pre>
*
* The table structure for the VFS can be found in
* horde/scripts/db/vfs.sql.
*
* Database specific notes:
*
* MSSQL:
* <pre>
* - The vfs_data field must be of type IMAGE.
* - You need the following php.ini settings:
* ; Valid range 0 - 2147483647. Default = 4096.
* mssql.textlimit = 0 ; zero to pass through
*
* ; Valid range 0 - 2147483647. Default = 4096.
* mssql.textsize = 0 ; zero to pass through
* </pre>
*
* $Horde: framework/VFS/VFS/sql.php,v 1.79 2004/05/25 14:39:19 jan Exp $
*
* Copyright 2002-2004 Chuck Hagenbuch <chuck at horde.org>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Chuck Hagenbuch <chuck at horde.org>
* @version $Revision: 1.1 $
* @since Horde 2.2
* @package VFS
*/
class VFS_sql extends VFS {
/**
* Handle for the current database connection.
*
* @var object DB $_db
*/
var $_db = false;
/**
* Retrieve a file from the VFS.
*
* @access public
*
* @param string $path The pathname to the file.
* @param string $name The filename to retrieve.
*
* @return string The file data.
*/
function read($path, $name)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
return $this->_readBlob($this->_params['table'], 'vfs_data',
array('vfs_path' => $path,
'vfs_name' => $name));
}
/**
* Store a file in the VFS.
*
* @access public
*
* @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 optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function write($path, $name, $tmpFile, $autocreate = false)
{
$dataFP = @fopen($tmpFile, 'rb');
$data = @fread($dataFP, filesize($tmpFile));
fclose($dataFP);
return $this->writeData($path, $name, $data, $autocreate);
}
/**
* Store a file in the VFS from raw data.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $name The filename to use.
* @param string $data The file data.
* @param optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function writeData($path, $name, $data, $autocreate = false)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
/* Check to see if the data already exists. */
$sql = sprintf('SELECT vfs_id FROM %s WHERE vfs_path %s AND vfs_name = %s',
$this->_params['table'],
(empty($path) && $this->_db->dbsyntax == 'oci8') ? ' IS NULL' : ' = ' . $this->_db->quote($path),
$this->_db->quote($name));
$id = $this->_db->getOne($sql);
if (is_a($id, 'PEAR_Error')) {
return $id;
}
if (!is_null($id)) {
return $this->_updateBlob($this->_params['table'], 'vfs_data',
$data, array('vfs_id' => $id),
array('vfs_modified' => time()));
} else {
/* Check to see if the folder already exists. */
$dirs = explode('/', $path);
$path_name = array_pop($dirs);
$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;
}
}
}
$id = $this->_db->nextId($this->_params['table']);
if (is_a($id, 'PEAR_Error')) {
return $id;
}
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']));
}
}
/**
* Delete a file from the VFS.
*
* @access public
*
* @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.
*/
function deleteFile($path, $name)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$sql = sprintf('DELETE FROM %s WHERE vfs_type = %s AND vfs_path %s AND vfs_name = %s',
$this->_params['table'],
$this->_db->quote(VFS_FILE),
(empty($path) && $this->_db->dbsyntax == 'oci8') ? ' IS NULL' : ' = ' . $this->_db->quote($path),
$this->_db->quote($name));
$result = $this->_db->query($sql);
if ($this->_db->affectedRows() == 0) {
return PEAR::raiseError(_("Unable to delete VFS file."));
}
return $result;
}
/**
* Rename a file or folder in the VFS.
*
* @access public
*
* @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)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$sql = sprintf('UPDATE %s SET vfs_path = %s, vfs_name = %s, vfs_modified = %s WHERE vfs_path = %s AND vfs_name = %s',
$this->_params['table'],
$this->_db->quote($newpath),
$this->_db->quote($newname),
$this->_db->quote(time()),
$this->_db->quote($oldpath),
$this->_db->quote($oldname));
$result = $this->_db->query($sql);
if ($this->_db->affectedRows() == 0) {
return PEAR::raiseError(_("Unable to rename VFS file."));
}
$rename = $this->_recursiveRename($oldpath, $oldname, $newpath, $newname);
if (is_a($rename, 'PEAR_Error')) {
return PEAR::raiseError(sprintf(_("Unable to rename VFS directory: %s."), $rename->getMessage()));
}
return $result;
}
/**
* Creates a folder on the VFS.
*
* @access public
*
* @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.
*/
function createFolder($path, $name)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$id = $this->_db->nextId($this->_params['table']);
if (is_a($id, 'PEAR_Error')) {
return $id;
}
$sql = sprintf('INSERT INTO %s (vfs_id, vfs_type, vfs_path, vfs_name, vfs_modified, vfs_owner) VALUES (%s, %s, %s, %s, %s, %s)',
$this->_params['table'],
$this->_db->quote($id),
$this->_db->quote(VFS_FOLDER),
$this->_db->quote($path),
$this->_db->quote($name),
$this->_db->quote(time()),
$this->_db->quote($this->_params['user']));
return $this->_db->query($sql);
}
/**
* Delete a folder from the VFS.
*
* @access public
*
* @param string $path The path of the folder.
* @param string $name The folder name to use.
* @param optional boolean $recursive Force a recursive delete?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function deleteFolder($path, $name, $recursive = false)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$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')) {
return $folderList;
} elseif (!empty($folderList)) {
return PEAR::raiseError(sprintf(_("Unable to delete %s, the directory is not empty"),
$path . '/' . $name));
}
}
/* First delete everything below the folder, so if error we get
* no orphans */
$sql = sprintf('DELETE FROM %s WHERE vfs_path %s',
$this->_params['table'],
(empty($folderPath) && $this->_db->dbsyntax == 'oci8') ? ' IS NULL' : ' LIKE ' . $this->_db->quote($this->_getNativePath($folderPath, '%')));
$deleteContents = $this->_db->query($sql);
if (is_a($deleteContents, 'PEAR_Error')) {
return PEAR::raiseError(sprintf(_("Unable to delete VFS recursively: %s."), $deleteContents->getMessage()));
}
/* Now delete everything inside the folder. */
$sql = sprintf('DELETE FROM %s WHERE vfs_path %s',
$this->_params['table'],
(empty($path) && $this->_db->dbsyntax == 'oci8') ? ' IS NULL' : ' = ' . $this->_db->quote($folderPath));
$delete = $this->_db->query($sql);
if (is_a($delete, 'PEAR_Error')) {
return PEAR::raiseError(sprintf(_("Unable to delete VFS directory: %s."), $delete->getMessage()));
}
/* All ok now delete the actual folder */
$sql = sprintf('DELETE FROM %s WHERE vfs_path %s AND vfs_name = %s',
$this->_params['table'],
(empty($path) && $this->_db->dbsyntax == 'oci8') ? ' IS NULL' : ' = ' . $this->_db->quote($path),
$this->_db->quote($name));
$delete = $this->_db->query($sql);
if (is_a($delete, 'PEAR_Error')) {
return PEAR::raiseError(sprintf(_("Unable to delete VFS directory: %s."), $delete->getMessage()));
}
return $delete;
}
/**
* Return a list of the contents of a folder.
*
* @access public
*
* @param string $path The directory path.
* @param optional mixed $filter String/hash of items to filter based
* on filename.
* @param optional boolean $dotfiles Show dotfiles?
* @param optional boolean $dironly Show directories only?
*
* @return mixed File list on success or false on failure.
*/
function listFolder($path, $filter = null, $dotfiles = true,
$dironly = false)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$files = array();
$fileList = array();
// Fix for an ODD Oracle quirk.
if (empty($path) && $this->_db->dbsyntax == 'oci8') {
$where = 'vfs_path IS NULL';
} else {
$where = 'vfs_path = ' . $this->_db->quote($path);
}
$sql = sprintf('SELECT vfs_name, vfs_type, vfs_data, vfs_modified, vfs_owner FROM %s WHERE %s',
$this->_params['table'],
$where);
$fileList = $this->_db->getAll($sql);
if (is_a($fileList, 'PEAR_Error')) {
return $fileList;
}
foreach ($fileList as $line) {
// Filter out dotfiles if they aren't wanted.
if (!$dotfiles && substr($line[0], 0, 1) == '.') {
continue;
}
$file['name'] = $line[0];
if ($line[1] == VFS_FILE) {
$name = explode('.', $line[0]);
if (count($name) == 1) {
$file['type'] = '**none';
} else {
$file['type'] = VFS::strtolower($name[count($name) - 1]);
}
$file['size'] = VFS::strlen($line[2]);
} elseif ($line[1] == VFS_FOLDER) {
$file['type'] = '**dir';
$file['size'] = -1;
}
$file['date'] = $line[3];
$file['owner'] = $line[4];
$file['perms'] = '-';
$file['group'] = '-';
// filtering
if ($this->_filterMatch($filter, $file['name'])) {
unset($file);
continue;
}
if ($dironly && $file['type'] !== '**dir') {
unset($file);
continue;
}
$files[$file['name']] = $file;
unset($file);
}
return $files;
}
/**
* Returns a sorted list of folders in specified directory.
*
* @access public
*
* @param optional string $path The path of the directory to get
* the directory list for.
* @param optional mixed $filter String/hash of items to filter
* based on folderlist.
* @param optional boolean $dotfolders Include dotfolders?
*
* @return mixed Folder list on success or PEAR_Error object on failure.
*/
function listFolders($path = '', $filter = null, $dotfolders = true)
{
$sql = sprintf('SELECT vfs_name, vfs_path FROM %s WHERE vfs_path = %s AND vfs_type = %s',
$this->_params['table'],
$path,
VFS_FOLDER);
$folderList = $this->_db->getAll($sql);
if (is_a($folderList, 'PEAR_Error')) {
return $folderList;
}
$folders = array();
foreach ($folderList as $line) {
$folder['val'] = $this->_getSQLNativePath($line[1], $line[0]);
$folder['abbrev'] = '';
$folder['label'] = '';
$count = substr_count($folder['val'], '/');
$x = 0;
while ($x < $count) {
$folder['abbrev'] .= ' ';
$folder['label'] .= ' ';
$x++;
}
$folder['abbrev'] .= $line[0];
$folder['label'] .= $line[0];
$strlen = VFS::strlen($folder['label']);
if ($strlen > 26) {
$folder['abbrev'] = substr($folder['label'], 0, ($count * 4));
$length = (29 - ($count * 4)) / 2;
$folder['abbrev'] .= substr($folder['label'], ($count * 4), $length);
$folder['abbrev'] .= '...';
$folder['abbrev'] .= substr($folder['label'], -1 * $length, $length);
}
$found = false;
foreach ($filter as $fltr) {
if ($folder['val'] == $fltr) {
$found = true;
}
}
if (!$found) {
$folders[$folder['val']] = $folder;
}
}
ksort($folders);
return $folders;
}
/**
* 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.
*/
function _recursiveRename($oldpath, $oldname, $newpath, $newname)
{
$sql = sprintf('SELECT vfs_name FROM %s WHERE vfs_type = %s AND vfs_path = %s',
$this->_params['table'],
$this->_db->quote(VFS_FOLDER),
$this->_db->quote($this->_getNativePath($oldpath, $oldname)));
$folderList = $this->_db->getCol($sql);
foreach ($folderList as $folder) {
$this->_recursiveRename($this->_getNativePath($oldpath, $oldname), $folder, $this->_getNativePath($newpath, $newname), $folder);
}
$sql = sprintf('UPDATE %s SET vfs_path = %s WHERE vfs_path = %s',
$this->_params['table'],
$this->_db->quote($this->_getNativePath($newpath, $newname)),
$this->_db->quote($this->_getNativePath($oldpath, $oldname)));
$result = $this->_db->query($sql);
return $result;
}
/**
* 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)
{
if (empty($path)) {
return $name;
}
if (!empty($path)) {
if (isset($this->_params['home']) &&
preg_match('|^~/?(.*)$|', $path, $matches)) {
$path = $this->_params['home'] . '/' . $matches[1];
}
}
return $path . '/' . $name;
}
/**
* Attempts to open a persistent connection to the SQL server.
*
* @access private
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function _connect()
{
if ($this->_db === false) {
if (!is_array($this->_params)) {
return PEAR::raiseError(_("No configuration information specified for SQL VFS."));
}
$required = array('phptype', 'hostspec', 'username', 'password', 'database');
foreach ($required as $val) {
if (!isset($this->_params[$val])) {
return PEAR::raiseError(sprintf(_("Required '%s' not specified in VFS configuration."), $val));
}
}
if (!isset($this->_params['table'])) {
$this->_params['table'] = 'horde_vfs';
}
/* 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'])));
if (is_a($this->_db, 'PEAR_Error')) {
$error = $this->_db;
$this->_db = false;
return $error;
}
/* Enable the "portability" option. */
$this->_db->setOption('optimize', 'portability');
}
return true;
}
/**
* Disconnect from the SQL server and clean up the connection.
*
* @access private
*/
function _disconnect()
{
if ($this->_db) {
$this->_db->disconnect();
$this->_db = false;
}
}
/**
* TODO
*
* @access private
*
* @param string $table TODO
* @param string $field TODO
* @param string $criteria TODO
*
* @return mixed TODO
*/
function _readBlob($table, $field, $criteria)
{
if (!count($criteria)) {
return PEAR::raiseError('You must specify the fetch criteria');
}
$where = '';
switch ($this->_db->dbsyntax) {
case 'oci8':
foreach ($criteria as $key => $value) {
if (!empty($where)) {
$where .= ' AND ';
}
if (empty($value)) {
$where .= $key . ' IS NULL';
} else {
$where .= $key . ' = ' . $this->_db->quote($value);
}
}
$statement = OCIParse($this->_db->connection,
sprintf('SELECT %s FROM %s WHERE %s',
$field, $table, $where));
OCIExecute($statement);
if (OCIFetchInto($statement, $lob)) {
$result = $lob[0]->load();
if (is_null($result)) {
$result = PEAR::raiseError('Unable to load SQL data.');
}
} else {
$result = PEAR::raiseError('Unable to load SQL data.');
}
OCIFreeStatement($statement);
break;
default:
foreach ($criteria as $key => $value) {
if (!empty($where)) {
$where .= ' AND ';
}
$where .= $key . ' = ' . $this->_db->quote($value);
}
$sql = sprintf('SELECT %s FROM %s WHERE %s',
$field, $table, $where);
$result = $this->_db->getOne($sql);
if (is_null($result)) {
$result = PEAR::raiseError('Unable to load SQL data.');
} else {
switch ($this->_db->dbsyntax) {
case 'pgsql':
$result = pack('H' . strlen($result), $result);
break;
}
}
}
return $result;
}
/**
* TODO
*
* @access private
*
* @param string $table TODO
* @param string $field TODO
* @param string $data TODO
* @param string $attributes TODO
*
* @return mixed TODO
*/
function _insertBlob($table, $field, $data, $attributes)
{
$fields = array();
$values = array();
switch ($this->_db->dbsyntax) {
case 'oci8':
foreach ($attributes as $key => $value) {
$fields[] = $key;
$values[] = $this->_db->quote($value);
}
$statement = OCIParse($this->_db->connection,
sprintf('INSERT INTO %s (%s, %s)' .
' VALUES (%s, EMPTY_BLOB()) RETURNING %s INTO :blob',
$table,
implode(', ', $fields),
$field,
implode(', ', $values),
$field));
$lob = OCINewDescriptor($this->_db->connection);
OCIBindByName($statement, ':blob', $lob, -1, SQLT_BLOB);
OCIExecute($statement, OCI_DEFAULT);
$lob->save($data);
$result = OCICommit($this->_db->connection);
$lob->free();
OCIFreeStatement($statement);
return $result ? true : PEAR::raiseError('Unknown Error');
default:
foreach ($attributes as $key => $value) {
$fields[] = $key;
$values[] = $value;
}
$query = sprintf('INSERT INTO %s (%s, %s) VALUES (%s)',
$table,
implode(', ', $fields),
$field,
'?' . str_repeat(', ?', count($values)));
break;
}
switch ($this->_db->dbsyntax) {
case 'mssql':
case 'pgsql':
$values[] = bin2hex($data);
break;
default:
$values[] = $data;
}
/* Execute the query. */
$stmt = $this->_db->prepare($query);
return $this->_db->execute($stmt, $values);
}
/**
* TODO
*
* @access private
*
* @param string $table TODO
* @param string $field TODO
* @param string $data TODO
* @param string $where TODO
* @param array $alsoupdate TODO
*
* @return mixed TODO
*/
function _updateBlob($table, $field, $data, $where, $alsoupdate)
{
$fields = array();
$values = array();
switch ($this->_db->dbsyntax) {
case 'oci8':
$wherestring = '';
foreach ($where as $key => $value) {
if (!empty($wherestring)) {
$wherestring .= ' AND ';
}
$wherestring .= $key . ' = ' . $this->_db->quote($value);
}
$statement = OCIParse($this->_db->connection,
sprintf('SELECT %s FROM %s FOR UPDATE WHERE %s',
$field,
$table,
$wherestring));
OCIExecute($statement, OCI_DEFAULT);
OCIFetchInto($statement, $lob);
$lob[0]->save($data);
$result = OCICommit($this->_db->connection);
$lob[0]->free();
OCIFreeStatement($statement);
return $result ? true : PEAR::raiseError('Unknown Error');
default:
$updatestring = '';
$values = array();
foreach ($alsoupdate as $key => $value) {
$updatestring .= $key . ' = ?, ';
$values[] = $value;
}
$updatestring .= $field . ' = ?';
switch ($this->_db->dbsyntax) {
case 'mssql':
case 'pgsql':
$values[] = bin2hex($data);
break;
default:
$values[] = $data;
}
$wherestring = '';
foreach ($where as $key => $value) {
if (!empty($wherestring)) {
$wherestring .= ' AND ';
}
$wherestring .= $key . ' = ?';
$values[] = $value;
}
$query = sprintf('UPDATE %s SET %s WHERE %s',
$table,
$updatestring,
$wherestring);
break;
}
/* Execute the query. */
$stmt = $this->_db->prepare($query);
return $this->_db->execute($stmt, $values);
}
}
--- NEW FILE: sql_file.php ---
<?php
/** @constant integer VFS_FILE File value for vfs_type column. */
define('VFS_FILE', 1);
/** @constant integer VFS_FOLDER Folder value for vfs_type column. */
define('VFS_FOLDER', 2);
/**
* VFS:: implementation using PHP's PEAR database abstraction
* layer and local file system for file storage.
*
* <pre>
* Required values for $params:
* 'phptype' The database type (ie. 'pgsql', 'mysql, etc.).
* 'hostspec' The hostname of the database server.
* 'protocol' The communication protocol ('tcp', 'unix', etc.).
* 'username' The username with which to connect to the database.
* 'password' The password associated with 'username'.
* 'database' The name of the database.
* 'vfsroot' 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'.
*
* Required by some database implementations:
* '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.
* </pre>
*
* The table structure for the VFS can be found in
* horde/scripts/db/vfs.sql.
*
* $Horde: framework/VFS/VFS/sql_file.php,v 1.40 2004/04/08 18:33:17 slusarz Exp $
*
* @author Michael Varghese <mike.varghese at ascellatech.com>
* @version $Revision: 1.1 $
* @since Horde 2.2
* @package VFS
*/
class VFS_sql_file extends VFS {
/**
* Handle for the current database connection.
*
* @var object DB $_db
*/
var $_db = false;
/**
* Retrieve a file from the VFS.
*
* @access public
*
* @param string $path The pathname to the file.
* @param string $name The filename to retrieve.
*
* @return string The file data.
*/
function read($path, $name)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$file = $this->_getNativePath($path, $name);
$fp = @fopen($file, 'rb');
if (!$fp) {
return PEAR::raiseError(_("Unable to open VFS file."));
}
$data = fread($fp, filesize($file));
fclose($fp);
return $data;
}
/**
* Store a file in the VFS, with the data copied from a temporary
* file.
*
* @access public
*
* @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 optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function write($path, $name, $tmpFile, $autocreate = false)
{
$dataFP = @fopen($tmpFile, 'rb');
$data = @fread($dataFP, filesize($tmpFile));
fclose($dataFP);
return $this->writeData($path, $name, $data, $autocreate);
}
/**
* Store a file in the VFS from raw data.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $name The filename to use.
* @param string $data The file data.
* @param optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function writeData($path, $name, $data, $autocreate = false)
{
$fp = @fopen($this->_getNativePath($path, $name), 'w');
if (!$fp) {
if ($autocreate) {
$result = $this->autocreatePath($path);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
$fp = @fopen($this->_getNativePath($path, $name), 'w');
if (!$fp) {
return PEAR::raiseError(_("Unable to open VFS file for writing."));
}
}
return PEAR::raiseError(_("Unable to open VFS file for writing."));
}
if (!@fwrite($fp, $data)) {
return PEAR::raiseError(_("Unable to write VFS file data."));
}
if (is_a($this->_writeSQLData($path, $name, $autocreate), 'PEAR_Error')) {
@unlink($this->_getNativePath($path, $name));
return PEAR::raiseError(_("Unable to write VFS file data."));
}
}
/**
* Moves a file in the database and the file system.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $name The old filename.
* @param string $dest The new filename.
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function move($path, $name, $dest)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$fileCheck = $this->listFolder($dest, null, false);
foreach ($fileCheck as $file) {
if ($file['name'] == $name) {
return PEAR::raiseError(_("Unable to move VFS file."));
}
}
if (strpos($dest, $this->_getSQLNativePath($path, $name)) !== false) {
return PEAR::raiseError(_("Unable to move VFS file."));
}
return $this->rename($path, $name, $dest, $name);
}
/**
* Copies a file through the backend.
*
* @access public
*
* @param string $path The path to store the file in.
* @param string $name The filename to use.
* @param string $dest The destination of the file.
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function copy($path, $name, $dest)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$fileCheck = $this->listFolder($dest, null, false);
foreach ($fileCheck as $file) {
if ($file['name'] == $name) {
return PEAR::raiseError(_("Unable to copy VFS file."));
}
}
if (strpos($dest, $this->_getSQLNativePath($path, $name)) !== false) {
return PEAR::raiseError(_("Unable to copy VFS file."));
}
if (is_dir($this->_getNativePath($path, $name))) {
return $this->_recursiveCopy($path, $name, $dest);
}
if (!@copy($this->_getNativePath($path, $name), $this->_getNativePath($dest, $name))) {
return PEAR::raiseError(_("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 (%s, %s, %s, %s, %s, %s)',
$this->_params['table'],
$this->_db->quote($id),
$this->_db->quote(VFS_FILE),
$this->_db->quote($dest),
$this->_db->quote($name),
$this->_db->quote(time()),
$this->_db->quote($this->_params['user'])
);
$result = $this->_db->query($query);
if (is_a($result, 'PEAR_Error')) {
unlink($this->_getNativePath($dest, $name));
return $result;
}
return true;
}
/**
* Creates a folder on the VFS.
*
* @access public
*
* @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.
*/
function createFolder($path, $name)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$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 (%s, %s, %s, %s, %s, %s)',
$this->_params['table'],
$this->_db->quote($id),
$this->_db->quote(VFS_FOLDER),
$this->_db->quote($path),
$this->_db->quote($name),
$this->_db->quote(time()),
$this->_db->quote($this->_params['user'])));
if (is_a($result, 'PEAR_Error')) {
return $result;
}
if (!@mkdir($this->_getNativePath($path, $name))) {
$result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_id = %s',
$this->_params['table'],
$this->_db->quote($id)));
return PEAR::raiseError(_("Unable to create VFS directory."));
}
return true;
}
/**
* Rename a file or folder in the VFS.
*
* @access public
*
* @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)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$result = $this->_db->query(sprintf('UPDATE %s SET vfs_path = %s, vfs_name = %s, vfs_modified = %s
WHERE vfs_path = %s AND vfs_name = %s',
$this->_params['table'],
$this->_db->quote($newpath),
$this->_db->quote($newname),
$this->_db->quote(time()),
$this->_db->quote($oldpath),
$this->_db->quote($oldname)));
if ($this->_db->affectedRows() == 0) {
return PEAR::raiseError(_("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 = %s, vfs_name = %s
WHERE vfs_path = %s AND vfs_name = %s',
$this->_params['table'],
$this->_db->quote($oldpath),
$this->_db->quote($oldname),
$this->_db->quote($newpath),
$this->_db->quote($newname)));
return PEAR::raiseError(_("Unable to rename VFS directory."));
}
if (!@rename($this->_getNativePath($oldpath, $oldname), $this->_getNativePath($newpath, $newname))) {
$result = $this->_db->query(sprintf('UPDATE %s SET vfs_path = %s, vfs_name = %s
WHERE vfs_path = %s AND vfs_name = %s',
$this->_params['table'],
$this->_db->quote($oldpath),
$this->_db->quote($oldname),
$this->_db->quote($newpath),
$this->_db->quote($newname)));
return PEAR::raiseError(_("Unable to rename VFS file."));
}
return true;
}
/**
* Delete a folder from the VFS.
*
* @access public
*
* @param string $path The path to delete the folder from.
* @param string $name The foldername to use.
* @param optional boolean $recursive Force a recursive delete?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function deleteFolder($path, $name, $recursive = false)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
if ($recursive) {
$result = $this->emptyFolder($path . '/' . $name);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
} 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));
}
}
$result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_type = %s AND vfs_path = %s AND vfs_name = %s',
$this->_params['table'],
$this->_db->quote(VFS_FOLDER),
$this->_db->quote($path),
$this->_db->quote($name)));
if ($this->_db->affectedRows() == 0 || is_a($result, 'PEAR_Error')) {
return PEAR::raiseError(_("Unable to delete VFS directory."));
}
if (is_a($this->_recursiveSQLDelete($path, $name), 'PEAR_Error')) {
return PEAR::raiseError(_("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;
}
/**
* Delete a file from the VFS.
*
* @access public
*
* @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.
*/
function deleteFile($path, $name)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_type = %s AND vfs_path = %s AND vfs_name = %s',
$this->_params['table'],
$this->_db->quote(VFS_FILE),
$this->_db->quote($path),
$this->_db->quote($name)));
if ($this->_db->affectedRows() == 0) {
return PEAR::raiseError(_("Unable to delete VFS file."));
}
if (is_a($result, 'PEAR_Error')) {
return $result;
}
if (!@unlink($this->_getNativePath($path, $name))) {
return PEAR::raiseError(_("Unable to delete VFS file."));
}
}
/**
* Return a list of the contents of a folder.
*
* @access public
*
* @param string $path The directory path.
* @param optional mixed $filter String/hash of items to filter based
* on filename.
* @param optional boolean $dotfiles Show dotfiles?
* @param optional boolean $dironly Show directories only?
*
* @return mixed File list on success or false on failure.
*/
function listFolder($path, $filter = null, $dotfiles = true,
$dironly = false)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$files = array();
$fileList = array();
$fileList = $this->_db->getAll(sprintf('SELECT vfs_name, vfs_type, vfs_modified, vfs_owner FROM %s
WHERE vfs_path = %s',
$this->_params['table'],
$this->_db->quote($path)));
if (is_a($fileList, 'PEAR_Error')) {
return $fileList;
}
foreach ($fileList as $line) {
// Filter out dotfiles if they aren't wanted.
if (!$dotfiles && substr($line[0], 0, 1) == '.') {
continue;
}
$file['name'] = $line[0];
if ($line[1] == VFS_FILE) {
$name = explode('.', $line[0]);
if (count($name) == 1) {
$file['type'] = '**none';
} else {
$file['type'] = VFS::strtolower($name[count($name) - 1]);
}
$file['size'] = filesize($this->_getNativePath($path, $line[0]));
} elseif ($line[1] == VFS_FOLDER) {
$file['type'] = '**dir';
$file['size'] = -1;
}
$file['date'] = $line[2];
$file['owner'] = $line[3];
$file['perms'] = '-';
$file['group'] = '-';
// Filtering.
if ($this->_filterMatch($filter, $file['name'])) {
unset($file);
continue;
}
if ($dironly && $file['type'] !== '**dir') {
unset($file);
continue;
}
$files[$file['name']] = $file;
unset($file);
}
return $files;
}
/**
* Returns a sorted list of folders in specified directory.
*
* @access public
*
* @param optional string $path The path of the directory to get
* the directory list for.
* @param optional mixed $filter String/hash of items to filter
* based on folderlist.
* @param optional boolean $dotfolders Include dotfolders?
*
* @return mixed Folder list on success or a PEAR_Error object on failure.
*/
function listFolders($path = '', $filter = null, $dotfolders = true)
{
$sql = sprintf('SELECT vfs_name, vfs_path FROM %s WHERE vfs_path = %s AND vfs_type = %s',
$this->_params['table'],
$path,
VFS_FOLDER);
$folderList = $this->_db->getAll($sql);
if (is_a($folderList, 'PEAR_Error')) {
return $folderList;
}
$folders = array();
foreach ($folderList as $line) {
$folder['val'] = $this->_getSQLNativePath($line[1], $line[0]);
$folder['abbrev'] = '';
$folder['label'] = '';
$count = substr_count($folder['val'], '/');
$x = 0;
while ($x < $count) {
$folder['abbrev'] .= ' ';
$folder['label'] .= ' ';
$x++;
}
$folder['abbrev'] .= $line[0];
$folder['label'] .= $line[0];
$strlen = VFS::strlen($folder['label']);
if ($strlen > 26) {
$folder['abbrev'] = substr($folder['label'], 0, ($count * 4));
$length = (29 - ($count * 4)) / 2;
$folder['abbrev'] .= substr($folder['label'], ($count * 4), $length);
$folder['abbrev'] .= '...';
$folder['abbrev'] .= substr($folder['label'], -1 * $length, $length);
}
$found = false;
foreach ($filter as $fltr) {
if ($folder['val'] == $fltr) {
$found = true;
}
}
if (!$found) {
$folders[$folder['val']] = $folder;
}
}
ksort($folders);
return $folders;
}
/**
* 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.
*/
function _recursiveCopy($path, $name, $dest)
{
$result = $this->createFolder($dest, $name);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
$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;
}
}
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 optional boolean $autocreate Automatically create directories?
*
* @return mixed True on success or a PEAR_Error object on failure.
*/
function _writeSQLData($path, $name, $autocreate = false)
{
$conn = $this->_connect();
if (is_a($conn, 'PEAR_Error')) {
return $conn;
}
$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 (%s, %s, %s, %s, %s, %s)',
$this->_params['table'],
$this->_db->quote($id),
$this->_db->quote(VFS_FILE),
$this->_db->quote($path),
$this->_db->quote($name),
$this->_db->quote(time()),
$this->_db->quote($this->_params['user']));
return $this->_db->query($query);
}
/**
* 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.
*/
function _recursiveSQLRename($oldpath, $oldname, $newpath, $newname)
{
$folderList = $this->_db->getCol(sprintf('SELECT vfs_name FROM %s WHERE vfs_type = %s AND vfs_path = %s',
$this->_params['table'],
$this->_db->quote(VFS_FOLDER),
$this->_db->quote($this->_getSQLNativePath($oldpath, $oldname))));
foreach ($folderList as $folder) {
$this->_recursiveSQLRename($this->_getSQLNativePath($oldpath, $oldname), $folder, $this->_getSQLNativePath($newpath, $newname), $folder);
}
$result = $this->_db->query(sprintf('UPDATE %s SET vfs_path = %s WHERE vfs_path = %s',
$this->_params['table'],
$this->_db->quote($this->_getSQLNativePath($newpath, $newname)),
$this->_db->quote($this->_getSQLNativePath($oldpath, $oldname))));
if (is_a($result, 'PEAR_Error')) {
return $result;
}
}
/**
* 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.
*/
function _recursiveSQLDelete($path, $name)
{
$result = $this->_db->query(sprintf('DELETE FROM %s WHERE vfs_type = %s AND vfs_path = %s',
$this->_params['table'],
$this->_db->quote(VFS_FILE),
$this->_db->quote($this->_getSQLNativePath($path, $name))));
if (is_a($result, 'PEAR_Error')) {
return $result;
}
$folderList = $this->_db->getCol(sprintf('SELECT vfs_name FROM %s WHERE vfs_type = %s AND vfs_path = %s',
$this->_params['table'],
$this->_db->quote(VFS_FOLDER),
$this->_db->quote($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 = %s AND vfs_name = %s AND vfs_path = %s',
$this->_params['table'],
$this->_db->quote(VFS_FOLDER),
$this->_db->quote($name),
$this->_db->quote($path)));
return $result;
}
/**
* 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.
*/
function _recursiveLFSDelete($path, $name)
{
$dir = $this->_getNativePath($path, $name);
$dh = @opendir($dir);
while (false !== ($file = readdir($dh))) {
if ($file != '.' && $file != '..') {
if (is_dir($dir . '/' . $file)) {
$this->_recursiveLFSDelete(empty($path) ? $name : $path . '/' . $name, $file);
} else {
@unlink($dir . '/' . $file);
}
}
}
@closedir($dh);
return 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.
*/
function _connect()
{
if ($this->_db === false) {
if (!is_array($this->_params)) {
return PEAR::raiseError(_("No configuration information specified for SQL-File VFS."));
}
$required = array('phptype', 'hostspec', 'username', 'password', 'database', 'vfsroot');
foreach ($required as $val) {
if (!isset($this->_params[$val])) {
return PEAR::raiseError(sprintf(_("Required '%s' not specified in VFS configuration."), $val));
}
}
if (!isset($this->_params['table'])) {
$this->_params['table'] = 'horde_vfs';
}
/* 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'])));
if (DB::isError($this->_db)) {
$error = $this->_db;
$this->_db = false;
return $error;
}
/* Enable the "portability" option. */
$this->_db->setOption('optimize', 'portability');
}
return true;
}
/**
* Disconnect from the SQL server and clean up the connection.
*
* @access private
*/
function _disconnect()
{
if ($this->_db) {
$this->_db->disconnect();
$this->_db = false;
}
}
/**
* 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)
{
if (!empty($name)) {
$name = '/' . $name;
}
if (isset($path)) {
if (isset($this->_params['home']) &&
preg_match('|^~/?(.*)$|', $path, $matches)) {
$path = $this->_params['home'] . '/' . $matches[1];
}
return $this->_params['vfsroot'] . '/' . $path . $name;
} else {
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)
{
if (empty($path)) {
return $name;
}
return $path . '/' . $name;
}
}
- Previous message: steffen: server/kolab-horde-framework/kolab-horde-framework/XML_WBXML/WBXML ContentHandler.php, NONE, 1.1 DTD.php, NONE, 1.1 DTDManager.php, NONE, 1.1 Decoder.php, NONE, 1.1 Encoder.php, NONE, 1.1
- Next message: steffen: server/kolab-horde-framework/kolab-horde-framework/XML_WBXML/WBXML/DTD SyncML.php, NONE, 1.1 SyncMLDevInf.php, NONE, 1.1 SyncMLMetInf.php, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the commits
mailing list