[ Index ]
 

Code source de Horde 3.1.3

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

title

Body

[fermer]

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

   1  <?php
   2  /**
   3   * VFS implementation for an FTP server.
   4   *
   5   * Required values for $params:<pre>
   6   *      'username'       The username with which to connect to the ftp server.
   7   *      'password'       The password with which to connect to the ftp server.
   8   *      'hostspec'       The ftp server to connect to.</pre>
   9   *
  10   * Optional values for $params:<pre>
  11   *      'maplocalids'    If true and the POSIX extension is available, the
  12   *                       driver will map the user and group IDs returned from
  13   *                       the FTP server with the local IDs from the local
  14   *                       password file.  This is useful only if the FTP server
  15   *                       is running on localhost or if the local user/group
  16   *                       IDs are identical to the remote FTP server.
  17   *      'pasv'           If true, connection will be set to passive mode.
  18   *      'port'           The port used to connect to the ftp server if other
  19   *                       than 21.
  20   *      'ssl'            If true, and PHP had been compiled with OpenSSL
  21   *                       support, TLS transport-level encryption will be
  22   *                       negotiated with the server.
  23   *      'timeout'        If defined, use this value as the timeout for the
  24   *                       server.</pre>
  25   *
  26   * $Horde: framework/VFS/VFS/ftp.php,v 1.75.4.21 2006/05/31 04:50:02 slusarz Exp $
  27   *
  28   * Copyright 2002-2006 Chuck Hagenbuch <chuck@horde.org>
  29   * Copyright 2002-2006 Michael Varghese <mike.varghese@ascellatech.com>
  30   *
  31   * See the enclosed file COPYING for license information (LGPL). If you did
  32   * not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  33   *
  34   * @author  Chuck Hagenbuch <chuck@horde.org>
  35   * @author  Michael Varghese <mike.varghese@ascellatech.com>
  36   * @package VFS
  37   */
  38  class VFS_ftp extends VFS {
  39  
  40      /**
  41       * List of additional credentials required for this VFS backend.
  42       *
  43       * @var array
  44       */
  45      var $_credentials = array('username', 'password');
  46  
  47      /**
  48       * List of permissions and if they can be changed in this VFS backend.
  49       *
  50       * @var array
  51       */
  52      var $_permissions = array(
  53          'owner' => array('read' => true, 'write' => true, 'execute' => true),
  54          'group' => array('read' => true, 'write' => true, 'execute' => true),
  55          'all'   => array('read' => true, 'write' => true, 'execute' => true));
  56  
  57      /**
  58       * Variable holding the connection to the ftp server.
  59       *
  60       * @var resource
  61       */
  62      var $_stream = false;
  63  
  64      /**
  65       * Local cache array for user IDs.
  66       *
  67       * @var array
  68       */
  69      var $_uids = array();
  70  
  71      /**
  72       * Local cache array for group IDs.
  73       *
  74       * @var array
  75       */
  76      var $_gids = array();
  77  
  78      /**
  79       * Returns the size of a file.
  80       *
  81       * @access public
  82       *
  83       * @param string $path  The path of the file.
  84       * @param string $name  The filename.
  85       *
  86       * @return integer  The size of the file in bytes or PEAR_Error on
  87       *                  failure.
  88       */
  89      function size($path, $name)
  90      {
  91          $conn = $this->_connect();
  92          if (is_a($conn, 'PEAR_Error')) {
  93              return $conn;
  94          }
  95  
  96          if (($size = @ftp_size($this->_stream, $this->_getPath($path, $name))) === false) {
  97              return PEAR::raiseError(sprintf(_("Unable to check file size of \"%s\"."), $this->_getPath($path, $name)));
  98          }
  99  
 100          return $size;
 101      }
 102  
 103      /**
 104       * Retrieves a file from the VFS.
 105       *
 106       * @param string $path  The pathname to the file.
 107       * @param string $name  The filename to retrieve.
 108       *
 109       * @return string  The file data.
 110       */
 111      function read($path, $name)
 112      {
 113          $conn = $this->_connect();
 114          if (is_a($conn, 'PEAR_Error')) {
 115              return $conn;
 116          }
 117  
 118          $tmpFile = $this->_getTempFile();
 119          $fetch = @ftp_get($this->_stream, $tmpFile,
 120                            $this->_getPath($path, $name), FTP_BINARY);
 121          if ($fetch === false) {
 122              return PEAR::raiseError(sprintf(_("Unable to open VFS file \"%s\"."), $this->_getPath($path, $name)));
 123          }
 124  
 125          $size = filesize($tmpFile);
 126          if ($size === 0) {
 127              return '';
 128          }
 129  
 130          if (OS_WINDOWS) {
 131              $mode = 'rb';
 132          } else {
 133              $mode = 'r';
 134          }
 135  
 136          if (function_exists('file_get_contents')) {
 137              $data = file_get_contents($tmpFile);
 138          } else {
 139              $fp = fopen($tmpFile, $mode);
 140              $data = fread($fp, $size);
 141              fclose($fp);
 142          }
 143          unlink($tmpFile);
 144  
 145          return $data;
 146      }
 147  
 148      /**
 149       * Stores a file in the VFS.
 150       *
 151       * @param string $path         The path to store the file in.
 152       * @param string $name         The filename to use.
 153       * @param string $tmpFile      The temporary file containing the data to
 154       *                             be stored.
 155       * @param boolean $autocreate  Automatically create directories?
 156       *
 157       * @return mixed  True on success or a PEAR_Error object on failure.
 158       */
 159      function write($path, $name, $tmpFile, $autocreate = false)
 160      {
 161          $conn = $this->_connect();
 162          if (is_a($conn, 'PEAR_Error')) {
 163              return $conn;
 164          }
 165  
 166          $res = $this->_checkQuotaWrite('file', $tmpFile);
 167          if (is_a($res, 'PEAR_Error')) {
 168              return $res;
 169          }
 170  
 171          if (!@ftp_put($this->_stream, $this->_getPath($path, $name), $tmpFile, FTP_BINARY)) {
 172              if ($autocreate) {
 173                  $result = $this->autocreatePath($path);
 174                  if (is_a($result, 'PEAR_Error')) {
 175                      return $result;
 176                  }
 177                  if (!@ftp_put($this->_stream, $this->_getPath($path, $name), $tmpFile, FTP_BINARY)) {
 178                      return PEAR::raiseError(sprintf(_("Unable to write VFS file \"%s\"."), $this->_getPath($path, $name)));
 179                  }
 180              } else {
 181                  return PEAR::raiseError(sprintf(_("Unable to write VFS file \"%s\"."), $this->_getPath($path, $name)));
 182              }
 183          }
 184  
 185          return true;
 186      }
 187  
 188      /**
 189       * Stores a file in the VFS from raw data.
 190       *
 191       * @param string $path         The path to store the file in.
 192       * @param string $name         The filename to use.
 193       * @param string $data         The file data.
 194       * @param boolean $autocreate  Automatically create directories?
 195       *
 196       * @return mixed  True on success or a PEAR_Error object on failure.
 197       */
 198      function writeData($path, $name, $data, $autocreate = false)
 199      {
 200          $res = $this->_checkQuotaWrite('string', $data);
 201          if (is_a($res, 'PEAR_Error')) {
 202              return $res;
 203          }
 204  
 205          $tmpFile = $this->_getTempFile();
 206          $fp = fopen($tmpFile, 'wb');
 207          fwrite($fp, $data);
 208          fclose($fp);
 209  
 210          $result = $this->write($path, $name, $tmpFile, $autocreate);
 211          unlink($tmpFile);
 212          return $result;
 213      }
 214  
 215      /**
 216       * Deletes a file from the VFS.
 217       *
 218       * @param string $path  The path to delete the file from.
 219       * @param string $name  The filename to delete.
 220       *
 221       * @return mixed  True on success or a PEAR_Error object on failure.
 222       */
 223      function deleteFile($path, $name)
 224      {
 225          $res = $this->_checkQuotaDelete($path, $name);
 226          if (is_a($res, 'PEAR_Error')) {
 227              return $res;
 228          }
 229  
 230          $conn = $this->_connect();
 231          if (is_a($conn, 'PEAR_Error')) {
 232              return $conn;
 233          }
 234  
 235          if (!@ftp_delete($this->_stream, $this->_getPath($path, $name))) {
 236              return PEAR::raiseError(sprintf(_("Unable to delete VFS file \"%s\"."), $this->_getPath($path, $name)));
 237          }
 238  
 239          return true;
 240      }
 241  
 242      /**
 243       * Checks if a given item is a folder.
 244       *
 245       * @param string $path  The parent folder.
 246       * @param string $name  The item name.
 247       *
 248       * @return boolean  True if it is a folder, false otherwise.
 249       */
 250      function isFolder($path, $name)
 251      {
 252          $conn = $this->_connect();
 253          if (is_a($conn, 'PEAR_Error')) {
 254              return $conn;
 255          }
 256  
 257          $result = false;
 258          $olddir = $this->getCurrentDirectory();
 259  
 260          /* See if we can change to the given path. */
 261          if (@ftp_chdir($this->_stream, $this->_getPath($path, $name))) {
 262              $result = true;
 263          }
 264  
 265          $this->_setPath($olddir);
 266  
 267          return $result;
 268      }
 269  
 270      /**
 271       * Deletes a folder from the VFS.
 272       *
 273       * @param string $path        The parent folder.
 274       * @param string $name        The name of the folder to delete.
 275       * @param boolean $recursive  Force a recursive delete?
 276       *
 277       * @return mixed  True on success or a PEAR_Error object on failure.
 278       */
 279      function deleteFolder($path, $name, $recursive = false)
 280      {
 281          $conn = $this->_connect();
 282          if (is_a($conn, 'PEAR_Error')) {
 283              return $conn;
 284          }
 285  
 286          $isDir = false;
 287          $dirCheck = $this->listFolder($path);
 288          foreach ($dirCheck as $file) {
 289              if ($file['name'] == $name && $file['type'] == '**dir') {
 290                  $isDir = true;
 291                  break;
 292              }
 293          }
 294  
 295          if ($isDir) {
 296              $file_list = $this->listFolder($this->_getPath($path, $name));
 297              if (is_a($file_list, 'PEAR_Error')) {
 298                  return $file_list;
 299              }
 300  
 301              if (count($file_list) && !$recursive) {
 302                  return PEAR::raiseError(sprintf(_("Unable to delete \"%s\", the directory is not empty."),
 303                                                  $this->_getPath($path, $name)));
 304              }
 305  
 306              foreach ($file_list as $file) {
 307                  if ($file['type'] == '**dir') {
 308                      $result = $this->deleteFolder($this->_getPath($path, $name), $file['name'], $recursive);
 309                  } else {
 310                      $result = $this->deleteFile($this->_getPath($path, $name), $file['name']);
 311                  }
 312                  if (is_a($result, 'PEAR_Error')) {
 313                      return $result;
 314                  }
 315              }
 316  
 317              if (!@ftp_rmdir($this->_stream, $this->_getPath($path, $name))) {
 318                  return PEAR::raiseError(sprintf(_("Cannot remove directory \"%s\"."), $this->_getPath($path, $name)));
 319              }
 320          } else {
 321              if (!@ftp_delete($this->_stream, $this->_getPath($path, $name))) {
 322                  return PEAR::raiseError(sprintf(_("Cannot delete file \"%s\"."), $this->_getPath($path, $name)));
 323              }
 324          }
 325  
 326          return true;
 327      }
 328  
 329      /**
 330       * Renames a file in the VFS.
 331       *
 332       * @param string $oldpath  The old path to the file.
 333       * @param string $oldname  The old filename.
 334       * @param string $newpath  The new path of the file.
 335       * @param string $newname  The new filename.
 336       *
 337       * @return mixed  True on success or a PEAR_Error object on failure.
 338       */
 339      function rename($oldpath, $oldname, $newpath, $newname)
 340      {
 341          if (is_a($conn = $this->_connect(), 'PEAR_Error')) {
 342              return $conn;
 343          }
 344  
 345          if (is_a($result = $this->autocreatePath($newpath), 'PEAR_Error')) {
 346              return $result;
 347          }
 348  
 349          if (!@ftp_rename($this->_stream, $this->_getPath($oldpath, $oldname), $this->_getPath($newpath, $newname))) {
 350              return PEAR::raiseError(sprintf(_("Unable to rename VFS file \"%s\"."), $this->_getPath($oldpath, $oldname)));
 351          }
 352  
 353          return true;
 354      }
 355  
 356      /**
 357       * Creates a folder on the VFS.
 358       *
 359       * @param string $path  The parent folder.
 360       * @param string $name  The name of the new folder.
 361       *
 362       * @return mixed  True on success or a PEAR_Error object on failure.
 363       */
 364      function createFolder($path, $name)
 365      {
 366          $conn = $this->_connect();
 367          if (is_a($conn, 'PEAR_Error')) {
 368              return $conn;
 369          }
 370  
 371          if (!@ftp_mkdir($this->_stream, $this->_getPath($path, $name))) {
 372              return PEAR::raiseError(sprintf(_("Unable to create VFS directory \"%s\"."), $this->_getPath($path, $name)));
 373          }
 374  
 375          return true;
 376      }
 377  
 378      /**
 379       * Changes permissions for an item on the VFS.
 380       *
 381       * @param string $path        The parent folder of the item.
 382       * @param string $name        The name of the item.
 383       * @param string $permission  The permission to set.
 384       *
 385       * @return mixed  True on success or a PEAR_Error object on failure.
 386       */
 387      function changePermissions($path, $name, $permission)
 388      {
 389          $conn = $this->_connect();
 390          if (is_a($conn, 'PEAR_Error')) {
 391              return $conn;
 392          }
 393  
 394          if (!@ftp_site($this->_stream, 'CHMOD ' . $permission . ' ' . $this->_getPath($path, $name))) {
 395              return PEAR::raiseError(sprintf(_("Unable to change permission for VFS file \"%s\"."), $this->_getPath($path, $name)));
 396          }
 397  
 398          return true;
 399      }
 400  
 401      /**
 402       * Returns an an unsorted file list of the specified directory.
 403       *
 404       * @param string $path       The path of the directory.
 405       * @param mixed $filter      String/hash to filter file/dirname on.
 406       * @param boolean $dotfiles  Show dotfiles?
 407       * @param boolean $dironly   Show only directories?
 408       *
 409       * @return array  File list on success or PEAR_Error on failure.
 410       */
 411      function _listFolder($path = '', $filter = null, $dotfiles = true,
 412                           $dironly = false)
 413      {
 414          $conn = $this->_connect();
 415          if (is_a($conn, 'PEAR_Error')) {
 416              return $conn;
 417          }
 418  
 419          $files = array();
 420          $type = VFS::strtolower(@ftp_systype($this->_stream));
 421          if ($type == 'unknown') {
 422              // Go with unix-style listings by default.
 423              $type = 'unix';
 424          } elseif (strpos($type, 'win') !== false) {
 425              $type = 'win';
 426          } elseif (strpos($type, 'netware') !== false) {
 427              $type = 'netware';
 428          }
 429  
 430          $olddir = $this->getCurrentDirectory();
 431          if (!empty($path)) {
 432              $res = $this->_setPath($path);
 433              if (is_a($res, 'PEAR_Error')) {
 434                  return $res;
 435              }
 436          }
 437  
 438          if ($type == 'unix') {
 439              // If we don't want dotfiles, We can save work here by not
 440              // doing an ls -a and then not doing the check later (by
 441              // setting $dotfiles to true, the if is short-circuited).
 442              if ($dotfiles) {
 443                  $list = ftp_rawlist($this->_stream, '-al');
 444                  $dotfiles = true;
 445              } else {
 446                  $list = ftp_rawlist($this->_stream, '-l');
 447              }
 448          } else {
 449             $list = ftp_rawlist($this->_stream, '');
 450          }
 451  
 452          if (!is_array($list)) {
 453              if (isset($olddir)) {
 454                  $res = $this->_setPath($olddir);
 455                  if (is_a($res, 'PEAR_Error')) {
 456                      return $res;
 457                  }
 458              }
 459              return array();
 460          }
 461  
 462          /* If 'maplocalids' is set, check for the POSIX extension. */
 463          $mapids = false;
 464          if (!empty($this->_params['maplocalids']) &&
 465              extension_loaded('posix')) {
 466              $mapids = true;
 467          }
 468  
 469          $currtime = time();
 470  
 471          foreach ($list as $line) {
 472              $file = array();
 473              $item = preg_split('/\s+/', $line);
 474              if ($type == 'unix' || ($type == 'win' && !preg_match('|\d\d-\d\d-\d\d|', $item[0]))) {
 475                  if (count($item) < 8 || substr($line, 0, 5) == 'total') {
 476                      continue;
 477                  }
 478                  $file['perms'] = $item[0];
 479                  if ($mapids) {
 480                      if (!isset($this->_uids[$item[2]])) {
 481                          $entry = posix_getpwuid($item[2]);
 482                          $this->_uids[$item[2]] = (empty($entry)) ? $item[2] : $entry['name'];
 483                      }
 484                      $file['owner'] = $this->_uids[$item[2]];
 485                      if (!isset($this->_uids[$item[3]])) {
 486                          $entry = posix_getgrgid($item[3]);
 487                          $this->_uids[$item[3]] = (empty($entry)) ? $item[3] : $entry['name'];
 488                      }
 489                      $file['group'] = $this->_uids[$item[3]];
 490  
 491                  } else {
 492                      $file['owner'] = $item[2];
 493                      $file['group'] = $item[3];
 494                  }
 495                  $file['name'] = substr($line, strpos($line, sprintf("%s %2s %5s", $item[5], $item[6], $item[7])) + 13);
 496  
 497                  // Filter out '.' and '..' entries.
 498                  if (preg_match('/^\.\.?\/?$/', $file['name'])) {
 499                      continue;
 500                  }
 501  
 502                  // Filter out dotfiles if they aren't wanted.
 503                  if (!$dotfiles && substr($file['name'], 0, 1) == '.') {
 504                      continue;
 505                  }
 506  
 507                  $p1 = substr($file['perms'], 0, 1);
 508                  if ($p1 === 'l') {
 509                      $file['link'] = substr($file['name'], strpos($file['name'], '->') + 3);
 510                      $file['name'] = substr($file['name'], 0, strpos($file['name'], '->') - 1);
 511                      $file['type'] = '**sym';
 512  
 513                     if ($this->isFolder('', $file['link'])) {
 514                                $file['linktype'] = '**dir';
 515                                                      } else {
 516                                                      $parts = explode('/', $file['link']);
 517                                                      $name = explode('.', array_pop($parts));
 518                                                      if (count($name) == 1 || ($name[0] === '' && count($name) == 2)) {
 519                                                          $file['linktype'] = '**none';
 520                                                          } else {
 521                                                              $file['linktype'] = VFS::strtolower(array_pop($name));
 522                                                              }
 523                                                                     }
 524                  } elseif ($p1 === 'd') {
 525                      $file['type'] = '**dir';
 526                  } else {
 527                      $name = explode('.', $file['name']);
 528                      if (count($name) == 1 || (substr($file['name'], 0, 1) === '.' && count($name) == 2)) {
 529                          $file['type'] = '**none';
 530                      } else {
 531                          $file['type'] = VFS::strtolower($name[count($name) - 1]);
 532                      }
 533                  }
 534                  if ($file['type'] == '**dir') {
 535                      $file['size'] = -1;
 536                  } else {
 537                      $file['size'] = $item[4];
 538                  }
 539                  if (strpos($item[7], ':') !== false) {
 540                      $file['date'] = strtotime($item[7] . ':00' . $item[5] . ' ' . $item[6] . ' ' . date('Y', $currtime));
 541                      // If the ftp server reports a file modification date more
 542                      // less than one day in the future, don't try to subtract
 543                      // a year from the date.  There is no way to know, for
 544                      // example, if the VFS server and the ftp server reside
 545                      // in different timezones.  We should simply report to the
 546                      //  user what the FTP server is returning.
 547                      if ($file['date'] > ($currtime + 86400)) {
 548                          $file['date'] = strtotime($item[7] . ':00' . $item[5] . ' ' . $item[6] . ' ' . (date('Y', $currtime) - 1));
 549                      }
 550                  } else {
 551                      $file['date'] = strtotime('00:00:00' . $item[5] . ' ' . $item[6] . ' ' . $item[7]);
 552                  }
 553              } elseif ($type == 'netware') {
 554                  $file = Array();
 555                  $file['perms'] = $item[1];
 556                  $file['owner'] = $item[2];
 557                  if ($item[0] == 'd') {
 558                      $file['type'] = '**dir';
 559                  } else {
 560                      $file['type'] = '**none';
 561                  }
 562                  $file['size'] = $item[3];
 563                  $file['name'] = $item[7];
 564                  $index = 8;
 565                  while ($index < count($item)) {
 566                      $file['name'] .= ' ' . $item[$index];
 567                      $index++;
 568                  }
 569              } else {
 570                  /* Handle Windows FTP servers returning DOS-style file
 571                   * listings. */
 572                  $file['perms'] = '';
 573                  $file['owner'] = '';
 574                  $file['group'] = '';
 575                  $file['name'] = $item[3];
 576                  $index = 4;
 577                  while ($index < count($item)) {
 578                      $file['name'] .= ' ' . $item[$index];
 579                      $index++;
 580                  }
 581                  $file['date'] = strtotime($item[0] . ' ' . $item[1]);
 582                  if ($item[2] == '<DIR>') {
 583                      $file['type'] = '**dir';
 584                      $file['size'] = -1;
 585                  } else {
 586                      $file['size'] = $item[2];
 587                      $name = explode('.', $file['name']);
 588                      if (count($name) == 1 || (substr($file['name'], 0, 1) === '.' && count($name) == 2)) {
 589                          $file['type'] = '**none';
 590                      } else {
 591                          $file['type'] = VFS::strtolower($name[count($name) - 1]);
 592                      }
 593                  }
 594              }
 595  
 596              // Filtering.
 597              if ($this->_filterMatch($filter, $file['name'])) {
 598                  unset($file);
 599                  continue;
 600              }
 601              if ($dironly && $file['type'] !== '**dir') {
 602                  unset($file);
 603                  continue;
 604              }
 605  
 606              $files[$file['name']] = $file;
 607              unset($file);
 608          }
 609  
 610          if (isset($olddir)) {
 611              $res = $this->_setPath($olddir);
 612              if (is_a($res, 'PEAR_Error')) {
 613                  return $res;
 614              }
 615          }
 616          return $files;
 617      }
 618  
 619      /**
 620       * Returns a sorted list of folders in the specified directory.
 621       *
 622       * @param string $path         The path of the directory to get the
 623       *                             directory list for.
 624       * @param mixed $filter        Hash of items to filter based on folderlist.
 625       * @param boolean $dotfolders  Include dotfolders?
 626       *
 627       * @return mixed  Folder list on success or a PEAR_Error object on failure.
 628       */
 629      function listFolders($path = '', $filter = null, $dotfolders = true)
 630      {
 631          $conn = $this->_connect();
 632          if (is_a($conn, 'PEAR_Error')) {
 633              return $conn;
 634          }
 635  
 636          $folders = array();
 637          $folder = array();
 638  
 639          $folderList = $this->listFolder($path, null, $dotfolders, true);
 640          if (is_a($folderList, 'PEAR_Error')) {
 641              return $folderList;
 642          }
 643  
 644          $folder['val'] = $this->_parentDir($path);
 645          $folder['abbrev'] = '..';
 646          $folder['label'] = '..';
 647  
 648          $folders[$folder['val']] = $folder;
 649  
 650          foreach ($folderList as $files) {
 651              $folder['val'] = $this->_getPath($path, $files['name']);
 652              $folder['abbrev'] = $files['name'];
 653              $folder['label'] = $folder['val'];
 654  
 655              $folders[$folder['val']] = $folder;
 656          }
 657  
 658          ksort($folders);
 659          return $folders;
 660      }
 661  
 662      /**
 663       * Copies a file through the backend.
 664       *
 665       * @param string $path  The path of the original file.
 666       * @param string $name  The name of the original file.
 667       * @param string $dest  The name of the destination directory.
 668       *
 669       * @return mixed  True on success or a PEAR_Error object on failure.
 670       */
 671      function copy($path, $name, $dest)
 672      {
 673          $orig = $this->_getPath($path, $name);
 674          if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) {
 675              return PEAR::raiseError(_("Cannot copy file(s) - source and destination are the same."));
 676          }
 677  
 678          $conn = $this->_connect();
 679          if (is_a($conn, 'PEAR_Error')) {
 680              return $conn;
 681          }
 682  
 683          $fileCheck = $this->listFolder($dest, null, true);
 684          if (is_a($fileCheck, 'PEAR_Error')) {
 685              return $fileCheck;
 686          }
 687          foreach ($fileCheck as $file) {
 688              if ($file['name'] == $name) {
 689                  return PEAR::raiseError(sprintf(_("%s already exists."), $this->_getPath($dest, $name)));
 690              }
 691          }
 692  
 693          $isDir = false;
 694          $dirCheck = $this->listFolder($path, null, false);
 695          if (is_a($dirCheck, 'PEAR_Error')) {
 696              return $dirCheck;
 697          }
 698          foreach ($dirCheck as $file) {
 699              if ($file['name'] == $name && $file['type'] == '**dir') {
 700                  $isDir = true;
 701                  break;
 702              }
 703          }
 704  
 705          if ($isDir) {
 706              $result = $this->createFolder($dest, $name);
 707  
 708              if (is_a($result, 'PEAR_Error')) {
 709                  return $result;
 710              }
 711  
 712              $file_list = $this->listFolder($this->_getPath($path, $name));
 713              foreach ($file_list as $file) {
 714                  $result = $this->copy($this->_getPath($path, $name), $file['name'], $this->_getPath($dest, $name));
 715                  if (is_a($result, 'PEAR_Error')) {
 716                      return $result;
 717                  }
 718              }
 719          } else {
 720              $tmpFile = $this->_getTempFile();
 721              $fetch = @ftp_get($this->_stream, $tmpFile, $orig, FTP_BINARY);
 722              if (!$fetch) {
 723                  unlink($tmpFile);
 724                  return PEAR::raiseError(sprintf(_("Failed to copy from \"%s\"."), $orig));
 725              }
 726  
 727              if (!@ftp_put($this->_stream, $this->_getPath($dest, $name), $tmpFile, FTP_BINARY)) {
 728                  unlink($tmpFile);
 729                  return PEAR::raiseError(sprintf(_("Failed to copy to \"%s\"."), $this->_getPath($dest, $name)));
 730              }
 731  
 732              unlink($tmpFile);
 733          }
 734  
 735          return true;
 736      }
 737  
 738      /**
 739       * Moves a file through the backend.
 740       *
 741       * @param string $path  The path of the original file.
 742       * @param string $name  The name of the original file.
 743       * @param string $dest  The destination file name.
 744       *
 745       * @return mixed  True on success or a PEAR_Error object on failure.
 746       */
 747      function move($path, $name, $dest)
 748      {
 749          $orig = $this->_getPath($path, $name);
 750          if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) {
 751              return PEAR::raiseError(_("Cannot move file(s) - destination is within source."));
 752          }
 753  
 754          $conn = $this->_connect();
 755          if (is_a($conn, 'PEAR_Error')) {
 756              return $conn;
 757          }
 758  
 759          $fileCheck = $this->listFolder($dest, null, true);
 760          foreach ($fileCheck as $file) {
 761              if ($file['name'] == $name) {
 762                  return PEAR::raiseError(sprintf(_("%s already exists."), $this->_getPath($dest, $name)));
 763              }
 764          }
 765  
 766          if (!@ftp_rename($this->_stream, $orig, $this->_getPath($dest, $name))) {
 767              return PEAR::raiseError(sprintf(_("Failed to move to \"%s\"."), $this->_getPath($dest, $name)));
 768          }
 769  
 770          return true;
 771      }
 772  
 773      /**
 774       * Returns the current working directory on the FTP server.
 775       *
 776       * @return string  The current working directory.
 777       */
 778      function getCurrentDirectory()
 779      {
 780          if (is_a($connected = $this->_connect(), 'PEAR_Error')) {
 781              return $connected;
 782          }
 783          return ftp_pwd($this->_stream);
 784      }
 785  
 786      /**
 787       * Changes the current directory on the server.
 788       *
 789       * @access private
 790       *
 791       * @param string $path  The path to change to.
 792       *
 793       * @return mixed  True on success, or a PEAR_Error on failure.
 794       */
 795      function _setPath($path)
 796      {
 797          if (!@ftp_chdir($this->_stream, $path)) {
 798              return PEAR::raiseError(sprintf(_("Unable to change to %s."), $path));
 799          }
 800          return true;
 801      }
 802  
 803      /**
 804       * Returns the full path of an item.
 805       *
 806       * @access private
 807       *
 808       * @param string $path  The directory of the item.
 809       * @param string $name  The name of the item.
 810       *
 811       * @return mixed  Full path to the file when $path is not empty and just
 812       *                $name when not set.
 813       */
 814      function _getPath($path, $name)
 815      {
 816          if ($path !== '') {
 817              return ($path . '/' . $name);
 818          }
 819          return ($name);
 820      }
 821  
 822      /**
 823       * Returns the parent directory of the specified path.
 824       *
 825       * @access private
 826       *
 827       * @param string $path  The path to get the parent of.
 828       *
 829       * @return string  The parent directory (string) on success or a PEAR_Error
 830       *                 object on failure.
 831       */
 832      function _parentDir($path)
 833      {
 834          $conn = $this->_connect();
 835          if (is_a($conn, 'PEAR_Error')) {
 836              return $conn;
 837          }
 838  
 839          $olddir = $this->getCurrentDirectory();
 840          @ftp_cdup($this->_stream);
 841  
 842          $parent = $this->getCurrentDirectory();
 843          $this->_setPath($olddir);
 844  
 845          if (!$parent) {
 846              return PEAR::raiseError(_("Unable to determine current directory."));
 847          }
 848  
 849          return $parent;
 850      }
 851  
 852      /**
 853       * Attempts to open a connection to the FTP server.
 854       *
 855       * @access private
 856       *
 857       * @return mixed  True on success or a PEAR_Error object on failure.
 858       */
 859      function _connect()
 860      {
 861          if ($this->_stream === false) {
 862              if (!extension_loaded('ftp')) {
 863                  return PEAR::raiseError(_("The FTP extension is not available."));
 864              }
 865  
 866              if (!is_array($this->_params)) {
 867                  return PEAR::raiseError(_("No configuration information specified for FTP VFS."));
 868              }
 869  
 870              $required = array('hostspec', 'username', 'password');
 871              foreach ($required as $val) {
 872                  if (!isset($this->_params[$val])) {
 873                      return PEAR::raiseError(sprintf(_("Required \"%s\" not specified in VFS configuration."), $val));
 874                  }
 875              }
 876  
 877              /* Connect to the ftp server using the supplied parameters. */
 878              if (!empty($this->_params['ssl'])) {
 879                  if (function_exists('ftp_ssl_connect')) {
 880                      $this->_stream = @ftp_ssl_connect($this->_params['hostspec'], $this->_params['port']);
 881                  } else {
 882                      return PEAR::raiseError(_("Unable to connect with SSL."));
 883                  }
 884              } else {
 885                  $this->_stream = @ftp_connect($this->_params['hostspec'], $this->_params['port']);
 886              }
 887              if (!$this->_stream) {
 888                  return PEAR::raiseError(_("Connection to FTP server failed."));
 889              }
 890  
 891              $connected = @ftp_login($this->_stream, $this->_params['username'], $this->_params['password']);
 892              if (!$connected) {
 893                  $this->_disconnect();
 894                  return PEAR::raiseError(_("Authentication to FTP server failed."));
 895              }
 896  
 897              if (!empty($this->_params['pasv'])) {
 898                  @ftp_pasv($this->_stream, true);
 899              }
 900  
 901              if (!empty($this->_params['timeout'])) {
 902                  ftp_set_option($this->_stream, FTP_TIMEOUT_SEC, $this->_params['timeout']);
 903              }
 904          }
 905  
 906          return true;
 907      }
 908  
 909      /**
 910       * Disconnects from the FTP server and cleans up the connection.
 911       *
 912       * @access private
 913       */
 914      function _disconnect()
 915      {
 916          @ftp_quit($this->_stream);
 917          $this->_stream = false;
 918      }
 919  
 920  }


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