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

Source for file ftp.php

Documentation is available at ftp.php

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

Documentation generated on Mon, 11 Mar 2019 15:16:27 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.