2008-05-30 18:14:05 +02:00
< ? php
2008-08-14 08:30:38 +02:00
/**
* Base WordPress Filesystem .
*
* @ package WordPress
* @ subpackage Filesystem
*/
/**
* Base WordPress Filesystem class for which Filesystem implementations extend
*
* @ since 2.5
*/
class WP_Filesystem_Base {
2008-10-10 12:02:46 +02:00
/**
2010-02-24 21:13:23 +01:00
* Whether to display debug data for the connection .
2008-10-10 12:02:46 +02:00
*
* @ since 2.5
* @ access public
* @ var bool
*/
2008-07-04 08:18:20 +02:00
var $verbose = false ;
2013-09-09 04:54:50 +02:00
2008-10-10 12:02:46 +02:00
/**
2011-05-14 11:56:59 +02:00
* Cached list of local filepaths to mapped remote filepaths .
2008-10-10 12:02:46 +02:00
*
* @ since 2.7
* @ access private
* @ var array
*/
2008-05-30 18:14:05 +02:00
var $cache = array ();
2008-08-09 07:36:14 +02:00
2008-10-10 12:02:46 +02:00
/**
* The Access method of the current connection , Set automatically .
*
* @ since 2.5
* @ access public
* @ var string
*/
2008-05-30 18:14:05 +02:00
var $method = '' ;
2008-08-09 07:36:14 +02:00
2008-10-10 12:02:46 +02:00
/**
* Returns the path on the remote filesystem of ABSPATH
*
* @ since 2.7
* @ access public
* @ return string The location of the remote path .
*/
2008-05-30 18:14:05 +02:00
function abspath () {
2008-10-10 12:40:04 +02:00
$folder = $this -> find_folder ( ABSPATH );
2013-09-09 04:54:50 +02:00
// Perhaps the FTP folder is rooted at the WordPress install, Check for wp-includes folder in root, Could have some false positives, but rare.
2008-10-10 12:40:04 +02:00
if ( ! $folder && $this -> is_dir ( '/wp-includes' ) )
$folder = '/' ;
return $folder ;
2008-05-30 18:14:05 +02:00
}
2013-09-09 04:54:50 +02:00
2008-10-10 12:02:46 +02:00
/**
* Returns the path on the remote filesystem of WP_CONTENT_DIR
*
* @ since 2.7
* @ access public
* @ return string The location of the remote path .
*/
2008-05-30 18:14:05 +02:00
function wp_content_dir () {
return $this -> find_folder ( WP_CONTENT_DIR );
}
2013-09-09 04:54:50 +02:00
2008-10-10 12:02:46 +02:00
/**
* Returns the path on the remote filesystem of WP_PLUGIN_DIR
*
* @ since 2.7
* @ access public
*
* @ return string The location of the remote path .
*/
2008-05-30 18:14:05 +02:00
function wp_plugins_dir () {
return $this -> find_folder ( WP_PLUGIN_DIR );
}
2013-09-09 04:54:50 +02:00
2008-10-10 12:02:46 +02:00
/**
* Returns the path on the remote filesystem of the Themes Directory
*
* @ since 2.7
* @ access public
*
2013-08-22 06:49:06 +02:00
* @ param string $theme The Theme stylesheet or template for the directory
2008-10-10 12:02:46 +02:00
* @ return string The location of the remote path .
*/
2013-08-22 06:49:06 +02:00
function wp_themes_dir ( $theme = false ) {
$theme_root = get_theme_root ( $theme );
// Account for relative theme roots
if ( '/themes' == $theme_root || ! is_dir ( $theme_root ) )
$theme_root = WP_CONTENT_DIR . $theme_root ;
return $this -> find_folder ( $theme_root );
2011-03-31 15:28:36 +02:00
}
2013-09-09 04:54:50 +02:00
2011-03-31 15:28:36 +02:00
/**
* Returns the path on the remote filesystem of WP_LANG_DIR
*
2011-06-11 06:40:18 +02:00
* @ since 3.2 . 0
2011-03-31 15:28:36 +02:00
* @ access public
*
* @ return string The location of the remote path .
*/
function wp_lang_dir () {
return $this -> find_folder ( WP_LANG_DIR );
2008-05-30 18:14:05 +02:00
}
2008-12-09 19:03:31 +01:00
2008-10-10 12:02:46 +02:00
/**
* Locates a folder on the remote filesystem .
*
* Deprecated ; use WP_Filesystem :: abspath () or WP_Filesystem :: wp_ * _dir () methods instead .
*
* @ since 2.5
* @ deprecated 2.7
* @ access public
*
* @ param string $base The folder to start searching from
* @ param bool $echo True to display debug information
* @ return string The location of the remote path .
*/
2008-05-30 18:14:05 +02:00
function find_base_dir ( $base = '.' , $echo = false ) {
2008-10-10 12:02:46 +02:00
_deprecated_function ( __FUNCTION__ , '2.7' , 'WP_Filesystem::abspath() or WP_Filesystem::wp_*_dir()' );
2008-05-30 18:14:05 +02:00
$this -> verbose = $echo ;
return $this -> abspath ();
}
2013-09-09 04:54:50 +02:00
2008-10-10 12:02:46 +02:00
/**
* Locates a folder on the remote filesystem .
*
* Deprecated ; use WP_Filesystem :: abspath () or WP_Filesystem :: wp_ * _dir () methods instead .
*
* @ since 2.5
* @ deprecated 2.7
* @ access public
*
* @ param string $base The folder to start searching from
* @ param bool $echo True to display debug information
* @ return string The location of the remote path .
*/
2008-05-30 18:14:05 +02:00
function get_base_dir ( $base = '.' , $echo = false ) {
2008-10-10 12:02:46 +02:00
_deprecated_function ( __FUNCTION__ , '2.7' , 'WP_Filesystem::abspath() or WP_Filesystem::wp_*_dir()' );
2008-05-30 18:14:05 +02:00
$this -> verbose = $echo ;
return $this -> abspath ();
}
2008-08-09 07:36:14 +02:00
2008-10-10 12:02:46 +02:00
/**
* Locates a folder on the remote filesystem .
*
* Assumes that on Windows systems , Stripping off the Drive letter is OK
* Sanitizes \\ to / in windows filepaths .
*
* @ since 2.7
* @ access public
2008-12-09 19:03:31 +01:00
*
2008-10-10 12:02:46 +02:00
* @ param string $folder the folder to locate
* @ return string The location of the remote path .
*/
2008-05-30 18:14:05 +02:00
function find_folder ( $folder ) {
2008-10-10 12:02:46 +02:00
2013-08-20 08:46:37 +02:00
if ( isset ( $this -> cache [ $folder ] ) )
return $this -> cache [ $folder ];
if ( stripos ( $this -> method , 'ftp' ) !== false ) {
$constant_overrides = array (
'FTP_BASE' => ABSPATH ,
'FTP_CONTENT_DIR' => WP_CONTENT_DIR ,
'FTP_PLUGIN_DIR' => WP_PLUGIN_DIR ,
'FTP_LANG_DIR' => WP_LANG_DIR
);
// Direct matches ( folder = CONSTANT/ )
foreach ( $constant_overrides as $constant => $dir ) {
if ( ! defined ( $constant ) )
continue ;
if ( $folder === $dir )
return trailingslashit ( constant ( $constant ) );
}
// Prefix Matches ( folder = CONSTANT/subdir )
foreach ( $constant_overrides as $constant => $dir ) {
if ( ! defined ( $constant ) )
continue ;
if ( 0 === stripos ( $folder , $dir ) ) { // $folder starts with $dir
$potential_folder = preg_replace ( '#^' . preg_quote ( $dir , '#' ) . '/#i' , trailingslashit ( constant ( $constant ) ), $folder );
$potential_folder = trailingslashit ( $potential_folder );
if ( $this -> is_dir ( $potential_folder ) ) {
$this -> cache [ $folder ] = $potential_folder ;
return $potential_folder ;
}
}
}
2009-04-13 18:11:02 +02:00
} elseif ( 'direct' == $this -> method ) {
2013-09-09 04:54:50 +02:00
$folder = str_replace ( '\\' , '/' , $folder ); // Windows path sanitisation
2009-04-13 18:11:02 +02:00
return trailingslashit ( $folder );
}
2013-09-09 04:54:50 +02:00
$folder = preg_replace ( '|^([a-z]{1}):|i' , '' , $folder ); // Strip out windows drive letter if it's there.
$folder = str_replace ( '\\' , '/' , $folder ); // Windows path sanitisation
2008-10-10 12:02:46 +02:00
2008-05-30 18:14:05 +02:00
if ( isset ( $this -> cache [ $folder ] ) )
return $this -> cache [ $folder ];
2013-09-09 04:54:50 +02:00
if ( $this -> exists ( $folder ) ) { // Folder exists at that absolute path.
2009-04-13 18:11:02 +02:00
$folder = trailingslashit ( $folder );
2008-05-30 18:14:05 +02:00
$this -> cache [ $folder ] = $folder ;
return $folder ;
}
2010-01-18 21:34:48 +01:00
if ( $return = $this -> search_for_folder ( $folder ) )
2008-05-30 18:14:05 +02:00
$this -> cache [ $folder ] = $return ;
return $return ;
}
2008-08-09 07:36:14 +02:00
2008-10-10 12:02:46 +02:00
/**
* Locates a folder on the remote filesystem .
*
* Expects Windows sanitized path
*
* @ since 2.7
* @ access private
2008-12-09 19:03:31 +01:00
*
2008-10-10 12:02:46 +02:00
* @ param string $folder the folder to locate
* @ param string $base the folder to start searching from
* @ param bool $loop if the function has recursed , Internal use only
* @ return string The location of the remote path .
*/
2008-05-30 18:14:05 +02:00
function search_for_folder ( $folder , $base = '.' , $loop = false ) {
if ( empty ( $base ) || '.' == $base )
$base = trailingslashit ( $this -> cwd ());
2008-08-09 07:36:14 +02:00
2008-10-10 12:02:46 +02:00
$folder = untrailingslashit ( $folder );
2008-08-09 07:36:14 +02:00
2013-08-15 07:59:36 +02:00
if ( $this -> verbose )
printf ( " \n " . __ ( 'Looking for %1$s in %2$s' ) . " <br/> \n " , $folder , $base );
2008-05-30 18:14:05 +02:00
$folder_parts = explode ( '/' , $folder );
2013-08-15 07:59:36 +02:00
$folder_part_keys = array_keys ( $folder_parts );
$last_index = array_pop ( $folder_part_keys );
2012-07-06 12:41:32 +02:00
$last_path = $folder_parts [ $last_index ];
2008-08-09 07:36:14 +02:00
2008-05-30 18:14:05 +02:00
$files = $this -> dirlist ( $base );
2008-08-09 07:36:14 +02:00
2012-07-06 12:41:32 +02:00
foreach ( $folder_parts as $index => $key ) {
if ( $index == $last_index )
2013-09-09 04:54:50 +02:00
continue ; // We want this to be caught by the next code block.
2008-05-30 18:14:05 +02:00
2013-09-09 04:54:50 +02:00
// Working from /home/ to /user/ to /wordpress/ see if that file exists within the current folder,
2012-12-20 16:55:32 +01:00
// If it's found, change into it and follow through looking for it.
2008-05-30 18:14:05 +02:00
// If it cant find WordPress down that route, it'll continue onto the next folder level, and see if that matches, and so on.
// If it reaches the end, and still cant find it, it'll return false for the entire function.
2009-04-13 18:11:02 +02:00
if ( isset ( $files [ $key ]) ){
2013-09-09 04:54:50 +02:00
// Lets try that folder:
2008-05-30 18:14:05 +02:00
$newdir = trailingslashit ( path_join ( $base , $key ));
2009-04-13 18:11:02 +02:00
if ( $this -> verbose )
2013-08-15 07:59:36 +02:00
printf ( " \n " . __ ( 'Changing to %s' ) . " <br/> \n " , $newdir );
2012-07-06 13:19:46 +02:00
// only search for the remaining path tokens in the directory, not the full path again
$newfolder = implode ( '/' , array_slice ( $folder_parts , $index + 1 ) );
if ( $ret = $this -> search_for_folder ( $newfolder , $newdir , $loop ) )
2008-05-30 18:14:05 +02:00
return $ret ;
}
}
2008-08-09 07:36:14 +02:00
2013-09-09 04:54:50 +02:00
// Only check this as a last resort, to prevent locating the incorrect install. All above procedures will fail quickly if this is the right branch to take.
2009-04-13 18:11:02 +02:00
if ( isset ( $files [ $last_path ] ) ) {
if ( $this -> verbose )
2013-08-15 07:59:36 +02:00
printf ( " \n " . __ ( 'Found %s' ) . " <br/> \n " , $base . $last_path );
2009-04-13 18:11:02 +02:00
return trailingslashit ( $base . $last_path );
2008-05-30 18:14:05 +02:00
}
2013-08-15 07:59:36 +02:00
// Prevent this function from looping again.
// No need to proceed if we've just searched in /
if ( $loop || '/' == $base )
return false ;
// As an extra last resort, Change back to / if the folder wasn't found.
// This comes into effect when the CWD is /home/user/ but WP is at /var/www/....
return $this -> search_for_folder ( $folder , '/' , true );
2008-08-09 07:36:14 +02:00
2008-05-30 18:14:05 +02:00
}
2008-08-09 07:36:14 +02:00
2008-10-10 12:02:46 +02:00
/**
* Returns the * nix style file permissions for a file
*
* From the PHP documentation page for fileperms ()
*
* @ link http :// docs . php . net / fileperms
* @ since 2.5
* @ access public
*
* @ param string $file string filename
2013-01-28 02:55:39 +01:00
* @ return string * nix style representation of permissions
2008-10-10 12:02:46 +02:00
*/
2008-05-30 18:14:05 +02:00
function gethchmod ( $file ){
$perms = $this -> getchmod ( $file );
if (( $perms & 0xC000 ) == 0xC000 ) // Socket
$info = 's' ;
elseif (( $perms & 0xA000 ) == 0xA000 ) // Symbolic Link
$info = 'l' ;
elseif (( $perms & 0x8000 ) == 0x8000 ) // Regular
$info = '-' ;
elseif (( $perms & 0x6000 ) == 0x6000 ) // Block special
$info = 'b' ;
elseif (( $perms & 0x4000 ) == 0x4000 ) // Directory
$info = 'd' ;
elseif (( $perms & 0x2000 ) == 0x2000 ) // Character special
$info = 'c' ;
2009-08-16 10:34:53 +02:00
elseif (( $perms & 0x1000 ) == 0x1000 ) // FIFO pipe
2008-05-30 18:14:05 +02:00
$info = 'p' ;
else // Unknown
$info = 'u' ;
// Owner
$info .= (( $perms & 0x0100 ) ? 'r' : '-' );
$info .= (( $perms & 0x0080 ) ? 'w' : '-' );
$info .= (( $perms & 0x0040 ) ?
(( $perms & 0x0800 ) ? 's' : 'x' ) :
(( $perms & 0x0800 ) ? 'S' : '-' ));
// Group
$info .= (( $perms & 0x0020 ) ? 'r' : '-' );
$info .= (( $perms & 0x0010 ) ? 'w' : '-' );
$info .= (( $perms & 0x0008 ) ?
(( $perms & 0x0400 ) ? 's' : 'x' ) :
(( $perms & 0x0400 ) ? 'S' : '-' ));
// World
$info .= (( $perms & 0x0004 ) ? 'r' : '-' );
$info .= (( $perms & 0x0002 ) ? 'w' : '-' );
$info .= (( $perms & 0x0001 ) ?
(( $perms & 0x0200 ) ? 't' : 'x' ) :
(( $perms & 0x0200 ) ? 'T' : '-' ));
return $info ;
}
2008-10-10 12:02:46 +02:00
/**
* Converts * nix style file permissions to a octal number .
*
* Converts '-rw-r--r--' to 0644
* From " info at rvgate dot nl " ' s comment on the PHP documentation for chmod ()
*
* @ link http :// docs . php . net / manual / en / function . chmod . php #49614
* @ since 2.5
* @ access public
*
* @ param string $mode string * nix style file permission
* @ return int octal representation
*/
2008-05-30 18:14:05 +02:00
function getnumchmodfromh ( $mode ) {
2008-10-10 12:02:46 +02:00
$realmode = '' ;
$legal = array ( '' , 'w' , 'r' , 'x' , '-' );
$attarray = preg_split ( '//' , $mode );
2008-05-30 18:14:05 +02:00
2010-01-18 21:34:48 +01:00
for ( $i = 0 ; $i < count ( $attarray ); $i ++ )
if ( $key = array_search ( $attarray [ $i ], $legal ))
2008-05-30 18:14:05 +02:00
$realmode .= $legal [ $key ];
2008-08-09 07:36:14 +02:00
2012-09-29 03:33:15 +02:00
$mode = str_pad ( $realmode , 10 , '-' , STR_PAD_LEFT );
2008-05-30 18:14:05 +02:00
$trans = array ( '-' => '0' , 'r' => '4' , 'w' => '2' , 'x' => '1' );
$mode = strtr ( $mode , $trans );
2008-08-09 07:36:14 +02:00
2012-09-29 03:33:15 +02:00
$newmode = $mode [ 0 ];
$newmode .= $mode [ 1 ] + $mode [ 2 ] + $mode [ 3 ];
$newmode .= $mode [ 4 ] + $mode [ 5 ] + $mode [ 6 ];
$newmode .= $mode [ 7 ] + $mode [ 8 ] + $mode [ 9 ];
2008-05-30 18:14:05 +02:00
return $newmode ;
}
2008-09-26 08:53:57 +02:00
/**
2008-10-10 12:02:46 +02:00
* Determines if the string provided contains binary characters .
*
* @ since 2.7
* @ access private
*
* @ param string $text String to test against
* @ return bool true if string is binary , false otherwise
*/
2008-09-26 08:53:57 +02:00
function is_binary ( $text ) {
2013-09-09 04:54:50 +02:00
return ( bool ) preg_match ( '|[^\x20-\x7E]|' , $text ); // chr(32)..chr(127)
2008-09-26 08:53:57 +02:00
}
2008-05-30 18:14:05 +02:00
}