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

Source for file ssh2.php

Documentation is available at ssh2.php

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

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