wp/wp-admin/includes/class-wp-filesystem-base.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
    53 	 *
    53 	 *
    54 	 * @return string The location of the remote path.
    54 	 * @return string The location of the remote path.
    55 	 */
    55 	 */
    56 	public function abspath() {
    56 	public function abspath() {
    57 		$folder = $this->find_folder( ABSPATH );
    57 		$folder = $this->find_folder( ABSPATH );
    58 		// Perhaps the FTP folder is rooted at the WordPress install, Check for wp-includes folder in root, Could have some false positives, but rare.
    58 
       
    59 		// Perhaps the FTP folder is rooted at the WordPress install.
       
    60 		// Check for wp-includes folder in root. Could have some false positives, but rare.
    59 		if ( ! $folder && $this->is_dir( '/' . WPINC ) ) {
    61 		if ( ! $folder && $this->is_dir( '/' . WPINC ) ) {
    60 			$folder = '/';
    62 			$folder = '/';
    61 		}
    63 		}
       
    64 
    62 		return $folder;
    65 		return $folder;
    63 	}
    66 	}
    64 
    67 
    65 	/**
    68 	/**
    66 	 * Returns the path on the remote filesystem of WP_CONTENT_DIR.
    69 	 * Returns the path on the remote filesystem of WP_CONTENT_DIR.
    94 	 * @return string The location of the remote path.
    97 	 * @return string The location of the remote path.
    95 	 */
    98 	 */
    96 	public function wp_themes_dir( $theme = false ) {
    99 	public function wp_themes_dir( $theme = false ) {
    97 		$theme_root = get_theme_root( $theme );
   100 		$theme_root = get_theme_root( $theme );
    98 
   101 
    99 		// Account for relative theme roots
   102 		// Account for relative theme roots.
   100 		if ( '/themes' == $theme_root || ! is_dir( $theme_root ) ) {
   103 		if ( '/themes' === $theme_root || ! is_dir( $theme_root ) ) {
   101 			$theme_root = WP_CONTENT_DIR . $theme_root;
   104 			$theme_root = WP_CONTENT_DIR . $theme_root;
   102 		}
   105 		}
   103 
   106 
   104 		return $this->find_folder( $theme_root );
   107 		return $this->find_folder( $theme_root );
   105 	}
   108 	}
   180 				'FTP_CONTENT_DIR' => WP_CONTENT_DIR,
   183 				'FTP_CONTENT_DIR' => WP_CONTENT_DIR,
   181 				'FTP_PLUGIN_DIR'  => WP_PLUGIN_DIR,
   184 				'FTP_PLUGIN_DIR'  => WP_PLUGIN_DIR,
   182 				'FTP_LANG_DIR'    => WP_LANG_DIR,
   185 				'FTP_LANG_DIR'    => WP_LANG_DIR,
   183 			);
   186 			);
   184 
   187 
   185 			// Direct matches ( folder = CONSTANT/ )
   188 			// Direct matches ( folder = CONSTANT/ ).
   186 			foreach ( $constant_overrides as $constant => $dir ) {
   189 			foreach ( $constant_overrides as $constant => $dir ) {
   187 				if ( ! defined( $constant ) ) {
   190 				if ( ! defined( $constant ) ) {
   188 					continue;
   191 					continue;
   189 				}
   192 				}
       
   193 
   190 				if ( $folder === $dir ) {
   194 				if ( $folder === $dir ) {
   191 					return trailingslashit( constant( $constant ) );
   195 					return trailingslashit( constant( $constant ) );
   192 				}
   196 				}
   193 			}
   197 			}
   194 
   198 
   195 			// Prefix Matches ( folder = CONSTANT/subdir )
   199 			// Prefix matches ( folder = CONSTANT/subdir ),
   196 			foreach ( $constant_overrides as $constant => $dir ) {
   200 			foreach ( $constant_overrides as $constant => $dir ) {
   197 				if ( ! defined( $constant ) ) {
   201 				if ( ! defined( $constant ) ) {
   198 					continue;
   202 					continue;
   199 				}
   203 				}
   200 				if ( 0 === stripos( $folder, $dir ) ) { // $folder starts with $dir
   204 
       
   205 				if ( 0 === stripos( $folder, $dir ) ) { // $folder starts with $dir.
   201 					$potential_folder = preg_replace( '#^' . preg_quote( $dir, '#' ) . '/#i', trailingslashit( constant( $constant ) ), $folder );
   206 					$potential_folder = preg_replace( '#^' . preg_quote( $dir, '#' ) . '/#i', trailingslashit( constant( $constant ) ), $folder );
   202 					$potential_folder = trailingslashit( $potential_folder );
   207 					$potential_folder = trailingslashit( $potential_folder );
   203 
   208 
   204 					if ( $this->is_dir( $potential_folder ) ) {
   209 					if ( $this->is_dir( $potential_folder ) ) {
   205 						$this->cache[ $folder ] = $potential_folder;
   210 						$this->cache[ $folder ] = $potential_folder;
       
   211 
   206 						return $potential_folder;
   212 						return $potential_folder;
   207 					}
   213 					}
   208 				}
   214 				}
   209 			}
   215 			}
   210 		} elseif ( 'direct' == $this->method ) {
   216 		} elseif ( 'direct' === $this->method ) {
   211 			$folder = str_replace( '\\', '/', $folder ); // Windows path sanitisation
   217 			$folder = str_replace( '\\', '/', $folder ); // Windows path sanitisation.
       
   218 
   212 			return trailingslashit( $folder );
   219 			return trailingslashit( $folder );
   213 		}
   220 		}
   214 
   221 
   215 		$folder = preg_replace( '|^([a-z]{1}):|i', '', $folder ); // Strip out windows drive letter if it's there.
   222 		$folder = preg_replace( '|^([a-z]{1}):|i', '', $folder ); // Strip out Windows drive letter if it's there.
   216 		$folder = str_replace( '\\', '/', $folder ); // Windows path sanitisation
   223 		$folder = str_replace( '\\', '/', $folder ); // Windows path sanitisation.
   217 
   224 
   218 		if ( isset( $this->cache[ $folder ] ) ) {
   225 		if ( isset( $this->cache[ $folder ] ) ) {
   219 			return $this->cache[ $folder ];
   226 			return $this->cache[ $folder ];
   220 		}
   227 		}
   221 
   228 
   222 		if ( $this->exists( $folder ) ) { // Folder exists at that absolute path.
   229 		if ( $this->exists( $folder ) ) { // Folder exists at that absolute path.
   223 			$folder                 = trailingslashit( $folder );
   230 			$folder                 = trailingslashit( $folder );
   224 			$this->cache[ $folder ] = $folder;
   231 			$this->cache[ $folder ] = $folder;
       
   232 
   225 			return $folder;
   233 			return $folder;
   226 		}
   234 		}
   227 		if ( $return = $this->search_for_folder( $folder ) ) {
   235 
       
   236 		$return = $this->search_for_folder( $folder );
       
   237 
       
   238 		if ( $return ) {
   228 			$this->cache[ $folder ] = $return;
   239 			$this->cache[ $folder ] = $return;
   229 		}
   240 		}
       
   241 
   230 		return $return;
   242 		return $return;
   231 	}
   243 	}
   232 
   244 
   233 	/**
   245 	/**
   234 	 * Locates a folder on the remote filesystem.
   246 	 * Locates a folder on the remote filesystem.
   237 	 *
   249 	 *
   238 	 * @since 2.7.0
   250 	 * @since 2.7.0
   239 	 *
   251 	 *
   240 	 * @param string $folder The folder to locate.
   252 	 * @param string $folder The folder to locate.
   241 	 * @param string $base   The folder to start searching from.
   253 	 * @param string $base   The folder to start searching from.
   242 	 * @param bool   $loop   If the function has recursed, Internal use only.
   254 	 * @param bool   $loop   If the function has recursed. Internal use only.
   243 	 * @return string|false The location of the remote path, false to cease looping.
   255 	 * @return string|false The location of the remote path, false to cease looping.
   244 	 */
   256 	 */
   245 	public function search_for_folder( $folder, $base = '.', $loop = false ) {
   257 	public function search_for_folder( $folder, $base = '.', $loop = false ) {
   246 		if ( empty( $base ) || '.' == $base ) {
   258 		if ( empty( $base ) || '.' === $base ) {
   247 			$base = trailingslashit( $this->cwd() );
   259 			$base = trailingslashit( $this->cwd() );
   248 		}
   260 		}
   249 
   261 
   250 		$folder = untrailingslashit( $folder );
   262 		$folder = untrailingslashit( $folder );
   251 
   263 
   252 		if ( $this->verbose ) {
   264 		if ( $this->verbose ) {
   253 			/* translators: 1: folder to locate, 2: folder to start searching from */
   265 			/* translators: 1: Folder to locate, 2: Folder to start searching from. */
   254 			printf( "\n" . __( 'Looking for %1$s in %2$s' ) . "<br/>\n", $folder, $base );
   266 			printf( "\n" . __( 'Looking for %1$s in %2$s' ) . "<br/>\n", $folder, $base );
   255 		}
   267 		}
   256 
   268 
   257 		$folder_parts     = explode( '/', $folder );
   269 		$folder_parts     = explode( '/', $folder );
   258 		$folder_part_keys = array_keys( $folder_parts );
   270 		$folder_part_keys = array_keys( $folder_parts );
   275 			 */
   287 			 */
   276 			if ( isset( $files[ $key ] ) ) {
   288 			if ( isset( $files[ $key ] ) ) {
   277 
   289 
   278 				// Let's try that folder:
   290 				// Let's try that folder:
   279 				$newdir = trailingslashit( path_join( $base, $key ) );
   291 				$newdir = trailingslashit( path_join( $base, $key ) );
       
   292 
   280 				if ( $this->verbose ) {
   293 				if ( $this->verbose ) {
   281 					/* translators: %s: directory name */
   294 					/* translators: %s: Directory name. */
   282 					printf( "\n" . __( 'Changing to %s' ) . "<br/>\n", $newdir );
   295 					printf( "\n" . __( 'Changing to %s' ) . "<br/>\n", $newdir );
   283 				}
   296 				}
   284 
   297 
   285 				// Only search for the remaining path tokens in the directory, not the full path again.
   298 				// Only search for the remaining path tokens in the directory, not the full path again.
   286 				$newfolder = implode( '/', array_slice( $folder_parts, $index + 1 ) );
   299 				$newfolder = implode( '/', array_slice( $folder_parts, $index + 1 ) );
   287 				if ( $ret = $this->search_for_folder( $newfolder, $newdir, $loop ) ) {
   300 				$ret       = $this->search_for_folder( $newfolder, $newdir, $loop );
       
   301 
       
   302 				if ( $ret ) {
   288 					return $ret;
   303 					return $ret;
   289 				}
   304 				}
   290 			}
   305 			}
   291 		}
   306 		}
   292 
   307 
   293 		// Only check this as a last resort, to prevent locating the incorrect install.
   308 		// Only check this as a last resort, to prevent locating the incorrect install.
   294 		// All above procedures will fail quickly if this is the right branch to take.
   309 		// All above procedures will fail quickly if this is the right branch to take.
   295 		if ( isset( $files[ $last_path ] ) ) {
   310 		if ( isset( $files[ $last_path ] ) ) {
   296 			if ( $this->verbose ) {
   311 			if ( $this->verbose ) {
   297 				/* translators: %s: directory name */
   312 				/* translators: %s: Directory name. */
   298 				printf( "\n" . __( 'Found %s' ) . "<br/>\n", $base . $last_path );
   313 				printf( "\n" . __( 'Found %s' ) . "<br/>\n", $base . $last_path );
   299 			}
   314 			}
       
   315 
   300 			return trailingslashit( $base . $last_path );
   316 			return trailingslashit( $base . $last_path );
   301 		}
   317 		}
   302 
   318 
   303 		// Prevent this function from looping again.
   319 		// Prevent this function from looping again.
   304 		// No need to proceed if we've just searched in /
   320 		// No need to proceed if we've just searched in `/`.
   305 		if ( $loop || '/' == $base ) {
   321 		if ( $loop || '/' === $base ) {
   306 			return false;
   322 			return false;
   307 		}
   323 		}
   308 
   324 
   309 		// As an extra last resort, Change back to / if the folder wasn't found.
   325 		// As an extra last resort, Change back to / if the folder wasn't found.
   310 		// This comes into effect when the CWD is /home/user/ but WP is at /var/www/....
   326 		// This comes into effect when the CWD is /home/user/ but WP is at /var/www/....
   315 	/**
   331 	/**
   316 	 * Returns the *nix-style file permissions for a file.
   332 	 * Returns the *nix-style file permissions for a file.
   317 	 *
   333 	 *
   318 	 * From the PHP documentation page for fileperms().
   334 	 * From the PHP documentation page for fileperms().
   319 	 *
   335 	 *
   320 	 * @link https://secure.php.net/manual/en/function.fileperms.php
   336 	 * @link https://www.php.net/manual/en/function.fileperms.php
   321 	 *
   337 	 *
   322 	 * @since 2.5.0
   338 	 * @since 2.5.0
   323 	 *
   339 	 *
   324 	 * @param string $file String filename.
   340 	 * @param string $file String filename.
   325 	 * @return string The *nix-style representation of permissions.
   341 	 * @return string The *nix-style representation of permissions.
   326 	 */
   342 	 */
   327 	public function gethchmod( $file ) {
   343 	public function gethchmod( $file ) {
   328 		$perms = intval( $this->getchmod( $file ), 8 );
   344 		$perms = intval( $this->getchmod( $file ), 8 );
   329 		if ( ( $perms & 0xC000 ) == 0xC000 ) { // Socket
   345 
       
   346 		if ( ( $perms & 0xC000 ) == 0xC000 ) { // Socket.
   330 			$info = 's';
   347 			$info = 's';
   331 		} elseif ( ( $perms & 0xA000 ) == 0xA000 ) { // Symbolic Link
   348 		} elseif ( ( $perms & 0xA000 ) == 0xA000 ) { // Symbolic Link.
   332 			$info = 'l';
   349 			$info = 'l';
   333 		} elseif ( ( $perms & 0x8000 ) == 0x8000 ) { // Regular
   350 		} elseif ( ( $perms & 0x8000 ) == 0x8000 ) { // Regular.
   334 			$info = '-';
   351 			$info = '-';
   335 		} elseif ( ( $perms & 0x6000 ) == 0x6000 ) { // Block special
   352 		} elseif ( ( $perms & 0x6000 ) == 0x6000 ) { // Block special.
   336 			$info = 'b';
   353 			$info = 'b';
   337 		} elseif ( ( $perms & 0x4000 ) == 0x4000 ) { // Directory
   354 		} elseif ( ( $perms & 0x4000 ) == 0x4000 ) { // Directory.
   338 			$info = 'd';
   355 			$info = 'd';
   339 		} elseif ( ( $perms & 0x2000 ) == 0x2000 ) { // Character special
   356 		} elseif ( ( $perms & 0x2000 ) == 0x2000 ) { // Character special.
   340 			$info = 'c';
   357 			$info = 'c';
   341 		} elseif ( ( $perms & 0x1000 ) == 0x1000 ) { // FIFO pipe
   358 		} elseif ( ( $perms & 0x1000 ) == 0x1000 ) { // FIFO pipe.
   342 			$info = 'p';
   359 			$info = 'p';
   343 		} else { // Unknown
   360 		} else { // Unknown.
   344 			$info = 'u';
   361 			$info = 'u';
   345 		}
   362 		}
   346 
   363 
   347 		// Owner
   364 		// Owner.
   348 		$info .= ( ( $perms & 0x0100 ) ? 'r' : '-' );
   365 		$info .= ( ( $perms & 0x0100 ) ? 'r' : '-' );
   349 		$info .= ( ( $perms & 0x0080 ) ? 'w' : '-' );
   366 		$info .= ( ( $perms & 0x0080 ) ? 'w' : '-' );
   350 		$info .= ( ( $perms & 0x0040 ) ?
   367 		$info .= ( ( $perms & 0x0040 ) ?
   351 					( ( $perms & 0x0800 ) ? 's' : 'x' ) :
   368 					( ( $perms & 0x0800 ) ? 's' : 'x' ) :
   352 					( ( $perms & 0x0800 ) ? 'S' : '-' ) );
   369 					( ( $perms & 0x0800 ) ? 'S' : '-' ) );
   353 
   370 
   354 		// Group
   371 		// Group.
   355 		$info .= ( ( $perms & 0x0020 ) ? 'r' : '-' );
   372 		$info .= ( ( $perms & 0x0020 ) ? 'r' : '-' );
   356 		$info .= ( ( $perms & 0x0010 ) ? 'w' : '-' );
   373 		$info .= ( ( $perms & 0x0010 ) ? 'w' : '-' );
   357 		$info .= ( ( $perms & 0x0008 ) ?
   374 		$info .= ( ( $perms & 0x0008 ) ?
   358 					( ( $perms & 0x0400 ) ? 's' : 'x' ) :
   375 					( ( $perms & 0x0400 ) ? 's' : 'x' ) :
   359 					( ( $perms & 0x0400 ) ? 'S' : '-' ) );
   376 					( ( $perms & 0x0400 ) ? 'S' : '-' ) );
   360 
   377 
   361 		// World
   378 		// World.
   362 		$info .= ( ( $perms & 0x0004 ) ? 'r' : '-' );
   379 		$info .= ( ( $perms & 0x0004 ) ? 'r' : '-' );
   363 		$info .= ( ( $perms & 0x0002 ) ? 'w' : '-' );
   380 		$info .= ( ( $perms & 0x0002 ) ? 'w' : '-' );
   364 		$info .= ( ( $perms & 0x0001 ) ?
   381 		$info .= ( ( $perms & 0x0001 ) ?
   365 					( ( $perms & 0x0200 ) ? 't' : 'x' ) :
   382 					( ( $perms & 0x0200 ) ? 't' : 'x' ) :
   366 					( ( $perms & 0x0200 ) ? 'T' : '-' ) );
   383 					( ( $perms & 0x0200 ) ? 'T' : '-' ) );
       
   384 
   367 		return $info;
   385 		return $info;
   368 	}
   386 	}
   369 
   387 
   370 	/**
   388 	/**
   371 	 * Gets the permissions of the specified file or filepath in their octal format.
   389 	 * Gets the permissions of the specified file or filepath in their octal format.
   383 	 * Converts *nix-style file permissions to a octal number.
   401 	 * Converts *nix-style file permissions to a octal number.
   384 	 *
   402 	 *
   385 	 * Converts '-rw-r--r--' to 0644
   403 	 * Converts '-rw-r--r--' to 0644
   386 	 * From "info at rvgate dot nl"'s comment on the PHP documentation for chmod()
   404 	 * From "info at rvgate dot nl"'s comment on the PHP documentation for chmod()
   387 	 *
   405 	 *
   388 	 * @link https://secure.php.net/manual/en/function.chmod.php#49614
   406 	 * @link https://www.php.net/manual/en/function.chmod.php#49614
   389 	 *
   407 	 *
   390 	 * @since 2.5.0
   408 	 * @since 2.5.0
   391 	 *
   409 	 *
   392 	 * @param string $mode string The *nix-style file permission.
   410 	 * @param string $mode string The *nix-style file permission.
   393 	 * @return int octal representation
   411 	 * @return int octal representation
   396 		$realmode = '';
   414 		$realmode = '';
   397 		$legal    = array( '', 'w', 'r', 'x', '-' );
   415 		$legal    = array( '', 'w', 'r', 'x', '-' );
   398 		$attarray = preg_split( '//', $mode );
   416 		$attarray = preg_split( '//', $mode );
   399 
   417 
   400 		for ( $i = 0, $c = count( $attarray ); $i < $c; $i++ ) {
   418 		for ( $i = 0, $c = count( $attarray ); $i < $c; $i++ ) {
   401 			if ( $key = array_search( $attarray[ $i ], $legal ) ) {
   419 			$key = array_search( $attarray[ $i ], $legal, true );
       
   420 
       
   421 			if ( $key ) {
   402 				$realmode .= $legal[ $key ];
   422 				$realmode .= $legal[ $key ];
   403 			}
   423 			}
   404 		}
   424 		}
   405 
   425 
   406 		$mode  = str_pad( $realmode, 10, '-', STR_PAD_LEFT );
   426 		$mode  = str_pad( $realmode, 10, '-', STR_PAD_LEFT );
   414 
   434 
   415 		$newmode  = $mode[0];
   435 		$newmode  = $mode[0];
   416 		$newmode .= $mode[1] + $mode[2] + $mode[3];
   436 		$newmode .= $mode[1] + $mode[2] + $mode[3];
   417 		$newmode .= $mode[4] + $mode[5] + $mode[6];
   437 		$newmode .= $mode[4] + $mode[5] + $mode[6];
   418 		$newmode .= $mode[7] + $mode[8] + $mode[9];
   438 		$newmode .= $mode[7] + $mode[8] + $mode[9];
       
   439 
   419 		return $newmode;
   440 		return $newmode;
   420 	}
   441 	}
   421 
   442 
   422 	/**
   443 	/**
   423 	 * Determines if the string provided contains binary characters.
   444 	 * Determines if the string provided contains binary characters.
   550 	 * @abstract
   571 	 * @abstract
   551 	 *
   572 	 *
   552 	 * @param string    $file      Path to the file.
   573 	 * @param string    $file      Path to the file.
   553 	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
   574 	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
   554 	 *                             0755 for directories. Default false.
   575 	 *                             0755 for directories. Default false.
   555 	 * @param bool      $recursive Optional. If set to true, changes file group recursively.
   576 	 * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
   556 	 *                             Default false.
   577 	 *                             Default false.
   557 	 * @return bool True on success, false on failure.
   578 	 * @return bool True on success, false on failure.
   558 	 */
   579 	 */
   559 	public function chmod( $file, $mode = false, $recursive = false ) {
   580 	public function chmod( $file, $mode = false, $recursive = false ) {
   560 		return false;
   581 		return false;
   625 	 *
   646 	 *
   626 	 * @since 2.5.0
   647 	 * @since 2.5.0
   627 	 * @abstract
   648 	 * @abstract
   628 	 *
   649 	 *
   629 	 * @param string       $file      Path to the file or directory.
   650 	 * @param string       $file      Path to the file or directory.
   630 	 * @param bool         $recursive Optional. If set to true, changes file group recursively.
   651 	 * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
   631 	 *                                Default false.
   652 	 *                                Default false.
   632 	 * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
   653 	 * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
   633 	 *                                Default false.
   654 	 *                                Default false.
   634 	 * @return bool True on success, false on failure.
   655 	 * @return bool True on success, false on failure.
   635 	 */
   656 	 */
   822 	 */
   843 	 */
   823 	public function dirlist( $path, $include_hidden = true, $recursive = false ) {
   844 	public function dirlist( $path, $include_hidden = true, $recursive = false ) {
   824 		return false;
   845 		return false;
   825 	}
   846 	}
   826 
   847 
   827 } // WP_Filesystem_Base
   848 }