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

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