wp/wp-admin/includes/class-wp-filesystem-ftpsockets.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
    31 	public function __construct( $opt = '' ) {
    31 	public function __construct( $opt = '' ) {
    32 		$this->method = 'ftpsockets';
    32 		$this->method = 'ftpsockets';
    33 		$this->errors = new WP_Error();
    33 		$this->errors = new WP_Error();
    34 
    34 
    35 		// Check if possible to use ftp functions.
    35 		// Check if possible to use ftp functions.
    36 		if ( ! @include_once( ABSPATH . 'wp-admin/includes/class-ftp.php' ) ) {
    36 		if ( ! include_once ABSPATH . 'wp-admin/includes/class-ftp.php' ) {
    37 			return;
    37 			return;
    38 		}
    38 		}
       
    39 
    39 		$this->ftp = new ftp();
    40 		$this->ftp = new ftp();
    40 
    41 
    41 		if ( empty( $opt['port'] ) ) {
    42 		if ( empty( $opt['port'] ) ) {
    42 			$this->options['port'] = 21;
    43 			$this->options['port'] = 21;
    43 		} else {
    44 		} else {
    79 		$this->ftp->setTimeout( FS_CONNECT_TIMEOUT );
    80 		$this->ftp->setTimeout( FS_CONNECT_TIMEOUT );
    80 
    81 
    81 		if ( ! $this->ftp->SetServer( $this->options['hostname'], $this->options['port'] ) ) {
    82 		if ( ! $this->ftp->SetServer( $this->options['hostname'], $this->options['port'] ) ) {
    82 			$this->errors->add(
    83 			$this->errors->add(
    83 				'connect',
    84 				'connect',
    84 				/* translators: %s: hostname:port */
       
    85 				sprintf(
    85 				sprintf(
       
    86 					/* translators: %s: hostname:port */
    86 					__( 'Failed to connect to FTP Server %s' ),
    87 					__( 'Failed to connect to FTP Server %s' ),
    87 					$this->options['hostname'] . ':' . $this->options['port']
    88 					$this->options['hostname'] . ':' . $this->options['port']
    88 				)
    89 				)
    89 			);
    90 			);
       
    91 
    90 			return false;
    92 			return false;
    91 		}
    93 		}
    92 
    94 
    93 		if ( ! $this->ftp->connect() ) {
    95 		if ( ! $this->ftp->connect() ) {
    94 			$this->errors->add(
    96 			$this->errors->add(
    95 				'connect',
    97 				'connect',
    96 				/* translators: %s: hostname:port */
       
    97 				sprintf(
    98 				sprintf(
       
    99 					/* translators: %s: hostname:port */
    98 					__( 'Failed to connect to FTP Server %s' ),
   100 					__( 'Failed to connect to FTP Server %s' ),
    99 					$this->options['hostname'] . ':' . $this->options['port']
   101 					$this->options['hostname'] . ':' . $this->options['port']
   100 				)
   102 				)
   101 			);
   103 			);
       
   104 
   102 			return false;
   105 			return false;
   103 		}
   106 		}
   104 
   107 
   105 		if ( ! $this->ftp->login( $this->options['username'], $this->options['password'] ) ) {
   108 		if ( ! $this->ftp->login( $this->options['username'], $this->options['password'] ) ) {
   106 			$this->errors->add(
   109 			$this->errors->add(
   107 				'auth',
   110 				'auth',
   108 				/* translators: %s: username */
       
   109 				sprintf(
   111 				sprintf(
       
   112 					/* translators: %s: Username. */
   110 					__( 'Username/Password incorrect for %s' ),
   113 					__( 'Username/Password incorrect for %s' ),
   111 					$this->options['username']
   114 					$this->options['username']
   112 				)
   115 				)
   113 			);
   116 			);
       
   117 
   114 			return false;
   118 			return false;
   115 		}
   119 		}
   116 
   120 
   117 		$this->ftp->SetType( FTP_BINARY );
   121 		$this->ftp->SetType( FTP_BINARY );
   118 		$this->ftp->Passive( true );
   122 		$this->ftp->Passive( true );
   119 		$this->ftp->setTimeout( FS_TIMEOUT );
   123 		$this->ftp->setTimeout( FS_TIMEOUT );
       
   124 
   120 		return true;
   125 		return true;
   121 	}
   126 	}
   122 
   127 
   123 	/**
   128 	/**
   124 	 * Reads entire file into a string.
   129 	 * Reads entire file into a string.
   132 	public function get_contents( $file ) {
   137 	public function get_contents( $file ) {
   133 		if ( ! $this->exists( $file ) ) {
   138 		if ( ! $this->exists( $file ) ) {
   134 			return false;
   139 			return false;
   135 		}
   140 		}
   136 
   141 
   137 		$temp = wp_tempnam( $file );
   142 		$tempfile   = wp_tempnam( $file );
   138 
   143 		$temphandle = fopen( $tempfile, 'w+' );
   139 		if ( ! $temphandle = fopen( $temp, 'w+' ) ) {
   144 
   140 			unlink( $temp );
   145 		if ( ! $temphandle ) {
       
   146 			unlink( $tempfile );
   141 			return false;
   147 			return false;
   142 		}
   148 		}
   143 
   149 
   144 		mbstring_binary_safe_encoding();
   150 		mbstring_binary_safe_encoding();
   145 
   151 
   146 		if ( ! $this->ftp->fget( $temphandle, $file ) ) {
   152 		if ( ! $this->ftp->fget( $temphandle, $file ) ) {
   147 			fclose( $temphandle );
   153 			fclose( $temphandle );
   148 			unlink( $temp );
   154 			unlink( $tempfile );
   149 
   155 
   150 			reset_mbstring_encoding();
   156 			reset_mbstring_encoding();
   151 
   157 
   152 			return ''; // Blank document, File does exist, It's just blank.
   158 			return ''; // Blank document. File does exist, it's just blank.
   153 		}
   159 		}
   154 
   160 
   155 		reset_mbstring_encoding();
   161 		reset_mbstring_encoding();
   156 
   162 
   157 		fseek( $temphandle, 0 ); // Skip back to the start of the file being written to
   163 		fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
   158 		$contents = '';
   164 		$contents = '';
   159 
   165 
   160 		while ( ! feof( $temphandle ) ) {
   166 		while ( ! feof( $temphandle ) ) {
   161 			$contents .= fread( $temphandle, 8 * KB_IN_BYTES );
   167 			$contents .= fread( $temphandle, 8 * KB_IN_BYTES );
   162 		}
   168 		}
   163 
   169 
   164 		fclose( $temphandle );
   170 		fclose( $temphandle );
   165 		unlink( $temp );
   171 		unlink( $tempfile );
       
   172 
   166 		return $contents;
   173 		return $contents;
   167 	}
   174 	}
   168 
   175 
   169 	/**
   176 	/**
   170 	 * Reads entire file into an array.
   177 	 * Reads entire file into an array.
   188 	 * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
   195 	 * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
   189 	 *                            Default false.
   196 	 *                            Default false.
   190 	 * @return bool True on success, false on failure.
   197 	 * @return bool True on success, false on failure.
   191 	 */
   198 	 */
   192 	public function put_contents( $file, $contents, $mode = false ) {
   199 	public function put_contents( $file, $contents, $mode = false ) {
   193 		$temp = wp_tempnam( $file );
   200 		$tempfile   = wp_tempnam( $file );
   194 		if ( ! $temphandle = @fopen( $temp, 'w+' ) ) {
   201 		$temphandle = @fopen( $tempfile, 'w+' );
   195 			unlink( $temp );
   202 
   196 			return false;
   203 		if ( ! $temphandle ) {
   197 		}
   204 			unlink( $tempfile );
   198 
   205 			return false;
   199 		// The FTP class uses string functions internally during file download/upload
   206 		}
       
   207 
       
   208 		// The FTP class uses string functions internally during file download/upload.
   200 		mbstring_binary_safe_encoding();
   209 		mbstring_binary_safe_encoding();
   201 
   210 
   202 		$bytes_written = fwrite( $temphandle, $contents );
   211 		$bytes_written = fwrite( $temphandle, $contents );
   203 		if ( false === $bytes_written || $bytes_written != strlen( $contents ) ) {
   212 
       
   213 		if ( false === $bytes_written || strlen( $contents ) != $bytes_written ) {
   204 			fclose( $temphandle );
   214 			fclose( $temphandle );
   205 			unlink( $temp );
   215 			unlink( $tempfile );
   206 
   216 
   207 			reset_mbstring_encoding();
   217 			reset_mbstring_encoding();
   208 
   218 
   209 			return false;
   219 			return false;
   210 		}
   220 		}
   211 
   221 
   212 		fseek( $temphandle, 0 ); // Skip back to the start of the file being written to
   222 		fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
   213 
   223 
   214 		$ret = $this->ftp->fput( $file, $temphandle );
   224 		$ret = $this->ftp->fput( $file, $temphandle );
   215 
   225 
   216 		reset_mbstring_encoding();
   226 		reset_mbstring_encoding();
   217 
   227 
   218 		fclose( $temphandle );
   228 		fclose( $temphandle );
   219 		unlink( $temp );
   229 		unlink( $tempfile );
   220 
   230 
   221 		$this->chmod( $file, $mode );
   231 		$this->chmod( $file, $mode );
   222 
   232 
   223 		return $ret;
   233 		return $ret;
   224 	}
   234 	}
   230 	 *
   240 	 *
   231 	 * @return string|false The current working directory on success, false on failure.
   241 	 * @return string|false The current working directory on success, false on failure.
   232 	 */
   242 	 */
   233 	public function cwd() {
   243 	public function cwd() {
   234 		$cwd = $this->ftp->pwd();
   244 		$cwd = $this->ftp->pwd();
       
   245 
   235 		if ( $cwd ) {
   246 		if ( $cwd ) {
   236 			$cwd = trailingslashit( $cwd );
   247 			$cwd = trailingslashit( $cwd );
   237 		}
   248 		}
       
   249 
   238 		return $cwd;
   250 		return $cwd;
   239 	}
   251 	}
   240 
   252 
   241 	/**
   253 	/**
   242 	 * Changes current directory.
   254 	 * Changes current directory.
   256 	 * @since 2.5.0
   268 	 * @since 2.5.0
   257 	 *
   269 	 *
   258 	 * @param string    $file      Path to the file.
   270 	 * @param string    $file      Path to the file.
   259 	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
   271 	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
   260 	 *                             0755 for directories. Default false.
   272 	 *                             0755 for directories. Default false.
   261 	 * @param bool      $recursive Optional. If set to true, changes file group recursively.
   273 	 * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
   262 	 *                             Default false.
   274 	 *                             Default false.
   263 	 * @return bool True on success, false on failure.
   275 	 * @return bool True on success, false on failure.
   264 	 */
   276 	 */
   265 	public function chmod( $file, $mode = false, $recursive = false ) {
   277 	public function chmod( $file, $mode = false, $recursive = false ) {
   266 		if ( ! $mode ) {
   278 		if ( ! $mode ) {
   274 		}
   286 		}
   275 
   287 
   276 		// chmod any sub-objects if recursive.
   288 		// chmod any sub-objects if recursive.
   277 		if ( $recursive && $this->is_dir( $file ) ) {
   289 		if ( $recursive && $this->is_dir( $file ) ) {
   278 			$filelist = $this->dirlist( $file );
   290 			$filelist = $this->dirlist( $file );
       
   291 
   279 			foreach ( (array) $filelist as $filename => $filemeta ) {
   292 			foreach ( (array) $filelist as $filename => $filemeta ) {
   280 				$this->chmod( $file . '/' . $filename, $mode, $recursive );
   293 				$this->chmod( $file . '/' . $filename, $mode, $recursive );
   281 			}
   294 			}
   282 		}
   295 		}
   283 
   296 
   284 		// chmod the file or directory
   297 		// chmod the file or directory.
   285 		return $this->ftp->chmod( $file, $mode );
   298 		return $this->ftp->chmod( $file, $mode );
   286 	}
   299 	}
   287 
   300 
   288 	/**
   301 	/**
   289 	 * Gets the file owner.
   302 	 * Gets the file owner.
   293 	 * @param string $file Path to the file.
   306 	 * @param string $file Path to the file.
   294 	 * @return string|false Username of the owner on success, false on failure.
   307 	 * @return string|false Username of the owner on success, false on failure.
   295 	 */
   308 	 */
   296 	public function owner( $file ) {
   309 	public function owner( $file ) {
   297 		$dir = $this->dirlist( $file );
   310 		$dir = $this->dirlist( $file );
       
   311 
   298 		return $dir[ $file ]['owner'];
   312 		return $dir[ $file ]['owner'];
   299 	}
   313 	}
   300 
   314 
   301 	/**
   315 	/**
   302 	 * Gets the permissions of the specified file or filepath in their octal format.
   316 	 * Gets the permissions of the specified file or filepath in their octal format.
   306 	 * @param string $file Path to the file.
   320 	 * @param string $file Path to the file.
   307 	 * @return string Mode of the file (the last 3 digits).
   321 	 * @return string Mode of the file (the last 3 digits).
   308 	 */
   322 	 */
   309 	public function getchmod( $file ) {
   323 	public function getchmod( $file ) {
   310 		$dir = $this->dirlist( $file );
   324 		$dir = $this->dirlist( $file );
       
   325 
   311 		return $dir[ $file ]['permsn'];
   326 		return $dir[ $file ]['permsn'];
   312 	}
   327 	}
   313 
   328 
   314 	/**
   329 	/**
   315 	 * Gets the file's group.
   330 	 * Gets the file's group.
   319 	 * @param string $file Path to the file.
   334 	 * @param string $file Path to the file.
   320 	 * @return string|false The group on success, false on failure.
   335 	 * @return string|false The group on success, false on failure.
   321 	 */
   336 	 */
   322 	public function group( $file ) {
   337 	public function group( $file ) {
   323 		$dir = $this->dirlist( $file );
   338 		$dir = $this->dirlist( $file );
       
   339 
   324 		return $dir[ $file ]['group'];
   340 		return $dir[ $file ]['group'];
   325 	}
   341 	}
   326 
   342 
   327 	/**
   343 	/**
   328 	 * Copies a file.
   344 	 * Copies a file.
   341 		if ( ! $overwrite && $this->exists( $destination ) ) {
   357 		if ( ! $overwrite && $this->exists( $destination ) ) {
   342 			return false;
   358 			return false;
   343 		}
   359 		}
   344 
   360 
   345 		$content = $this->get_contents( $source );
   361 		$content = $this->get_contents( $source );
       
   362 
   346 		if ( false === $content ) {
   363 		if ( false === $content ) {
   347 			return false;
   364 			return false;
   348 		}
   365 		}
   349 
   366 
   350 		return $this->put_contents( $destination, $content, $mode );
   367 		return $this->put_contents( $destination, $content, $mode );
   369 	 * Deletes a file or directory.
   386 	 * Deletes a file or directory.
   370 	 *
   387 	 *
   371 	 * @since 2.5.0
   388 	 * @since 2.5.0
   372 	 *
   389 	 *
   373 	 * @param string       $file      Path to the file or directory.
   390 	 * @param string       $file      Path to the file or directory.
   374 	 * @param bool         $recursive Optional. If set to true, changes file group recursively.
   391 	 * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
   375 	 *                                Default false.
   392 	 *                                Default false.
   376 	 * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
   393 	 * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
   377 	 *                                Default false.
   394 	 *                                Default false.
   378 	 * @return bool True on success, false on failure.
   395 	 * @return bool True on success, false on failure.
   379 	 */
   396 	 */
   380 	public function delete( $file, $recursive = false, $type = false ) {
   397 	public function delete( $file, $recursive = false, $type = false ) {
   381 		if ( empty( $file ) ) {
   398 		if ( empty( $file ) ) {
   382 			return false;
   399 			return false;
   383 		}
   400 		}
   384 		if ( 'f' == $type || $this->is_file( $file ) ) {
   401 
       
   402 		if ( 'f' === $type || $this->is_file( $file ) ) {
   385 			return $this->ftp->delete( $file );
   403 			return $this->ftp->delete( $file );
   386 		}
   404 		}
       
   405 
   387 		if ( ! $recursive ) {
   406 		if ( ! $recursive ) {
   388 			return $this->ftp->rmdir( $file );
   407 			return $this->ftp->rmdir( $file );
   389 		}
   408 		}
   390 
   409 
   391 		return $this->ftp->mdel( $file );
   410 		return $this->ftp->mdel( $file );
   404 
   423 
   405 		if ( empty( $list ) && $this->is_dir( $file ) ) {
   424 		if ( empty( $list ) && $this->is_dir( $file ) ) {
   406 			return true; // File is an empty directory.
   425 			return true; // File is an empty directory.
   407 		}
   426 		}
   408 
   427 
   409 		return ! empty( $list ); //empty list = no file, so invert.
   428 		return ! empty( $list ); // Empty list = no file, so invert.
   410 		// Return $this->ftp->is_exists($file); has issues with ABOR+426 responses on the ncFTPd server.
   429 		// Return $this->ftp->is_exists($file); has issues with ABOR+426 responses on the ncFTPd server.
   411 	}
   430 	}
   412 
   431 
   413 	/**
   432 	/**
   414 	 * Checks if resource is a file.
   433 	 * Checks if resource is a file.
   420 	 */
   439 	 */
   421 	public function is_file( $file ) {
   440 	public function is_file( $file ) {
   422 		if ( $this->is_dir( $file ) ) {
   441 		if ( $this->is_dir( $file ) ) {
   423 			return false;
   442 			return false;
   424 		}
   443 		}
       
   444 
   425 		if ( $this->exists( $file ) ) {
   445 		if ( $this->exists( $file ) ) {
   426 			return true;
   446 			return true;
   427 		}
   447 		}
       
   448 
   428 		return false;
   449 		return false;
   429 	}
   450 	}
   430 
   451 
   431 	/**
   452 	/**
   432 	 * Checks if resource is a directory.
   453 	 * Checks if resource is a directory.
   436 	 * @param string $path Directory path.
   457 	 * @param string $path Directory path.
   437 	 * @return bool Whether $path is a directory.
   458 	 * @return bool Whether $path is a directory.
   438 	 */
   459 	 */
   439 	public function is_dir( $path ) {
   460 	public function is_dir( $path ) {
   440 		$cwd = $this->cwd();
   461 		$cwd = $this->cwd();
       
   462 
   441 		if ( $this->chdir( $path ) ) {
   463 		if ( $this->chdir( $path ) ) {
   442 			$this->chdir( $cwd );
   464 			$this->chdir( $cwd );
   443 			return true;
   465 			return true;
   444 		}
   466 		}
       
   467 
   445 		return false;
   468 		return false;
   446 	}
   469 	}
   447 
   470 
   448 	/**
   471 	/**
   449 	 * Checks if a file is readable.
   472 	 * Checks if a file is readable.
   537 	 *                          Default false.
   560 	 *                          Default false.
   538 	 * @return bool True on success, false on failure.
   561 	 * @return bool True on success, false on failure.
   539 	 */
   562 	 */
   540 	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
   563 	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
   541 		$path = untrailingslashit( $path );
   564 		$path = untrailingslashit( $path );
       
   565 
   542 		if ( empty( $path ) ) {
   566 		if ( empty( $path ) ) {
   543 			return false;
   567 			return false;
   544 		}
   568 		}
   545 
   569 
   546 		if ( ! $this->ftp->mkdir( $path ) ) {
   570 		if ( ! $this->ftp->mkdir( $path ) ) {
   547 			return false;
   571 			return false;
   548 		}
   572 		}
       
   573 
   549 		if ( ! $chmod ) {
   574 		if ( ! $chmod ) {
   550 			$chmod = FS_CHMOD_DIR;
   575 			$chmod = FS_CHMOD_DIR;
   551 		}
   576 		}
       
   577 
   552 		$this->chmod( $path, $chmod );
   578 		$this->chmod( $path, $chmod );
       
   579 
   553 		return true;
   580 		return true;
   554 	}
   581 	}
   555 
   582 
   556 	/**
   583 	/**
   557 	 * Deletes a directory.
   584 	 * Deletes a directory.
   601 		}
   628 		}
   602 
   629 
   603 		mbstring_binary_safe_encoding();
   630 		mbstring_binary_safe_encoding();
   604 
   631 
   605 		$list = $this->ftp->dirlist( $path );
   632 		$list = $this->ftp->dirlist( $path );
       
   633 
   606 		if ( empty( $list ) && ! $this->exists( $path ) ) {
   634 		if ( empty( $list ) && ! $this->exists( $path ) ) {
   607 
   635 
   608 			reset_mbstring_encoding();
   636 			reset_mbstring_encoding();
   609 
   637 
   610 			return false;
   638 			return false;
   611 		}
   639 		}
   612 
   640 
   613 		$ret = array();
   641 		$ret = array();
       
   642 
   614 		foreach ( $list as $struc ) {
   643 		foreach ( $list as $struc ) {
   615 
   644 
   616 			if ( '.' == $struc['name'] || '..' == $struc['name'] ) {
   645 			if ( '.' === $struc['name'] || '..' === $struc['name'] ) {
   617 				continue;
   646 				continue;
   618 			}
   647 			}
   619 
   648 
   620 			if ( ! $include_hidden && '.' == $struc['name'][0] ) {
   649 			if ( ! $include_hidden && '.' === $struc['name'][0] ) {
   621 				continue;
   650 				continue;
   622 			}
   651 			}
   623 
   652 
   624 			if ( $limit_file && $struc['name'] != $limit_file ) {
   653 			if ( $limit_file && $struc['name'] != $limit_file ) {
   625 				continue;
   654 				continue;
   626 			}
   655 			}
   627 
   656 
   628 			if ( 'd' == $struc['type'] ) {
   657 			if ( 'd' === $struc['type'] ) {
   629 				if ( $recursive ) {
   658 				if ( $recursive ) {
   630 					$struc['files'] = $this->dirlist( $path . '/' . $struc['name'], $include_hidden, $recursive );
   659 					$struc['files'] = $this->dirlist( $path . '/' . $struc['name'], $include_hidden, $recursive );
   631 				} else {
   660 				} else {
   632 					$struc['files'] = array();
   661 					$struc['files'] = array();
   633 				}
   662 				}
   634 			}
   663 			}
   635 
   664 
   636 			// Replace symlinks formatted as "source -> target" with just the source name
   665 			// Replace symlinks formatted as "source -> target" with just the source name.
   637 			if ( $struc['islink'] ) {
   666 			if ( $struc['islink'] ) {
   638 				$struc['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $struc['name'] );
   667 				$struc['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $struc['name'] );
   639 			}
   668 			}
   640 
   669 
   641 			// Add the Octal representation of the file permissions
   670 			// Add the octal representation of the file permissions.
   642 			$struc['permsn'] = $this->getnumchmodfromh( $struc['perms'] );
   671 			$struc['permsn'] = $this->getnumchmodfromh( $struc['perms'] );
   643 
   672 
   644 			$ret[ $struc['name'] ] = $struc;
   673 			$ret[ $struc['name'] ] = $struc;
   645 		}
   674 		}
   646 
   675