357 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			357 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * File: Util_WpFile.php
 | |
|  *
 | |
|  * @package W3TC
 | |
|  */
 | |
| 
 | |
| namespace W3TC;
 | |
| 
 | |
| /**
 | |
|  * Class: Util_WpFile
 | |
|  */
 | |
| class Util_WpFile {
 | |
| 	/**
 | |
| 	 * Check WP_Filesystem credentials when running ajax.
 | |
| 	 *
 | |
| 	 * @since 2.2.1
 | |
| 	 *
 | |
| 	 * @param string $extra Extra markup for an error message.
 | |
| 	 */
 | |
| 	public static function ajax_check_credentials( $extra = null ) {
 | |
| 		$access_type = get_filesystem_method();
 | |
| 		ob_start();
 | |
| 		$credentials = request_filesystem_credentials(
 | |
| 			site_url() . '/wp-admin/',
 | |
| 			$access_type
 | |
| 		);
 | |
| 		ob_end_clean();
 | |
| 
 | |
| 		if ( false === $credentials || ! WP_Filesystem( $credentials ) ) {
 | |
| 			global $wp_filesystem;
 | |
| 
 | |
| 			$status['error'] = sprintf(
 | |
| 				// translators: 1: Filesystem access method: "direct", "ssh2", "ftpext" or "ftpsockets".
 | |
| 				__(
 | |
| 					'Unable to connect to the filesystem (using %1$s). Please confirm your credentials.  %2$s',
 | |
| 					'w3-total-cache'
 | |
| 				),
 | |
| 				$access_type,
 | |
| 				$extra
 | |
| 			);
 | |
| 
 | |
| 			// Pass through the error from WP_Filesystem if one was raised.
 | |
| 			if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) &&
 | |
| 				$wp_filesystem->errors->has_errors() ) {
 | |
| 					$status['error'] = esc_html( $wp_filesystem->errors->get_error_message() );
 | |
| 			}
 | |
| 
 | |
| 			wp_send_json_error( $status );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Tries to write file content
 | |
| 	 *
 | |
| 	 * @param string  $filename path to file
 | |
| 	 * @param string  $content  data to write
 | |
| 	 * @param string  $method   Which method to use when creating
 | |
| 	 * @param string  $url      Where to redirect after creation
 | |
| 	 * @param bool|string $context  folder in which to write file
 | |
| 	 * @throws Util_WpFile_FilesystemWriteException
 | |
| 	 * @return void
 | |
| 	 */
 | |
| 	static public function write_to_file( $filename, $content ) {
 | |
| 		if ( @file_put_contents( $filename, $content ) )
 | |
| 			return;
 | |
| 
 | |
| 		try {
 | |
| 			self::request_filesystem_credentials();
 | |
| 		} catch ( Util_WpFile_FilesystemOperationException $ex ) {
 | |
| 			throw new Util_WpFile_FilesystemWriteException( $ex->getMessage(),
 | |
| 				$ex->credentials_form(), $filename, $content );
 | |
| 		}
 | |
| 
 | |
| 		global $wp_filesystem;
 | |
| 		if ( !$wp_filesystem->put_contents( $filename, $content ) ) {
 | |
| 			throw new Util_WpFile_FilesystemWriteException(
 | |
| 				'FTP credentials don\'t allow to write to file <strong>' .
 | |
| 				$filename . '</strong>', self::get_filesystem_credentials_form(),
 | |
| 				$filename, $content );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Copy file using WordPress filesystem functions.
 | |
| 	 *
 | |
| 	 * @param unknown $source_filename
 | |
| 	 * @param unknown $destination_filename
 | |
| 	 * @param string  $method               Which method to use when creating
 | |
| 	 * @param string  $url                  Where to redirect after creation
 | |
| 	 * @param bool|string $context              folder to copy files too
 | |
| 	 * @throws Util_WpFile_FilesystemCopyException
 | |
| 	 */
 | |
| 	static public function copy_file( $source_filename, $destination_filename ) {
 | |
| 		$contents = @file_get_contents( $source_filename );
 | |
| 		if ( $contents ) {
 | |
| 			@file_put_contents( $destination_filename, $contents );
 | |
| 		}
 | |
| 		if ( @file_exists( $destination_filename ) ) {
 | |
| 			if ( @file_get_contents( $destination_filename ) == $contents )
 | |
| 				return;
 | |
| 		}
 | |
| 
 | |
| 		try {
 | |
| 			self::request_filesystem_credentials();
 | |
| 		} catch ( Util_WpFile_FilesystemOperationException $ex ) {
 | |
| 			throw new Util_WpFile_FilesystemCopyException( $ex->getMessage(),
 | |
| 				$ex->credentials_form(),
 | |
| 				$source_filename, $destination_filename );
 | |
| 		}
 | |
| 
 | |
| 		global $wp_filesystem;
 | |
| 		if ( !$wp_filesystem->put_contents( $destination_filename, $contents,
 | |
| 				FS_CHMOD_FILE ) ) {
 | |
| 			throw new Util_WpFile_FilesystemCopyException(
 | |
| 				'FTP credentials don\'t allow to copy to file <strong>' .
 | |
| 				$destination_filename . '</strong>',
 | |
| 				self::get_filesystem_credentials_form(),
 | |
| 				$source_filename, $destination_filename );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 *
 | |
| 	 *
 | |
| 	 * @param unknown $folder
 | |
| 	 * @param string  $method  Which method to use when creating
 | |
| 	 * @param string  $url     Where to redirect after creation
 | |
| 	 * @param bool|string $context folder to create folder in
 | |
| 	 * @throws Util_WpFile_FilesystemMkdirException
 | |
| 	 */
 | |
| 	static private function create_folder( $folder, $from_folder ) {
 | |
| 		if ( @is_dir( $folder ) )
 | |
| 			return;
 | |
| 
 | |
| 		if ( Util_File::mkdir_from_safe( $folder, $from_folder ) )
 | |
| 			return;
 | |
| 
 | |
| 		try {
 | |
| 			self::request_filesystem_credentials();
 | |
| 		} catch ( Util_WpFile_FilesystemOperationException $ex ) {
 | |
| 			throw new Util_WpFile_FilesystemMkdirException( $ex->getMessage(),
 | |
| 				$ex->credentials_form(), $folder );
 | |
| 		}
 | |
| 
 | |
| 		global $wp_filesystem;
 | |
| 		if ( !$wp_filesystem->mkdir( $folder, FS_CHMOD_DIR ) ) {
 | |
| 			throw new Util_WpFile_FilesystemMkdirException(
 | |
| 				'FTP credentials don\'t allow to create folder <strong>' .
 | |
| 				$folder . '</strong>',
 | |
| 				self::get_filesystem_credentials_form(),
 | |
| 				$folder );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 *
 | |
| 	 *
 | |
| 	 * @param unknown $folder
 | |
| 	 * @param string  $method  Which method to use when creating
 | |
| 	 * @param string  $url     Where to redirect after creation
 | |
| 	 * @param bool|string $context folder to create folder in
 | |
| 	 * @throws Util_WpFile_FilesystemOperationException with S/FTP form if it can't get the required filesystem credentials
 | |
| 	 * @throws FileOperationException
 | |
| 	 */
 | |
| 	static public function create_writeable_folder( $folder, $from_folder ) {
 | |
| 		self::create_folder( $folder, $from_folder );
 | |
| 
 | |
| 		$permissions = array( 0755, 0775, 0777 );
 | |
| 
 | |
| 		for ( $set_index = 0; $set_index < count( $permissions ); $set_index++ ) {
 | |
| 			if ( is_writable( $folder ) )
 | |
| 				break;
 | |
| 
 | |
| 			self::chmod( $folder, $permissions[$set_index] );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 *
 | |
| 	 *
 | |
| 	 * @param unknown $folder
 | |
| 	 * @param string  $method  Which method to use when creating
 | |
| 	 * @param string  $url     Where to redirect after creation
 | |
| 	 * @param bool|string $context path folder where delete folders resides
 | |
| 	 * @throws Util_WpFile_FilesystemRmdirException
 | |
| 	 */
 | |
| 	static public function delete_folder( $folder ) {
 | |
| 		if ( !@is_dir( $folder ) )
 | |
| 			return;
 | |
| 
 | |
| 		Util_File::rmdir( $folder );
 | |
| 		if ( !@is_dir( $folder ) )
 | |
| 			return;
 | |
| 
 | |
| 		try {
 | |
| 			self::request_filesystem_credentials();
 | |
| 		} catch ( Util_WpFile_FilesystemOperationException $ex ) {
 | |
| 			throw new Util_WpFile_FilesystemRmdirException( $ex->getMessage(),
 | |
| 				$ex->credentials_form(), $folder );
 | |
| 		}
 | |
| 
 | |
| 		global $wp_filesystem;
 | |
| 		if ( !$wp_filesystem->rmdir( $folder ) ) {
 | |
| 			throw new Util_WpFile_FilesystemRmdirException(
 | |
| 				__( 'FTP credentials don\'t allow to delete folder ', 'w3-total-cache' ) .
 | |
| 				'<strong>' . $folder . '</strong>',
 | |
| 				self::get_filesystem_credentials_form(),
 | |
| 				$folder );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 *
 | |
| 	 *
 | |
| 	 * @param string  $filename
 | |
| 	 * @param int     $permission
 | |
| 	 * @return void
 | |
| 	 * @throws Util_WpFile_FilesystemChmodException
 | |
| 	 */
 | |
| 	static private function chmod( $filename, $permission ) {
 | |
| 		if ( @chmod( $filename, $permission ) )
 | |
| 			return;
 | |
| 
 | |
| 
 | |
| 		try {
 | |
| 			self::request_filesystem_credentials();
 | |
| 		} catch ( Util_WpFile_FilesystemOperationException $ex ) {
 | |
| 			throw new Util_WpFile_FilesystemChmodException( $ex->getMessage(),
 | |
| 				$ex->credentials_form(), $filename, $permission );
 | |
| 		}
 | |
| 
 | |
| 		global $wp_filesystem;
 | |
| 		if ( !$wp_filesystem->chmod( $filename, $permission, true ) ) {
 | |
| 			throw new Util_WpFile_FilesystemChmodException(
 | |
| 				__( 'FTP credentials don\'t allow to chmod ', 'w3-total-cache' ) .
 | |
| 				'<strong>' . $filename . '</strong>',
 | |
| 				self::get_filesystem_credentials_form(),
 | |
| 				$filename, $permission );
 | |
| 		}
 | |
| 
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 *
 | |
| 	 *
 | |
| 	 * @param unknown $file
 | |
| 	 * @param string  $method
 | |
| 	 * @param string  $url
 | |
| 	 * @param bool|string $context folder where file to be deleted resides
 | |
| 	 * @throws Util_WpFile_FilesystemOperationException with S/FTP form if it can't get the required filesystem credentials
 | |
| 	 */
 | |
| 	static public function delete_file( $filename ) {
 | |
| 		if ( !@file_exists( $filename ) )
 | |
| 			return;
 | |
| 		if ( @unlink( $filename ) )
 | |
| 			return;
 | |
| 
 | |
| 		try {
 | |
| 			self::request_filesystem_credentials();
 | |
| 		} catch ( Util_WpFile_FilesystemOperationException $ex ) {
 | |
| 			throw new Util_WpFile_FilesystemRmException( $ex->getMessage(),
 | |
| 				$ex->credentials_form(), $filename );
 | |
| 		}
 | |
| 
 | |
| 		global $wp_filesystem;
 | |
| 		if ( !$wp_filesystem->delete( $filename ) ) {
 | |
| 			throw new Util_WpFile_FilesystemRmException(
 | |
| 				__( 'FTP credentials don\'t allow to delete ', 'w3-total-cache' ) .
 | |
| 				'<strong>' . $filename . '</strong>',
 | |
| 				self::get_filesystem_credentials_form(),
 | |
| 				$filename );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get WordPress filesystems credentials. Required for WP filesystem usage.
 | |
| 	 *
 | |
| 	 * @param string  $method  Which method to use when creating
 | |
| 	 * @param string  $url     Where to redirect after creation
 | |
| 	 * @param bool|string $context path to folder that should be have filesystem credentials.
 | |
| 	 * If false WP_CONTENT_DIR is assumed
 | |
| 	 * @throws Util_WpFile_FilesystemOperationException with S/FTP form if it can't get the required filesystem credentials
 | |
| 	 */
 | |
| 	private static function request_filesystem_credentials( $method = '', $url = '', $context = false ) {
 | |
| 		if ( strlen( $url ) <= 0 ) {
 | |
| 			$url = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
 | |
| 		}
 | |
| 
 | |
| 		$url = preg_replace( '/&w3tc_note=([^&]+)/', '', $url );
 | |
| 
 | |
| 		// Ensure request_filesystem_credentials() is available.
 | |
| 		require_once ABSPATH . 'wp-admin/includes/file.php';
 | |
| 		require_once ABSPATH . 'wp-admin/includes/template.php';
 | |
| 
 | |
| 		$success = true;
 | |
| 		ob_start();
 | |
| 		if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, $context, array() ) ) ) {
 | |
| 			$success =  false;
 | |
| 		}
 | |
| 		$form = ob_get_contents();
 | |
| 		ob_end_clean();
 | |
| 
 | |
| 		ob_start();
 | |
| 		// If first check failed try again and show error message
 | |
| 		if ( !WP_Filesystem( $creds ) && $success ) {
 | |
| 			request_filesystem_credentials( $url, $method, true, false, array() );
 | |
| 			$success =  false;
 | |
| 			$form = ob_get_contents();
 | |
| 		}
 | |
| 		ob_end_clean();
 | |
| 
 | |
| 		$error = '';
 | |
| 		if ( preg_match( "/<div([^c]+)class=\"error\">(.+)<\/div>/", $form, $matches ) ) {
 | |
| 			$error = $matches[2];
 | |
| 			$form = str_replace( $matches[0], '', $form );
 | |
| 		}
 | |
| 
 | |
| 		if ( !$success ) {
 | |
| 			throw new Util_WpFile_FilesystemOperationException( $error, $form );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 *
 | |
| 	 *
 | |
| 	 * @param string  $method
 | |
| 	 * @param string  $url
 | |
| 	 * @param bool|string $context
 | |
| 	 * @return Util_WpFile_FilesystemOperationException with S/FTP form
 | |
| 	 */
 | |
| 	static private function get_filesystem_credentials_form( $method = '', $url = '',
 | |
| 		$context = false ) {
 | |
| 		// Ensure request_filesystem_credentials() is available.
 | |
| 		require_once ABSPATH . 'wp-admin/includes/file.php';
 | |
| 		require_once ABSPATH . 'wp-admin/includes/template.php';
 | |
| 
 | |
| 		ob_start();
 | |
| 		// If first check failed try again and show error message
 | |
| 		request_filesystem_credentials( $url, $method, true, false, array() );
 | |
| 		$success =  false;
 | |
| 		$form = ob_get_contents();
 | |
| 
 | |
| 		ob_end_clean();
 | |
| 
 | |
| 		$error = '';
 | |
| 		if ( preg_match( "/<div([^c]+)class=\"error\">(.+)<\/div>/", $form, $matches ) ) {
 | |
| 			$form = str_replace( $matches[0], '', $form );
 | |
| 		}
 | |
| 
 | |
| 		$form = str_replace( '<input ', '<input class="w3tc-ignore-change" ', $form );
 | |
| 
 | |
| 		return $form;
 | |
| 	}
 | |
| }
 |