= count( $filename_parts ) || $equal_number >= count( $base_dir_parts ) ) {
break;
}
if ( $filename_parts[ $equal_number ] !== $base_dir_parts[ $equal_number ] ) {
break;
}
}
$relative_dir = str_repeat( '../', count( $base_dir_parts ) - $equal_number );
$relative_dir .= implode( '/', array_slice( $filename_parts, $equal_number ) );
return $relative_dir;
}
/**
* Returns open basedirs
*
* @return array
*/
public static function get_open_basedirs() {
$open_basedir_ini = ini_get( 'open_basedir' );
$open_basedirs = ( W3TC_WIN ? preg_split( '~[;,]~', $open_basedir_ini ) : explode( ':', $open_basedir_ini ) );
$result = array();
foreach ( $open_basedirs as $open_basedir ) {
$open_basedir = trim( $open_basedir );
if ( ! empty( $open_basedir ) && '' !== $open_basedir ) {
$result[] = Util_Environment::realpath( $open_basedir );
}
}
return $result;
}
/**
* Checks if path is restricted by open_basedir
*
* @param string $path Path.
*
* @return boolean
*/
public static function check_open_basedir( $path ) {
$path = Util_Environment::realpath( $path );
$open_basedirs = self::get_open_basedirs();
if ( ! count( $open_basedirs ) ) {
return true;
}
foreach ( $open_basedirs as $open_basedir ) {
if ( strstr( $path, $open_basedir ) !== false ) {
return true;
}
}
return false;
}
/**
* Get the octal file permission number of a file or directory.
*
* @param string $file File path.
*
* @return int
*/
public static function get_file_permissions( $file ) {
if ( function_exists( 'fileperms' ) && $fileperms = @fileperms( $file ) ) { // phpcs:ignore
$fileperms = 0777 & $fileperms;
} else {
clearstatcache();
$stat = @stat( $file ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
if ( $stat ) {
$fileperms = 0777 & $stat['mode'];
} else {
$fileperms = 0;
}
}
return intval( decoct( $fileperms ) );
}
/**
* Get file owner
*
* @param string $file File path.
*
* @return string
*/
public static function get_file_owner( $file = '' ) {
$fileowner = 'unknown';
$filegroup = 'unknown';
if ( $file ) {
if ( function_exists( 'fileowner' ) && function_exists( 'fileowner' ) ) {
$fileowner = @fileowner( $file );
$filegroup = @filegroup( $file );
if ( function_exists( 'posix_getpwuid' ) && function_exists( 'posix_getgrgid' ) ) {
$fileowner = @posix_getpwuid( $fileowner );
$fileowner = $fileowner['name'];
$filegroup = @posix_getgrgid( $filegroup );
$filegroup = $filegroup['name'];
}
}
} elseif ( function_exists( 'getmyuid' ) && function_exists( 'getmygid' ) ) {
$fileowner = @getmyuid();
$filegroup = @getmygid();
if ( function_exists( 'posix_getpwuid' ) && function_exists( 'posix_getgrgid' ) ) {
$fileowner = @posix_getpwuid( $fileowner );
$fileowner = $fileowner['name'];
$filegroup = @posix_getgrgid( $filegroup );
$filegroup = $filegroup['name'];
}
}
return $fileowner . ':' . $filegroup;
}
/**
* Creates W3TC_CACHE_TMP_DIR dir if required
*
* @throws \Exception Exception.
*
* @return string
*/
public static function create_tmp_dir() {
if ( ! is_dir( W3TC_CACHE_TMP_DIR ) || ! is_writable( W3TC_CACHE_TMP_DIR ) ) {
self::mkdir_from( W3TC_CACHE_TMP_DIR, W3TC_CACHE_DIR );
if ( ! is_dir( W3TC_CACHE_TMP_DIR ) || ! is_writable( W3TC_CACHE_TMP_DIR ) ) {
$e = error_get_last();
$description = ( isset( $e['message'] ) ? $e['message'] : '' );
throw new \Exception(
\wp_kses_post(
sprintf(
// Translators: 1 Cache TMP dir path surround by HTML strong tag, 2 Description.
\__( 'Can\'t create folder %1$s: %2$s', 'w3-total-cache' ),
'' . W3TC_CACHE_TMP_DIR . '',
$description
)
)
);
}
}
return W3TC_CACHE_TMP_DIR;
}
/**
* Atomically writes file inside W3TC_CACHE_DIR dir
*
* @param unknown $filename Filename.
* @param unknown $content Content.
*
* @throws \Exception Exception.
*
* @return void
*/
public static function file_put_contents_atomic( $filename, $content ) {
self::create_tmp_dir();
$temp = tempnam( W3TC_CACHE_TMP_DIR, 'temp' );
try {
$f = @fopen( $temp, 'wb' );
if ( ! $f ) {
if ( file_exists( $temp ) ) {
@unlink( $temp );
}
throw new \Exception( 'Can\'t write to temporary file ' . $temp . '' );
}
fwrite( $f, $content );
fclose( $f );
if ( ! @rename( $temp, $filename ) ) {
@unlink( $filename );
if ( ! @rename( $temp, $filename ) ) {
self::mkdir_from( dirname( $filename ), W3TC_CACHE_DIR );
if ( ! @rename( $temp, $filename ) ) {
throw new \Exception( 'Can\'t write to file ' . $filename . '' );
}
}
}
$chmod = 0644;
if ( defined( 'FS_CHMOD_FILE' ) ) {
$chmod = FS_CHMOD_FILE;
}
@chmod( $filename, $chmod );
} catch ( \Exception $ex ) {
if ( file_exists( $temp ) ) {
@unlink( $temp );
}
throw $ex;
}
}
/**
* Takes a W3TC settings array and formats it to a PHP String
*
* @param unknown $data Data.
*
* @return string
*/
public static function format_data_as_settings_file( $data ) {
$config = " $value ) {
$config .= self::format_array_entry_as_settings_file_entry( 1, $key, $value );
}
$config .= ');';
return $config;
}
/**
* Writes array item to file
*
* @param int $tabs Tabs.
* @param string $key Key.
* @param mixed $value Value.
*
* @return string
*/
public static function format_array_entry_as_settings_file_entry( $tabs, $key, $value ) {
$item = str_repeat( "\t", $tabs );
if ( is_numeric( $key ) && (string) (int) $key === (string) $key ) {
$item .= sprintf( '%d => ', $key );
} else {
$item .= sprintf( "'%s' => ", addcslashes( $key, "'\\" ) );
}
switch ( gettype( $value ) ) {
case 'object':
case 'array':
$item .= "array(\r\n";
foreach ( (array) $value as $k => $v ) {
$item .= self::format_array_entry_as_settings_file_entry( $tabs + 1, $k, $v );
}
$item .= sprintf( "%s),\r\n", str_repeat( "\t", $tabs ) );
return $item;
case 'integer':
$data = (string) $value;
break;
case 'double':
$data = (string) $value;
break;
case 'boolean':
$data = ( $value ? 'true' : 'false' );
break;
case 'NULL':
$data = 'null';
break;
default:
case 'string':
$data = "'" . addcslashes( $value, "'\\" ) . "'";
break;
}
$item .= $data . ",\r\n";
return $item;
}
/**
* Ensure that ".htaccess" exists in the specified directory.
*
* If the WP_Filesystem is "direct", then create the file (with mode 0644) if needed.
*
* @since 2.8.2
*
* @param string $dir Directory.
* @return bool
*/
public static function check_htaccess( string $dir ): bool {
$filepath = $dir . DIRECTORY_SEPARATOR . '.htaccess';
if ( ! @file_exists( $filepath ) ) {
$chmod = 0644;
if ( defined( 'FS_CHMOD_FILE' ) ) {
$chmod = FS_CHMOD_FILE;
}
$contents = "\n # Apache 2.4\n Require all denied\n\n\n\n # Apache 2.2\n Deny from all\n\n";
return @file_put_contents( $filepath, $contents ) && chmod( $filepath, $chmod );
}
return false;
}
}