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

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