[ Index ]

PHP Cross Reference of WordPress

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 ( ! include_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.
 372       *
 373       * @since 2.5.0
 374       *
 375       * @param string $source      Path to the source file.
 376       * @param string $destination Path to the destination file.
 377       * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
 378       *                            Default false.
 379       * @return bool True on success, false on failure.
 380       */
 381  	public function move( $source, $destination, $overwrite = false ) {
 382          return $this->ftp->rename( $source, $destination );
 383      }
 384  
 385      /**
 386       * Deletes a file or directory.
 387       *
 388       * @since 2.5.0
 389       *
 390       * @param string       $file      Path to the file or directory.
 391       * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
 392       *                                Default false.
 393       * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
 394       *                                Default false.
 395       * @return bool True on success, false on failure.
 396       */
 397  	public function delete( $file, $recursive = false, $type = false ) {
 398          if ( empty( $file ) ) {
 399              return false;
 400          }
 401  
 402          if ( 'f' === $type || $this->is_file( $file ) ) {
 403              return $this->ftp->delete( $file );
 404          }
 405  
 406          if ( ! $recursive ) {
 407              return $this->ftp->rmdir( $file );
 408          }
 409  
 410          return $this->ftp->mdel( $file );
 411      }
 412  
 413      /**
 414       * Checks if a file or directory exists.
 415       *
 416       * @since 2.5.0
 417       *
 418       * @param string $file Path to file or directory.
 419       * @return bool Whether $file exists or not.
 420       */
 421  	public function exists( $file ) {
 422          $list = $this->ftp->nlist( $file );
 423  
 424          if ( empty( $list ) && $this->is_dir( $file ) ) {
 425              return true; // File is an empty directory.
 426          }
 427  
 428          return ! empty( $list ); // Empty list = no file, so invert.
 429          // Return $this->ftp->is_exists($file); has issues with ABOR+426 responses on the ncFTPd server.
 430      }
 431  
 432      /**
 433       * Checks if resource is a file.
 434       *
 435       * @since 2.5.0
 436       *
 437       * @param string $file File path.
 438       * @return bool Whether $file is a file.
 439       */
 440  	public function is_file( $file ) {
 441          if ( $this->is_dir( $file ) ) {
 442              return false;
 443          }
 444  
 445          if ( $this->exists( $file ) ) {
 446              return true;
 447          }
 448  
 449          return false;
 450      }
 451  
 452      /**
 453       * Checks if resource is a directory.
 454       *
 455       * @since 2.5.0
 456       *
 457       * @param string $path Directory path.
 458       * @return bool Whether $path is a directory.
 459       */
 460  	public function is_dir( $path ) {
 461          $cwd = $this->cwd();
 462  
 463          if ( $this->chdir( $path ) ) {
 464              $this->chdir( $cwd );
 465              return true;
 466          }
 467  
 468          return false;
 469      }
 470  
 471      /**
 472       * Checks if a file is readable.
 473       *
 474       * @since 2.5.0
 475       *
 476       * @param string $file Path to file.
 477       * @return bool Whether $file is readable.
 478       */
 479  	public function is_readable( $file ) {
 480          return true;
 481      }
 482  
 483      /**
 484       * Checks if a file or directory is writable.
 485       *
 486       * @since 2.5.0
 487       *
 488       * @param string $file Path to file or directory.
 489       * @return bool Whether $file is writable.
 490       */
 491  	public function is_writable( $file ) {
 492          return true;
 493      }
 494  
 495      /**
 496       * Gets the file's last access time.
 497       *
 498       * @since 2.5.0
 499       *
 500       * @param string $file Path to file.
 501       * @return int|false Unix timestamp representing last access time, false on failure.
 502       */
 503  	public function atime( $file ) {
 504          return false;
 505      }
 506  
 507      /**
 508       * Gets the file modification time.
 509       *
 510       * @since 2.5.0
 511       *
 512       * @param string $file Path to file.
 513       * @return int|false Unix timestamp representing modification time, false on failure.
 514       */
 515  	public function mtime( $file ) {
 516          return $this->ftp->mdtm( $file );
 517      }
 518  
 519      /**
 520       * Gets the file size (in bytes).
 521       *
 522       * @since 2.5.0
 523       *
 524       * @param string $file Path to file.
 525       * @return int|false Size of the file in bytes on success, false on failure.
 526       */
 527  	public function size( $file ) {
 528          return $this->ftp->filesize( $file );
 529      }
 530  
 531      /**
 532       * Sets the access and modification times of a file.
 533       *
 534       * Note: If $file doesn't exist, it will be created.
 535       *
 536       * @since 2.5.0
 537       *
 538       * @param string $file  Path to file.
 539       * @param int    $time  Optional. Modified time to set for file.
 540       *                      Default 0.
 541       * @param int    $atime Optional. Access time to set for file.
 542       *                      Default 0.
 543       * @return bool True on success, false on failure.
 544       */
 545  	public function touch( $file, $time = 0, $atime = 0 ) {
 546          return false;
 547      }
 548  
 549      /**
 550       * Creates a directory.
 551       *
 552       * @since 2.5.0
 553       *
 554       * @param string           $path  Path for new directory.
 555       * @param int|false        $chmod Optional. The permissions as octal number (or false to skip chmod).
 556       *                                Default false.
 557       * @param string|int|false $chown Optional. A user name or number (or false to skip chown).
 558       *                                Default false.
 559       * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
 560       *                                Default false.
 561       * @return bool True on success, false on failure.
 562       */
 563  	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
 564          $path = untrailingslashit( $path );
 565  
 566          if ( empty( $path ) ) {
 567              return false;
 568          }
 569  
 570          if ( ! $this->ftp->mkdir( $path ) ) {
 571              return false;
 572          }
 573  
 574          if ( ! $chmod ) {
 575              $chmod = FS_CHMOD_DIR;
 576          }
 577  
 578          $this->chmod( $path, $chmod );
 579  
 580          return true;
 581      }
 582  
 583      /**
 584       * Deletes a directory.
 585       *
 586       * @since 2.5.0
 587       *
 588       * @param string $path      Path to directory.
 589       * @param bool   $recursive Optional. Whether to recursively remove files/directories.
 590       *                          Default false.
 591       * @return bool True on success, false on failure.
 592       */
 593  	public function rmdir( $path, $recursive = false ) {
 594          return $this->delete( $path, $recursive );
 595      }
 596  
 597      /**
 598       * Gets details for files in a directory or a specific file.
 599       *
 600       * @since 2.5.0
 601       *
 602       * @param string $path           Path to directory or file.
 603       * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
 604       *                               Default true.
 605       * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
 606       *                               Default false.
 607       * @return array|false {
 608       *     Array of files. False if unable to list directory contents.
 609       *
 610       *     @type string $name        Name of the file or directory.
 611       *     @type string $perms       *nix representation of permissions.
 612       *     @type string $permsn      Octal representation of permissions.
 613       *     @type string $owner       Owner name or ID.
 614       *     @type int    $size        Size of file in bytes.
 615       *     @type int    $lastmodunix Last modified unix timestamp.
 616       *     @type mixed  $lastmod     Last modified month (3 letter) and day (without leading 0).
 617       *     @type int    $time        Last modified time.
 618       *     @type string $type        Type of resource. 'f' for file, 'd' for directory.
 619       *     @type mixed  $files       If a directory and `$recursive` is true, contains another array of files.
 620       * }
 621       */
 622  	public function dirlist( $path = '.', $include_hidden = true, $recursive = false ) {
 623          if ( $this->is_file( $path ) ) {
 624              $limit_file = basename( $path );
 625              $path       = dirname( $path ) . '/';
 626          } else {
 627              $limit_file = false;
 628          }
 629  
 630          mbstring_binary_safe_encoding();
 631  
 632          $list = $this->ftp->dirlist( $path );
 633  
 634          if ( empty( $list ) && ! $this->exists( $path ) ) {
 635  
 636              reset_mbstring_encoding();
 637  
 638              return false;
 639          }
 640  
 641          $ret = array();
 642  
 643          foreach ( $list as $struc ) {
 644  
 645              if ( '.' === $struc['name'] || '..' === $struc['name'] ) {
 646                  continue;
 647              }
 648  
 649              if ( ! $include_hidden && '.' === $struc['name'][0] ) {
 650                  continue;
 651              }
 652  
 653              if ( $limit_file && $struc['name'] !== $limit_file ) {
 654                  continue;
 655              }
 656  
 657              if ( 'd' === $struc['type'] ) {
 658                  if ( $recursive ) {
 659                      $struc['files'] = $this->dirlist( $path . '/' . $struc['name'], $include_hidden, $recursive );
 660                  } else {
 661                      $struc['files'] = array();
 662                  }
 663              }
 664  
 665              // Replace symlinks formatted as "source -> target" with just the source name.
 666              if ( $struc['islink'] ) {
 667                  $struc['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $struc['name'] );
 668              }
 669  
 670              // Add the octal representation of the file permissions.
 671              $struc['permsn'] = $this->getnumchmodfromh( $struc['perms'] );
 672  
 673              $ret[ $struc['name'] ] = $struc;
 674          }
 675  
 676          reset_mbstring_encoding();
 677  
 678          return $ret;
 679      }
 680  
 681      /**
 682       * Destructor.
 683       *
 684       * @since 2.5.0
 685       */
 686  	public function __destruct() {
 687          $this->ftp->quit();
 688      }
 689  }


Generated: Tue Mar 19 01:00:02 2024 Cross-referenced by PHPXref 0.7.1