Logo Search packages:      
Sourcecode: egroupware version File versions  Download package

class.vfs_shared.inc.php

<?php
  /**************************************************************************\
  * eGroupWare API - VFS base class                                          *
  * This file written by Jason Wies (Zone) <zone@phpgroupware.org>           *
  * 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: class.vfs_shared.inc.php,v 1.6.2.1 2004/07/25 01:34:57 ralfbecker Exp $ */

      /* 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
       */
00049       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
       */
00076       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())
             */
00146             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
             */
00202             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.
             */
00238             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.
             */
00272             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.
            */
00285              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.
             */
00331             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.
             */
00342             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.
             */
00352             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.
             */
00362             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.
             */
00371             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.
             */
00380             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.
             */
00410              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.
             */
00419             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.
             */
00430             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.
             */
00449             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.
             */
00486             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.
             */
00509             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.
             */
00577             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.
             */
00605             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'.
             */
00632             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.
             */
00657             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.
             */
00772             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
             */
00819             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.
             */
00843             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
             */
00894             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 "<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)
             */
01102             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.
             */
01174             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
             */
01209             function copy ($data)
            {
                  return $this->cp ($data);
            }

            /*!
             * @function move
             * @abstract shortcut to mv
             */
01218             function move ($data)
            {
                  return $this->mv ($data);
            }

            /*!
             * @function delete
             * @abstract shortcut to rm
             */
01227             function delete ($data)
            {
                  return $this->rm ($data);
            }

            /*!
             * @function dir
             * @abstract shortcut to ls
             */
01236             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
             */
01253             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;
            }
      }

?>

Generated by  Doxygen 1.6.0   Back to index