phpgroupware-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Phpgroupware-cvs] property/class.vfs_shared.php, 1.1.2.1


From: nomail
Subject: [Phpgroupware-cvs] property/class.vfs_shared.php, 1.1.2.1
Date: Sun, 23 May 2004 14:10:02 -0000

Update of /property
Added Files:
        Branch: proposal-branch
          class.vfs_shared.php

date: 2004/04/30 17:35:58;  author: sigurdne;  state: Exp;  lines: +1422 -0

Log Message:
no message
=====================================================================
<?php
        /**
        * Virtual File System
        * @author Jason Wies <address@hidden>
    * @author Giancarlo Susin
        * @copyright Copyright (C) 2001 Jason Wies
        * @copyright Portions Copyright (C) 2004 Free Software Foundation, Inc. 
http://www.fsf.org/
        * @license http://www.fsf.org/licenses/lgpl.html GNU Lesser General 
Public License
        * @package phpgwapi
        * @subpackage vfs
        * @version $Id: class.vfs_shared.php,v 1.1.2.1 2004/04/30 17:35:58 
sigurdne Exp $
        */

        /**
        * Relative root path
        * @see getabsolutepath()
        */
        define ('RELATIVE_ROOT', 1);
        /**
        * Relative user path
        * @see getabsolutepath()
        */
        define ('RELATIVE_USER', 2);
        /**
        * Relative current user path
        * @see getabsolutepath()
        */
        define ('RELATIVE_CURR_USER', 4);
        /**
        * Relative user application path
        * @see getabsolutepath()
        */
        define ('RELATIVE_USER_APP', 8);
        /**
        * Relative path
        * @see getabsolutepath()
        */
        define ('RELATIVE_PATH', 16);
        /**
        * Relative none path
        * @see getabsolutepath()
        */
        define ('RELATIVE_NONE', 32);
        /**
        * Relative current path
        * @see getabsolutepath()
        */
        define ('RELATIVE_CURRENT', 64);
        /**
        * VFS real path
        * @see getabsolutepath()
        */
        define ('VFS_REAL', 1024);
        /**
        * Relative path
        * @see getabsolutepath()
        */
        define ('RELATIVE_ALL', RELATIVE_PATH);


        /**
        * Journal message: VFS operation created
        * @see add_journal()
        */
        define ('VFS_OPERATION_CREATED', 1);
        /**
        * Journal message: VFS operation edited
        * @see add_journal()
        */
        define ('VFS_OPERATION_EDITED', 2);
        /**
        * Journal message: VFS operation edited comment
        * @see add_journal()
        */
        define ('VFS_OPERATION_EDITED_COMMENT', 4);
        /**
        * Journal message: VFS operation copied
        * @see add_journal()
        */
        define ('VFS_OPERATION_COPIED', 8);
        /**
        * Journal message: VFS operation moved
        * @see add_journal()
        */
        define ('VFS_OPERATION_MOVED', 16);
        /**
        * Journal message: VFS operation deleted
        * @see add_journal()
        */
        define ('VFS_OPERATION_DELETED', 32);


        /**
        * Helper class for path_parts
        *
        * @package phpgwapi
        * @subpackage vfs
        */
        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;
        }


        /**
        * Base class for Virtual File System classes
        *
        * @package phpgwapi
        * @subpackage vfs
        */
        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_data']['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
                 */

                /*!
                 * @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; }

                /*
                 * 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
                 */

                /* 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 = ereg_replace ("'", "\'", $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_data']['user']['lid'] . $sep;
                        }

                        if ($data['mask'][0] & RELATIVE_USER_APP)
                        {
                                $basedir = $basedir . "." . 
$GLOBALS['phpgw_data']['flags']['req_app'] . $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<sizeof($contents);$i++)
                        {
                                if (!ereg("^#",$contents[$i]))
                                {
                                        $line=split("[[:space:]]+", 
$contents[$i]);
                                        if (sizeof($line) >= 2)
                                        {
                                                for($j=1;$j<sizeof($line);$j++)
                                                {
                                                        if($line[$j] == $ext)
                                                        {
                                                                return $line[0];
                                                        }
                                                }
                                        }
                                }
                        }

                        return '';
                }

                /* PUBLIC functions (mandatory) */

                /*!
                 * @function set_relative
                 * @abstract Sets the current relativity, the relativity used
                 *           when RELATIVE_CURRENT is passed to a function
                 * @optional mask       Relative bitmask.  If not set, 
relativity
                 *                      will be returned to the default.
                 * @result Void
                 */
                function set_relative ($data)
                {
                        if (!is_array ($data))
                        {
                                $data = array ();
                        }

                        if (!$data['mask'])
                        {
                                unset ($this->relative);
                        }
                        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 (ereg ("^$this->basedir" . $sep, $string))
                                {
                                        $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)
                        {
                                $dispsep = ($rarray['real_extra_path'] ? $sep : 
'');
                                $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 "<br>fake_full_path: $rarray[fake_full_path]
                                <br>fake_leading_dirs: 
$rarray[fake_leading_dirs]
                                <br>fake_extra_path: $rarray[fake_extra_path]
                                <br>fake_name: $rarray[fake_name]
                                <br>real_full_path: $rarray[real_full_path]
                                <br>real_leading_dirs: 
$rarray[real_leading_dirs]
                                <br>real_extra_path: $rarray[real_extra_path]
                                <br>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;
                }
        }

?>




reply via email to

[Prev in Thread] Current Thread [Next in Thread]