Source for file file.php
Documentation is available at file.php
* VFS implementation for a standard filesystem.
* Required parameters:<pre>
* '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 specify as the 'vfsroot'.
* $Horde: framework/VFS/lib/VFS/file.php,v 1.1.2.6 2009/10/15 17:18:48 jan Exp $
* Copyright 2002-2009 The Horde Project (http://www.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
* List of permissions and if they can be changed in this VFS
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.
* @param array $params A hash containing connection parameters.
if (!empty ($this->_params['vfsroot'])) {
if (substr($this->_params['vfsroot'], -1 ) == '/' ||
substr($this->_params['vfsroot'], -1 ) == '\\') {
$this->_params['vfsroot'] = substr($this->_params['vfsroot'], 0 , strlen($this->_params['vfsroot']) - 1 );
* Retrieves the filesize from the VFS.
* @param string $path The pathname to the file.
* @param string $name The filename to retrieve.
* @return integer The file size.
function size($path, $name)
$size = @filesize($this->_getNativePath ($path, $name));
return PEAR ::raiseError (sprintf(_("Unable to check file size of \"%s/%s\"."), $path, $name));
* Retrieve a file from the VFS.
* @param string $path The pathname to the file.
* @param string $name The filename to retrieve.
* @return string The file data.
function read($path, $name)
return PEAR ::raiseError (_("Unable to open VFS file."));
* Retrieves a file from the VFS as an on-disk local file.
* This function provides a file on local disk with the data of a VFS file
* in it. This file <em>cannot</em> be modified! The behavior if you do
* modify it is undefined. It will be removed at the end of the request.
* @param string $path The pathname to the file.
* @param string $name The filename to retrieve.
* @return string A local filename.
return $this->_getNativePath ($path, $name);
* Open a read-only stream to a file in the VFS.
* @param string $path The pathname to the file.
* @param string $name The filename to retrieve.
* @return resource The stream.
$mode = OS_WINDOWS ? 'rb' : 'r';
$stream = @fopen($this->_getNativePath ($path, $name), $mode);
return PEAR ::raiseError (_("Unable to open VFS file."));
* Retrieves a part of a file from the VFS. Particularly useful when
* reading large files which would exceed the PHP memory limits if they
* were stored in a string.
* @param string $path The pathname to the file.
* @param string $name The filename to retrieve.
* @param integer $offset The offset of the part. (The new offset will
* @param integer $length The length of the part. If the length = -1,
* the whole part after the offset is retrieved.
* If more bytes are given as exists after the
* given offset. Only the available bytes are
* @param integer $remaining The bytes that are left, after the part that
* @return string The file data.
function readByteRange($path, $name, &$offset, $length = -1 , &$remaining)
return PEAR ::raiseError (sprintf(_("Wrong offset %d while reading a VFS file."), $offset));
// Calculate how many bytes MUST be read, so the remainging
// bytes and the new offset can be calculated correctly.
$file = $this->_getNativePath ($path, $name);
if ($length == -1 || (($length + $offset) > $size)) {
$length = $size - $offset;
$fp = @fopen($file, 'rb');
return PEAR ::raiseError (_("Unable to open VFS file."));
$data = fread($fp, $length);
$remaining = $size - $offset;
* Store a file in the VFS, with the data copied from a temporary
* @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
* @param 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 (is_a($res, 'PEAR_Error')) {
return PEAR ::raiseError (_("VFS directory does not exist."));
$res = $this->_checkQuotaWrite ('file', $tmpFile);
if (is_a($res, 'PEAR_Error')) {
// Since we already have the data in a file, don't read it
// into PHP's memory at all - just copy() it to the new
// location. We leave it to the caller to clean up the
// temporary file, so we don't use rename().
if (@copy($tmpFile, $this->_getNativePath ($path, $name))) {
return PEAR ::raiseError (_("Unable to write VFS file (copy() failed)."));
* Moves a file in the database and the file system.
* @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.
* @param boolean $autocreate Automatically create directories?
* @return mixed True on success or a PEAR_Error object on failure.
function move($path, $name, $dest, $autocreate = false )
$orig = $this->_getNativePath ($path, $name);
return PEAR ::raiseError (_("Cannot move file(s) - destination is within source."));
if (is_a($result, 'PEAR_Error')) {
if (is_a($fileCheck, 'PEAR_Error')) {
foreach ($fileCheck as $file) {
if ($file['name'] == $name) {
return PEAR ::raiseError (_("Unable to move VFS file."));
if (!@rename($orig, $this->_getNativePath ($dest, $name))) {
return PEAR ::raiseError (_("Unable to move VFS file."));
* Copies a file through the backend.
* @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.
* @param boolean $autocreate Automatically create directories?
* @return mixed True on success or a PEAR_Error object on failure.
function copy($path, $name, $dest, $autocreate = false )
$orig = $this->_getNativePath ($path, $name);
return PEAR ::raiseError (_("Cannot copy file(s) - source and destination are the same."));
if (is_a($result, 'PEAR_Error')) {
if (is_a($fileCheck, 'PEAR_Error')) {
foreach ($fileCheck as $file) {
if ($file['name'] == $name) {
return PEAR ::raiseError (_("Unable to copy VFS file."));
$res = $this->_checkQuotaWrite ('file', $orig);
if (is_a($res, 'PEAR_Error')) {
if (!@copy($orig, $this->_getNativePath ($dest, $name))) {
return PEAR ::raiseError (_("Unable to copy VFS file."));
* Store a file in the VFS from raw data.
* @param string $path The path to store the file in.
* @param string $name The filename to use.
* @param string $data The file data.
* @param boolean $autocreate Automatically create directories?
* @return mixed True on success or a PEAR_Error object on failure.
function writeData($path, $name, $data, $autocreate = true )
if (!@is_dir($this->_getNativePath ($path))) {
if (is_a($res, 'PEAR_Error')) {
return PEAR ::raiseError (_("VFS directory does not exist."));
// Treat an attempt to write an empty file as a touch() call,
// since otherwise the file will not be created at all.
if (@touch($this->_getNativePath ($path, $name))) {
return PEAR ::raiseError (_("Unable to create empty VFS file."));
$res = $this->_checkQuotaWrite ('string', $data);
if (is_a($res, 'PEAR_Error')) {
// Otherwise we go ahead and try to write out the file.
return PEAR ::raiseError (_("Unable to write VFS file data."));
$fp = @fopen($this->_getNativePath ($path, $name), 'w');
return PEAR ::raiseError (_("Unable to open VFS file for writing."));
return PEAR ::raiseError (_("Unable to write VFS file data."));
* 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.
$res = $this->_checkQuotaDelete ($path, $name);
if (is_a($res, 'PEAR_Error')) {
if (!@unlink($this->_getNativePath ($path, $name))) {
return PEAR ::raiseError (_("Unable to delete VFS file."));
* Delete a folder from the VFS.
* @param string $path The path to delete the folder from.
* @param string $name The foldername to use.
* @param boolean $recursive Force a recursive delete?
* @return mixed True on success or a PEAR_Error object on failure.
if (is_a($result, 'PEAR_Error')) {
if (is_a($list, 'PEAR_Error')) {
return PEAR ::raiseError (sprintf(_("Unable to delete %s, the directory is not empty"),
if (!@rmdir($this->_getNativePath ($path, $name))) {
return PEAR ::raiseError (_("Unable to delete VFS directory."));
* Creates a folder on the VFS.
* @param string $path The path to create the folder in.
* @param string $name The foldername to use.
* @return mixed True on success or a PEAR_Error object on failure.
if (!@mkdir($this->_getNativePath ($path, $name))) {
return PEAR ::raiseError (_("Unable to create VFS directory."));
* Check if a given pathname is a folder.
* @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.
return @is_dir($this->_getNativePath ($path, $name));
* Changes permissions for an item in the VFS.
* @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.
if (!@chmod($this->_getNativePath ($path, $name), $permission)) {
return PEAR ::raiseError (sprintf(_("Unable to change permission for VFS file %s/%s."), $path, $name));
* Return a list of the contents of a folder.
* @param string $path The path of the directory.
* @param mixed $filter String/hash to filter file/dirname on.
* @param boolean $dotfiles Show dotfiles?
* @param boolean $dironly Show only directories?
* @return array File list on success, PEAR_Error on error.
function _listFolder ($path, $filter = null , $dotfiles = true ,
$path = isset ($path) ? $this->_getNativePath ($path) : $this->_getNativePath ();
return PEAR ::raiseError (_("Not a directory"));
return PEAR ::raiseError (_("Unable to access VFS directory."));
while (($entry = readdir($handle)) !== false ) {
// Filter out '.' and '..' entries.
if ($entry == '.' || $entry == '..') {
// Filter out dotfiles if they aren't wanted.
if (!$dotfiles && substr($entry, 0 , 1 ) == '.') {
// Unix style file permissions
$file['perms'] = $this->_getUnixPerms (fileperms($entry));
$file['owner'] = $owner['name'];
if (PHP_VERSION != '5.2.1') {
$file['group'] = $group['name'];
$file['perms'] = 'd' . $file['perms'];
$file['perms'] = 'l' . $file['perms'];
$file['linktype'] = '**none';
$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'] = '**broken';
$file['perms'] = '-' . $file['perms'];
if (count($ext) == 1 || (substr($file['name'], 0 , 1 ) === '.' && count($ext) == 2 )) {
$file['type'] = '**none';
$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'];
$file['perms'] = '?' . $file['perms'];
if ($this->_filterMatch ($filter, $file['name'])) {
if ($dironly && $file['type'] !== '**dir') {
$files[$file['name']] = $file;
* Returns a sorted list of folders in specified directory.
* @param string $path The path of the directory to get the
* @param mixed $filter Hash of items to filter based on folderlist.
* @param boolean $dotfolders Include dotfolders?
* @return mixed Folder list on success or a PEAR_Error object on failure.
function listFolders($path = '', $filter = null , $dotfolders = true )
$conn = $this->_connect ();
if (is_a($conn, 'PEAR_Error')) {
$folderList = $this->listFolder($path, null , $dotfolders, true );
if (is_a($folderList, 'PEAR_Error')) {
foreach ($folderList as $name => $files) {
$folders[$name] = array ('val' => $path . '/' . $files['name'],
'abbrev' => $files['name'],
'label' => $path . '/' . $files['name']);
* Return Unix style perms.
* @param integer $perms The permissions to set.
* @return string Unix style perms.
function _getUnixPerms ($perms)
$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
$owner['execute'] = ($owner['execute'] == 'x') ? 's' : 'S';
$group['execute'] = ($group['execute'] == 'x') ? 's' : 'S';
$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'];
* Rename a file or folder 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, $oldname, $newpath, $newname)
if (!@is_dir($this->_getNativePath ($newpath))) {
if (!@rename($this->_getNativePath ($oldpath, $oldname),
$this->_getNativePath ($newpath, $newname))) {
return PEAR ::raiseError (sprintf(_("Unable to rename VFS file %s/%s."), $oldpath, $oldname));
* Returns if a given file or folder exists in a folder.
* @param string $path The path to the folder.
* @param string $name The file or folder name.
* @return boolean True if it exists, false otherwise.
return file_exists($this->_getNativePath ($path, $name));
* Return a full filename on the native filesystem, from a VFS
* @param string $path The VFS file path.
* @param string $name The VFS filename.
* @return string The full native filename.
function _getNativePath ($path = '', $name = '')
if (substr($name, 0 , 1 ) != '/') {
if (isset ($this->_params['home']) &&
$path = $this->_params['home'] . '/' . $matches[1 ];
if (substr($path, 0 , 1 ) == '/') {
return $this->_params['vfsroot'] . $path . $name;
return $this->_params['vfsroot'] . '/' . $path . $name;
return $this->_params['vfsroot'] . $name;
* Stub to check if we have a valid connection. Makes sure that
* the vfsroot is readable.
* @return mixed True if vfsroot is readable, PEAR_Error if it isn't.
if ((@is_dir($this->_params['vfsroot']) &&
@mkdir($this->_params['vfsroot'])) {
return PEAR ::raiseError (_("Unable to read the vfsroot directory."));
Documentation generated on Mon, 11 Mar 2019 15:34:53 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|