diff --git a/phpgwapi/inc/class.vfs.inc.php b/phpgwapi/inc/class.vfs.inc.php index ac3e3b6da7..6ffca95e2a 100644 --- a/phpgwapi/inc/class.vfs.inc.php +++ b/phpgwapi/inc/class.vfs.inc.php @@ -1,9 +1,1415 @@ * + * This class handles file/dir access for eGroupWare * + * Copyright (C) 2001 Jason Wies * + * -------------------------------------------------------------------------* + * This library is part of the eGroupWare API * + * http://www.egroupware.org/api * + * ------------------------------------------------------------------------ * + * This library is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published by * + * the Free Software Foundation; either version 2.1 of the License, * + * or any later version. * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU Lesser General Public License for more details. * + * You should have received a copy of the GNU Lesser General Public License * + * along with this library; if not, write to the Free Software Foundation, * + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + \**************************************************************************/ + + /* $Id$ */ + if (empty ($GLOBALS['phpgw_info']['server']['file_repository'])) { $GLOBALS['phpgw_info']['server']['file_repository'] = 'sql'; } - include (PHPGW_API_INC . '/class.vfs_shared.inc.php'); + /* Relative defines. Used mainly by getabsolutepath () */ + define ('RELATIVE_ROOT', 1); + define ('RELATIVE_USER', 2); + define ('RELATIVE_CURR_USER', 4); + define ('RELATIVE_USER_APP', 8); + define ('RELATIVE_PATH', 16); + define ('RELATIVE_NONE', 32); + define ('RELATIVE_CURRENT', 64); + define ('VFS_REAL', 1024); + define ('RELATIVE_ALL', RELATIVE_PATH); + + /* These are used in calls to add_journal (), and allow journal messages to be more standard */ + define ('VFS_OPERATION_CREATED', 1); + define ('VFS_OPERATION_EDITED', 2); + define ('VFS_OPERATION_EDITED_COMMENT', 4); + define ('VFS_OPERATION_COPIED', 8); + define ('VFS_OPERATION_MOVED', 16); + define ('VFS_OPERATION_DELETED', 32); + + /*! + * @class path_class + * @abstract helper class for path_parts + */ + class path_class + { + var $mask; + var $outside; + var $fake_full_path; + var $fake_leading_dirs; + var $fake_extra_path; + var $fake_name; + var $real_full_path; + var $real_leading_dirs; + var $real_extra_path; + var $real_name; + var $fake_full_path_clean; + var $fake_leading_dirs_clean; + var $fake_extra_path_clean; + var $fake_name_clean; + var $real_full_path_clean; + var $real_leading_dirs_clean; + var $real_extra_path_clean; + var $real_name_clean; + } + + /*! + * @class vfs_shared + * @abstract Base class for Virtual File System classes + * @author Zone + */ + class vfs_shared + { + /* + * All VFS classes must have some form of 'linked directories'. + * Linked directories allow an otherwise disparate "real" directory + * to be linked into the "virtual" filesystem. See make_link(). + */ + var $linked_dirs = array (); + + /* + * All VFS classes need to support the access control in some form + * (see acl_check()). There are times when applications will need + * to explictly disable access checking, for example when creating a + * user's home directory for the first time or when the admin is + * performing maintanence. When override_acl is set, any access + * checks must return True. + */ + var $override_acl = 0; + + /* + * The current relativity. See set_relative() and get_relative(). + */ + var $relative; + + /* + * Implementation dependant 'base real directory'. It is not required + * that derived classes use $basedir, but some of the shared functions + * below rely on it, so those functions will need to be overload if + * basedir isn't appropriate for a particular backend. + */ + var $basedir; + + /* + * Fake base directory. Only the administrator should change this. + */ + var $fakebase = '/home'; + + /* + * All derived classes must store certain information about each + * location. The attributes in the 'attributes' array represent + * the minimum attributes that must be stored. Derived classes + * should add to this array any custom attributes. + * + * Not all of the attributes below are appropriate for all backends. + * Those that don't apply can be replaced by dummy values, ie. '' or 0. + */ + var $attributes = array( + 'file_id', /* Integer. Unique to each location */ + 'owner_id', /* phpGW account_id of owner */ + 'createdby_id', /* phpGW account_id of creator */ + 'modifiedby_id',/* phpGW account_id of who last modified */ + 'created', /* Datetime created, in SQL format */ + 'modified', /* Datetime last modified, in SQL format */ + 'size', /* Size in bytes */ + 'mime_type', /* Mime type. 'Directory' for directories */ + 'comment', /* User-supplied comment. Can be empty */ + 'app', /* Name of phpGW application responsible for location */ + 'directory', /* Directory location is in */ + 'name', /* Name of file/directory */ + 'link_directory', /* Directory location is linked to, if any */ + 'link_name', /* Name location is linked to, if any */ + 'version', /* Version of file. May be 0 */ + ); + + /*! + * @function vfs_shared + * @abstract constructor + * @description All derived classes should call this function in their + * constructor ($this->vfs_shared()) + */ + function vfs_shared () + { + } + + /* + * Definitions for functions that every derived + * class must have, and suggestions for private functions + * to completement the public ones. The prototypes for + * the public functions need to be uniform for all + * classes. Of course, each derived class should overload these + * functions with their own version. + */ + + /* + * Journal functions. + * + * See also: VFS_OPERATION_* defines + * + * Overview: + * Each action performed on a location + * should be recorded, in both machine and human + * readable format. + * + * PRIVATE functions (suggested examples only, not mandatory): + * + * add_journal - Add journal entry + * flush_journal - Clear all journal entries for a location + * + * PUBLIC functions (mandatory): + * + * get_journal - Get journal entries for a location + */ + + /* Private, suggestions only */ + function add_journal ($data) {} + function flush_journal ($data) {} + + /*! + * @function get_journal + * @abstract Get journal entries for a location + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @optional type [0|1|2] + * 0 = any journal entries + * 1 = current journal entries + * 2 = deleted journal entries + * @result Array of arrays of journal entries + * The keys will vary depending on the implementation, + * with most attributes in this->attributes being valid, + * and these keys being mandatory: + * created - Datetime in SQL format that journal entry + * was entered + * comment - Human readable comment describing the action + * version - May be 0 if the derived class does not support + * versioning + */ + function get_journal ($data) { return array(array()); } + + /* + * Access checking functions. + * + * Overview: + * Each derived class should have some kind of + * user and group access control. This will + * usually be based directly on the ACL class. + * + * If $this->override_acl is set, acl_check() + * must always return True. + * + * PUBLIC functions (mandatory): + * + * acl_check() - Check access for a user to a given + */ + + /*! + * @function acl_check + * @abstract Check access for a user to a given location + * @discussion If $this->override_acl is set, always return True + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @required operation Operation to check access for. Any combination + * of the PHPGW_ACL_* defines, for example: + * PHPGW_ACL_READ + * PHPGW_ACL_READ|PHPGW_ACL_WRITE + * @optional owner_id phpGW ID to check access for. + * Default: $GLOBALS['phpgw_info']['user']['account_id'] + * @optional must_exist If set, string must exist, and acl_check() must + * return False if it doesn't. If must_exist isn't + * passed, and string doesn't exist, check the owner_id's + * access to the parent directory, if it exists. + * @result Boolean. True if access is ok, False otherwise. + */ + function acl_check ($data) { return True; } + + /* + * Operations functions. + * + * Overview: + * These functions perform basic file operations. + * + * PUBLIC functions (mandatory): + * + * read - Retreive file contents + * + * write - Store file contents + * + * touch - Create a file if it doesn't exist. + * Optionally, update the modified time and + * modified user if the file exists. + * + * cp - Copy location + * + * mv - Move location + * + * rm - Delete location + * + * mkdir - Create directory + */ + + /*! + * @function read + * @abstract Retreive file contents + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @result String. Contents of 'string', or False on error. + */ + function read ($data) { return False; } + + /*! + @function view + @abstract Views the specified file (does not return!) + @param string filename + @param relatives Relativity array + @result None (doesnt return) + @discussion By default this function just reads the file and + outputs it too the browser, after setting the content-type header + appropriately. For some other VFS implementations though, there + may be some more sensible way of viewing the file. + */ + function view($data) + { + + $default_values = array + ( + 'relatives' => array (RELATIVE_CURRENT) + ); + $data = array_merge ($this->default_values ($data, $default_values), $data); + + $GLOBALS['phpgw_info']['flags']['noheader'] = true; + $GLOBALS['phpgw_info']['flags']['nonavbar'] = true; + $GLOBALS['phpgw_info']['flags']['noappheader'] = true; + $GLOBALS['phpgw_info']['flags']['noappfooter'] = true; + $ls_array = $this->ls (array ( + 'string' => $data['string'], + 'relatives' => $data['relatives'], + 'checksubdirs' => False, + 'nofiles' => True + ) + ); + + if ($ls_array[0]['mime_type']) + { + $mime_type = $ls_array[0]['mime_type']; + } + elseif ($GLOBALS['settings']['viewtextplain']) + { + $mime_type = 'text/plain'; + } + + header('Content-type: ' . $mime_type); + echo $this->read (array ( + 'string' => $data['string'], + 'relatives' => $data['relatives'], + ) + ); + exit(); + } + + /*! + * @function write + * @abstract Store file contents + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @result Boolean. True on success, False otherwise. + */ + function write ($data) { return False; } + + /*! + * @function touch + * @abstract Create a file if it doesn't exist. + * Optionally, update the modified time and + * modified user if the file exists. + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @result Boolean. True on success, False otherwise. + */ + function touch ($data) { return False; } + + /*! + * @function cp + * @abstract Copy location + * @required from Path to location to copy from + * @required to Path to location to copy to + * @optional relatives Relativity array (default: RELATIVE_CURRENT, RELATIVE_CURRENT) + * @result Boolean. True on success, False otherwise. + */ + function cp ($data) { return False; } + + /*! + * @function mv + * @abstract Move location + * @required from Path to location to move from + * @required to Path to location to move to + * @optional relatives Relativity array (default: RELATIVE_CURRENT, RELATIVE_CURRENT) + * @result Boolean. True on success, False otherwise. + */ + function mv ($data) { return False; } + + /*! + * @function rm + * @abstract Delete location + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @result Boolean. True on success, False otherwise. + */ + function rm ($data) { return False; } + + /*! + * @function mkdir + * @abstract Create directory + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @result Boolean. True on success, False otherwise. + */ + function mkdir ($data) { return False; } + + /* + * Information functions. + * + * Overview: + * These functions set or return information about locations. + * + * PUBLIC functions (mandatory): + * + * set_attributes - Set attributes for a location + * + * file_exists - Check if a location (file or directory) exists + * + * get_size - Determine size of location + * + * ls - Return detailed information for location(s) + */ + + /*! + * @function set_attributes + * @abstract Set attributes for a location + * @discussion Valid attributes are listed in vfs->attributes, + * which may be extended by each derived class + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @optional attributes Keyed array of attributes. Key is attribute + * name, value is attribute value. + * @result Boolean. True on success, False otherwise. + */ + function set_attributes ($data) { return False; } + + /*! + * @function file_exists + * @abstract Check if a location (file or directory) exists + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @result Boolean. True if file exists, False otherwise. + */ + function file_exists ($data) { return False; } + + /*! + * @function get_size + * @abstract Determine size of location + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @optional checksubdirs Boolean. If set, include the size of + * all subdirectories recursively. + * @result Integer. Size of location in bytes. + */ + function get_size ($data) { return 0; } + + /*! + * @function ls + * @abstract Return detailed information for location(s) + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @optional checksubdirs Boolean. If set, return information for all + * subdirectories recursively. + * @optional mime String. Only return information for locations with MIME type + * specified. VFS classes must recogize these special types: + * "Directory" - Location is a directory + * " " - Location doesn't not have a MIME type + * @optional nofiles Boolean. If set and 'string' is a directory, return + * information about the directory, not the files in it. + * @result Array of arrays of file information. + * Keys may vary depending on the implementation, but must include + * at least those attributes listed in $this->attributes. + */ + function ls ($data) { return array(array()); } + + /* + * Linked directory functions. + * + * Overview: + * One 'special' feature that VFS classes must support + * is linking an otherwise unrelated 'real' directory into + * the virtual filesystem. For a traditional filesystem, this + * might mean linking /var/specialdir in the real filesystem to + * /home/user/specialdir in the VFS. For networked filesystems, + * this might mean linking 'another.host.com/dir' to + * 'this.host.com/home/user/somedir'. + * + * This is a feature that will be used mostly be administrators, + * in order to present a consistent view to users. Each VFS class + * will almost certainly need a new interface for the administrator + * to use to make links, but the concept is the same across all the + * VFS backends. + * + * Note that by using $this->linked_dirs in conjunction with + * $this->path_parts(), you can keep the implementation of linked + * directories very isolated in your code. + * + * PUBLIC functions (mandatory): + * + * make_link - Create a real to virtual directory link + */ + + /*! + * @function make_link + * @abstract Create a real to virtual directory link + * @required rdir Real directory to make link from/to + * @required vdir Virtual directory to make link to/from + * @optional relatives Relativity array (default: RELATIVE_CURRENT, RELATIVE_CURRENT) + * @result Boolean. True on success, False otherwise. + */ + function make_link ($data) { return False; } + + /* + * Miscellaneous functions. + * + * PUBLIC functions (mandatory): + * + * update_real - Ensure that information about a location is + * up-to-date + * + * compress - Archives a file or set of files in a compressed file + * + * extract - Dearchives a file or set of files of a compressed file + */ + + /*! + * @function update_real + * @abstract Ensure that information about a location is up-to-date + * @discussion Some VFS backends store information about locations + * in a secondary location, for example in a database + * or in a cache file. update_real() can be called to + * ensure that the information in the secondary location + * is up-to-date. + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @result Boolean. True on success, False otherwise. + */ + function update_real ($data) { return False; } + + /*! + * @function compress + * @abstract Creates an archive from a file or a set of files + * @required files File names to be stored in archive (array) + * @required name Name of archive + * @optional type The type of compression, can be 'zip'(default)or 'gz' + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * Note: the last item is the relativity of the dest archive + * @result Boolean. True on success, False otherwise. + */ + + function compress ($data) { return False; } + + /*! + * @function extract + * @abstract Extracts a file (or files) from archive + * @required name Name of archive + * @required dest The destination path of files to be extracted + * @optional type The type of compression, can be 'zip' or 'gz'. If + * not specified, uses according to the extension + * @optional files Files to be extracted from archive + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * Note: the first item is the relativity of the archive, the last of + * the dest dir + * @result Boolean. True on success, False otherwise. + */ + + function extract ($data) { return False; } + + + + /* + * SHARED FUNCTIONS + * + * The rest of the functions in this file are shared between + * all derived VFS classes. + * + * Derived classes can overload any of these functions if they + * see it fit to do so, as long as the prototypes and return + * values are the same for public functions, and the function + * accomplishes the same goal. + * + * PRIVATE functions: + * + * securitycheck - Check if location string is ok to use in VFS functions + * + * sanitize - Remove any possible security problems from a location + * string (i.e. remove leading '..') + * + * clean_string - Clean location string. This function is used if + * any special characters need to be escaped or removed + * before accessing a database, network protocol, etc. + * The default is to escape characters before doing an SQL + * query. + * + * getabsolutepath - Translate a location string depending on the + * relativity. This is the only function that is + * directly concerned with relativity. + * + * get_ext_mime_type - Return MIME type based on file extension + * + * PUBLIC functions (mandatory): + * + * set_relative - Sets the current relativity, the relativity used + * when RELATIVE_CURRENT is passed to a function + * + * get_relative - Return the current relativity + * + * path_parts - Return information about the component parts of a location string + * + * cd - Change current directory. This function is used to store the + * current directory in a standard way, so that it may be accessed + * throughout phpGroupWare to provide a consistent view for the user. + * + * pwd - Return current directory + * + * copy - Alias for cp + * + * move - Alias for mv + * + * delete - Alias for rm + * + * dir - Alias for ls + * + * command_line - Process and run a Unix-sytle command line + * + * compress - Archives a file or set of files in a compressed file + * + * extract - Dearchives a file or set of files of a compressed file + */ + + /* PRIVATE functions */ + + /*! + * @function securitycheck + * @abstract Check if location string is ok to use in VFS functions + * @discussion Checks for basic violations such as .. + * If securitycheck () fails, run your string through $this->sanitize () + * @required string Path to location + * @result Boolean. True if string is ok, False otherwise. + */ + function securitycheck ($data) + { + if (!is_array ($data)) + { + $data = array (); + } + + if (substr ($data['string'], 0, 1) == "\\" || strstr ($data['string'], "..") || strstr ($data['string'], "\\..") || strstr ($data['string'], ".\\.")) + { + return False; + } + else + { + return True; + } + } + + /*! + * @function sanitize + * @abstract Remove any possible security problems from a location + * string (i.e. remove leading '..') + * @discussion You should not pass all filenames through sanitize () + * unless you plan on rejecting .files. Instead, pass + * the name through securitycheck () first, and if it fails, + * pass it through sanitize. + * @required string Path to location + * @result String. 'string' with any security problems fixed. + */ + function sanitize ($data) + { + if (!is_array ($data)) + { + $data = array (); + } + + /* We use path_parts () just to parse the string, not translate paths */ + $p = $this->path_parts (array( + 'string' => $data['string'], + 'relatives' => array (RELATIVE_NONE) + ) + ); + + return (ereg_replace ("^\.+", '', $p->fake_name)); + } + + /*! + * @function clean_string + * @abstract Clean location string. This function is used if + * any special characters need to be escaped or removed + * before accessing a database, network protocol, etc. + * The default is to escape characters before doing an SQL + * query. + * @required string Location string to clean + * @result String. Cleaned version of 'string'. + */ + function clean_string ($data) + { + if (!is_array ($data)) + { + $data = array (); + } + + $string = $GLOBALS['phpgw']->db->db_addslashes ($data['string']); + + return $string; + } + + /*! + * @function getabsolutepath + * @abstract Translate a location string depending on the + * relativity. This is the only function that is + * directly concerned with relativity. + * @optional string Path to location, relative to mask[0]. + * Defaults to empty string. + * @optional mask Relativity array (default: RELATIVE_CURRENT) + * @optional fake Boolean. If set, returns the 'fake' path, + * i.e. /home/user/dir/file. This is not always + * possible, use path_parts() instead. + * @result String. Full fake or real path, or False on error. + */ + function getabsolutepath ($data) + { + if (!is_array ($data)) + { + $data = array (); + } + + $default_values = array + ( + 'string' => False, + 'mask' => array (RELATIVE_CURRENT), + 'fake' => True + ); + + $data = array_merge ($this->default_values ($data, $default_values), $data); + + $currentdir = $this->pwd (False); + + /* If they supply just VFS_REAL, we assume they want current relativity */ + if ($data['mask'][0] == VFS_REAL) + { + $data['mask'][0] |= RELATIVE_CURRENT; + } + + if (!$this->securitycheck (array( + 'string' => $data['string'] + )) + ) + { + return False; + } + + if ($data['mask'][0] & RELATIVE_NONE) + { + return $data['string']; + } + + if ($data['fake']) + { + $sep = '/'; + } + else + { + $sep = SEP; + } + + /* if RELATIVE_CURRENT, retrieve the current mask */ + if ($data['mask'][0] & RELATIVE_CURRENT) + { + $mask = $data['mask'][0]; + /* Respect any additional masks by re-adding them after retrieving the current mask*/ + $data['mask'][0] = $this->get_relative () + ($mask - RELATIVE_CURRENT); + } + + if ($data['fake']) + { + $basedir = "/"; + } + else + { + $basedir = $this->basedir . $sep; + + /* This allows all requests to use /'s */ + $data['string'] = preg_replace ("|/|", $sep, $data['string']); + } + + if (($data['mask'][0] & RELATIVE_PATH) && $currentdir) + { + $basedir = $basedir . $currentdir . $sep; + } + elseif (($data['mask'][0] & RELATIVE_USER) || ($data['mask'][0] & RELATIVE_USER_APP)) + { + $basedir = $basedir . $this->fakebase . $sep; + } + + if ($data['mask'][0] & RELATIVE_CURR_USER) + { + $basedir = $basedir . $this->working_lid . $sep; + } + + if (($data['mask'][0] & RELATIVE_USER) || ($data['mask'][0] & RELATIVE_USER_APP)) + { + $basedir = $basedir . $GLOBALS['phpgw_info']['user']['account_lid'] . $sep; + } + + if ($data['mask'][0] & RELATIVE_USER_APP) + { + $basedir = $basedir . "." . $GLOBALS['phpgw_info']['flags']['currentapp'] . $sep; + } + + /* Don't add string if it's a /, just for aesthetics */ + if ($data['string'] && $data['string'] != $sep) + { + $basedir = $basedir . $data['string']; + } + + /* Let's not return // */ + while (ereg ($sep . $sep, $basedir)) + { + $basedir = ereg_replace ($sep . $sep, $sep, $basedir); + } + + $basedir = ereg_replace ($sep . '$', '', $basedir); + + return $basedir; + } + + /*! + * @function get_ext_mime_type + * @abstract Return MIME type based on file extension + * @description Internal use only. Applications should call vfs->file_type () + * @author skeeter + * @required string Real path to file, with or without leading paths + * @result String. MIME type based on file extension. + */ + function get_ext_mime_type ($data) + { + if (!is_array ($data)) + { + $data = array (); + } + + $file=basename($data['string']); + $mimefile=PHPGW_API_INC.'/phpgw_mime.types'; + $fp=fopen($mimefile,'r'); + $contents = explode("\n",fread($fp,filesize($mimefile))); + fclose($fp); + + $parts=explode('.',strtolower($file)); + $ext=$parts[(sizeof($parts)-1)]; + + for($i=0;$i= 2) + { + for($j=1;$jrelative); + } + else + { + $this->relative = $data['mask']; + } + } + + /*! + * @function get_relative + * @abstract Return the current relativity + * @discussion Returns relativity bitmask, or the default + * of "completely relative" if unset + * @result Integer. One of the RELATIVE_* defines. + */ + function get_relative () + { + if (isset ($this->relative) && $this->relative) + { + return $this->relative; + } + else + { + return RELATIVE_ALL; + } + } + + /*! + * @function path_parts + * @abstract Return information about the component parts of a location string + * @discussion Most VFS functions call path_parts() with their 'string' and + * 'relatives' arguments before doing their work, in order to + * determine the file/directory to work on. + * @required string Path to location + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + * @optional object If set, return an object instead of an array + * @optional nolinks Don't check for linked directories (made with + * make_link()). Used internally to prevent recursion. + * @result Array or object. Contains the fake and real component parts of the path. + * @discussion Returned values are: + * mask + * outside + * fake_full_path + * fake_leading_dirs + * fake_extra_path BROKEN + * fake_name + * real_full_path + * real_leading_dirs + * real_extra_path BROKEN + * real_name + * fake_full_path_clean + * fake_leading_dirs_clean + * fake_extra_path_clean BROKEN + * fake_name_clean + * real_full_path_clean + * real_leading_dirs_clean + * real_extra_path_clean BROKEN + * real_name_clean + * "clean" values are run through vfs->clean_string () and + * are safe for use in SQL queries that use key='value' + * They should be used ONLY for SQL queries, so are used + * mostly internally + * mask is either RELATIVE_NONE or RELATIVE_NONE|VFS_REAL, + * and is used internally + * outside is boolean, True if 'relatives' contains VFS_REAL + */ + function path_parts ($data) + { + if (!is_array ($data)) + { + $data = array (); + } + + $default_values = array + ( + 'relatives' => array (RELATIVE_CURRENT), + 'object' => True, + 'nolinks' => False + ); + + $data = array_merge ($this->default_values ($data, $default_values), $data); + + $sep = SEP; + + $rarray['mask'] = RELATIVE_NONE; + + if (!($data['relatives'][0] & VFS_REAL)) + { + $rarray['outside'] = False; + $fake = True; + } + else + { + $rarray['outside'] = True; + $rarray['mask'] |= VFS_REAL; + } + + $string = $this->getabsolutepath (array( + 'string' => $data['string'], + 'mask' => array ($data['relatives'][0]), + 'fake' => $fake + ) + ); + + if ($fake) + { + $base_sep = '/'; + $base = '/'; + + $opp_base = $this->basedir . $sep; + + $rarray['fake_full_path'] = $string; + } + else + { + $base_sep = $sep; + if (substr($string,0,strlen($this->basedir)+1) == $this->basedir . $sep) + { + $base = $this->basedir . $sep; + } + else + { + $base = $sep; + } + + $opp_base = '/'; + + $rarray['real_full_path'] = $string; + } + + /* This is needed because of substr's handling of negative lengths */ + $baselen = strlen ($base); + $lastslashpos = @strrpos ($string, $base_sep); + $length = $lastslashpos < $baselen ? 0 : $lastslashpos - $baselen; + + $extra_path = $rarray['fake_extra_path'] = $rarray['real_extra_path'] = substr ($string, strlen ($base), $length); + if($string[1] != ':') + { + $name = $rarray['fake_name'] = $rarray['real_name'] = substr ($string, @strrpos ($string, $base_sep) + 1); + } + else + { + $name = $rarray['fake_name'] = $rarray['real_name'] = $string; + } + + if ($fake) + { + $rarray['real_extra_path'] ? $dispsep = $sep : $dispsep = ''; + $rarray['real_full_path'] = $opp_base . $rarray['real_extra_path'] . $dispsep . $rarray['real_name']; + if ($extra_path) + { + $rarray['fake_leading_dirs'] = $base . $extra_path; + $rarray['real_leading_dirs'] = $opp_base . $extra_path; + } + elseif (@strrpos ($rarray['fake_full_path'], $sep) == 0) + { + /* If there is only one $sep in the path, we don't want to strip it off */ + $rarray['fake_leading_dirs'] = $sep; + $rarray['real_leading_dirs'] = substr ($opp_base, 0, strlen ($opp_base) - 1); + } + else + { + /* These strip the ending / */ + $rarray['fake_leading_dirs'] = substr ($base, 0, strlen ($base) - 1); + $rarray['real_leading_dirs'] = substr ($opp_base, 0, strlen ($opp_base) - 1); + } + } + else + { + if($rarray['fake_name'][1] != ':') + { + $rarray['fake_full_path'] = $opp_base . $rarray['fake_extra_path'] . '/' . $rarray['fake_name']; + } + else + { + $rarray['fake_full_path'] = $rarray['fake_name']; + } + if ($extra_path) + { + $rarray['fake_leading_dirs'] = $opp_base . $extra_path; + $rarray['real_leading_dirs'] = $base . $extra_path; + } + else + { + $rarray['fake_leading_dirs'] = substr ($opp_base, 0, strlen ($opp_base) - 1); + $rarray['real_leading_dirs'] = substr ($base, 0, strlen ($base) - 1); + } + } + + /* We check for linked dirs made with make_link (). This could be better, but it works */ + if (!$data['nolinks']) + { + reset ($this->linked_dirs); + while (list ($num, $link_info) = each ($this->linked_dirs)) + { + if (ereg ("^$link_info[directory]/$link_info[name](/|$)", $rarray['fake_full_path'])) + { + $rarray['real_full_path'] = ereg_replace ("^$this->basedir", '', $rarray['real_full_path']); + $rarray['real_full_path'] = ereg_replace ("^$link_info[directory]" . SEP . "$link_info[name]", $link_info['link_directory'] . SEP . $link_info['link_name'], $rarray['real_full_path']); + + $p = $this->path_parts (array( + 'string' => $rarray['real_full_path'], + 'relatives' => array (RELATIVE_NONE|VFS_REAL), + 'nolinks' => True + ) + ); + + $rarray['real_leading_dirs'] = $p->real_leading_dirs; + $rarray['real_extra_path'] = $p->real_extra_path; + $rarray['real_name'] = $p->real_name; + } + } + } + + /* + We have to count it before because new keys will be added, + which would create an endless loop + */ + $count = count ($rarray); + reset ($rarray); + for ($i = 0; (list ($key, $value) = each ($rarray)) && $i != $count; $i++) + { + $rarray[$key . '_clean'] = $this->clean_string (array ('string' => $value)); + } + + if ($data['object']) + { + $robject = new path_class; + + reset ($rarray); + while (list ($key, $value) = each ($rarray)) + { + $robject->$key = $value; + } + } + + /* + echo "
fake_full_path: $rarray[fake_full_path] +
fake_leading_dirs: $rarray[fake_leading_dirs] +
fake_extra_path: $rarray[fake_extra_path] +
fake_name: $rarray[fake_name] +
real_full_path: $rarray[real_full_path] +
real_leading_dirs: $rarray[real_leading_dirs] +
real_extra_path: $rarray[real_extra_path] +
real_name: $rarray[real_name]"; + */ + + if ($data['object']) + { + return ($robject); + } + else + { + return ($rarray); + } + } + + /*! + * @function cd + * @abstract Change current directory. This function is used to store the + * current directory in a standard way, so that it may be accessed + * throughout phpGroupWare to provide a consistent view for the user. + * @discussion To cd to the root '/', use: + * cd (array( + * 'string' => '/', + * 'relative' => False, + * 'relatives' => array (RELATIVE_NONE) + * )); + * @optional string Directory location to cd into. Default is '/'. + * @optional relative If set, add target to current path. + * Else, pass 'relative' as mask to getabsolutepath() + * Default is True. + * @optional relatives Relativity array (default: RELATIVE_CURRENT) + */ + function cd ($data = '') + { + if (!is_array ($data)) + { + $noargs = 1; + $data = array (); + } + + $default_values = array + ( + 'string' => '/', + 'relative' => True, + 'relatives' => array (RELATIVE_CURRENT) + ); + + $data = array_merge ($this->default_values ($data, $default_values), $data); + + if ($data['relatives'][0] & VFS_REAL) + { + $sep = SEP; + } + else + { + $sep = '/'; + } + + if ($data['relative'] == 'relative' || $data['relative'] == True) + { + /* if 'string' is "/" and 'relative' is set, we cd to the user/group home dir */ + if ($data['string'] == '/') + { + $data['relatives'][0] = RELATIVE_USER; + $basedir = $this->getabsolutepath (array( + 'string' => False, + 'mask' => array ($data['relatives'][0]), + 'fake' => True + ) + ); + } + else + { + $currentdir = $GLOBALS['phpgw']->session->appsession('vfs',''); + $basedir = $this->getabsolutepath (array( + 'string' => $currentdir . $sep . $data['string'], + 'mask' => array ($data['relatives'][0]), + 'fake' => True + ) + ); + } + } + else + { + $basedir = $this->getabsolutepath (array( + 'string' => $data['string'], + 'mask' => array ($data['relatives'][0]) + ) + ); + } + + $GLOBALS['phpgw']->session->appsession('vfs','',$basedir); + + return True; + } + + /*! + * @function pwd + * @abstract Return current directory + * @optional full If set, return full fake path, else just + * the extra dirs (False strips the leading /). + * Default is True. + * @result String. The current directory. + */ + function pwd ($data = '') + { + if (!is_array ($data)) + { + $data = array (); + } + + $default_values = array + ( + 'full' => True + ); + + $data = array_merge ($this->default_values ($data, $default_values), $data); + + $currentdir = $GLOBALS['phpgw']->session->appsession('vfs',''); + + if (!$data['full']) + { + $currentdir = ereg_replace ("^/", '', $currentdir); + } + + if ($currentdir == '' && $data['full']) + { + $currentdir = '/'; + } + + $currentdir = trim ($currentdir); + + return $currentdir; + } + + /*! + * @function copy + * @abstract shortcut to cp + */ + function copy ($data) + { + return $this->cp ($data); + } + + /*! + * @function move + * @abstract shortcut to mv + */ + function move ($data) + { + return $this->mv ($data); + } + + /*! + * @function delete + * @abstract shortcut to rm + */ + function delete ($data) + { + return $this->rm ($data); + } + + /*! + * @function dir + * @abstract shortcut to ls + */ + function dir ($data) + { + return $this->ls ($data); + } + + /*! + * @function command_line + * @abstract Process and run a Unix-sytle command line + * @discussion EXPERIMENTAL. DANGEROUS. DO NOT USE THIS UNLESS YOU + * KNOW WHAT YOU'RE DOING! + * This is mostly working, but the command parser needs + * to be improved to take files with spaces into + * consideration (those should be in ""). + * @required command_line Unix-style command line with one of the + * commands in the $args array + * @result The return value of the actual VFS call + */ + function command_line ($data) + { + if (!is_array ($data)) + { + $data = array (); + } + + $args = array + ( + array ('name' => 'mv', 'params' => 2), + array ('name' => 'cp', 'params' => 2), + array ('name' => 'rm', 'params' => 1), + array ('name' => 'ls', 'params' => -1), + array ('name' => 'du', 'params' => 1, 'func' => get_size), + array ('name' => 'cd', 'params' => 1), + array ('name' => 'pwd', 'params' => 0), + array ('name' => 'cat', 'params' => 1, 'func' => read), + array ('name' => 'file', 'params' => 1, 'func' => file_type), + array ('name' => 'mkdir', 'params' => 1), + array ('name' => 'touch', 'params' => 1) + ); + + if (!$first_space = strpos ($data['command_line'], ' ')) + { + $first_space = strlen ($data['command_line']); + } + if ((!$last_space = strrpos ($data['command_line'], ' ')) || ($last_space == $first_space)) + { + $last_space = strlen ($data['command_line']) + 1; + } + $argv[0] = substr ($data['command_line'], 0, $first_space); + if (strlen ($argv[0]) != strlen ($data['command_line'])) + { + $argv[1] = substr ($data['command_line'], $first_space + 1, $last_space - ($first_space + 1)); + if ((strlen ($argv[0]) + 1 + strlen ($argv[1])) != strlen ($data['command_line'])) + { + $argv[2] = substr ($data['command_line'], $last_space + 1); + } + } + $argc = count ($argv); + + reset ($args); + while (list (,$arg_info) = each ($args)) + { + if ($arg_info['name'] == $argv[0]) + { + $command_ok = 1; + if (($argc == ($arg_info['params'] + 1)) || ($arg_info['params'] == -1)) + { + $param_count_ok = 1; + } + break; + } + } + + if (!$command_ok) + { +// return E_VFS_BAD_COMMAND; + return False; + } + if (!$param_count_ok) + { +// return E_VFS_BAD_PARAM_COUNT; + return False; + } + + for ($i = 1; $i != ($arg_info['params'] + 1); $i++) + { + if (substr ($argv[$i], 0, 1) == "/") + { + $relatives[] = RELATIVE_NONE; + } + else + { + $relatives[] = RELATIVE_ALL; + } + } + + $func = $arg_info['func'] ? $arg_info['func'] : $arg_info['name']; + + if (!$argv[2]) + { + $rv = $this->$func (array( + 'string' => $argv[1], + 'relatives' => $relatives + ) + ); + } + else + { + $rv = $this->$func (array( + 'from' => $argv[1], + 'to' => $argv[2], + 'relatives' => $relatives + ) + ); + } + + return ($rv); + } + + /* Helper functions, not public */ + + function default_values ($data, $default_values) + { + for ($i = 0; list ($key, $value) = each ($default_values); $i++) + { + if (!isset ($data[$key])) + { + $data[$key] = $value; + } + } + + return $data; + } + + } + include (PHPGW_API_INC . '/class.vfs_' . $GLOBALS['phpgw_info']['server']['file_repository'] . '.inc.php'); -?> diff --git a/phpgwapi/inc/class.vfs_shared.inc.php b/phpgwapi/inc/class.vfs_shared.inc.php deleted file mode 100644 index 3c8ca642cf..0000000000 --- a/phpgwapi/inc/class.vfs_shared.inc.php +++ /dev/null @@ -1,1410 +0,0 @@ - * - * This class handles file/dir access for eGroupWare * - * Copyright (C) 2001 Jason Wies * - * -------------------------------------------------------------------------* - * This library is part of the eGroupWare API * - * http://www.egroupware.org/api * - * ------------------------------------------------------------------------ * - * This library is free software; you can redistribute it and/or modify it * - * under the terms of the GNU Lesser General Public License as published by * - * the Free Software Foundation; either version 2.1 of the License, * - * or any later version. * - * This library is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * - * See the GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License * - * along with this library; if not, write to the Free Software Foundation, * - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - \**************************************************************************/ - - /* $Id$ */ - - /* Relative defines. Used mainly by getabsolutepath () */ - define ('RELATIVE_ROOT', 1); - define ('RELATIVE_USER', 2); - define ('RELATIVE_CURR_USER', 4); - define ('RELATIVE_USER_APP', 8); - define ('RELATIVE_PATH', 16); - define ('RELATIVE_NONE', 32); - define ('RELATIVE_CURRENT', 64); - define ('VFS_REAL', 1024); - define ('RELATIVE_ALL', RELATIVE_PATH); - - /* These are used in calls to add_journal (), and allow journal messages to be more standard */ - define ('VFS_OPERATION_CREATED', 1); - define ('VFS_OPERATION_EDITED', 2); - define ('VFS_OPERATION_EDITED_COMMENT', 4); - define ('VFS_OPERATION_COPIED', 8); - define ('VFS_OPERATION_MOVED', 16); - define ('VFS_OPERATION_DELETED', 32); - - /*! - * @class path_class - * @abstract helper class for path_parts - */ - class path_class - { - var $mask; - var $outside; - var $fake_full_path; - var $fake_leading_dirs; - var $fake_extra_path; - var $fake_name; - var $real_full_path; - var $real_leading_dirs; - var $real_extra_path; - var $real_name; - var $fake_full_path_clean; - var $fake_leading_dirs_clean; - var $fake_extra_path_clean; - var $fake_name_clean; - var $real_full_path_clean; - var $real_leading_dirs_clean; - var $real_extra_path_clean; - var $real_name_clean; - } - - /*! - * @class vfs_shared - * @abstract Base class for Virtual File System classes - * @author Zone - */ - class vfs_shared - { - /* - * All VFS classes must have some form of 'linked directories'. - * Linked directories allow an otherwise disparate "real" directory - * to be linked into the "virtual" filesystem. See make_link(). - */ - var $linked_dirs = array (); - - /* - * All VFS classes need to support the access control in some form - * (see acl_check()). There are times when applications will need - * to explictly disable access checking, for example when creating a - * user's home directory for the first time or when the admin is - * performing maintanence. When override_acl is set, any access - * checks must return True. - */ - var $override_acl = 0; - - /* - * The current relativity. See set_relative() and get_relative(). - */ - var $relative; - - /* - * Implementation dependant 'base real directory'. It is not required - * that derived classes use $basedir, but some of the shared functions - * below rely on it, so those functions will need to be overload if - * basedir isn't appropriate for a particular backend. - */ - var $basedir; - - /* - * Fake base directory. Only the administrator should change this. - */ - var $fakebase = '/home'; - - /* - * All derived classes must store certain information about each - * location. The attributes in the 'attributes' array represent - * the minimum attributes that must be stored. Derived classes - * should add to this array any custom attributes. - * - * Not all of the attributes below are appropriate for all backends. - * Those that don't apply can be replaced by dummy values, ie. '' or 0. - */ - var $attributes = array( - 'file_id', /* Integer. Unique to each location */ - 'owner_id', /* phpGW account_id of owner */ - 'createdby_id', /* phpGW account_id of creator */ - 'modifiedby_id',/* phpGW account_id of who last modified */ - 'created', /* Datetime created, in SQL format */ - 'modified', /* Datetime last modified, in SQL format */ - 'size', /* Size in bytes */ - 'mime_type', /* Mime type. 'Directory' for directories */ - 'comment', /* User-supplied comment. Can be empty */ - 'app', /* Name of phpGW application responsible for location */ - 'directory', /* Directory location is in */ - 'name', /* Name of file/directory */ - 'link_directory', /* Directory location is linked to, if any */ - 'link_name', /* Name location is linked to, if any */ - 'version', /* Version of file. May be 0 */ - ); - - /*! - * @function vfs_shared - * @abstract constructor - * @description All derived classes should call this function in their - * constructor ($this->vfs_shared()) - */ - function vfs_shared () - { - } - - /* - * Definitions for functions that every derived - * class must have, and suggestions for private functions - * to completement the public ones. The prototypes for - * the public functions need to be uniform for all - * classes. Of course, each derived class should overload these - * functions with their own version. - */ - - /* - * Journal functions. - * - * See also: VFS_OPERATION_* defines - * - * Overview: - * Each action performed on a location - * should be recorded, in both machine and human - * readable format. - * - * PRIVATE functions (suggested examples only, not mandatory): - * - * add_journal - Add journal entry - * flush_journal - Clear all journal entries for a location - * - * PUBLIC functions (mandatory): - * - * get_journal - Get journal entries for a location - */ - - /* Private, suggestions only */ - function add_journal ($data) {} - function flush_journal ($data) {} - - /*! - * @function get_journal - * @abstract Get journal entries for a location - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @optional type [0|1|2] - * 0 = any journal entries - * 1 = current journal entries - * 2 = deleted journal entries - * @result Array of arrays of journal entries - * The keys will vary depending on the implementation, - * with most attributes in this->attributes being valid, - * and these keys being mandatory: - * created - Datetime in SQL format that journal entry - * was entered - * comment - Human readable comment describing the action - * version - May be 0 if the derived class does not support - * versioning - */ - function get_journal ($data) { return array(array()); } - - /* - * Access checking functions. - * - * Overview: - * Each derived class should have some kind of - * user and group access control. This will - * usually be based directly on the ACL class. - * - * If $this->override_acl is set, acl_check() - * must always return True. - * - * PUBLIC functions (mandatory): - * - * acl_check() - Check access for a user to a given - */ - - /*! - * @function acl_check - * @abstract Check access for a user to a given location - * @discussion If $this->override_acl is set, always return True - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @required operation Operation to check access for. Any combination - * of the PHPGW_ACL_* defines, for example: - * PHPGW_ACL_READ - * PHPGW_ACL_READ|PHPGW_ACL_WRITE - * @optional owner_id phpGW ID to check access for. - * Default: $GLOBALS['phpgw_info']['user']['account_id'] - * @optional must_exist If set, string must exist, and acl_check() must - * return False if it doesn't. If must_exist isn't - * passed, and string doesn't exist, check the owner_id's - * access to the parent directory, if it exists. - * @result Boolean. True if access is ok, False otherwise. - */ - function acl_check ($data) { return True; } - - /* - * Operations functions. - * - * Overview: - * These functions perform basic file operations. - * - * PUBLIC functions (mandatory): - * - * read - Retreive file contents - * - * write - Store file contents - * - * touch - Create a file if it doesn't exist. - * Optionally, update the modified time and - * modified user if the file exists. - * - * cp - Copy location - * - * mv - Move location - * - * rm - Delete location - * - * mkdir - Create directory - */ - - /*! - * @function read - * @abstract Retreive file contents - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @result String. Contents of 'string', or False on error. - */ - function read ($data) { return False; } - - /*! - @function view - @abstract Views the specified file (does not return!) - @param string filename - @param relatives Relativity array - @result None (doesnt return) - @discussion By default this function just reads the file and - outputs it too the browser, after setting the content-type header - appropriately. For some other VFS implementations though, there - may be some more sensible way of viewing the file. - */ - function view($data) - { - - $default_values = array - ( - 'relatives' => array (RELATIVE_CURRENT) - ); - $data = array_merge ($this->default_values ($data, $default_values), $data); - - $GLOBALS['phpgw_info']['flags']['noheader'] = true; - $GLOBALS['phpgw_info']['flags']['nonavbar'] = true; - $GLOBALS['phpgw_info']['flags']['noappheader'] = true; - $GLOBALS['phpgw_info']['flags']['noappfooter'] = true; - $ls_array = $this->ls (array ( - 'string' => $data['string'], - 'relatives' => $data['relatives'], - 'checksubdirs' => False, - 'nofiles' => True - ) - ); - - if ($ls_array[0]['mime_type']) - { - $mime_type = $ls_array[0]['mime_type']; - } - elseif ($GLOBALS['settings']['viewtextplain']) - { - $mime_type = 'text/plain'; - } - - header('Content-type: ' . $mime_type); - echo $this->read (array ( - 'string' => $data['string'], - 'relatives' => $data['relatives'], - ) - ); - exit(); - } - - /*! - * @function write - * @abstract Store file contents - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @result Boolean. True on success, False otherwise. - */ - function write ($data) { return False; } - - /*! - * @function touch - * @abstract Create a file if it doesn't exist. - * Optionally, update the modified time and - * modified user if the file exists. - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @result Boolean. True on success, False otherwise. - */ - function touch ($data) { return False; } - - /*! - * @function cp - * @abstract Copy location - * @required from Path to location to copy from - * @required to Path to location to copy to - * @optional relatives Relativity array (default: RELATIVE_CURRENT, RELATIVE_CURRENT) - * @result Boolean. True on success, False otherwise. - */ - function cp ($data) { return False; } - - /*! - * @function mv - * @abstract Move location - * @required from Path to location to move from - * @required to Path to location to move to - * @optional relatives Relativity array (default: RELATIVE_CURRENT, RELATIVE_CURRENT) - * @result Boolean. True on success, False otherwise. - */ - function mv ($data) { return False; } - - /*! - * @function rm - * @abstract Delete location - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @result Boolean. True on success, False otherwise. - */ - function rm ($data) { return False; } - - /*! - * @function mkdir - * @abstract Create directory - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @result Boolean. True on success, False otherwise. - */ - function mkdir ($data) { return False; } - - /* - * Information functions. - * - * Overview: - * These functions set or return information about locations. - * - * PUBLIC functions (mandatory): - * - * set_attributes - Set attributes for a location - * - * file_exists - Check if a location (file or directory) exists - * - * get_size - Determine size of location - * - * ls - Return detailed information for location(s) - */ - - /*! - * @function set_attributes - * @abstract Set attributes for a location - * @discussion Valid attributes are listed in vfs->attributes, - * which may be extended by each derived class - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @optional attributes Keyed array of attributes. Key is attribute - * name, value is attribute value. - * @result Boolean. True on success, False otherwise. - */ - function set_attributes ($data) { return False; } - - /*! - * @function file_exists - * @abstract Check if a location (file or directory) exists - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @result Boolean. True if file exists, False otherwise. - */ - function file_exists ($data) { return False; } - - /*! - * @function get_size - * @abstract Determine size of location - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @optional checksubdirs Boolean. If set, include the size of - * all subdirectories recursively. - * @result Integer. Size of location in bytes. - */ - function get_size ($data) { return 0; } - - /*! - * @function ls - * @abstract Return detailed information for location(s) - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @optional checksubdirs Boolean. If set, return information for all - * subdirectories recursively. - * @optional mime String. Only return information for locations with MIME type - * specified. VFS classes must recogize these special types: - * "Directory" - Location is a directory - * " " - Location doesn't not have a MIME type - * @optional nofiles Boolean. If set and 'string' is a directory, return - * information about the directory, not the files in it. - * @result Array of arrays of file information. - * Keys may vary depending on the implementation, but must include - * at least those attributes listed in $this->attributes. - */ - function ls ($data) { return array(array()); } - - /* - * Linked directory functions. - * - * Overview: - * One 'special' feature that VFS classes must support - * is linking an otherwise unrelated 'real' directory into - * the virtual filesystem. For a traditional filesystem, this - * might mean linking /var/specialdir in the real filesystem to - * /home/user/specialdir in the VFS. For networked filesystems, - * this might mean linking 'another.host.com/dir' to - * 'this.host.com/home/user/somedir'. - * - * This is a feature that will be used mostly be administrators, - * in order to present a consistent view to users. Each VFS class - * will almost certainly need a new interface for the administrator - * to use to make links, but the concept is the same across all the - * VFS backends. - * - * Note that by using $this->linked_dirs in conjunction with - * $this->path_parts(), you can keep the implementation of linked - * directories very isolated in your code. - * - * PUBLIC functions (mandatory): - * - * make_link - Create a real to virtual directory link - */ - - /*! - * @function make_link - * @abstract Create a real to virtual directory link - * @required rdir Real directory to make link from/to - * @required vdir Virtual directory to make link to/from - * @optional relatives Relativity array (default: RELATIVE_CURRENT, RELATIVE_CURRENT) - * @result Boolean. True on success, False otherwise. - */ - function make_link ($data) { return False; } - - /* - * Miscellaneous functions. - * - * PUBLIC functions (mandatory): - * - * update_real - Ensure that information about a location is - * up-to-date - * - * compress - Archives a file or set of files in a compressed file - * - * extract - Dearchives a file or set of files of a compressed file - */ - - /*! - * @function update_real - * @abstract Ensure that information about a location is up-to-date - * @discussion Some VFS backends store information about locations - * in a secondary location, for example in a database - * or in a cache file. update_real() can be called to - * ensure that the information in the secondary location - * is up-to-date. - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @result Boolean. True on success, False otherwise. - */ - function update_real ($data) { return False; } - - /*! - * @function compress - * @abstract Creates an archive from a file or a set of files - * @required files File names to be stored in archive (array) - * @required name Name of archive - * @optional type The type of compression, can be 'zip'(default)or 'gz' - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * Note: the last item is the relativity of the dest archive - * @result Boolean. True on success, False otherwise. - */ - - function compress ($data) { return False; } - - /*! - * @function extract - * @abstract Extracts a file (or files) from archive - * @required name Name of archive - * @required dest The destination path of files to be extracted - * @optional type The type of compression, can be 'zip' or 'gz'. If - * not specified, uses according to the extension - * @optional files Files to be extracted from archive - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * Note: the first item is the relativity of the archive, the last of - * the dest dir - * @result Boolean. True on success, False otherwise. - */ - - function extract ($data) { return False; } - - - - /* - * SHARED FUNCTIONS - * - * The rest of the functions in this file are shared between - * all derived VFS classes. - * - * Derived classes can overload any of these functions if they - * see it fit to do so, as long as the prototypes and return - * values are the same for public functions, and the function - * accomplishes the same goal. - * - * PRIVATE functions: - * - * securitycheck - Check if location string is ok to use in VFS functions - * - * sanitize - Remove any possible security problems from a location - * string (i.e. remove leading '..') - * - * clean_string - Clean location string. This function is used if - * any special characters need to be escaped or removed - * before accessing a database, network protocol, etc. - * The default is to escape characters before doing an SQL - * query. - * - * getabsolutepath - Translate a location string depending on the - * relativity. This is the only function that is - * directly concerned with relativity. - * - * get_ext_mime_type - Return MIME type based on file extension - * - * PUBLIC functions (mandatory): - * - * set_relative - Sets the current relativity, the relativity used - * when RELATIVE_CURRENT is passed to a function - * - * get_relative - Return the current relativity - * - * path_parts - Return information about the component parts of a location string - * - * cd - Change current directory. This function is used to store the - * current directory in a standard way, so that it may be accessed - * throughout phpGroupWare to provide a consistent view for the user. - * - * pwd - Return current directory - * - * copy - Alias for cp - * - * move - Alias for mv - * - * delete - Alias for rm - * - * dir - Alias for ls - * - * command_line - Process and run a Unix-sytle command line - * - * compress - Archives a file or set of files in a compressed file - * - * extract - Dearchives a file or set of files of a compressed file - */ - - /* PRIVATE functions */ - - /*! - * @function securitycheck - * @abstract Check if location string is ok to use in VFS functions - * @discussion Checks for basic violations such as .. - * If securitycheck () fails, run your string through $this->sanitize () - * @required string Path to location - * @result Boolean. True if string is ok, False otherwise. - */ - function securitycheck ($data) - { - if (!is_array ($data)) - { - $data = array (); - } - - if (substr ($data['string'], 0, 1) == "\\" || strstr ($data['string'], "..") || strstr ($data['string'], "\\..") || strstr ($data['string'], ".\\.")) - { - return False; - } - else - { - return True; - } - } - - /*! - * @function sanitize - * @abstract Remove any possible security problems from a location - * string (i.e. remove leading '..') - * @discussion You should not pass all filenames through sanitize () - * unless you plan on rejecting .files. Instead, pass - * the name through securitycheck () first, and if it fails, - * pass it through sanitize. - * @required string Path to location - * @result String. 'string' with any security problems fixed. - */ - function sanitize ($data) - { - if (!is_array ($data)) - { - $data = array (); - } - - /* We use path_parts () just to parse the string, not translate paths */ - $p = $this->path_parts (array( - 'string' => $data['string'], - 'relatives' => array (RELATIVE_NONE) - ) - ); - - return (ereg_replace ("^\.+", '', $p->fake_name)); - } - - /*! - * @function clean_string - * @abstract Clean location string. This function is used if - * any special characters need to be escaped or removed - * before accessing a database, network protocol, etc. - * The default is to escape characters before doing an SQL - * query. - * @required string Location string to clean - * @result String. Cleaned version of 'string'. - */ - function clean_string ($data) - { - if (!is_array ($data)) - { - $data = array (); - } - - $string = $GLOBALS['phpgw']->db->db_addslashes ($data['string']); - - return $string; - } - - /*! - * @function getabsolutepath - * @abstract Translate a location string depending on the - * relativity. This is the only function that is - * directly concerned with relativity. - * @optional string Path to location, relative to mask[0]. - * Defaults to empty string. - * @optional mask Relativity array (default: RELATIVE_CURRENT) - * @optional fake Boolean. If set, returns the 'fake' path, - * i.e. /home/user/dir/file. This is not always - * possible, use path_parts() instead. - * @result String. Full fake or real path, or False on error. - */ - function getabsolutepath ($data) - { - if (!is_array ($data)) - { - $data = array (); - } - - $default_values = array - ( - 'string' => False, - 'mask' => array (RELATIVE_CURRENT), - 'fake' => True - ); - - $data = array_merge ($this->default_values ($data, $default_values), $data); - - $currentdir = $this->pwd (False); - - /* If they supply just VFS_REAL, we assume they want current relativity */ - if ($data['mask'][0] == VFS_REAL) - { - $data['mask'][0] |= RELATIVE_CURRENT; - } - - if (!$this->securitycheck (array( - 'string' => $data['string'] - )) - ) - { - return False; - } - - if ($data['mask'][0] & RELATIVE_NONE) - { - return $data['string']; - } - - if ($data['fake']) - { - $sep = '/'; - } - else - { - $sep = SEP; - } - - /* if RELATIVE_CURRENT, retrieve the current mask */ - if ($data['mask'][0] & RELATIVE_CURRENT) - { - $mask = $data['mask'][0]; - /* Respect any additional masks by re-adding them after retrieving the current mask*/ - $data['mask'][0] = $this->get_relative () + ($mask - RELATIVE_CURRENT); - } - - if ($data['fake']) - { - $basedir = "/"; - } - else - { - $basedir = $this->basedir . $sep; - - /* This allows all requests to use /'s */ - $data['string'] = preg_replace ("|/|", $sep, $data['string']); - } - - if (($data['mask'][0] & RELATIVE_PATH) && $currentdir) - { - $basedir = $basedir . $currentdir . $sep; - } - elseif (($data['mask'][0] & RELATIVE_USER) || ($data['mask'][0] & RELATIVE_USER_APP)) - { - $basedir = $basedir . $this->fakebase . $sep; - } - - if ($data['mask'][0] & RELATIVE_CURR_USER) - { - $basedir = $basedir . $this->working_lid . $sep; - } - - if (($data['mask'][0] & RELATIVE_USER) || ($data['mask'][0] & RELATIVE_USER_APP)) - { - $basedir = $basedir . $GLOBALS['phpgw_info']['user']['account_lid'] . $sep; - } - - if ($data['mask'][0] & RELATIVE_USER_APP) - { - $basedir = $basedir . "." . $GLOBALS['phpgw_info']['flags']['currentapp'] . $sep; - } - - /* Don't add string if it's a /, just for aesthetics */ - if ($data['string'] && $data['string'] != $sep) - { - $basedir = $basedir . $data['string']; - } - - /* Let's not return // */ - while (ereg ($sep . $sep, $basedir)) - { - $basedir = ereg_replace ($sep . $sep, $sep, $basedir); - } - - $basedir = ereg_replace ($sep . '$', '', $basedir); - - return $basedir; - } - - /*! - * @function get_ext_mime_type - * @abstract Return MIME type based on file extension - * @description Internal use only. Applications should call vfs->file_type () - * @author skeeter - * @required string Real path to file, with or without leading paths - * @result String. MIME type based on file extension. - */ - function get_ext_mime_type ($data) - { - if (!is_array ($data)) - { - $data = array (); - } - - $file=basename($data['string']); - $mimefile=PHPGW_API_INC.'/phpgw_mime.types'; - $fp=fopen($mimefile,'r'); - $contents = explode("\n",fread($fp,filesize($mimefile))); - fclose($fp); - - $parts=explode('.',strtolower($file)); - $ext=$parts[(sizeof($parts)-1)]; - - for($i=0;$i= 2) - { - for($j=1;$jrelative); - } - else - { - $this->relative = $data['mask']; - } - } - - /*! - * @function get_relative - * @abstract Return the current relativity - * @discussion Returns relativity bitmask, or the default - * of "completely relative" if unset - * @result Integer. One of the RELATIVE_* defines. - */ - function get_relative () - { - if (isset ($this->relative) && $this->relative) - { - return $this->relative; - } - else - { - return RELATIVE_ALL; - } - } - - /*! - * @function path_parts - * @abstract Return information about the component parts of a location string - * @discussion Most VFS functions call path_parts() with their 'string' and - * 'relatives' arguments before doing their work, in order to - * determine the file/directory to work on. - * @required string Path to location - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - * @optional object If set, return an object instead of an array - * @optional nolinks Don't check for linked directories (made with - * make_link()). Used internally to prevent recursion. - * @result Array or object. Contains the fake and real component parts of the path. - * @discussion Returned values are: - * mask - * outside - * fake_full_path - * fake_leading_dirs - * fake_extra_path BROKEN - * fake_name - * real_full_path - * real_leading_dirs - * real_extra_path BROKEN - * real_name - * fake_full_path_clean - * fake_leading_dirs_clean - * fake_extra_path_clean BROKEN - * fake_name_clean - * real_full_path_clean - * real_leading_dirs_clean - * real_extra_path_clean BROKEN - * real_name_clean - * "clean" values are run through vfs->clean_string () and - * are safe for use in SQL queries that use key='value' - * They should be used ONLY for SQL queries, so are used - * mostly internally - * mask is either RELATIVE_NONE or RELATIVE_NONE|VFS_REAL, - * and is used internally - * outside is boolean, True if 'relatives' contains VFS_REAL - */ - function path_parts ($data) - { - if (!is_array ($data)) - { - $data = array (); - } - - $default_values = array - ( - 'relatives' => array (RELATIVE_CURRENT), - 'object' => True, - 'nolinks' => False - ); - - $data = array_merge ($this->default_values ($data, $default_values), $data); - - $sep = SEP; - - $rarray['mask'] = RELATIVE_NONE; - - if (!($data['relatives'][0] & VFS_REAL)) - { - $rarray['outside'] = False; - $fake = True; - } - else - { - $rarray['outside'] = True; - $rarray['mask'] |= VFS_REAL; - } - - $string = $this->getabsolutepath (array( - 'string' => $data['string'], - 'mask' => array ($data['relatives'][0]), - 'fake' => $fake - ) - ); - - if ($fake) - { - $base_sep = '/'; - $base = '/'; - - $opp_base = $this->basedir . $sep; - - $rarray['fake_full_path'] = $string; - } - else - { - $base_sep = $sep; - if (substr($string,0,strlen($this->basedir)+1) == $this->basedir . $sep) - { - $base = $this->basedir . $sep; - } - else - { - $base = $sep; - } - - $opp_base = '/'; - - $rarray['real_full_path'] = $string; - } - - /* This is needed because of substr's handling of negative lengths */ - $baselen = strlen ($base); - $lastslashpos = @strrpos ($string, $base_sep); - $length = $lastslashpos < $baselen ? 0 : $lastslashpos - $baselen; - - $extra_path = $rarray['fake_extra_path'] = $rarray['real_extra_path'] = substr ($string, strlen ($base), $length); - if($string[1] != ':') - { - $name = $rarray['fake_name'] = $rarray['real_name'] = substr ($string, @strrpos ($string, $base_sep) + 1); - } - else - { - $name = $rarray['fake_name'] = $rarray['real_name'] = $string; - } - - if ($fake) - { - $rarray['real_extra_path'] ? $dispsep = $sep : $dispsep = ''; - $rarray['real_full_path'] = $opp_base . $rarray['real_extra_path'] . $dispsep . $rarray['real_name']; - if ($extra_path) - { - $rarray['fake_leading_dirs'] = $base . $extra_path; - $rarray['real_leading_dirs'] = $opp_base . $extra_path; - } - elseif (@strrpos ($rarray['fake_full_path'], $sep) == 0) - { - /* If there is only one $sep in the path, we don't want to strip it off */ - $rarray['fake_leading_dirs'] = $sep; - $rarray['real_leading_dirs'] = substr ($opp_base, 0, strlen ($opp_base) - 1); - } - else - { - /* These strip the ending / */ - $rarray['fake_leading_dirs'] = substr ($base, 0, strlen ($base) - 1); - $rarray['real_leading_dirs'] = substr ($opp_base, 0, strlen ($opp_base) - 1); - } - } - else - { - if($rarray['fake_name'][1] != ':') - { - $rarray['fake_full_path'] = $opp_base . $rarray['fake_extra_path'] . '/' . $rarray['fake_name']; - } - else - { - $rarray['fake_full_path'] = $rarray['fake_name']; - } - if ($extra_path) - { - $rarray['fake_leading_dirs'] = $opp_base . $extra_path; - $rarray['real_leading_dirs'] = $base . $extra_path; - } - else - { - $rarray['fake_leading_dirs'] = substr ($opp_base, 0, strlen ($opp_base) - 1); - $rarray['real_leading_dirs'] = substr ($base, 0, strlen ($base) - 1); - } - } - - /* We check for linked dirs made with make_link (). This could be better, but it works */ - if (!$data['nolinks']) - { - reset ($this->linked_dirs); - while (list ($num, $link_info) = each ($this->linked_dirs)) - { - if (ereg ("^$link_info[directory]/$link_info[name](/|$)", $rarray['fake_full_path'])) - { - $rarray['real_full_path'] = ereg_replace ("^$this->basedir", '', $rarray['real_full_path']); - $rarray['real_full_path'] = ereg_replace ("^$link_info[directory]" . SEP . "$link_info[name]", $link_info['link_directory'] . SEP . $link_info['link_name'], $rarray['real_full_path']); - - $p = $this->path_parts (array( - 'string' => $rarray['real_full_path'], - 'relatives' => array (RELATIVE_NONE|VFS_REAL), - 'nolinks' => True - ) - ); - - $rarray['real_leading_dirs'] = $p->real_leading_dirs; - $rarray['real_extra_path'] = $p->real_extra_path; - $rarray['real_name'] = $p->real_name; - } - } - } - - /* - We have to count it before because new keys will be added, - which would create an endless loop - */ - $count = count ($rarray); - reset ($rarray); - for ($i = 0; (list ($key, $value) = each ($rarray)) && $i != $count; $i++) - { - $rarray[$key . '_clean'] = $this->clean_string (array ('string' => $value)); - } - - if ($data['object']) - { - $robject = new path_class; - - reset ($rarray); - while (list ($key, $value) = each ($rarray)) - { - $robject->$key = $value; - } - } - - /* - echo "
fake_full_path: $rarray[fake_full_path] -
fake_leading_dirs: $rarray[fake_leading_dirs] -
fake_extra_path: $rarray[fake_extra_path] -
fake_name: $rarray[fake_name] -
real_full_path: $rarray[real_full_path] -
real_leading_dirs: $rarray[real_leading_dirs] -
real_extra_path: $rarray[real_extra_path] -
real_name: $rarray[real_name]"; - */ - - if ($data['object']) - { - return ($robject); - } - else - { - return ($rarray); - } - } - - /*! - * @function cd - * @abstract Change current directory. This function is used to store the - * current directory in a standard way, so that it may be accessed - * throughout phpGroupWare to provide a consistent view for the user. - * @discussion To cd to the root '/', use: - * cd (array( - * 'string' => '/', - * 'relative' => False, - * 'relatives' => array (RELATIVE_NONE) - * )); - * @optional string Directory location to cd into. Default is '/'. - * @optional relative If set, add target to current path. - * Else, pass 'relative' as mask to getabsolutepath() - * Default is True. - * @optional relatives Relativity array (default: RELATIVE_CURRENT) - */ - function cd ($data = '') - { - if (!is_array ($data)) - { - $noargs = 1; - $data = array (); - } - - $default_values = array - ( - 'string' => '/', - 'relative' => True, - 'relatives' => array (RELATIVE_CURRENT) - ); - - $data = array_merge ($this->default_values ($data, $default_values), $data); - - if ($data['relatives'][0] & VFS_REAL) - { - $sep = SEP; - } - else - { - $sep = '/'; - } - - if ($data['relative'] == 'relative' || $data['relative'] == True) - { - /* if 'string' is "/" and 'relative' is set, we cd to the user/group home dir */ - if ($data['string'] == '/') - { - $data['relatives'][0] = RELATIVE_USER; - $basedir = $this->getabsolutepath (array( - 'string' => False, - 'mask' => array ($data['relatives'][0]), - 'fake' => True - ) - ); - } - else - { - $currentdir = $GLOBALS['phpgw']->session->appsession('vfs',''); - $basedir = $this->getabsolutepath (array( - 'string' => $currentdir . $sep . $data['string'], - 'mask' => array ($data['relatives'][0]), - 'fake' => True - ) - ); - } - } - else - { - $basedir = $this->getabsolutepath (array( - 'string' => $data['string'], - 'mask' => array ($data['relatives'][0]) - ) - ); - } - - $GLOBALS['phpgw']->session->appsession('vfs','',$basedir); - - return True; - } - - /*! - * @function pwd - * @abstract Return current directory - * @optional full If set, return full fake path, else just - * the extra dirs (False strips the leading /). - * Default is True. - * @result String. The current directory. - */ - function pwd ($data = '') - { - if (!is_array ($data)) - { - $data = array (); - } - - $default_values = array - ( - 'full' => True - ); - - $data = array_merge ($this->default_values ($data, $default_values), $data); - - $currentdir = $GLOBALS['phpgw']->session->appsession('vfs',''); - - if (!$data['full']) - { - $currentdir = ereg_replace ("^/", '', $currentdir); - } - - if ($currentdir == '' && $data['full']) - { - $currentdir = '/'; - } - - $currentdir = trim ($currentdir); - - return $currentdir; - } - - /*! - * @function copy - * @abstract shortcut to cp - */ - function copy ($data) - { - return $this->cp ($data); - } - - /*! - * @function move - * @abstract shortcut to mv - */ - function move ($data) - { - return $this->mv ($data); - } - - /*! - * @function delete - * @abstract shortcut to rm - */ - function delete ($data) - { - return $this->rm ($data); - } - - /*! - * @function dir - * @abstract shortcut to ls - */ - function dir ($data) - { - return $this->ls ($data); - } - - /*! - * @function command_line - * @abstract Process and run a Unix-sytle command line - * @discussion EXPERIMENTAL. DANGEROUS. DO NOT USE THIS UNLESS YOU - * KNOW WHAT YOU'RE DOING! - * This is mostly working, but the command parser needs - * to be improved to take files with spaces into - * consideration (those should be in ""). - * @required command_line Unix-style command line with one of the - * commands in the $args array - * @result The return value of the actual VFS call - */ - function command_line ($data) - { - if (!is_array ($data)) - { - $data = array (); - } - - $args = array - ( - array ('name' => 'mv', 'params' => 2), - array ('name' => 'cp', 'params' => 2), - array ('name' => 'rm', 'params' => 1), - array ('name' => 'ls', 'params' => -1), - array ('name' => 'du', 'params' => 1, 'func' => get_size), - array ('name' => 'cd', 'params' => 1), - array ('name' => 'pwd', 'params' => 0), - array ('name' => 'cat', 'params' => 1, 'func' => read), - array ('name' => 'file', 'params' => 1, 'func' => file_type), - array ('name' => 'mkdir', 'params' => 1), - array ('name' => 'touch', 'params' => 1) - ); - - if (!$first_space = strpos ($data['command_line'], ' ')) - { - $first_space = strlen ($data['command_line']); - } - if ((!$last_space = strrpos ($data['command_line'], ' ')) || ($last_space == $first_space)) - { - $last_space = strlen ($data['command_line']) + 1; - } - $argv[0] = substr ($data['command_line'], 0, $first_space); - if (strlen ($argv[0]) != strlen ($data['command_line'])) - { - $argv[1] = substr ($data['command_line'], $first_space + 1, $last_space - ($first_space + 1)); - if ((strlen ($argv[0]) + 1 + strlen ($argv[1])) != strlen ($data['command_line'])) - { - $argv[2] = substr ($data['command_line'], $last_space + 1); - } - } - $argc = count ($argv); - - reset ($args); - while (list (,$arg_info) = each ($args)) - { - if ($arg_info['name'] == $argv[0]) - { - $command_ok = 1; - if (($argc == ($arg_info['params'] + 1)) || ($arg_info['params'] == -1)) - { - $param_count_ok = 1; - } - break; - } - } - - if (!$command_ok) - { -// return E_VFS_BAD_COMMAND; - return False; - } - if (!$param_count_ok) - { -// return E_VFS_BAD_PARAM_COUNT; - return False; - } - - for ($i = 1; $i != ($arg_info['params'] + 1); $i++) - { - if (substr ($argv[$i], 0, 1) == "/") - { - $relatives[] = RELATIVE_NONE; - } - else - { - $relatives[] = RELATIVE_ALL; - } - } - - $func = $arg_info['func'] ? $arg_info['func'] : $arg_info['name']; - - if (!$argv[2]) - { - $rv = $this->$func (array( - 'string' => $argv[1], - 'relatives' => $relatives - ) - ); - } - else - { - $rv = $this->$func (array( - 'from' => $argv[1], - 'to' => $argv[2], - 'relatives' => $relatives - ) - ); - } - - return ($rv); - } - - /* Helper functions, not public */ - - function default_values ($data, $default_values) - { - for ($i = 0; list ($key, $value) = each ($default_values); $i++) - { - if (!isset ($data[$key])) - { - $data[$key] = $value; - } - } - - return $data; - } - - } - -?> diff --git a/phpgwapi/inc/class.vfs_sql.inc.php b/phpgwapi/inc/class.vfs_sql.inc.php index 66a7324677..b8b1000e97 100644 --- a/phpgwapi/inc/class.vfs_sql.inc.php +++ b/phpgwapi/inc/class.vfs_sql.inc.php @@ -41,7 +41,8 @@ var $meta_types; var $now; var $file_actions; // true if the content is stored in the file-system, false if it's stored in the DB too - var $vfs_table = 'phpgw_vfs'; + var $vfs_table = 'egw_vfs'; + var $vfs_column_prefix = 'vfs_'; /*! @function vfs @@ -66,6 +67,12 @@ $this->attributes[] = 'deleteable'; $this->attributes[] = 'content'; + // set up the keys as db-column-names + foreach($this->attributes as $n => $attr) + { + unset($this->attributes[$n]); + $this->attributes[$this->vfs_column_prefix.$attr] = $attr; + } /* Decide whether to use any actual filesystem calls (fopen(), fread(), unlink(), rmdir(), touch(), etc.). If not, then we're working completely @@ -94,7 +101,7 @@ $this->meta_types = array ('journal', 'journal-deleted'); - $this->db = $GLOBALS['phpgw']->db; + $this->db = clone($GLOBALS['phpgw']->db); $this->db->set_app('phpgwapi'); /* We store the linked directories in an array now, so we don't have to make the SQL call again */ @@ -103,24 +110,29 @@ case 'mssql': case 'sybase': $where = array( - "CONVERT(varchar,link_directory) != ''", - "CONVERT(varchar,link_name) != ''", + "CONVERT(varchar,vfs_link_directory) != ''", + "CONVERT(varchar,vfs_link_name) != ''", ); break; default: $where = array( - "(link_directory IS NOT NULL OR link_directory != '')", - "(link_name IS NOT NULL or link_name != '')", + "(vfs_link_directory IS NOT NULL OR vfs_link_directory != '')", + "(vfs_link_name IS NOT NULL OR vfs_link_name != '')", ); break; } $where[] = $this->extra_sql(array('query_type' => VFS_SQL_SELECT)); - $this->db->select($this->vfs_table,'directory,name,link_directory,link_name',$where,__LINE__,__FILE__); + $this->db->select($this->vfs_table,'vfs_directory,vfs_name,vfs_link_directory,vfs_link_name',$where,__LINE__,__FILE__); $this->linked_dirs = array (); while ($this->db->next_record ()) { - $this->linked_dirs[] = $this->db->Record; + $this->linked_dirs[] = array( + 'directory' => $this->db->Record['vfs_directory'], + 'name' => $this->db->Record['vfs_name'], + 'link_directory' => $this->db->Record['vfs_link_directory'], + 'link_name' => $this->db->Record['vfs_link_name'], + ); } } @@ -164,7 +176,7 @@ if ($data['query_type'] == VFS_SQL_SELECT || $data['query_type'] == VFS_SQL_DELETE || $data['query_type'] = VFS_SQL_UPDATE) { - return "((mime_type != '".implode("' AND mime_type != '",$this->meta_types)."') OR mime_type IS NULL)"; + return "((vfs_mime_type != '".implode("' AND vfs_mime_type != '",$this->meta_types)."') OR vfs_mime_type IS NULL)"; } return ''; } @@ -377,7 +389,7 @@ if (isset ($value)) { - $to_write[$attribute] = $value; + $to_write[$this->vfs_column_prefix.$attribute] = $value; } } /* @@ -438,10 +450,10 @@ ) ); - $this->db->update($this->vfs_table,array('mime_type'=>'journal-deleted'),array( - 'directory' => $state_one_path_parts->fake_leading_dirs, - 'name' => $state_one_path_parts->fake_name, - 'mime_type' => 'journal', + $this->db->update($this->vfs_table,array('vfs_mime_type'=>'journal-deleted'),array( + 'vfs_directory' => $state_one_path_parts->fake_leading_dirs, + 'vfs_name' => $state_one_path_parts->fake_name, + 'vfs_mime_type' => 'journal', ),__LINE__,__FILE__); /* @@ -466,11 +478,11 @@ if ($data['operation'] == VFS_OPERATION_DELETED) { $this->db->update($this->vfs_table,array( - 'mime_type' => 'journal-deleted' + 'vfs_mime_type' => 'journal-deleted' ),array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, - 'mime_type' => 'journal', + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, + 'vfs_mime_type' => 'journal', ),__LINE__,__FILE); } @@ -512,15 +524,15 @@ ); $where = array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, ); if (!$data['deleteall']) { - $where[] = "(mime_type != 'journal' AND comment != 'Created')"; + $where[] = "(vfs_mime_type != 'journal' AND vfs_comment != 'Created')"; } - $where[] = "(mime_type='journal-deleted'".(!$data['deletedonly']?" OR mime_type='journal'":'').')'; + $where[] = "(vfs_mime_type='journal-deleted'".(!$data['deletedonly']?" OR vfs_mime_type='journal'":'').')'; return !!$this->db->delete($this->vfs_table,$where, __LINE__, __FILE__); } @@ -558,33 +570,33 @@ } $where = array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, ); if ($data['type'] == 1) { - $where[] = "mime_type='journal'"; + $where[] = "vfs_mime_type='journal'"; } elseif ($data['type'] == 2) { - $where[] = "mime_type='journal-deleted'"; + $where[] = "vfs_mime_type='journal-deleted'"; } else { - $where[] = "(mime_type='journal' OR mime_type='journal-deleted')"; + $where[] = "(vfs_mime_type='journal' OR vfs_mime_type='journal-deleted')"; } $this->db->select($this->vfs_table,'*',$where, __LINE__, __FILE__); - while ($this->db->next_record ()) + while (($row = $this->db->Row(true))) { - $rarray[] = $this->db->Record; + $rarray[] = $this->remove_prefix($row); } return $rarray; } - + /* * See vfs_shared */ @@ -674,14 +686,14 @@ We don't use ls () to get owner_id as we normally would, because ls () calls acl_check (), which would create an infinite loop */ - $this->db->select($this->vfs_table,'owner_id',array( - 'directory' => $p2->fake_leading_dirs, - 'name' => $p2->fake_name, + $this->db->select($this->vfs_table,'vfs_owner_id',array( + 'vfs_directory' => $p2->fake_leading_dirs, + 'vfs_name' => $p2->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_SELECT)) ), __LINE__, __FILE__); $this->db->next_record (); - $owner_id = $this->db->Record['owner_id']; + $owner_id = $this->db->Record['vfs_owner_id']; } else { @@ -738,10 +750,7 @@ } elseif (!$rights && $group_ok) { - $conf = CreateObject('phpgwapi.config', 'phpgwapi'); - $conf->read_repository(); - - return $conf->config_data['acl_default'] == 'grant'; + return $GLOBALS['phpgw_info']['server']['acl_default'] == 'grant'; } else { @@ -782,8 +791,6 @@ return False; } - $conf = CreateObject('phpgwapi.config', 'phpgwapi'); - $conf->read_repository(); if ($this->file_actions || $p->outside) { if (($fp = fopen ($p->real_full_path, 'rb'))) @@ -870,8 +877,6 @@ ) ); - $conf = CreateObject('phpgwapi.config', 'phpgwapi'); - $conf->read_repository(); if ($this->file_actions) { if (($fp = fopen ($p->real_full_path, 'wb'))) @@ -1006,9 +1011,9 @@ } $query = $this->db->insert($this->vfs_table,array( - 'owner_id' => $this->working_id, - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + 'vfs_owner_id' => $this->working_id, + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, ),false,__LINE__,__FILE__); $this->set_attributes(array( @@ -1453,20 +1458,20 @@ 'relatives' => array ($t->mask) ) ); - $this->db->update($this->vfs_table,array('size'=>$size),array( - 'directory' => $t->fake_leading_dirs, - 'name' => $t->fake_name, + $this->db->update($this->vfs_table,array('vfs_size'=>$size),array( + 'vfs_directory' => $t->fake_leading_dirs, + 'vfs_name' => $t->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_UPDATE)), ), __LINE__, __FILE__); } elseif (!$t->outside) { $this->db->update($this->vfs_table,array( - 'directory' => $t->fake_leading_dirs, - 'name' => $t->fake_name, + 'vfs_directory' => $t->fake_leading_dirs, + 'vfs_name' => $t->fake_name, ),array( - 'directory' => $f->fake_leading_dirs, - 'name' => $f->fake_name, + 'vfs_directory' => $f->fake_leading_dirs, + 'vfs_name' => $f->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_UPDATE)), ), __LINE__, __FILE__); } @@ -1522,9 +1527,9 @@ $newdir = ereg_replace ("^$f->fake_full_path", $t->fake_full_path, $entry['directory']); $this->db->update($this->vfs_table,array( - 'directory' => $newdir + 'vfs_directory' => $newdir ),array( - 'file_id' => $entry['file_id'], + 'vfs_file_id' => $entry['file_id'], $this->extra_sql(array ('query_type' => VFS_SQL_UPDATE)) ), __LINE__, __FILE__); @@ -1620,8 +1625,8 @@ ); $query = $this->db->delete($this->vfs_table,array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_DELETE)) ), __LINE__, __FILE__); @@ -1710,8 +1715,8 @@ ); $this->db->delete($this->vfs_table,array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_DELETE)) ), __LINE__, __FILE__); @@ -1794,9 +1799,9 @@ ) { $this->db->insert($this->vfs_table,array( - 'owner_id' => $this->working_id, - 'name' => $p->fake_name, - 'directory' => $p->fake_leading_dirs, + 'vfs_owner_id' => $this->working_id, + 'vfs_name' => $p->fake_name, + 'vfs_directory' => $p->fake_leading_dirs, ),false,__LINE__,__FILE__); $this->set_attributes(array( @@ -1991,7 +1996,7 @@ { $edited_comment = 1; } - $to_write[$attribute] = $data['attributes'][$attribute]; + $to_write[$this->vfs_column_prefix.$attribute] = $data['attributes'][$attribute]; } } @@ -2000,7 +2005,7 @@ return True; // nothing to do } if (!$this->db->update($this->vfs_table,$to_write,array( - 'file_id' => $record['file_id'], + 'vfs_file_id' => $record['file_id'], $this->extra_sql(array ('query_type' => VFS_SQL_UPDATE)), ), __LINE__, __FILE__)) { @@ -2132,23 +2137,23 @@ We don't use ls () because it calls file_type () to determine if it has been passed a directory */ - $db2 = $this->db; - $db2->select($this->vfs_table,'mime_type',array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + $db2 = clone($this->db); + $db2->select($this->vfs_table,'vfs_mime_type',array( + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_SELECT)) ), __LINE__, __FILE__); $db2->next_record (); - $mime_type = $db2->Record['mime_type']; + $mime_type = $db2->Record['vfs_mime_type']; if(!$mime_type) { $mime_type = $this->get_ext_mime_type (array ('string' => $data['string'])); { $db2->update($this->vfs_table,array( - 'mime_type' => $mime_type + 'vfs_mime_type' => $mime_type ),array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_SELECT)) ), __LINE__, __FILE__); } @@ -2186,10 +2191,10 @@ return $rr; } - $db2 = $this->db; - $db2->select($this->vfs_table,'name',array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + $db2 = clone($this->db); + $db2->select($this->vfs_table,'vfs_name',array( + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_SELECT)) ), __LINE__, __FILE__); @@ -2265,9 +2270,9 @@ if ($data['checksubdirs']) { - $this->db->select($this->vfs_table,'size',array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + $this->db->select($this->vfs_table,'vfs_size',array( + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_SELECT)) ), __LINE__, __FILE__); $this->db->next_record (); @@ -2319,7 +2324,6 @@ */ function ls ($data) { -//echo "

vfs_sql::ls(".print_r($data,true).")

\n"; if (!is_array ($data)) { $data = array (); @@ -2335,7 +2339,6 @@ ); $data = array_merge ($this->default_values ($data, $default_values), $data); -//echo "

vfs_sql::ls: data=".print_r($data,true)."

\n"; $p = $this->path_parts (array( 'string' => $data['string'], @@ -2343,7 +2346,6 @@ ) ); $dir = $p->fake_full_path; -//echo "

vfs_sql::ls: dir='$dir', p=".print_r($p,true)."

\n"; /* If they pass us a file or 'nofiles' is set, return the info for $dir only */ if (@$data['file_id'] || ($this->file_type (array( @@ -2354,20 +2356,19 @@ /* SELECT all, the, attributes */ if (@$data['file_id']) { - $where = array('file_id' => $data['file_id']); + $where = array('vfs_file_id' => $data['file_id']); } else { $where = array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_SELECT)) ); } - $this->db->select($this->vfs_table,$this->attributes,$where,__LINE__,__FILE__); + $this->db->select($this->vfs_table,array_keys($this->attributes),$where,__LINE__,__FILE__); - $this->db->next_record (); - $record = $this->db->Record; + $record = $this->db->Row(true,$this->vfs_column_prefix); /* We return an array of one array to maintain the standard */ $rarray = array (); @@ -2383,10 +2384,10 @@ if($record[$attribute]) { $this->db->update($this->vfs_table,array( - 'mime_type' => $record[$attribute] + 'vfs_mime_type' => $record[$attribute] ),array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_SELECT)) ), __LINE__, __FILE__); } @@ -2442,22 +2443,22 @@ /* $dir's not a file, is inside the virtual root, and they want to check subdirs */ /* SELECT all, the, attributes FROM $this->vfs_table WHERE file=$dir */ - $db2 = $this->db; + $db2 = clone($this->db); $where = array( - 'directory LIKE '.$this->db->quote($dir.'%'), + 'vfs_directory LIKE '.$this->db->quote($dir.'%'), $this->extra_sql(array ('query_type' => VFS_SQL_SELECT)), ); if ($data['mime_type']) { - $where['mime_type'] = $data['mime_type']; + $where['vfs_mime_type'] = $data['mime_type']; } - $this->db->select($this->vfs_table,$this->attributes,$where, __LINE__, __FILE__,false,'ORDER BY '.$data['orderby']); + $this->db->select($this->vfs_table,array_keys($this->attributes),$where, __LINE__, __FILE__,false, + isset($this->attributes[$this->vfs_column_prefix.$data['orderby']]) ? + 'ORDER BY '.$this->vfs_column_prefix.$data['orderby'] : ''); $rarray = array (); - for ($i = 0; $this->db->next_record (); $i++) + for ($i = 0; ($record = $this->db->Row(true,$this->vfs_column_prefix)); $i++) { - $record = $this->db->Record; - /* Further checking on the directory. This makes sure /home/user/test won't match /home/user/test22 */ if (@!ereg ("^$dir(/|$)", $record['directory'])) { @@ -2482,10 +2483,10 @@ if($record[$attribute]) { $db2->update($this->vfs_table,array( - 'mime_type' => $record[$attribute] + 'vfs_mime_type' => $record[$attribute] ),array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_SELECT)) ), __LINE__, __FILE__); } @@ -2633,10 +2634,10 @@ if($mime_type) { $this->db->update($this->vfs_table,array( - 'mime_type' => $mime_type + 'vfs_mime_type' => $mime_type ),array( - 'directory' => $p->fake_leading_dirs, - 'name' => $p->fake_name, + 'vfs_directory' => $p->fake_leading_dirs, + 'vfs_name' => $p->fake_name, $this->extra_sql(array ('query_type' => VFS_SQL_SELECT)) ), __LINE__, __FILE__); }