[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-admin/includes/ -> class-wp-filesystem-ssh2.php (source)

   1  <?php
   2  /**
   3   * WordPress Filesystem Class for implementing SSH2
   4   *
   5   * To use this class you must follow these steps for PHP 5.2.6+
   6   *
   7   * @contrib http://kevin.vanzonneveld.net/techblog/article/make_ssh_connections_with_php/ - Installation Notes
   8   *
   9   * Compile libssh2 (Note: Only 0.14 is officaly working with PHP 5.2.6+ right now, But many users have found the latest versions work)
  10   *
  11   * cd /usr/src
  12   * wget https://www.libssh2.org/download/libssh2-0.14.tar.gz
  13   * tar -zxvf libssh2-0.14.tar.gz
  14   * cd libssh2-0.14/
  15   * ./configure
  16   * make all install
  17   *
  18   * Note: Do not leave the directory yet!
  19   *
  20   * Enter: pecl install -f ssh2
  21   *
  22   * Copy the ssh.so file it creates to your PHP Module Directory.
  23   * Open up your PHP.INI file and look for where extensions are placed.
  24   * Add in your PHP.ini file: extension=ssh2.so
  25   *
  26   * Restart Apache!
  27   * Check phpinfo() streams to confirm that: ssh2.shell, ssh2.exec, ssh2.tunnel, ssh2.scp, ssh2.sftp  exist.
  28   *
  29   * Note: As of WordPress 2.8, this utilises the PHP5+ function `stream_get_contents()`.
  30   *
  31   * @since 2.7.0
  32   *
  33   * @package WordPress
  34   * @subpackage Filesystem
  35   */
  36  class WP_Filesystem_SSH2 extends WP_Filesystem_Base {
  37  
  38      /**
  39       * @since 2.7.0
  40       * @var resource
  41       */
  42      public $link = false;
  43  
  44      /**
  45       * @since 2.7.0
  46       * @var resource
  47       */
  48      public $sftp_link;
  49  
  50      /**
  51       * @since 2.7.0
  52       * @var bool
  53       */
  54      public $keys = false;
  55  
  56      /**
  57       * Constructor.
  58       *
  59       * @since 2.7.0
  60       *
  61       * @param array $opt
  62       */
  63  	public function __construct( $opt = '' ) {
  64          $this->method = 'ssh2';
  65          $this->errors = new WP_Error();
  66  
  67          // Check if possible to use ssh2 functions.
  68          if ( ! extension_loaded( 'ssh2' ) ) {
  69              $this->errors->add( 'no_ssh2_ext', __( 'The ssh2 PHP extension is not available' ) );
  70              return;
  71          }
  72  
  73          // Set defaults:
  74          if ( empty( $opt['port'] ) ) {
  75              $this->options['port'] = 22;
  76          } else {
  77              $this->options['port'] = $opt['port'];
  78          }
  79  
  80          if ( empty( $opt['hostname'] ) ) {
  81              $this->errors->add( 'empty_hostname', __( 'SSH2 hostname is required' ) );
  82          } else {
  83              $this->options['hostname'] = $opt['hostname'];
  84          }
  85  
  86          // Check if the options provided are OK.
  87          if ( ! empty( $opt['public_key'] ) && ! empty( $opt['private_key'] ) ) {
  88              $this->options['public_key']  = $opt['public_key'];
  89              $this->options['private_key'] = $opt['private_key'];
  90  
  91              $this->options['hostkey'] = array( 'hostkey' => 'ssh-rsa' );
  92  
  93              $this->keys = true;
  94          } elseif ( empty( $opt['username'] ) ) {
  95              $this->errors->add( 'empty_username', __( 'SSH2 username is required' ) );
  96          }
  97  
  98          if ( ! empty( $opt['username'] ) ) {
  99              $this->options['username'] = $opt['username'];
 100          }
 101  
 102          if ( empty( $opt['password'] ) ) {
 103              // Password can be blank if we are using keys.
 104              if ( ! $this->keys ) {
 105                  $this->errors->add( 'empty_password', __( 'SSH2 password is required' ) );
 106              }
 107          } else {
 108              $this->options['password'] = $opt['password'];
 109          }
 110      }
 111  
 112      /**
 113       * Connects filesystem.
 114       *
 115       * @since 2.7.0
 116       *
 117       * @return bool True on success, false on failure.
 118       */
 119  	public function connect() {
 120          if ( ! $this->keys ) {
 121              $this->link = @ssh2_connect( $this->options['hostname'], $this->options['port'] );
 122          } else {
 123              $this->link = @ssh2_connect( $this->options['hostname'], $this->options['port'], $this->options['hostkey'] );
 124          }
 125  
 126          if ( ! $this->link ) {
 127              $this->errors->add(
 128                  'connect',
 129                  sprintf(
 130                      /* translators: %s: hostname:port */
 131                      __( 'Failed to connect to SSH2 Server %s' ),
 132                      $this->options['hostname'] . ':' . $this->options['port']
 133                  )
 134              );
 135  
 136              return false;
 137          }
 138  
 139          if ( ! $this->keys ) {
 140              if ( ! @ssh2_auth_password( $this->link, $this->options['username'], $this->options['password'] ) ) {
 141                  $this->errors->add(
 142                      'auth',
 143                      sprintf(
 144                          /* translators: %s: Username. */
 145                          __( 'Username/Password incorrect for %s' ),
 146                          $this->options['username']
 147                      )
 148                  );
 149  
 150                  return false;
 151              }
 152          } else {
 153              if ( ! @ssh2_auth_pubkey_file( $this->link, $this->options['username'], $this->options['public_key'], $this->options['private_key'], $this->options['password'] ) ) {
 154                  $this->errors->add(
 155                      'auth',
 156                      sprintf(
 157                          /* translators: %s: Username. */
 158                          __( 'Public and Private keys incorrect for %s' ),
 159                          $this->options['username']
 160                      )
 161                  );
 162  
 163                  return false;
 164              }
 165          }
 166  
 167          $this->sftp_link = ssh2_sftp( $this->link );
 168  
 169          if ( ! $this->sftp_link ) {
 170              $this->errors->add(
 171                  'connect',
 172                  sprintf(
 173                      /* translators: %s: hostname:port */
 174                      __( 'Failed to initialize a SFTP subsystem session with the SSH2 Server %s' ),
 175                      $this->options['hostname'] . ':' . $this->options['port']
 176                  )
 177              );
 178  
 179              return false;
 180          }
 181  
 182          return true;
 183      }
 184  
 185      /**
 186       * Gets the ssh2.sftp PHP stream wrapper path to open for the given file.
 187       *
 188       * This method also works around a PHP bug where the root directory (/) cannot
 189       * be opened by PHP functions, causing a false failure. In order to work around
 190       * this, the path is converted to /./ which is semantically the same as /
 191       * See https://bugs.php.net/bug.php?id=64169 for more details.
 192       *
 193       * @since 4.4.0
 194       *
 195       * @param string $path The File/Directory path on the remote server to return
 196       * @return string The ssh2.sftp:// wrapped path to use.
 197       */
 198  	public function sftp_path( $path ) {
 199          if ( '/' === $path ) {
 200              $path = '/./';
 201          }
 202  
 203          return 'ssh2.sftp://' . $this->sftp_link . '/' . ltrim( $path, '/' );
 204      }
 205  
 206      /**
 207       * @since 2.7.0
 208       *
 209       * @param string $command
 210       * @param bool $returnbool
 211       * @return bool|string True on success, false on failure. String if the command was executed, `$returnbool`
 212       *                     is false (default), and data from the resulting stream was retrieved.
 213       */
 214  	public function run_command( $command, $returnbool = false ) {
 215          if ( ! $this->link ) {
 216              return false;
 217          }
 218  
 219          $stream = ssh2_exec( $this->link, $command );
 220  
 221          if ( ! $stream ) {
 222              $this->errors->add(
 223                  'command',
 224                  sprintf(
 225                      /* translators: %s: Command. */
 226                      __( 'Unable to perform command: %s' ),
 227                      $command
 228                  )
 229              );
 230          } else {
 231              stream_set_blocking( $stream, true );
 232              stream_set_timeout( $stream, FS_TIMEOUT );
 233              $data = stream_get_contents( $stream );
 234              fclose( $stream );
 235  
 236              if ( $returnbool ) {
 237                  return ( false === $data ) ? false : '' !== trim( $data );
 238              } else {
 239                  return $data;
 240              }
 241          }
 242  
 243          return false;
 244      }
 245  
 246      /**
 247       * Reads entire file into a string.
 248       *
 249       * @since 2.7.0
 250       *
 251       * @param string $file Name of the file to read.
 252       * @return string|false Read data on success, false if no temporary file could be opened,
 253       *                      or if the file couldn't be retrieved.
 254       */
 255  	public function get_contents( $file ) {
 256          return file_get_contents( $this->sftp_path( $file ) );
 257      }
 258  
 259      /**
 260       * Reads entire file into an array.
 261       *
 262       * @since 2.7.0
 263       *
 264       * @param string $file Path to the file.
 265       * @return array|false File contents in an array on success, false on failure.
 266       */
 267  	public function get_contents_array( $file ) {
 268          return file( $this->sftp_path( $file ) );
 269      }
 270  
 271      /**
 272       * Writes a string to a file.
 273       *
 274       * @since 2.7.0
 275       *
 276       * @param string    $file     Remote path to the file where to write the data.
 277       * @param string    $contents The data to write.
 278       * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
 279       *                            Default false.
 280       * @return bool True on success, false on failure.
 281       */
 282  	public function put_contents( $file, $contents, $mode = false ) {
 283          $ret = file_put_contents( $this->sftp_path( $file ), $contents );
 284  
 285          if ( strlen( $contents ) !== $ret ) {
 286              return false;
 287          }
 288  
 289          $this->chmod( $file, $mode );
 290  
 291          return true;
 292      }
 293  
 294      /**
 295       * Gets the current working directory.
 296       *
 297       * @since 2.7.0
 298       *
 299       * @return string|false The current working directory on success, false on failure.
 300       */
 301  	public function cwd() {
 302          $cwd = ssh2_sftp_realpath( $this->sftp_link, '.' );
 303  
 304          if ( $cwd ) {
 305              $cwd = trailingslashit( trim( $cwd ) );
 306          }
 307  
 308          return $cwd;
 309      }
 310  
 311      /**
 312       * Changes current directory.
 313       *
 314       * @since 2.7.0
 315       *
 316       * @param string $dir The new current directory.
 317       * @return bool True on success, false on failure.
 318       */
 319  	public function chdir( $dir ) {
 320          return $this->run_command( 'cd ' . $dir, true );
 321      }
 322  
 323      /**
 324       * Changes the file group.
 325       *
 326       * @since 2.7.0
 327       *
 328       * @param string     $file      Path to the file.
 329       * @param string|int $group     A group name or number.
 330       * @param bool       $recursive Optional. If set to true, changes file group recursively.
 331       *                              Default false.
 332       * @return bool True on success, false on failure.
 333       */
 334  	public function chgrp( $file, $group, $recursive = false ) {
 335          if ( ! $this->exists( $file ) ) {
 336              return false;
 337          }
 338  
 339          if ( ! $recursive || ! $this->is_dir( $file ) ) {
 340              return $this->run_command( sprintf( 'chgrp %s %s', escapeshellarg( $group ), escapeshellarg( $file ) ), true );
 341          }
 342  
 343          return $this->run_command( sprintf( 'chgrp -R %s %s', escapeshellarg( $group ), escapeshellarg( $file ) ), true );
 344      }
 345  
 346      /**
 347       * Changes filesystem permissions.
 348       *
 349       * @since 2.7.0
 350       *
 351       * @param string    $file      Path to the file.
 352       * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
 353       *                             0755 for directories. Default false.
 354       * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
 355       *                             Default false.
 356       * @return bool True on success, false on failure.
 357       */
 358  	public function chmod( $file, $mode = false, $recursive = false ) {
 359          if ( ! $this->exists( $file ) ) {
 360              return false;
 361          }
 362  
 363          if ( ! $mode ) {
 364              if ( $this->is_file( $file ) ) {
 365                  $mode = FS_CHMOD_FILE;
 366              } elseif ( $this->is_dir( $file ) ) {
 367                  $mode = FS_CHMOD_DIR;
 368              } else {
 369                  return false;
 370              }
 371          }
 372  
 373          if ( ! $recursive || ! $this->is_dir( $file ) ) {
 374              return $this->run_command( sprintf( 'chmod %o %s', $mode, escapeshellarg( $file ) ), true );
 375          }
 376  
 377          return $this->run_command( sprintf( 'chmod -R %o %s', $mode, escapeshellarg( $file ) ), true );
 378      }
 379  
 380      /**
 381       * Changes the owner of a file or directory.
 382       *
 383       * @since 2.7.0
 384       *
 385       * @param string     $file      Path to the file or directory.
 386       * @param string|int $owner     A user name or number.
 387       * @param bool       $recursive Optional. If set to true, changes file owner recursively.
 388       *                              Default false.
 389       * @return bool True on success, false on failure.
 390       */
 391  	public function chown( $file, $owner, $recursive = false ) {
 392          if ( ! $this->exists( $file ) ) {
 393              return false;
 394          }
 395  
 396          if ( ! $recursive || ! $this->is_dir( $file ) ) {
 397              return $this->run_command( sprintf( 'chown %s %s', escapeshellarg( $owner ), escapeshellarg( $file ) ), true );
 398          }
 399  
 400          return $this->run_command( sprintf( 'chown -R %s %s', escapeshellarg( $owner ), escapeshellarg( $file ) ), true );
 401      }
 402  
 403      /**
 404       * Gets the file owner.
 405       *
 406       * @since 2.7.0
 407       *
 408       * @param string $file Path to the file.
 409       * @return string|false Username of the owner on success, false on failure.
 410       */
 411  	public function owner( $file ) {
 412          $owneruid = @fileowner( $this->sftp_path( $file ) );
 413  
 414          if ( ! $owneruid ) {
 415              return false;
 416          }
 417  
 418          if ( ! function_exists( 'posix_getpwuid' ) ) {
 419              return $owneruid;
 420          }
 421  
 422          $ownerarray = posix_getpwuid( $owneruid );
 423  
 424          if ( ! $ownerarray ) {
 425              return false;
 426          }
 427  
 428          return $ownerarray['name'];
 429      }
 430  
 431      /**
 432       * Gets the permissions of the specified file or filepath in their octal format.
 433       *
 434       * @since 2.7.0
 435       *
 436       * @param string $file Path to the file.
 437       * @return string Mode of the file (the last 3 digits).
 438       */
 439  	public function getchmod( $file ) {
 440          return substr( decoct( @fileperms( $this->sftp_path( $file ) ) ), -3 );
 441      }
 442  
 443      /**
 444       * Gets the file's group.
 445       *
 446       * @since 2.7.0
 447       *
 448       * @param string $file Path to the file.
 449       * @return string|false The group on success, false on failure.
 450       */
 451  	public function group( $file ) {
 452          $gid = @filegroup( $this->sftp_path( $file ) );
 453  
 454          if ( ! $gid ) {
 455              return false;
 456          }
 457  
 458          if ( ! function_exists( 'posix_getgrgid' ) ) {
 459              return $gid;
 460          }
 461  
 462          $grouparray = posix_getgrgid( $gid );
 463  
 464          if ( ! $grouparray ) {
 465              return false;
 466          }
 467  
 468          return $grouparray['name'];
 469      }
 470  
 471      /**
 472       * Copies a file.
 473       *
 474       * @since 2.7.0
 475       *
 476       * @param string    $source      Path to the source file.
 477       * @param string    $destination Path to the destination file.
 478       * @param bool      $overwrite   Optional. Whether to overwrite the destination file if it exists.
 479       *                               Default false.
 480       * @param int|false $mode        Optional. The permissions as octal number, usually 0644 for files,
 481       *                               0755 for dirs. Default false.
 482       * @return bool True on success, false on failure.
 483       */
 484  	public function copy( $source, $destination, $overwrite = false, $mode = false ) {
 485          if ( ! $overwrite && $this->exists( $destination ) ) {
 486              return false;
 487          }
 488  
 489          $content = $this->get_contents( $source );
 490  
 491          if ( false === $content ) {
 492              return false;
 493          }
 494  
 495          return $this->put_contents( $destination, $content, $mode );
 496      }
 497  
 498      /**
 499       * Moves a file.
 500       *
 501       * @since 2.7.0
 502       *
 503       * @param string $source      Path to the source file.
 504       * @param string $destination Path to the destination file.
 505       * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
 506       *                            Default false.
 507       * @return bool True on success, false on failure.
 508       */
 509  	public function move( $source, $destination, $overwrite = false ) {
 510          if ( $this->exists( $destination ) ) {
 511              if ( $overwrite ) {
 512                  // We need to remove the destination file before we can rename the source.
 513                  $this->delete( $destination, false, 'f' );
 514              } else {
 515                  // If we're not overwriting, the rename will fail, so return early.
 516                  return false;
 517              }
 518          }
 519  
 520          return ssh2_sftp_rename( $this->sftp_link, $source, $destination );
 521      }
 522  
 523      /**
 524       * Deletes a file or directory.
 525       *
 526       * @since 2.7.0
 527       *
 528       * @param string       $file      Path to the file or directory.
 529       * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
 530       *                                Default false.
 531       * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
 532       *                                Default false.
 533       * @return bool True on success, false on failure.
 534       */
 535  	public function delete( $file, $recursive = false, $type = false ) {
 536          if ( 'f' === $type || $this->is_file( $file ) ) {
 537              return ssh2_sftp_unlink( $this->sftp_link, $file );
 538          }
 539  
 540          if ( ! $recursive ) {
 541              return ssh2_sftp_rmdir( $this->sftp_link, $file );
 542          }
 543  
 544          $filelist = $this->dirlist( $file );
 545  
 546          if ( is_array( $filelist ) ) {
 547              foreach ( $filelist as $filename => $fileinfo ) {
 548                  $this->delete( $file . '/' . $filename, $recursive, $fileinfo['type'] );
 549              }
 550          }
 551  
 552          return ssh2_sftp_rmdir( $this->sftp_link, $file );
 553      }
 554  
 555      /**
 556       * Checks if a file or directory exists.
 557       *
 558       * @since 2.7.0
 559       *
 560       * @param string $file Path to file or directory.
 561       * @return bool Whether $file exists or not.
 562       */
 563  	public function exists( $file ) {
 564          return file_exists( $this->sftp_path( $file ) );
 565      }
 566  
 567      /**
 568       * Checks if resource is a file.
 569       *
 570       * @since 2.7.0
 571       *
 572       * @param string $file File path.
 573       * @return bool Whether $file is a file.
 574       */
 575  	public function is_file( $file ) {
 576          return is_file( $this->sftp_path( $file ) );
 577      }
 578  
 579      /**
 580       * Checks if resource is a directory.
 581       *
 582       * @since 2.7.0
 583       *
 584       * @param string $path Directory path.
 585       * @return bool Whether $path is a directory.
 586       */
 587  	public function is_dir( $path ) {
 588          return is_dir( $this->sftp_path( $path ) );
 589      }
 590  
 591      /**
 592       * Checks if a file is readable.
 593       *
 594       * @since 2.7.0
 595       *
 596       * @param string $file Path to file.
 597       * @return bool Whether $file is readable.
 598       */
 599  	public function is_readable( $file ) {
 600          return is_readable( $this->sftp_path( $file ) );
 601      }
 602  
 603      /**
 604       * Checks if a file or directory is writable.
 605       *
 606       * @since 2.7.0
 607       *
 608       * @param string $file Path to file or directory.
 609       * @return bool Whether $file is writable.
 610       */
 611  	public function is_writable( $file ) {
 612          // PHP will base its writable checks on system_user === file_owner, not ssh_user === file_owner.
 613          return true;
 614      }
 615  
 616      /**
 617       * Gets the file's last access time.
 618       *
 619       * @since 2.7.0
 620       *
 621       * @param string $file Path to file.
 622       * @return int|false Unix timestamp representing last access time, false on failure.
 623       */
 624  	public function atime( $file ) {
 625          return fileatime( $this->sftp_path( $file ) );
 626      }
 627  
 628      /**
 629       * Gets the file modification time.
 630       *
 631       * @since 2.7.0
 632       *
 633       * @param string $file Path to file.
 634       * @return int|false Unix timestamp representing modification time, false on failure.
 635       */
 636  	public function mtime( $file ) {
 637          return filemtime( $this->sftp_path( $file ) );
 638      }
 639  
 640      /**
 641       * Gets the file size (in bytes).
 642       *
 643       * @since 2.7.0
 644       *
 645       * @param string $file Path to file.
 646       * @return int|false Size of the file in bytes on success, false on failure.
 647       */
 648  	public function size( $file ) {
 649          return filesize( $this->sftp_path( $file ) );
 650      }
 651  
 652      /**
 653       * Sets the access and modification times of a file.
 654       *
 655       * Note: Not implemented.
 656       *
 657       * @since 2.7.0
 658       *
 659       * @param string $file  Path to file.
 660       * @param int    $time  Optional. Modified time to set for file.
 661       *                      Default 0.
 662       * @param int    $atime Optional. Access time to set for file.
 663       *                      Default 0.
 664       */
 665  	public function touch( $file, $time = 0, $atime = 0 ) {
 666          // Not implemented.
 667      }
 668  
 669      /**
 670       * Creates a directory.
 671       *
 672       * @since 2.7.0
 673       *
 674       * @param string     $path  Path for new directory.
 675       * @param int|false  $chmod Optional. The permissions as octal number (or false to skip chmod).
 676       *                          Default false.
 677       * @param string|int $chown Optional. A user name or number (or false to skip chown).
 678       *                          Default false.
 679       * @param string|int $chgrp Optional. A group name or number (or false to skip chgrp).
 680       *                          Default false.
 681       * @return bool True on success, false on failure.
 682       */
 683  	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
 684          $path = untrailingslashit( $path );
 685  
 686          if ( empty( $path ) ) {
 687              return false;
 688          }
 689  
 690          if ( ! $chmod ) {
 691              $chmod = FS_CHMOD_DIR;
 692          }
 693  
 694          if ( ! ssh2_sftp_mkdir( $this->sftp_link, $path, $chmod, true ) ) {
 695              return false;
 696          }
 697  
 698          // Set directory permissions.
 699          ssh2_sftp_chmod( $this->sftp_link, $path, $chmod );
 700  
 701          if ( $chown ) {
 702              $this->chown( $path, $chown );
 703          }
 704  
 705          if ( $chgrp ) {
 706              $this->chgrp( $path, $chgrp );
 707          }
 708  
 709          return true;
 710      }
 711  
 712      /**
 713       * Deletes a directory.
 714       *
 715       * @since 2.7.0
 716       *
 717       * @param string $path      Path to directory.
 718       * @param bool   $recursive Optional. Whether to recursively remove files/directories.
 719       *                          Default false.
 720       * @return bool True on success, false on failure.
 721       */
 722  	public function rmdir( $path, $recursive = false ) {
 723          return $this->delete( $path, $recursive );
 724      }
 725  
 726      /**
 727       * Gets details for files in a directory or a specific file.
 728       *
 729       * @since 2.7.0
 730       *
 731       * @param string $path           Path to directory or file.
 732       * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
 733       *                               Default true.
 734       * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
 735       *                               Default false.
 736       * @return array|false {
 737       *     Array of files. False if unable to list directory contents.
 738       *
 739       *     @type string $name        Name of the file or directory.
 740       *     @type string $perms       *nix representation of permissions.
 741       *     @type int    $permsn      Octal representation of permissions.
 742       *     @type string $owner       Owner name or ID.
 743       *     @type int    $size        Size of file in bytes.
 744       *     @type int    $lastmodunix Last modified unix timestamp.
 745       *     @type mixed  $lastmod     Last modified month (3 letter) and day (without leading 0).
 746       *     @type int    $time        Last modified time.
 747       *     @type string $type        Type of resource. 'f' for file, 'd' for directory.
 748       *     @type mixed  $files       If a directory and $recursive is true, contains another array of files.
 749       * }
 750       */
 751  	public function dirlist( $path, $include_hidden = true, $recursive = false ) {
 752          if ( $this->is_file( $path ) ) {
 753              $limit_file = basename( $path );
 754              $path       = dirname( $path );
 755          } else {
 756              $limit_file = false;
 757          }
 758  
 759          if ( ! $this->is_dir( $path ) || ! $this->is_readable( $path ) ) {
 760              return false;
 761          }
 762  
 763          $ret = array();
 764          $dir = dir( $this->sftp_path( $path ) );
 765  
 766          if ( ! $dir ) {
 767              return false;
 768          }
 769  
 770          while ( false !== ( $entry = $dir->read() ) ) {
 771              $struc         = array();
 772              $struc['name'] = $entry;
 773  
 774              if ( '.' === $struc['name'] || '..' === $struc['name'] ) {
 775                  continue; // Do not care about these folders.
 776              }
 777  
 778              if ( ! $include_hidden && '.' === $struc['name'][0] ) {
 779                  continue;
 780              }
 781  
 782              if ( $limit_file && $struc['name'] != $limit_file ) {
 783                  continue;
 784              }
 785  
 786              $struc['perms']       = $this->gethchmod( $path . '/' . $entry );
 787              $struc['permsn']      = $this->getnumchmodfromh( $struc['perms'] );
 788              $struc['number']      = false;
 789              $struc['owner']       = $this->owner( $path . '/' . $entry );
 790              $struc['group']       = $this->group( $path . '/' . $entry );
 791              $struc['size']        = $this->size( $path . '/' . $entry );
 792              $struc['lastmodunix'] = $this->mtime( $path . '/' . $entry );
 793              $struc['lastmod']     = gmdate( 'M j', $struc['lastmodunix'] );
 794              $struc['time']        = gmdate( 'h:i:s', $struc['lastmodunix'] );
 795              $struc['type']        = $this->is_dir( $path . '/' . $entry ) ? 'd' : 'f';
 796  
 797              if ( 'd' === $struc['type'] ) {
 798                  if ( $recursive ) {
 799                      $struc['files'] = $this->dirlist( $path . '/' . $struc['name'], $include_hidden, $recursive );
 800                  } else {
 801                      $struc['files'] = array();
 802                  }
 803              }
 804  
 805              $ret[ $struc['name'] ] = $struc;
 806          }
 807  
 808          $dir->close();
 809          unset( $dir );
 810  
 811          return $ret;
 812      }
 813  }


Generated : Fri Jul 3 08:20:01 2020 Cross-referenced by PHPXref