VFS
[ class tree: VFS ] [ index: VFS ] [ all elements ]

Source for file file.php

Documentation is available at file.php

  1. <?php
  2. /**
  3.  * VFS implementation for a standard filesystem.
  4.  *
  5.  * <pre>
  6.  * Required values for $params:
  7.  *      'vfsroot'       The root path
  8.  * </pre>
  9.  *
  10.  * Note: The user that your webserver runs as (commonly 'nobody',
  11.  * 'apache', or 'www-data') MUST have read/write permission to the
  12.  * directory you specific as the 'vfsroot'.
  13.  *
  14.  * $Horde: framework/VFS/VFS/file.php,v 1.66 2005/03/28 17:24:21 chuck Exp $
  15.  *
  16.  * Copyright 2002-2005 Chuck Hagenbuch <chuck@horde.org>
  17.  *
  18.  * See the enclosed file COPYING for license information (LGPL). If you
  19.  * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  20.  *
  21.  * @author  Chuck Hagenbuch
  22.  * @since   Horde 2.2
  23.  * @package VFS
  24.  */
  25. class VFS_file extends VFS {
  26.  
  27.     /**
  28.      * List of permissions and if they can be changed in this VFS
  29.      * backend.
  30.      *
  31.      * @var array $_permissions 
  32.      */
  33.     var $_permissions = array(
  34.         'owner' => array('read' => true'write' => true'execute' => true),
  35.         'group' => array('read' => true'write' => true'execute' => true),
  36.         'all'   => array('read' => true'write' => true'execute' => true)
  37.     );
  38.  
  39.     /**
  40.      * Constructs a new Filesystem based VFS object.
  41.      *
  42.      * @access public
  43.      *
  44.      * @param optional array $params  A hash containing connection parameters.
  45.      */
  46.     function VFS_file($params = array())
  47.     {
  48.         parent::VFS($params);
  49.  
  50.         if (!empty($this->_params['vfsroot'])) {
  51.             if (substr($this->_params['vfsroot']-1== '/' ||
  52.                 substr($this->_params['vfsroot']-1== '\\'{
  53.                 $this->_params['vfsroot'substr($this->_params['vfsroot']0strlen($this->_params['vfsroot']- 1);
  54.             }
  55.         }
  56.     }
  57.  
  58.     /**
  59.      * Retrieve a file from the VFS.
  60.      *
  61.      * @access public
  62.      *
  63.      * @param string $path  The pathname to the file.
  64.      * @param string $name  The filename to retrieve.
  65.      *
  66.      * @return string  The file data.
  67.      */
  68.     function read($path$name)
  69.     {
  70.         $file $this->_getNativePath($path$name);
  71.         $fp @fopen($file'rb');
  72.         if (!$fp{
  73.             return PEAR::raiseError(_("Unable to open VFS file."));
  74.         }
  75.         $filesize filesize($file);
  76.         if ($filesize == 0{
  77.             $data '';
  78.         else {
  79.             $data fread($fp$filesize);
  80.         }
  81.         fclose($fp);
  82.  
  83.         return $data;
  84.     }
  85.  
  86.     /**
  87.      * Store a file in the VFS, with the data copied from a temporary
  88.      * file.
  89.      *
  90.      * @access public
  91.      *
  92.      * @param string $path                  The path to store the file in.
  93.      * @param string $name                  The filename to use.
  94.      * @param string $tmpFile               The temporary file containing the
  95.      *                                       data to be stored.
  96.      * @param optional boolean $autocreate  Automatically create directories?
  97.      *
  98.      * @return mixed  True on success or a PEAR_Error object on failure.
  99.      */
  100.     function write($path$name$tmpFile$autocreate = true)
  101.     {
  102.         if (!@is_dir($this->_getNativePath($path))) {
  103.             if ($autocreate{
  104.                 $res $this->autocreatePath($path);
  105.                 if (is_a($res'PEAR_Error')) {
  106.                     return $res;
  107.                 }
  108.             else {
  109.                 return PEAR::raiseError(_("VFS directory does not exist."));
  110.             }
  111.         }
  112.  
  113.         // Since we already have the data in a file, don't read it
  114.         // into PHP's memory at all - just copy() it to the new
  115.         // location. We leave it to the caller to clean up the
  116.         // temporary file, so we don't use rename().
  117.         if (@copy($tmpFile$this->_getNativePath($path$name))) {
  118.             return true;
  119.         else {
  120.             return PEAR::raiseError(_("Unable to write VFS file (copy() failed)."));
  121.         }
  122.     }
  123.  
  124.     /**
  125.      * Moves a file in the database and the file system.
  126.      *
  127.      * @access public
  128.      *
  129.      * @param string $path  The path to store the file in.
  130.      * @param string $name  The filename to use.
  131.      *
  132.      * @return mixed  True on success or a PEAR_Error object on failure.
  133.      */
  134.     function move($path$name$dest)
  135.     {
  136.         $fileCheck $this->listFolder($destfalse);
  137.         foreach ($fileCheck as $file{
  138.             if ($file['name'== $name{
  139.                 return PEAR::raiseError(_("Unable to move VFS file."));
  140.             }
  141.         }
  142.  
  143.         if (!@rename($this->_getNativePath($path$name)$this->_getNativePath($dest$name))) {
  144.             return PEAR::raiseError(_("Unable to move VFS file."));
  145.         }
  146.  
  147.         return true;
  148.     }
  149.  
  150.     /**
  151.      * Copies a file through the backend.
  152.      *
  153.      * @access public
  154.      *
  155.      * @param string $path  The path to store the file in.
  156.      * @param string $name  The filename to use.
  157.      * @param string $dest  The destination of the file.
  158.      *
  159.      * @return mixed  True on success or a PEAR_Error object on failure.
  160.      */
  161.     function copy($path$name$dest)
  162.     {
  163.         if ($path == $dest{
  164.             return PEAR::raiseError(_("The file can not be copied onto itself."));
  165.         }
  166.  
  167.         $fileCheck $this->listFolder($destfalse);
  168.         foreach ($fileCheck as $file{
  169.             if ($file['name'== $name{
  170.                 return PEAR::raiseError(_("Unable to copy VFS file."));
  171.             }
  172.         }
  173.  
  174.         if (!@copy($this->_getNativePath($path$name)$this->_getNativePath($dest$name))) {
  175.             return PEAR::raiseError(_("Unable to copy VFS file."));
  176.         }
  177.  
  178.         return true;
  179.     }
  180.  
  181.     /**
  182.      * Store a file in the VFS from raw data.
  183.      *
  184.      * @access public
  185.      *
  186.      * @param string $path                  The path to store the file in.
  187.      * @param string $name                  The filename to use.
  188.      * @param string $data                  The file data.
  189.      * @param optional boolean $autocreate  Automatically create directories?
  190.      *
  191.      * @return mixed  True on success or a PEAR_Error object on failure.
  192.      */
  193.     function writeData($path$name$data$autocreate = true)
  194.     {
  195.         if (!@is_dir($this->_getNativePath($path))) {
  196.             if ($autocreate{
  197.                 $res $this->autocreatePath($path);
  198.                 if (is_a($res'PEAR_Error')) {
  199.                     return $res;
  200.                 }
  201.             else {
  202.                 return PEAR::raiseError(_("VFS directory does not exist."));
  203.             }
  204.         }
  205.  
  206.         // Treat an attempt to write an empty file as a touch() call,
  207.         // since otherwise the file will not be created at all.
  208.         if (!strlen($data)) {
  209.             if (@touch($this->_getNativePath($path$name))) {
  210.                 return true;
  211.             else {
  212.                 return PEAR::raiseError(_("Unable to create empty VFS file."));
  213.             }
  214.         }
  215.  
  216.         // Otherwise we go ahead and try to write out the file.
  217.         $fp @fopen($this->_getNativePath($path$name)'w');
  218.         if (!$fp{
  219.             return PEAR::raiseError(_("Unable to open VFS file for writing."));
  220.         }
  221.  
  222.         if (!@fwrite($fp$data)) {
  223.             return PEAR::raiseError(_("Unable to write VFS file data."));
  224.         }
  225.  
  226.         return true;
  227.     }
  228.  
  229.     /**
  230.      * Delete a file from the VFS.
  231.      *
  232.      * @access public
  233.      *
  234.      * @param string $path  The path to store the file in.
  235.      * @param string $name  The filename to use.
  236.      *
  237.      * @return mixed  True on success or a PEAR_Error object on failure.
  238.      */
  239.     function deleteFile($path$name)
  240.     {
  241.         if (!@unlink($this->_getNativePath($path$name))) {
  242.             return PEAR::raiseError(_("Unable to delete VFS file."));
  243.         }
  244.     }
  245.  
  246.     /**
  247.      * Delete a folder from the VFS.
  248.      *
  249.      * @access public
  250.      *
  251.      * @param string $path                 The path to delete the folder from.
  252.      * @param string $name                 The foldername to use.
  253.      * @param optional boolean $recursive  Force a recursive delete?
  254.      *
  255.      * @return mixed True on success or a PEAR_Error object on failure.
  256.      */
  257.     function deleteFolder($path$name$recursive = false)
  258.     {
  259.         if ($recursive{
  260.             $result $this->emptyFolder($path '/' $name);
  261.             if (is_a($result'PEAR_Error')) {
  262.                 return $result;
  263.             }
  264.         else {
  265.             $list $this->listFolder($path '/' $name);
  266.             if (is_a($list'PEAR_Error')) {
  267.                 return $list;
  268.             }
  269.             if (count($list)) {
  270.                 return PEAR::raiseError(sprintf(_("Unable to delete %s, the directory is not empty"),
  271.                                                 $path '/' $name));
  272.             }
  273.         }
  274.  
  275.         if (!@rmdir($this->_getNativePath($path$name))) {
  276.             return PEAR::raiseError(_("Unable to delete VFS directory."));
  277.         }
  278.  
  279.         return true;
  280.     }
  281.  
  282.     /**
  283.      * Creates a folder on the VFS.
  284.      *
  285.      * @access public
  286.      *
  287.      * @param string $path  The path to delete the folder from.
  288.      * @param string $name  The foldername to use.
  289.      *
  290.      * @return mixed  True on success or a PEAR_Error object on failure.
  291.      */
  292.     function createFolder($path$name)
  293.     {
  294.         if (!@mkdir($this->_getNativePath($path$name))) {
  295.             return PEAR::raiseError(_("Unable to create VFS directory."));
  296.         }
  297.  
  298.         return true;
  299.     }
  300.  
  301.     /**
  302.      * Check if a given pathname is a folder.
  303.      *
  304.      * @access public
  305.      *
  306.      * @param string $path  The path to the folder.
  307.      * @param string $name  The file/folder name.
  308.      *
  309.      * @return boolean  True if it is a folder, false otherwise.
  310.      */
  311.     function isFolder($path$name)
  312.     {
  313.         return @is_dir($this->_getNativePath($path$name));
  314.     }
  315.  
  316.     /**
  317.      * Changes permissions for an item in the VFS.
  318.      *
  319.      * @access public
  320.      *
  321.      * @param string $path         The path of directory of the item.
  322.      * @param string $name         The name of the item.
  323.      * @param integer $permission  The octal value of the new permission.
  324.      *
  325.      * @return mixed  True on success or a PEAR_Error object on failure.
  326.      */
  327.     function changePermissions($path$name$permission)
  328.     {
  329.         if (!@chmod($this->_getNativePath($path$name)$permission)) {
  330.             return PEAR::raiseError(sprintf(_("Unable to change permission for VFS file %s/%s.")$path$name));
  331.         }
  332.  
  333.         return true;
  334.     }
  335.  
  336.     /**
  337.      * Return a list of the contents of a folder.
  338.      *
  339.      * @access public
  340.      *
  341.      * @param string $path                The path of the directory.
  342.      * @param optional mixed $filter      String/hash to filter file/dirname
  343.      *                                     on.
  344.      * @param optional boolean $dotfiles  Show dotfiles?
  345.      * @param optional boolean $dironly   Show only directories?
  346.      *
  347.      * @return array  File list on success, PEAR_Error on error.
  348.      */
  349.     function _listFolder($path$filter = null$dotfiles = true,
  350.                          $dironly = false)
  351.     {
  352.         $files = array();
  353.         $path = isset($path$this->_getNativePath($path$this->_getNativePath();
  354.  
  355.         if (!@is_dir($path)) {
  356.             return PEAR::raiseError(_("Not a directory"));
  357.         }
  358.  
  359.         if (!@chdir($path)) {
  360.             return PEAR::raiseError(_("Unable to access VFS directory."));
  361.         }
  362.  
  363.         $handle opendir($path);
  364.         while (($entry readdir($handle)) !== false{
  365.             // Filter out '.' and '..' entries.
  366.             if ($entry == '.' || $entry == '..'{
  367.                 continue;
  368.             }
  369.  
  370.             // Filter out dotfiles if they aren't wanted.
  371.             if (!$dotfiles && substr($entry01== '.'{
  372.                 continue;
  373.             }
  374.  
  375.             // File name
  376.             $file['name'$entry;
  377.  
  378.             // Unix style file permissions
  379.             $file['perms'$this->_getUnixPerms(fileperms($entry));
  380.  
  381.             // Owner
  382.             $file['owner'fileowner($entry);
  383.             if (function_exists('posix_getpwuid')) {
  384.                 $owner posix_getpwuid($file['owner']);
  385.                 $file['owner'$owner['name'];
  386.             }
  387.  
  388.             // Group
  389.             $file['group'filegroup($entry);
  390.             if (function_exists('posix_getgrgid')) {
  391.                 $group posix_getgrgid($file['group']);
  392.                 $file['group'$group['name'];
  393.             }
  394.  
  395.             // Size
  396.             $file['size'filesize($entry);
  397.  
  398.             // Date
  399.             $file['date'filemtime($entry);
  400.  
  401.             // Type
  402.             if (@is_dir($entry&& !is_link($entry)) {
  403.                 $file['perms''d' $file['perms'];
  404.                 $file['type''**dir';
  405.                 $file['size'= -1;
  406.             elseif (is_link($entry)) {
  407.                 $file['perms''l' $file['perms'];
  408.                 $file['type''**sym';
  409.                 $file['link'readlink($entry);
  410.                 $file['linktype''**none';
  411.                 if (file_exists($file['link'])) {
  412.                     if (is_dir($file['link'])) {
  413.                         $file['linktype''**dir';
  414.                     elseif (is_link($file['link'])) {
  415.                         $file['linktype''**sym';
  416.                     elseif (is_file($file['link'])) {
  417.                         $ext explode('.'$file['link']);
  418.                         if (!(count($ext== 1 || ($ext[0=== '' && count($ext== 2))) {
  419.                             $file['linktype'VFS::strtolower($ext[count($ext- 1]);
  420.                         }
  421.                     }
  422.                 else {
  423.                     $file['linktype''**broken';
  424.                 }
  425.             elseif (is_file($entry)) {
  426.                 $file['perms''-' $file['perms'];
  427.                 $ext explode('.'$entry);
  428.  
  429.                 if (count($ext== 1 || (substr($file['name']01=== '.' && count($ext== 2)) {
  430.                     $file['type''**none';
  431.                 else {
  432.                     $file['type'VFS::strtolower($ext[count($ext- 1]);
  433.                 }
  434.             else {
  435.                 $file['type''**none';
  436.                 if ((fileperms($entry0xC000== 0xC000{
  437.                     $file['perms''s' $file['perms'];
  438.                 elseif ((fileperms($entry0x6000== 0x6000{
  439.                     $file['perms''b' $file['perms'];
  440.                 elseif ((fileperms($entry0x2000== 0x2000{
  441.                     $file['perms''c' $file['perms'];
  442.                 elseif ((fileperms($entry0x1000== 0x1000{
  443.                     $file['perms''p' $file['perms'];
  444.                 else {
  445.                     $file['perms''?' $file['perms'];
  446.                 }
  447.             }
  448.  
  449.             // Filtering.
  450.             if ($this->_filterMatch($filter$file['name'])) {
  451.                 unset($file);
  452.                 continue;
  453.             }
  454.             if ($dironly && $file['type'!== '**dir'{
  455.                 unset($file);
  456.                 continue;
  457.             }
  458.  
  459.             $files[$file['name']] $file;
  460.             unset($file);
  461.         }
  462.  
  463.         return $files;
  464.     }
  465.  
  466.     /**
  467.      * Returns a sorted list of folders in specified directory.
  468.      *
  469.      * @access public
  470.      *
  471.      * @param optional string $path         The path of the directory to get
  472.      *                                       the directory list for.
  473.      * @param optional mixed $filter        Hash of items to filter based on
  474.      *                                       folderlist.
  475.      * @param optional boolean $dotfolders  Include dotfolders?
  476.      *
  477.      * @return mixed  Folder list on success or a PEAR_Error object on failure.
  478.      */
  479.     function listFolders($path ''$filter = null$dotfolders = true)
  480.     {
  481.         $conn $this->_connect();
  482.         if (is_a($conn'PEAR_Error')) {
  483.             return $conn;
  484.         }
  485.  
  486.         $folders = array();
  487.         $folders[dirname($path)= array('val' => dirname($path),
  488.                                          'abbrev' => '..',
  489.                                          'label' => '..');
  490.  
  491.         $folderList $this->listFolder($pathnull$dotfolderstrue);
  492.         if (is_a($folderList'PEAR_Error')) {
  493.             return $folderList;
  494.         }
  495.  
  496.         foreach ($folderList as $files{
  497.             $folders[$folder['val']] = array('val' => $path '/' $files['name'],
  498.                                              'abbrev' => $files['name'],
  499.                                              'label' => $path '/' $files['name']);
  500.         }
  501.  
  502.         ksort($folders);
  503.  
  504.         return $folders;
  505.     }
  506.  
  507.     /**
  508.      * Return Unix style perms.
  509.      *
  510.      * @access private
  511.      *
  512.      * @param integer $perms  The permissions to set.
  513.      *
  514.      * @return string  Unix style perms.
  515.      */
  516.     function _getUnixPerms($perms)
  517.     {
  518.         // Determine permissions
  519.         $owner['read']    ($perms 00400'r' '-';
  520.         $owner['write']   ($perms 00200'w' '-';
  521.         $owner['execute'($perms 00100'x' '-';
  522.         $group['read']    ($perms 00040'r' '-';
  523.         $group['write']   ($perms 00020'w' '-';
  524.         $group['execute'($perms 00010'x' '-';
  525.         $world['read']    ($perms 00004'r' '-';
  526.         $world['write']   ($perms 00002'w' '-';
  527.         $world['execute'($perms 00001'x' '-';
  528.  
  529.         // Adjust for SUID, SGID and sticky bit
  530.         if ($perms 0x800{
  531.             $owner['execute'($owner['execute'== 'x''s' 'S';
  532.         }
  533.         if ($perms 0x400{
  534.             $group['execute'($group['execute'== 'x''s' 'S';
  535.         }
  536.         if ($perms 0x200{
  537.             $world['execute'($world['execute'== 'x''t' 'T';
  538.         }
  539.  
  540.         $unixPerms $owner['read'$owner['write'$owner['execute'.
  541.                      $group['read'$group['write'$group['execute'.
  542.                      $world['read'$world['write'$world['execute'];
  543.  
  544.         return $unixPerms;
  545.     }
  546.  
  547.     /**
  548.      * Rename a file or folder in the VFS.
  549.      *
  550.      * @access public
  551.      *
  552.      * @param string $oldpath  The old path to the file.
  553.      * @param string $oldname  The old filename.
  554.      * @param string $newpath  The new path of the file.
  555.      * @param string $newname  The new filename.
  556.      *
  557.      * @return mixed  True on success or a PEAR_Error object on failure.
  558.      */
  559.     function rename($oldpath$oldname$newpath$newname)
  560.     {
  561.         if (!@rename($this->_getNativePath($oldpath$oldname),
  562.                      $this->_getNativePath($newpath$newname))) {
  563.             return PEAR::raiseError(sprintf(_("Unable to rename VFS file %s/%s.")$oldpath$oldname));
  564.         }
  565.  
  566.         return true;
  567.     }
  568.  
  569.     /**
  570.      * Return a full filename on the native filesystem, from a VFS
  571.      * path and name.
  572.      *
  573.      * @access private
  574.      *
  575.      * @param optional string $path  The VFS file path.
  576.      * @param optional string $name  The VFS filename.
  577.      *
  578.      * @return string  The full native filename.
  579.      */
  580.     function _getNativePath($path ''$name '')
  581.     {
  582.         $name basename($name);
  583.         if (!empty($name)) {
  584.             $name str_replace('..'''$name);
  585.             if (substr($name01!= '/'{
  586.                 $name '/' $name;
  587.             }
  588.         }
  589.  
  590.         if (!empty($path)) {
  591.             if (isset($this->_params['home']&&
  592.                 preg_match('|^~/?(.*)$|'$path$matches)) {
  593.                 $path $this->_params['home''/' $matches[1];
  594.             }
  595.  
  596.             $path str_replace('..'''$path);
  597.             if (substr($path01== '/'{
  598.                 return $this->_params['vfsroot'$path $name;
  599.             else {
  600.                 return $this->_params['vfsroot''/' $path $name;
  601.             }
  602.         else {
  603.             return $this->_params['vfsroot'$name;
  604.         }
  605.     }
  606.  
  607.     /**
  608.      * Stub to check if we have a valid connection. Makes sure that
  609.      * the vfsroot is readable.
  610.      *
  611.      * @access private
  612.      *
  613.      * @return mixed  True if vfsroot is readable, PEAR_Error if it isn't.
  614.      */
  615.     function _connect()
  616.     {
  617.         if ((@is_dir($this->_params['vfsroot']&&
  618.              @is_readable($this->_params['vfsroot'])) ||
  619.             @mkdir($this->_params['vfsroot'])) {
  620.             return true;
  621.         else {
  622.             return PEAR::raiseError(_("Unable to read the vfsroot directory."));
  623.         }
  624.     }
  625.  
  626. }

Documentation generated on Mon, 11 Mar 2019 14:31:24 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.