gluon-web-remote

Web remote Administration for big size of gluon routers
git clone git://archive.git.mtrnord.blog/MTRNord/gluon-web-remote.git
Log | Files | Refs | README

Sftp.php (8164B)


      1 <?php
      2 
      3 namespace Ssh;
      4 
      5 use RuntimeException;
      6 
      7 /**
      8  * Secure File Transfer Protocol
      9  *
     10  * @author Antoine Hérault <antoine.herault@gmail.com>
     11  */
     12 class Sftp extends Subsystem
     13 {
     14     /**
     15      * Stats a symbolic link
     16      *
     17      * @param  string $path The path of the symbolic link
     18      *
     19      * @return array
     20      */
     21     public function lstat($path)
     22     {
     23         return ssh2_sftp_lstat($this->getResource(), $path);
     24     }
     25 
     26     /**
     27      * Creates a directory
     28      *
     29      * @param  string  $dirname   The name of the new directory
     30      * @param  int     $mod       The permissions on the new directory
     31      * @param  Boolean $recursive Whether to automatically create any required
     32      *                            parent directory
     33      *
     34      * @return Boolean
     35      */
     36     public function mkdir($dirname, $mod = 0777, $recursive = false)
     37     {
     38         return ssh2_sftp_mkdir($this->getResource(), $dirname, $mod, $recursive);
     39     }
     40 
     41     /**
     42      * Returns the target of a symbolic link
     43      *
     44      * @param  string $link The path of the symbolic link
     45      *
     46      * @return string The target of the symbolic link
     47      */
     48     public function readlink($link)
     49     {
     50         return ssh2_sftp_readlink($this->getResource(), $link);
     51     }
     52 
     53     /**
     54      * Resolves the realpath of a provided path string
     55      *
     56      * @param  string $filename The filename to resolve
     57      *
     58      * @return string The real path of the file
     59      */
     60     public function realpath($filename)
     61     {
     62         // This function creates a not documented warning on failure.
     63         return @ssh2_sftp_realpath($this->getResource(), $filename);
     64     }
     65 
     66     /**
     67      * Renames a remote file
     68      *
     69      * @param  string $from The current file that is being renamed
     70      * @param  string $to   The new file name that replaces from
     71      *
     72      * @return Boolean TRUE on success, or FALSE on failure
     73      */
     74     public function rename($from, $to)
     75     {
     76         return ssh2_sftp_rename($this->getResource(), $from, $to);
     77     }
     78 
     79     /**
     80      * Removes a directory
     81      *
     82      * @param  string $dirname The directory that is being removed
     83      *
     84      * @return Boolean TRUE on success, or FALSE on failure
     85      */
     86     public function rmdir($dirname)
     87     {
     88         return ssh2_sftp_rmdir($this->getResource(), $dirname);
     89     }
     90 
     91     /**
     92      * Stats a file on the remote filesystem
     93      *
     94      * @param  string $path The path of the file
     95      *
     96      * @return array
     97      */
     98     public function stat($path)
     99     {
    100         // This function creates a undocumented warning on missing files.
    101         return @ssh2_sftp_stat($this->getResource(), $path);
    102     }
    103 
    104     /**
    105      * Creates a symlink
    106      *
    107      * @param  string $target The target of the symlink
    108      * @param  string $link   The path of the link
    109      *
    110      * @return Boolean TRUE on success, or FALSE on failure
    111      */
    112     public function symlink($target, $link)
    113     {
    114         return ssh2_sftp_symlink($this->getResource(), $target, $link);
    115     }
    116 
    117     /**
    118      * Deletes a file
    119      *
    120      * @param  string $filename The name of the file that is being deleted
    121      *
    122      * @return Boolean TRUE on success, or FALSE on failure
    123      */
    124     public function unlink($filename)
    125     {
    126         return ssh2_sftp_unlink($this->getResource(), $filename);
    127     }
    128 
    129     /**
    130      * Indicates whether the specified distant file exists
    131      *
    132      * @param  string $filename The distant filename
    133      *
    134      * @return boolean
    135      */
    136     public function exists($filename)
    137     {
    138         return file_exists($this->getUrl($filename));
    139     }
    140 
    141     /**
    142      * Reads the content of the specified remote file.
    143      * Will return false if file does not exist.
    144      *
    145      * @param  string $filename The remote filename
    146      *
    147      * @return string|false
    148      */
    149     public function read($filename)
    150     {
    151         // Suppress a warning, when file does not exist.
    152         return @file_get_contents($this->getUrl($filename));
    153     }
    154 
    155     /**
    156      * Writes the given content to the specified remote file
    157      *
    158      * @param  string $filename The remote filename
    159      *
    160      * @return integer The number of bytes that were written into the file, or
    161      *                 FALSE on failure
    162      */
    163     public function write($filename, $content)
    164     {
    165         return file_put_contents($this->getUrl($filename), $content);
    166     }
    167 
    168     /**
    169      * Receive the specified distant file as the specified local file
    170      *
    171      * @param  string $distant The distant filename
    172      * @param  string $local   The local filename
    173      *
    174      * @return boolean TRUE on success, or FALSE on failure
    175      */
    176     public function receive($distant, $local)
    177     {
    178         return file_put_contents($local, $this->read($distant));
    179     }
    180 
    181     /**
    182      * Sends the specified local file as the specified remote file
    183      *
    184      * @param  string $local   The local filename
    185      * @param  string $distant The distant filename
    186      *
    187      * @return integer|false The number of bytes that were sent,
    188      *                       or FALSE on failure
    189      */
    190     public function send($local, $distant)
    191     {
    192         return $this->write($distant, file_get_contents($local));
    193     }
    194 
    195     /**
    196      * Returns the URL of the specified file with the ssh2.sftp protocol. The
    197      * result URL is suitable for stream resource creation (e.g using fopen)
    198      *
    199      * @param  string $filename The distant filename
    200      *
    201      * @return string
    202      */
    203     public function getUrl($filename)
    204     {
    205         return sprintf('ssh2.sftp://%s/%s', $this->getResource(), $filename);
    206     }
    207 
    208     /**
    209      * Lists files and directories of the specified directory
    210      *
    211      * The returned array is of the form:
    212      *
    213      *      array(
    214      *          'files'       => array(...),
    215      *          'directories' => array(...)
    216      *      )
    217      *
    218      * @param  string $directory
    219      * @param  Boolean $recursive
    220      *
    221      * @return array
    222      */
    223     public function listDirectory($directory, $recursive = false)
    224     {
    225         $results = $this->scanDirectory($directory, $recursive);
    226 
    227         if (false === $results) {
    228             throw new \RuntimeException(sprintf(
    229                 'Unable to list directory "%s", maybe it is not a directory '.
    230                 'or it does not exist.',
    231                 $directory
    232             ));
    233         }
    234 
    235         return array(
    236             'files'       => $results[0],
    237             'directories' => $results[1]
    238         );
    239     }
    240 
    241     /**
    242      * {@inheritDoc}
    243      */
    244     protected function createResource()
    245     {
    246         $resource = ssh2_sftp($this->getSessionResource());
    247 
    248         if (!is_resource($resource)) {
    249             throw new RuntimeException('The initialization of the SFTP subsystem failed.');
    250         }
    251 
    252         $this->resource = $resource;
    253     }
    254 
    255     /**
    256      * Scans a directory
    257      *
    258      * Unfortunately, using a (recursive) directory iterator is not possible
    259      * over SFTP: see https://bugs.php.net/bug.php?id=57378. Also, is_dir() is
    260      * unreliable and often returns false for valid directories. Therefore, I
    261      * use @scandir() instead.
    262      *
    263      * @param  string  $directory
    264      * @param  Boolean $recursive
    265      *
    266      * @return array
    267      */
    268     private function scanDirectory($directory, $recursive)
    269     {
    270         if (!$results = @scandir($this->getUrl($directory))) {
    271             return false;
    272         }
    273 
    274         $files       = array();
    275         $directories = array();
    276 
    277         foreach ($results as $result) {
    278             if (in_array($result, array('.', '..'))) {
    279                 continue;
    280             }
    281 
    282             $filename = sprintf('%s/%s', $directory, $result);
    283 
    284             if (false === @scandir($this->getUrl($filename))) {
    285                 $files[] = $filename;
    286             } else {
    287                 $directories[] = $filename;
    288 
    289                 if ($recursive) {
    290                     $children    = $this->scanDirectory($filename, $recursive);
    291                     if (is_array($children)) {
    292                         $files       = array_merge($files, $children[0]);
    293                         $directories = array_merge($directories, $children[1]);
    294                     }
    295                 }
    296             }
    297         }
    298 
    299         return array($files, $directories);
    300     }
    301 }