[ Index ]
 

Code source de Horde 3.1.3

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/VFS/ -> file.php (source)

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


Généré le : Sun Feb 25 18:01:28 2007 par Balluche grâce à PHPXref 0.7