[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

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

   1  <?php
   2  /**
   3   * WordPress FTP Sockets Filesystem.
   4   *
   5   * @package WordPress
   6   * @subpackage Filesystem
   7   */
   8  
   9  /**
  10   * WordPress Filesystem Class for implementing FTP Sockets.
  11   *
  12   * @since 2.5.0
  13   *
  14   * @see WP_Filesystem_Base
  15   */
  16  class WP_Filesystem_ftpsockets extends WP_Filesystem_Base {
  17  
  18      /**
  19       * @since 2.5.0
  20       * @var ftp
  21       */
  22      public $ftp;
  23  
  24      /**
  25       * Constructor.
  26       *
  27       * @since 2.5.0
  28       *
  29       * @param array $opt
  30       */
  31  	public function __construct( $opt = '' ) {
  32          $this->method = 'ftpsockets';
  33          $this->errors = new WP_Error();
  34  
  35          // Check if possible to use ftp functions.
  36          if ( ! require_once ABSPATH . 'wp-admin/includes/class-ftp.php' ) {
  37              return;
  38          }
  39  
  40          $this->ftp = new ftp();
  41  
  42          if ( empty( $opt['port'] ) ) {
  43              $this->options['port'] = 21;
  44          } else {
  45              $this->options['port'] = (int) $opt['port'];
  46          }
  47  
  48          if ( empty( $opt['hostname'] ) ) {
  49              $this->errors->add( 'empty_hostname', __( 'FTP hostname is required' ) );
  50          } else {
  51              $this->options['hostname'] = $opt['hostname'];
  52          }
  53  
  54          // Check if the options provided are OK.
  55          if ( empty( $opt['username'] ) ) {
  56              $this->errors->add( 'empty_username', __( 'FTP username is required' ) );
  57          } else {
  58              $this->options['username'] = $opt['username'];
  59          }
  60  
  61          if ( empty( $opt['password'] ) ) {
  62              $this->errors->add( 'empty_password', __( 'FTP password is required' ) );
  63          } else {
  64              $this->options['password'] = $opt['password'];
  65          }
  66      }
  67  
  68      /**
  69       * Connects filesystem.
  70       *
  71       * @since 2.5.0
  72       *
  73       * @return bool True on success, false on failure.
  74       */
  75  	public function connect() {
  76          if ( ! $this->ftp ) {
  77              return false;
  78          }
  79  
  80          $this->ftp->setTimeout( FS_CONNECT_TIMEOUT );
  81  
  82          if ( ! $this->ftp->SetServer( $this->options['hostname'], $this->options['port'] ) ) {
  83              $this->errors->add(
  84                  'connect',
  85                  sprintf(
  86                      /* translators: %s: hostname:port */
  87                      __( 'Failed to connect to FTP Server %s' ),
  88                      $this->options['hostname'] . ':' . $this->options['port']
  89                  )
  90              );
  91  
  92              return false;
  93          }
  94  
  95          if ( ! $this->ftp->connect() ) {
  96              $this->errors->add(
  97                  'connect',
  98                  sprintf(
  99                      /* translators: %s: hostname:port */
 100                      __( 'Failed to connect to FTP Server %s' ),
 101                      $this->options['hostname'] . ':' . $this->options['port']
 102                  )
 103              );
 104  
 105              return false;
 106          }
 107  
 108          if ( ! $this->ftp->login( $this->options['username'], $this->options['password'] ) ) {
 109              $this->errors->add(
 110                  'auth',
 111                  sprintf(
 112                      /* translators: %s: Username. */
 113                      __( 'Username/Password incorrect for %s' ),
 114                      $this->options['username']
 115                  )
 116              );
 117  
 118              return false;
 119          }
 120  
 121          $this->ftp->SetType( FTP_BINARY );
 122          $this->ftp->Passive( true );
 123          $this->ftp->setTimeout( FS_TIMEOUT );
 124  
 125          return true;
 126      }
 127  
 128      /**
 129       * Reads entire file into a string.
 130       *
 131       * @since 2.5.0
 132       *
 133       * @param string $file Name of the file to read.
 134       * @return string|false Read data on success, false if no temporary file could be opened,
 135       *                      or if the file couldn't be retrieved.
 136       */
 137  	public function get_contents( $file ) {
 138          if ( ! $this->exists( $file ) ) {
 139              return false;
 140          }
 141  
 142          $tempfile   = wp_tempnam( $file );
 143          $temphandle = fopen( $tempfile, 'w+' );
 144  
 145          if ( ! $temphandle ) {
 146              unlink( $tempfile );
 147              return false;
 148          }
 149  
 150          mbstring_binary_safe_encoding();
 151  
 152          if ( ! $this->ftp->fget( $temphandle, $file ) ) {
 153              fclose( $temphandle );
 154              unlink( $tempfile );
 155  
 156              reset_mbstring_encoding();
 157  
 158              return ''; // Blank document. File does exist, it's just blank.
 159          }
 160  
 161          reset_mbstring_encoding();
 162  
 163          fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
 164          $contents = '';
 165  
 166          while ( ! feof( $temphandle ) ) {
 167              $contents .= fread( $temphandle, 8 * KB_IN_BYTES );
 168          }
 169  
 170          fclose( $temphandle );
 171          unlink( $tempfile );
 172  
 173          return $contents;
 174      }
 175  
 176      /**
 177       * Reads entire file into an array.
 178       *
 179       * @since 2.5.0
 180       *
 181       * @param string $file Path to the file.
 182       * @return array|false File contents in an array on success, false on failure.
 183       */
 184  	public function get_contents_array( $file ) {
 185          return explode( "\n", $this->get_contents( $file ) );
 186      }
 187  
 188      /**
 189       * Writes a string to a file.
 190       *
 191       * @since 2.5.0
 192       *
 193       * @param string    $file     Remote path to the file where to write the data.
 194       * @param string    $contents The data to write.
 195       * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
 196       *                            Default false.
 197       * @return bool True on success, false on failure.
 198       */
 199  	public function put_contents( $file, $contents, $mode = false ) {
 200          $tempfile   = wp_tempnam( $file );
 201          $temphandle = @fopen( $tempfile, 'w+' );
 202  
 203          if ( ! $temphandle ) {
 204              unlink( $tempfile );
 205              return false;
 206          }
 207  
 208          // The FTP class uses string functions internally during file download/upload.
 209          mbstring_binary_safe_encoding();
 210  
 211          $bytes_written = fwrite( $temphandle, $contents );
 212  
 213          if ( false === $bytes_written || strlen( $contents ) !== $bytes_written ) {
 214              fclose( $temphandle );
 215              unlink( $tempfile );
 216  
 217              reset_mbstring_encoding();
 218  
 219              return false;
 220          }
 221  
 222          fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
 223  
 224          $ret = $this->ftp->fput( $file, $temphandle );
 225  
 226          reset_mbstring_encoding();
 227  
 228          fclose( $temphandle );
 229          unlink( $tempfile );
 230  
 231          $this->chmod( $file, $mode );
 232  
 233          return $ret;
 234      }
 235  
 236      /**
 237       * Gets the current working directory.
 238       *
 239       * @since 2.5.0
 240       *
 241       * @return string|false The current working directory on success, false on failure.
 242       */
 243  	public function cwd() {
 244          $cwd = $this->ftp->pwd();
 245  
 246          if ( $cwd ) {
 247              $cwd = trailingslashit( $cwd );
 248          }
 249  
 250          return $cwd;
 251      }
 252  
 253      /**
 254       * Changes current directory.
 255       *
 256       * @since 2.5.0
 257       *
 258       * @param string $dir The new current directory.
 259       * @return bool True on success, false on failure.
 260       */
 261  	public function chdir( $dir ) {
 262          return $this->ftp->chdir( $dir );
 263      }
 264  
 265      /**
 266       * Changes filesystem permissions.
 267       *
 268       * @since 2.5.0
 269       *
 270       * @param string    $file      Path to the file.
 271       * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
 272       *                             0755 for directories. Default false.
 273       * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
 274       *                             Default false.
 275       * @return bool True on success, false on failure.
 276       */
 277  	public function chmod( $file, $mode = false, $recursive = false ) {
 278          if ( ! $mode ) {
 279              if ( $this->is_file( $file ) ) {
 280                  $mode = FS_CHMOD_FILE;
 281              } elseif ( $this->is_dir( $file ) ) {
 282                  $mode = FS_CHMOD_DIR;
 283              } else {
 284                  return false;
 285              }
 286          }
 287  
 288          // chmod any sub-objects if recursive.
 289          if ( $recursive && $this->is_dir( $file ) ) {
 290              $filelist = $this->dirlist( $file );
 291  
 292              foreach ( (array) $filelist as $filename => $filemeta ) {
 293                  $this->chmod( $file . '/' . $filename, $mode, $recursive );
 294              }
 295          }
 296  
 297          // chmod the file or directory.
 298          return $this->ftp->chmod( $file, $mode );
 299      }
 300  
 301      /**
 302       * Gets the file owner.
 303       *
 304       * @since 2.5.0
 305       *
 306       * @param string $file Path to the file.
 307       * @return string|false Username of the owner on success, false on failure.
 308       */
 309  	public function owner( $file ) {
 310          $dir = $this->dirlist( $file );
 311  
 312          return $dir[ $file ]['owner'];
 313      }
 314  
 315      /**
 316       * Gets the permissions of the specified file or filepath in their octal format.
 317       *
 318       * @since 2.5.0
 319       *
 320       * @param string $file Path to the file.
 321       * @return string Mode of the file (the last 3 digits).
 322       */
 323  	public function getchmod( $file ) {
 324          $dir = $this->dirlist( $file );
 325  
 326          return $dir[ $file ]['permsn'];
 327      }
 328  
 329      /**
 330       * Gets the file's group.
 331       *
 332       * @since 2.5.0
 333       *
 334       * @param string $file Path to the file.
 335       * @return string|false The group on success, false on failure.
 336       */
 337  	public function group( $file ) {
 338          $dir = $this->dirlist( $file );
 339  
 340          return $dir[ $file ]['group'];
 341      }
 342  
 343      /**
 344       * Copies a file.
 345       *
 346       * @since 2.5.0
 347       *
 348       * @param string    $source      Path to the source file.
 349       * @param string    $destination Path to the destination file.
 350       * @param bool      $overwrite   Optional. Whether to overwrite the destination file if it exists.
 351       *                               Default false.
 352       * @param int|false $mode        Optional. The permissions as octal number, usually 0644 for files,
 353       *                               0755 for dirs. Default false.
 354       * @return bool True on success, false on failure.
 355       */
 356  	public function copy( $source, $destination, $overwrite = false, $mode = false ) {
 357          if ( ! $overwrite && $this->exists( $destination ) ) {
 358              return false;
 359          }
 360  
 361          $content = $this->get_contents( $source );
 362  
 363          if ( false === $content ) {
 364              return false;
 365          }
 366  
 367          return $this->put_contents( $destination, $content, $mode );
 368      }
 369  
 370      /**
 371       * Moves a file or directory.
 372       *
 373       * After moving files or directories, OPcache will need to be invalidated.
 374       *
 375       * If moving a directory fails, `copy_dir()` can be used for a recursive copy.
 376       *
 377       * Use `move_dir()` for moving directories with OPcache invalidation and a
 378       * fallback to `copy_dir()`.
 379       *
 380       * @since 2.5.0
 381       *
 382       * @param string $source      Path to the source file or directory.
 383       * @param string $destination Path to the destination file or directory.
 384       * @param bool   $overwrite   Optional. Whether to overwrite the destination if it exists.
 385       *                            Default false.
 386       * @return bool True on success, false on failure.
 387       */
 388  	public function move( $source, $destination, $overwrite = false ) {
 389          return $this->ftp->rename( $source, $destination );
 390      }
 391  
 392      /**
 393       * Deletes a file or directory.
 394       *
 395       * @since 2.5.0
 396       *
 397       * @param string       $file      Path to the file or directory.
 398       * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
 399       *                                Default false.
 400       * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
 401       *                                Default false.
 402       * @return bool True on success, false on failure.
 403       */
 404  	public function delete( $file, $recursive = false, $type = false ) {
 405          if ( empty( $file ) ) {
 406              return false;
 407          }
 408  
 409          if ( 'f' === $type || $this->is_file( $file ) ) {
 410              return $this->ftp->delete( $file );
 411          }
 412  
 413          if ( ! $recursive ) {
 414              return $this->ftp->rmdir( $file );
 415          }
 416  
 417          return $this->ftp->mdel( $file );
 418      }
 419  
 420      /**
 421       * Checks if a file or directory exists.
 422       *
 423       * @since 2.5.0
 424       * @since 6.3.0 Returns false for an empty path.
 425       *
 426       * @param string $path Path to file or directory.
 427       * @return bool Whether $path exists or not.
 428       */
 429  	public function exists( $path ) {
 430          /*
 431           * Check for empty path. If ftp::nlist() receives an empty path,
 432           * it checks the current working directory and may return true.
 433           *
 434           * See https://core.trac.wordpress.org/ticket/33058.
 435           */
 436          if ( '' === $path ) {
 437              return false;
 438          }
 439  
 440          $list = $this->ftp->nlist( $path );
 441  
 442          if ( empty( $list ) && $this->is_dir( $path ) ) {
 443              return true; // File is an empty directory.
 444          }
 445  
 446          return ! empty( $list ); // Empty list = no file, so invert.
 447          // Return $this->ftp->is_exists($file); has issues with ABOR+426 responses on the ncFTPd server.
 448      }
 449  
 450      /**
 451       * Checks if resource is a file.
 452       *
 453       * @since 2.5.0
 454       *
 455       * @param string $file File path.
 456       * @return bool Whether $file is a file.
 457       */
 458  	public function is_file( $file ) {
 459          if ( $this->is_dir( $file ) ) {
 460              return false;
 461          }
 462  
 463          if ( $this->exists( $file ) ) {
 464              return true;
 465          }
 466  
 467          return false;
 468      }
 469  
 470      /**
 471       * Checks if resource is a directory.
 472       *
 473       * @since 2.5.0
 474       *
 475       * @param string $path Directory path.
 476       * @return bool Whether $path is a directory.
 477       */
 478  	public function is_dir( $path ) {
 479          $cwd = $this->cwd();
 480  
 481          if ( $this->chdir( $path ) ) {
 482              $this->chdir( $cwd );
 483              return true;
 484          }
 485  
 486          return false;
 487      }
 488  
 489      /**
 490       * Checks if a file is readable.
 491       *
 492       * @since 2.5.0
 493       *
 494       * @param string $file Path to file.
 495       * @return bool Whether $file is readable.
 496       */
 497  	public function is_readable( $file ) {
 498          return true;
 499      }
 500  
 501      /**
 502       * Checks if a file or directory is writable.
 503       *
 504       * @since 2.5.0
 505       *
 506       * @param string $path Path to file or directory.
 507       * @return bool Whether $path is writable.
 508       */
 509  	public function is_writable( $path ) {
 510          return true;
 511      }
 512  
 513      /**
 514       * Gets the file's last access time.
 515       *
 516       * @since 2.5.0
 517       *
 518       * @param string $file Path to file.
 519       * @return int|false Unix timestamp representing last access time, false on failure.
 520       */
 521  	public function atime( $file ) {
 522          return false;
 523      }
 524  
 525      /**
 526       * Gets the file modification time.
 527       *
 528       * @since 2.5.0
 529       *
 530       * @param string $file Path to file.
 531       * @return int|false Unix timestamp representing modification time, false on failure.
 532       */
 533  	public function mtime( $file ) {
 534          return $this->ftp->mdtm( $file );
 535      }
 536  
 537      /**
 538       * Gets the file size (in bytes).
 539       *
 540       * @since 2.5.0
 541       *
 542       * @param string $file Path to file.
 543       * @return int|false Size of the file in bytes on success, false on failure.
 544       */
 545  	public function size( $file ) {
 546          return $this->ftp->filesize( $file );
 547      }
 548  
 549      /**
 550       * Sets the access and modification times of a file.
 551       *
 552       * Note: If $file doesn't exist, it will be created.
 553       *
 554       * @since 2.5.0
 555       *
 556       * @param string $file  Path to file.
 557       * @param int    $time  Optional. Modified time to set for file.
 558       *                      Default 0.
 559       * @param int    $atime Optional. Access time to set for file.
 560       *                      Default 0.
 561       * @return bool True on success, false on failure.
 562       */
 563  	public function touch( $file, $time = 0, $atime = 0 ) {
 564          return false;
 565      }
 566  
 567      /**
 568       * Creates a directory.
 569       *
 570       * @since 2.5.0
 571       *
 572       * @param string           $path  Path for new directory.
 573       * @param int|false        $chmod Optional. The permissions as octal number (or false to skip chmod).
 574       *                                Default false.
 575       * @param string|int|false $chown Optional. A user name or number (or false to skip chown).
 576       *                                Default false.
 577       * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
 578       *                                Default false.
 579       * @return bool True on success, false on failure.
 580       */
 581  	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
 582          $path = untrailingslashit( $path );
 583  
 584          if ( empty( $path ) ) {
 585              return false;
 586          }
 587  
 588          if ( ! $this->ftp->mkdir( $path ) ) {
 589              return false;
 590          }
 591  
 592          if ( ! $chmod ) {
 593              $chmod = FS_CHMOD_DIR;
 594          }
 595  
 596          $this->chmod( $path, $chmod );
 597  
 598          return true;
 599      }
 600  
 601      /**
 602       * Deletes a directory.
 603       *
 604       * @since 2.5.0
 605       *
 606       * @param string $path      Path to directory.
 607       * @param bool   $recursive Optional. Whether to recursively remove files/directories.
 608       *                          Default false.
 609       * @return bool True on success, false on failure.
 610       */
 611  	public function rmdir( $path, $recursive = false ) {
 612          return $this->delete( $path, $recursive );
 613      }
 614  
 615      /**
 616       * Gets details for files in a directory or a specific file.
 617       *
 618       * @since 2.5.0
 619       *
 620       * @param string $path           Path to directory or file.
 621       * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
 622       *                               Default true.
 623       * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
 624       *                               Default false.
 625       * @return array|false {
 626       *     Array of arrays containing file information. False if unable to list directory contents.
 627       *
 628       *     @type array ...$0 {
 629       *         Array of file information. Note that some elements may not be available on all filesystems.
 630       *
 631       *         @type string           $name        Name of the file or directory.
 632       *         @type string           $perms       *nix representation of permissions.
 633       *         @type string           $permsn      Octal representation of permissions.
 634       *         @type int|string|false $number      File number. May be a numeric string. False if not available.
 635       *         @type string|false     $owner       Owner name or ID, or false if not available.
 636       *         @type string|false     $group       File permissions group, or false if not available.
 637       *         @type int|string|false $size        Size of file in bytes. May be a numeric string.
 638       *                                             False if not available.
 639       *         @type int|string|false $lastmodunix Last modified unix timestamp. May be a numeric string.
 640       *                                             False if not available.
 641       *         @type string|false     $lastmod     Last modified month (3 letters) and day (without leading 0), or
 642       *                                             false if not available.
 643       *         @type string|false     $time        Last modified time, or false if not available.
 644       *         @type string           $type        Type of resource. 'f' for file, 'd' for directory, 'l' for link.
 645       *         @type array|false      $files       If a directory and `$recursive` is true, contains another array of
 646       *                                             files. False if unable to list directory contents.
 647       *     }
 648       * }
 649       */
 650  	public function dirlist( $path = '.', $include_hidden = true, $recursive = false ) {
 651          if ( $this->is_file( $path ) ) {
 652              $limit_file = basename( $path );
 653              $path       = dirname( $path ) . '/';
 654          } else {
 655              $limit_file = false;
 656          }
 657  
 658          mbstring_binary_safe_encoding();
 659  
 660          $list = $this->ftp->dirlist( $path );
 661  
 662          if ( empty( $list ) && ! $this->exists( $path ) ) {
 663  
 664              reset_mbstring_encoding();
 665  
 666              return false;
 667          }
 668  
 669          $path = trailingslashit( $path );
 670          $ret  = array();
 671  
 672          foreach ( $list as $struc ) {
 673  
 674              if ( '.' === $struc['name'] || '..' === $struc['name'] ) {
 675                  continue;
 676              }
 677  
 678              if ( ! $include_hidden && '.' === $struc['name'][0] ) {
 679                  continue;
 680              }
 681  
 682              if ( $limit_file && $struc['name'] !== $limit_file ) {
 683                  continue;
 684              }
 685  
 686              if ( 'd' === $struc['type'] ) {
 687                  if ( $recursive ) {
 688                      $struc['files'] = $this->dirlist( $path . $struc['name'], $include_hidden, $recursive );
 689                  } else {
 690                      $struc['files'] = array();
 691                  }
 692              }
 693  
 694              // Replace symlinks formatted as "source -> target" with just the source name.
 695              if ( $struc['islink'] ) {
 696                  $struc['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $struc['name'] );
 697              }
 698  
 699              // Add the octal representation of the file permissions.
 700              $struc['permsn'] = $this->getnumchmodfromh( $struc['perms'] );
 701  
 702              $ret[ $struc['name'] ] = $struc;
 703          }
 704  
 705          reset_mbstring_encoding();
 706  
 707          return $ret;
 708      }
 709  
 710      /**
 711       * Destructor.
 712       *
 713       * @since 2.5.0
 714       */
 715  	public function __destruct() {
 716          $this->ftp->quit();
 717      }
 718  }


Generated : Sat Dec 21 08:20:01 2024 Cross-referenced by PHPXref