X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/wordpress.git/blobdiff_plain/177fd6fefd2e3d5a0ea6591c71d660cabdb3c1a4..refs/tags/wordpress-2.9:/wp-admin/includes/file.php?ds=sidebyside diff --git a/wp-admin/includes/file.php b/wp-admin/includes/file.php index 575a6782..4120532d 100644 --- a/wp-admin/includes/file.php +++ b/wp-admin/includes/file.php @@ -1,30 +1,78 @@ __( 'Main Index Template' ), 'style.css' => __( 'Stylesheet' ), 'rtl.css' => __( 'RTL Stylesheet' ), 'comments.php' => __( 'Comments' ), 'comments-popup.php' => __( 'Popup Comments' ), 'footer.php' => __( 'Footer' ), 'header.php' => __( 'Header' ), 'sidebar.php' => __( 'Sidebar' ), 'archive.php' => __( 'Archives' ), 'category.php' => __( 'Category Template' ), 'page.php' => __( 'Page Template' ), 'search.php' => __( 'Search Results' ), 'searchform.php' => __( 'Search Form' ), 'single.php' => __( 'Single Post' ), '404.php' => __( '404 Template' ), 'link.php' => __( 'Links Template' ), 'functions.php' => __( 'Theme Functions' ), 'attachment.php' => __( 'Attachment Template' ), 'my-hacks.php' => __( 'my-hacks.php (legacy hacks support)' ), '.htaccess' => __( '.htaccess (for rewrite rules )' ), +/** + * File contains all the administration image manipulation functions. + * + * @package WordPress + * @subpackage Administration + */ + +/** The descriptions for theme files. */ +$wp_file_descriptions = array ( + 'index.php' => __( 'Main Index Template' ), + 'style.css' => __( 'Stylesheet' ), + 'rtl.css' => __( 'RTL Stylesheet' ), + 'comments.php' => __( 'Comments' ), + 'comments-popup.php' => __( 'Popup Comments' ), + 'footer.php' => __( 'Footer' ), + 'header.php' => __( 'Header' ), + 'sidebar.php' => __( 'Sidebar' ), + 'archive.php' => __( 'Archives' ), + 'category.php' => __( 'Category Template' ), + 'page.php' => __( 'Page Template' ), + 'search.php' => __( 'Search Results' ), + 'searchform.php' => __( 'Search Form' ), + 'single.php' => __( 'Single Post' ), + '404.php' => __( '404 Template' ), + 'link.php' => __( 'Links Template' ), + 'functions.php' => __( 'Theme Functions' ), + 'attachment.php' => __( 'Attachment Template' ), + 'image.php' => __('Image Attachment Template'), + 'video.php' => __('Video Attachment Template'), + 'audio.php' => __('Audio Attachment Template'), + 'application.php' => __('Application Attachment Template'), + 'my-hacks.php' => __( 'my-hacks.php (legacy hacks support)' ), + '.htaccess' => __( '.htaccess (for rewrite rules )' ), // Deprecated files 'wp-layout.css' => __( 'Stylesheet' ), 'wp-comments.php' => __( 'Comments Template' ), 'wp-comments-popup.php' => __( 'Popup Comments Template' )); + +/** + * {@internal Missing Short Description}} + * + * @since unknown + * + * @param unknown_type $file + * @return unknown + */ function get_file_description( $file ) { global $wp_file_descriptions; if ( isset( $wp_file_descriptions[basename( $file )] ) ) { return $wp_file_descriptions[basename( $file )]; } - elseif ( file_exists( ABSPATH . $file ) && is_file( ABSPATH . $file ) ) { - $template_data = implode( '', file( ABSPATH . $file ) ); - if ( preg_match( "|Template Name:(.*)|i", $template_data, $name )) - return $name[1]; + elseif ( file_exists( WP_CONTENT_DIR . $file ) && is_file( WP_CONTENT_DIR . $file ) ) { + $template_data = implode( '', file( WP_CONTENT_DIR . $file ) ); + if ( preg_match( '|Template Name:(.*)$|mi', $template_data, $name )) + return _cleanup_header_comment($name[1]) . ' Page Template'; } return basename( $file ); } +/** + * {@internal Missing Short Description}} + * + * @since unknown + * + * @return unknown + */ function get_home_path() { $home = get_option( 'home' ); - if ( $home != '' && $home != get_option( 'siteurl' ) ) { - $home_path = parse_url( $home ); - $home_path = $home_path['path']; - $root = str_replace( $_SERVER["PHP_SELF"], '', $_SERVER["SCRIPT_FILENAME"] ); - $home_path = trailingslashit( $root.$home_path ); + $siteurl = get_option( 'siteurl' ); + if ( $home != '' && $home != $siteurl ) { + $wp_path_rel_to_home = str_replace($home, '', $siteurl); /* $siteurl - $home */ + $pos = strpos($_SERVER["SCRIPT_FILENAME"], $wp_path_rel_to_home); + $home_path = substr($_SERVER["SCRIPT_FILENAME"], 0, $pos); + $home_path = trailingslashit( $home_path ); } else { $home_path = ABSPATH; } @@ -32,21 +80,76 @@ function get_home_path() { return $home_path; } +/** + * {@internal Missing Short Description}} + * + * @since unknown + * + * @param unknown_type $file + * @return unknown + */ function get_real_file_to_edit( $file ) { if ('index.php' == $file || '.htaccess' == $file ) { - $real_file = get_home_path().$file; + $real_file = get_home_path() . $file; } else { - $real_file = ABSPATH.$file; + $real_file = WP_CONTENT_DIR . $file; } return $real_file; } +/** + * Returns a listing of all files in the specified folder and all subdirectories up to 100 levels deep. + * The depth of the recursiveness can be controlled by the $levels param. + * + * @since 2.6.0 + * + * @param string $folder Full path to folder + * @param int $levels (optional) Levels of folders to follow, Default: 100 (PHP Loop limit). + * @return bool|array False on failure, Else array of files + */ +function list_files( $folder = '', $levels = 100 ) { + if( empty($folder) ) + return false; + + if( ! $levels ) + return false; + + $files = array(); + if ( $dir = @opendir( $folder ) ) { + while (($file = readdir( $dir ) ) !== false ) { + if ( in_array($file, array('.', '..') ) ) + continue; + if ( is_dir( $folder . '/' . $file ) ) { + $files2 = list_files( $folder . '/' . $file, $levels - 1); + if( $files2 ) + $files = array_merge($files, $files2 ); + else + $files[] = $folder . '/' . $file . '/'; + } else { + $files[] = $folder . '/' . $file; + } + } + } + @closedir( $dir ); + return $files; +} + +/** + * Determines a writable directory for temporary files. + * Function's preference is to WP_CONTENT_DIR followed by the return value of sys_get_temp_dir(), before finally defaulting to /tmp/ + * + * In the event that this function does not find a writable location, It may be overridden by the WP_TEMP_DIR constant in your wp-config.php file. + * + * @since 2.5.0 + * + * @return string Writable temporary directory + */ function get_temp_dir() { if ( defined('WP_TEMP_DIR') ) return trailingslashit(WP_TEMP_DIR); - $temp = ABSPATH . 'wp-content/'; + $temp = WP_CONTENT_DIR . '/'; if ( is_dir($temp) && is_writable($temp) ) return $temp; @@ -56,25 +159,42 @@ function get_temp_dir() { return '/tmp/'; } -function validate_file( $file, $allowed_files = '' ) { - if ( false !== strpos( $file, '..' )) - return 1; - - if ( false !== strpos( $file, './' )) - return 1; - - if (':' == substr( $file, 1, 1 )) - return 2; - - if (!empty ( $allowed_files ) && (!in_array( $file, $allowed_files ) ) ) - return 3; - - return 0; +/** + * Returns a filename of a Temporary unique file. + * Please note that the calling function must unlink() this itself. + * + * The filename is based off the passed parameter or defaults to the current unix timestamp, + * while the directory can either be passed as well, or by leaving it blank, default to a writable temporary directory. + * + * @since 2.6.0 + * + * @param string $filename (optional) Filename to base the Unique file off + * @param string $dir (optional) Directory to store the file in + * @return string a writable filename + */ +function wp_tempnam($filename = '', $dir = ''){ + if ( empty($dir) ) + $dir = get_temp_dir(); + $filename = basename($filename); + if ( empty($filename) ) + $filename = time(); + + $filename = preg_replace('|\..*$|', '.tmp', $filename); + $filename = $dir . wp_unique_filename($dir, $filename); + touch($filename); + return $filename; } +/** + * {@internal Missing Short Description}} + * + * @since unknown + * + * @param unknown_type $file + * @param unknown_type $allowed_files + * @return unknown + */ function validate_file_to_edit( $file, $allowed_files = '' ) { - $file = stripslashes( $file ); - $code = validate_file( $file, $allowed_files ); if (!$code ) @@ -82,22 +202,26 @@ function validate_file_to_edit( $file, $allowed_files = '' ) { switch ( $code ) { case 1 : - wp_die( __('Sorry, can’t edit files with ".." in the name. If you are trying to edit a file in your WordPress home directory, you can just type the name of the file in.' )); + wp_die( __('Sorry, can’t edit files with “..” in the name. If you are trying to edit a file in your WordPress home directory, you can just type the name of the file in.' )); - case 2 : - wp_die( __('Sorry, can’t call files with their real path.' )); + //case 2 : + // wp_die( __('Sorry, can’t call files with their real path.' )); case 3 : wp_die( __('Sorry, that file cannot be edited.' )); } } -// array wp_handle_upload ( array &file [, array overrides] ) -// file: reference to a single element of $_FILES. Call the function once for each uploaded file. -// overrides: an associative array of names=>values to override default variables with extract( $overrides, EXTR_OVERWRITE ). -// On success, returns an associative array of file attributes. -// On failure, returns $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ). -function wp_handle_upload( &$file, $overrides = false ) { +/** + * {@internal Missing Short Description}} + * + * @since unknown + * + * @param array $file Reference to a single element of $_FILES. Call the function once for each uploaded file. + * @param array $overrides Optional. An associative array of names=>values to override default variables with extract( $overrides, EXTR_OVERWRITE ). + * @return array On success, returns an associative array of file attributes. On failure, returns $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ). + */ +function wp_handle_upload( &$file, $overrides = false, $time = null ) { // The default error handler. if (! function_exists( 'wp_handle_upload_error' ) ) { function wp_handle_upload_error( &$file, $message ) { @@ -105,9 +229,18 @@ function wp_handle_upload( &$file, $overrides = false ) { } } + $file = apply_filters( 'wp_handle_upload_prefilter', $file ); + // You may define your own function and pass the name in $overrides['upload_error_handler'] $upload_error_handler = 'wp_handle_upload_error'; + // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully. + if ( isset( $file['error'] ) && !ctype_digit( $file['error'] ) && $file['error'] ) + return $upload_error_handler( $file, $file['error'] ); + + // You may define your own function and pass the name in $overrides['unique_filename_callback'] + $unique_filename_callback = null; + // $_POST['action'] must be set and its value must equal $overrides['action'] or this: $action = 'wp_handle_upload'; @@ -117,8 +250,10 @@ function wp_handle_upload( &$file, $overrides = false ) { __( "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form." ), __( "The uploaded file was only partially uploaded." ), __( "No file was uploaded." ), + '', __( "Missing a temporary folder." ), - __( "Failed to write file to disk." )); + __( "Failed to write file to disk." ), + __( "File upload stopped by extension." )); // All tests are on by default. Most can be turned off by $override[{test_name}] = false; $test_form = true; @@ -142,7 +277,7 @@ function wp_handle_upload( &$file, $overrides = false ) { // A non-empty file will pass this test. if ( $test_size && !($file['size'] > 0 ) ) - return $upload_error_handler( $file, __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini.' )); + return $upload_error_handler( $file, __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.' )); // A properly uploaded file will pass this test. There should be no reason to override this one. if (! @ is_uploaded_file( $file['tmp_name'] ) ) @@ -162,10 +297,12 @@ function wp_handle_upload( &$file, $overrides = false ) { if ( !$type ) $type = $file['type']; + } else { + $type = ''; } // A writable uploads dir will pass this test. Again, there's no point overriding this one. - if ( ! ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) ) + if ( ! ( ( $uploads = wp_upload_dir($time) ) && false === $uploads['error'] ) ) return $upload_error_handler( $file, $uploads['error'] ); $filename = wp_unique_filename( $uploads['path'], $file['name'], $unique_filename_callback ); @@ -184,51 +321,185 @@ function wp_handle_upload( &$file, $overrides = false ) { // Compute the URL $url = $uploads['url'] . "/$filename"; + return apply_filters( 'wp_handle_upload', array( 'file' => $new_file, 'url' => $url, 'type' => $type ) ); +} + +/** + * {@internal Missing Short Description}} + * + * Pass this function an array similar to that of a $_FILES POST array. + * + * @since unknown + * + * @param unknown_type $file + * @param unknown_type $overrides + * @return unknown + */ +function wp_handle_sideload( &$file, $overrides = false ) { + // The default error handler. + if (! function_exists( 'wp_handle_upload_error' ) ) { + function wp_handle_upload_error( &$file, $message ) { + return array( 'error'=>$message ); + } + } + + // You may define your own function and pass the name in $overrides['upload_error_handler'] + $upload_error_handler = 'wp_handle_upload_error'; + + // You may define your own function and pass the name in $overrides['unique_filename_callback'] + $unique_filename_callback = null; + + // $_POST['action'] must be set and its value must equal $overrides['action'] or this: + $action = 'wp_handle_sideload'; + + // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error']. + $upload_error_strings = array( false, + __( "The uploaded file exceeds the upload_max_filesize directive in php.ini." ), + __( "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form." ), + __( "The uploaded file was only partially uploaded." ), + __( "No file was uploaded." ), + '', + __( "Missing a temporary folder." ), + __( "Failed to write file to disk." ), + __( "File upload stopped by extension." )); + + // All tests are on by default. Most can be turned off by $override[{test_name}] = false; + $test_form = true; + $test_size = true; + + // If you override this, you must provide $ext and $type!!!! + $test_type = true; + $mimes = false; + + // Install user overrides. Did we mention that this voids your warranty? + if ( is_array( $overrides ) ) + extract( $overrides, EXTR_OVERWRITE ); + + // A correct form post will pass this test. + if ( $test_form && (!isset( $_POST['action'] ) || ($_POST['action'] != $action ) ) ) + return $upload_error_handler( $file, __( 'Invalid form submission.' )); + + // A successful upload will pass this test. It makes no sense to override this one. + if ( $file['error'] > 0 ) + return $upload_error_handler( $file, $upload_error_strings[$file['error']] ); + + // A non-empty file will pass this test. + if ( $test_size && !(filesize($file['tmp_name']) > 0 ) ) + return $upload_error_handler( $file, __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini.' )); + + // A properly uploaded file will pass this test. There should be no reason to override this one. + if (! @ is_file( $file['tmp_name'] ) ) + return $upload_error_handler( $file, __( 'Specified file does not exist.' )); + + // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter. + if ( $test_type ) { + $wp_filetype = wp_check_filetype( $file['name'], $mimes ); + + extract( $wp_filetype ); + + if ( ( !$type || !$ext ) && !current_user_can( 'unfiltered_upload' ) ) + return $upload_error_handler( $file, __( 'File type does not meet security guidelines. Try another.' )); + + if ( !$ext ) + $ext = ltrim(strrchr($file['name'], '.'), '.'); + + if ( !$type ) + $type = $file['type']; + } + + // A writable uploads dir will pass this test. Again, there's no point overriding this one. + if ( ! ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) ) + return $upload_error_handler( $file, $uploads['error'] ); + + $filename = wp_unique_filename( $uploads['path'], $file['name'], $unique_filename_callback ); + + // Strip the query strings. + $filename = str_replace('?','-', $filename); + $filename = str_replace('&','-', $filename); + + // Move the file to the uploads dir + $new_file = $uploads['path'] . "/$filename"; + if ( false === @ rename( $file['tmp_name'], $new_file ) ) { + return $upload_error_handler( $file, sprintf( __('The uploaded file could not be moved to %s.' ), $uploads['path'] ) ); + } + + // Set correct file permissions + $stat = stat( dirname( $new_file )); + $perms = $stat['mode'] & 0000666; + @ chmod( $new_file, $perms ); + + // Compute the URL + $url = $uploads['url'] . "/$filename"; + $return = apply_filters( 'wp_handle_upload', array( 'file' => $new_file, 'url' => $url, 'type' => $type ) ); return $return; } /** -* Downloads a url to a local file using the Snoopy HTTP Class -* -* @param string $url the URL of the file to download -* @return mixed WP_Error on failure, string Filename on success. -*/ + * Downloads a url to a local temporary file using the WordPress HTTP Class. + * Please note, That the calling function must unlink() the file. + * + * @since 2.5.0 + * + * @param string $url the URL of the file to download + * @return mixed WP_Error on failure, string Filename on success. + */ function download_url( $url ) { //WARNING: The file is not automatically deleted, The script must unlink() the file. - if( ! $url ) + if ( ! $url ) return new WP_Error('http_no_url', __('Invalid URL Provided')); - $tmpfname = tempnam(get_temp_dir(), 'wpupdate'); - if( ! $tmpfname ) + $tmpfname = wp_tempnam($url); + if ( ! $tmpfname ) return new WP_Error('http_no_file', __('Could not create Temporary file')); - $handle = @fopen($tmpfname, 'w'); - if( ! $handle ) + $handle = @fopen($tmpfname, 'wb'); + if ( ! $handle ) return new WP_Error('http_no_file', __('Could not create Temporary file')); - require_once( ABSPATH . 'wp-includes/class-snoopy.php' ); - $snoopy = new Snoopy(); - $snoopy->fetch($url); + $response = wp_remote_get($url, array('timeout' => 60)); + + if ( is_wp_error($response) ) { + fclose($handle); + unlink($tmpfname); + return $response; + } - if( $snoopy->status != '200' ){ + if ( $response['response']['code'] != '200' ){ fclose($handle); unlink($tmpfname); - return new WP_Error('http_404', trim($snoopy->response_code)); + return new WP_Error('http_404', trim($response['response']['message'])); } - fwrite($handle, $snoopy->results); + + fwrite($handle, $response['body']); fclose($handle); return $tmpfname; } +/** + * Unzip's a specified ZIP file to a location on the Filesystem via the WordPress Filesystem Abstraction. + * Assumes that WP_Filesystem() has already been called and set up. + * + * Attempts to increase the PHP Memory limit to 256M before uncompressing, + * However, The most memory required shouldn't be much larger than the Archive itself. + * + * @since 2.5.0 + * + * @param string $file Full path and filename of zip archive + * @param string $to Full path on the filesystem to extract archive to + * @return mixed WP_Error on failure, True on success + */ function unzip_file($file, $to) { global $wp_filesystem; if ( ! $wp_filesystem || !is_object($wp_filesystem) ) return new WP_Error('fs_unavailable', __('Could not access filesystem.')); + // Unzip uses a lot of memory, but not this much hopefully + @ini_set('memory_limit', '256M'); + $fs =& $wp_filesystem; require_once(ABSPATH . 'wp-admin/includes/class-pclzip.php'); @@ -242,37 +513,57 @@ function unzip_file($file, $to) { if ( 0 == count($archive_files) ) return new WP_Error('empty_archive', __('Empty archive')); - $to = trailingslashit($to); - $path = explode('/', $to); - $tmppath = ''; - for ( $j = 0; $j < count($path) - 1; $j++ ) { - $tmppath .= $path[$j] . '/'; - if ( ! $fs->is_dir($tmppath) ) - $fs->mkdir($tmppath, 0755); + $path = explode('/', untrailingslashit($to)); + for ( $i = count($path); $i > 0; $i-- ) { //>0 = first element is empty allways for paths starting with '/' + $tmppath = implode('/', array_slice($path, 0, $i) ); + if ( $fs->is_dir($tmppath) ) { //Found the highest folder that exists, Create from here(ie +1) + for ( $i = $i + 1; $i <= count($path); $i++ ) { + $tmppath = implode('/', array_slice($path, 0, $i) ); + if ( ! $fs->mkdir($tmppath, FS_CHMOD_DIR) ) + return new WP_Error('mkdir_failed', __('Could not create directory'), $tmppath); + } + break; //Exit main for loop + } } + $to = trailingslashit($to); foreach ($archive_files as $file) { - $path = explode('/', $file['filename']); - $tmppath = ''; - - // Loop through each of the items and check that the folder exists. - for ( $j = 0; $j < count($path) - 1; $j++ ) { - $tmppath .= $path[$j] . '/'; - if ( ! $fs->is_dir($to . $tmppath) ) - if ( !$fs->mkdir($to . $tmppath, 0755) ) - return new WP_Error('mkdir_failed', __('Could not create directory')); + $path = $file['folder'] ? $file['filename'] : dirname($file['filename']); + $path = explode('/', $path); + for ( $i = count($path); $i >= 0; $i-- ) { //>=0 as the first element contains data + if ( empty($path[$i]) ) + continue; + $tmppath = $to . implode('/', array_slice($path, 0, $i) ); + if ( $fs->is_dir($tmppath) ) {//Found the highest folder that exists, Create from here + for ( $i = $i + 1; $i <= count($path); $i++ ) { //< count() no file component please. + $tmppath = $to . implode('/', array_slice($path, 0, $i) ); + if ( ! $fs->is_dir($tmppath) && ! $fs->mkdir($tmppath, FS_CHMOD_DIR) ) + return new WP_Error('mkdir_failed', __('Could not create directory'), $tmppath); + } + break; //Exit main for loop + } } // We've made sure the folders are there, so let's extract the file now: - if ( ! $file['folder'] ) + if ( ! $file['folder'] ) { if ( !$fs->put_contents( $to . $file['filename'], $file['content']) ) - return new WP_Error('copy_failed', __('Could not copy file')); - $fs->chmod($to . $file['filename'], 0644); + return new WP_Error('copy_failed', __('Could not copy file'), $to . $file['filename']); + $fs->chmod($to . $file['filename'], FS_CHMOD_FILE); + } } - return true; } +/** + * Copies a directory from one location to another via the WordPress Filesystem Abstraction. + * Assumes that WP_Filesystem() has already been called and setup. + * + * @since 2.5.0 + * + * @param string $from source directory + * @param string $to destination directory + * @return mixed WP_Error on failure, True on success. + */ function copy_dir($from, $to) { global $wp_filesystem; @@ -283,53 +574,292 @@ function copy_dir($from, $to) { foreach ( (array) $dirlist as $filename => $fileinfo ) { if ( 'f' == $fileinfo['type'] ) { - if ( ! $wp_filesystem->copy($from . $filename, $to . $filename, true) ) - return false; - $wp_filesystem->chmod($to . $filename, 0644); + if ( ! $wp_filesystem->copy($from . $filename, $to . $filename, true) ) { + // If copy failed, chmod file to 0644 and try again. + $wp_filesystem->chmod($to . $filename, 0644); + if ( ! $wp_filesystem->copy($from . $filename, $to . $filename, true) ) + return new WP_Error('copy_failed', __('Could not copy file'), $to . $filename); + } + $wp_filesystem->chmod($to . $filename, FS_CHMOD_FILE); } elseif ( 'd' == $fileinfo['type'] ) { - if ( !$wp_filesystem->mkdir($to . $filename, 0755) ) - return false; - if ( !copy_dir($from . $filename, $to . $filename) ) - return false; + if ( !$wp_filesystem->is_dir($to . $filename) ) { + if ( !$wp_filesystem->mkdir($to . $filename, FS_CHMOD_DIR) ) + return new WP_Error('mkdir_failed', __('Could not create directory'), $to . $filename); + } + $result = copy_dir($from . $filename, $to . $filename); + if ( is_wp_error($result) ) + return $result; } } - return true; } -function WP_Filesystem( $args = false, $preference = false ) { +/** + * Initialises and connects the WordPress Filesystem Abstraction classes. + * This function will include the chosen transport and attempt connecting. + * + * Plugins may add extra transports, And force WordPress to use them by returning the filename via the 'filesystem_method_file' filter. + * + * @since 2.5.0 + * + * @param array $args (optional) Connection args, These are passed directly to the WP_Filesystem_*() classes. + * @param string $context (optional) Context for get_filesystem_method(), See function declaration for more information. + * @return boolean false on failure, true on success + */ +function WP_Filesystem( $args = false, $context = false ) { global $wp_filesystem; - $method = get_filesystem_method($preference); + require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php'); + + $method = get_filesystem_method($args, $context); + if ( ! $method ) return false; - require_once('class-wp-filesystem-'.$method.'.php'); + if ( ! class_exists("WP_Filesystem_$method") ) { + $abstraction_file = apply_filters('filesystem_method_file', ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php', $method); + if( ! file_exists($abstraction_file) ) + return; + + require_once($abstraction_file); + } $method = "WP_Filesystem_$method"; $wp_filesystem = new $method($args); - if ( $wp_filesystem->errors->get_error_code() ) + //Define the timeouts for the connections. Only available after the construct is called to allow for per-transport overriding of the default. + if ( ! defined('FS_CONNECT_TIMEOUT') ) + define('FS_CONNECT_TIMEOUT', 30); + if ( ! defined('FS_TIMEOUT') ) + define('FS_TIMEOUT', 30); + + if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() ) return false; if ( !$wp_filesystem->connect() ) return false; //There was an erorr connecting to the server. + // Set the permission constants if not already set. + if ( ! defined('FS_CHMOD_DIR') ) + define('FS_CHMOD_DIR', 0755 ); + if ( ! defined('FS_CHMOD_FILE') ) + define('FS_CHMOD_FILE', 0644 ); + return true; } -function get_filesystem_method() { - $tempFile = tempnam(get_temp_dir(), 'WPU'); +/** + * Determines which Filesystem Method to use. + * The priority of the Transports are: Direct, SSH2, FTP PHP Extension, FTP Sockets (Via Sockets class, or fsoxkopen()) + * + * Note that the return value of this function can be overridden in 2 ways + * - By defining FS_METHOD in your wp-config.php file + * - By using the filesystem_method filter + * Valid values for these are: 'direct', 'ssh', 'ftpext' or 'ftpsockets' + * Plugins may also define a custom transport handler, See the WP_Filesystem function for more information. + * + * @since 2.5.0 + * + * @param array $args Connection details. + * @param string $context Full path to the directory that is tested for being writable. + * @return string The transport to use, see description for valid return values. + */ +function get_filesystem_method($args = array(), $context = false) { + $method = defined('FS_METHOD') ? FS_METHOD : false; //Please ensure that this is either 'direct', 'ssh', 'ftpext' or 'ftpsockets' + + if( ! $method && function_exists('getmyuid') && function_exists('fileowner') ){ + if ( !$context ) + $context = WP_CONTENT_DIR; + $context = trailingslashit($context); + $temp_file_name = $context . 'temp-write-test-' . time(); + $temp_handle = @fopen($temp_file_name, 'w'); + if ( $temp_handle ) { + if ( getmyuid() == @fileowner($temp_file_name) ) + $method = 'direct'; + @fclose($temp_handle); + @unlink($temp_file_name); + } + } + + if ( ! $method && isset($args['connection_type']) && 'ssh' == $args['connection_type'] && extension_loaded('ssh2') && function_exists('stream_get_contents') ) $method = 'ssh2'; + if ( ! $method && extension_loaded('ftp') ) $method = 'ftpext'; + if ( ! $method && ( extension_loaded('sockets') || function_exists('fsockopen') ) ) $method = 'ftpsockets'; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread + return apply_filters('filesystem_method', $method, $args); +} - if ( getmyuid() == fileowner($tempFile) ) { - unlink($tempFile); - return 'direct'; +/** + * Displays a form to the user to request for their FTP/SSH details in order to connect to the filesystem. + * All chosen/entered details are saved, Excluding the Password. + * + * Hostnames may be in the form of hostname:portnumber (eg: wordpress.org:2467) to specify an alternate FTP/SSH port. + * + * Plugins may override this form by returning true|false via the request_filesystem_credentials filter. + * + * @since 2.5.0 + * + * @param string $form_post the URL to post the form to + * @param string $type the chosen Filesystem method in use + * @param boolean $error if the current request has failed to connect + * @param string $context The directory which is needed access to, The write-test will be performed on this directory by get_filesystem_method() + * @return boolean False on failure. True on success. + */ +function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false) { + $req_cred = apply_filters('request_filesystem_credentials', '', $form_post, $type, $error, $context); + if ( '' !== $req_cred ) + return $req_cred; + + if ( empty($type) ) + $type = get_filesystem_method(array(), $context); + + if ( 'direct' == $type ) + return true; + + $credentials = get_option('ftp_credentials', array( 'hostname' => '', 'username' => '')); + + // If defined, set it to that, Else, If POST'd, set it to that, If not, Set it to whatever it previously was(saved details in option) + $credentials['hostname'] = defined('FTP_HOST') ? FTP_HOST : (!empty($_POST['hostname']) ? stripslashes($_POST['hostname']) : $credentials['hostname']); + $credentials['username'] = defined('FTP_USER') ? FTP_USER : (!empty($_POST['username']) ? stripslashes($_POST['username']) : $credentials['username']); + $credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($_POST['password']) ? stripslashes($_POST['password']) : ''); + + // Check to see if we are setting the public/private keys for ssh + $credentials['public_key'] = defined('FTP_PUBKEY') ? FTP_PUBKEY : (!empty($_POST['public_key']) ? stripslashes($_POST['public_key']) : ''); + $credentials['private_key'] = defined('FTP_PRIKEY') ? FTP_PRIKEY : (!empty($_POST['private_key']) ? stripslashes($_POST['private_key']) : ''); + + //sanitize the hostname, Some people might pass in odd-data: + $credentials['hostname'] = preg_replace('|\w+://|', '', $credentials['hostname']); //Strip any schemes off + + if ( strpos($credentials['hostname'], ':') ) { + list( $credentials['hostname'], $credentials['port'] ) = explode(':', $credentials['hostname'], 2); + if ( ! is_numeric($credentials['port']) ) + unset($credentials['port']); } else { - unlink($tempFile); + unset($credentials['port']); } - if ( extension_loaded('ftp') ) return 'ftpext'; - if ( extension_loaded('sockets') || function_exists('fsockopen') ) return 'ftpsockets'; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread + if ( (defined('FTP_SSH') && FTP_SSH) || (defined('FS_METHOD') && 'ssh' == FS_METHOD) ) + $credentials['connection_type'] = 'ssh'; + else if ( (defined('FTP_SSL') && FTP_SSL) && 'ftpext' == $type ) //Only the FTP Extension understands SSL + $credentials['connection_type'] = 'ftps'; + else if ( !empty($_POST['connection_type']) ) + $credentials['connection_type'] = stripslashes($_POST['connection_type']); + else if ( !isset($credentials['connection_type']) ) //All else fails (And its not defaulted to something else saved), Default to FTP + $credentials['connection_type'] = 'ftp'; + + if ( ! $error && + ( + ( !empty($credentials['password']) && !empty($credentials['username']) && !empty($credentials['hostname']) ) || + ( 'ssh' == $credentials['connection_type'] && !empty($credentials['public_key']) && !empty($credentials['private_key']) ) + ) ) { + $stored_credentials = $credentials; + if ( !empty($stored_credentials['port']) ) //save port as part of hostname to simplify above code. + $stored_credentials['hostname'] .= ':' . $stored_credentials['port']; + + unset($stored_credentials['password'], $stored_credentials['port'], $stored_credentials['private_key'], $stored_credentials['public_key']); + update_option('ftp_credentials', $stored_credentials); + return $credentials; + } + $hostname = ''; + $username = ''; + $password = ''; + $connection_type = ''; + if ( !empty($credentials) ) + extract($credentials, EXTR_OVERWRITE); + if ( $error ) { + $error_string = __('Error: There was an error connecting to the server, Please verify the settings are correct.'); + if ( is_wp_error($error) ) + $error_string = $error->get_error_message(); + echo '

' . $error_string . '

'; + } + + $types = array(); + if ( extension_loaded('ftp') || extension_loaded('sockets') || function_exists('fsockopen') ) + $types[ 'ftp' ] = __('FTP'); + if ( extension_loaded('ftp') ) //Only this supports FTPS + $types[ 'ftps' ] = __('FTPS (SSL)'); + if ( extension_loaded('ssh2') && function_exists('stream_get_contents') ) + $types[ 'ssh' ] = __('SSH2'); + + $types = apply_filters('fs_ftp_connection_types', $types, $credentials, $type, $error, $context); + +?> + +
+
+ +

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
" size="40" />
size="40" />
size="40" />
+
+
+ +

size="40" />
size="40" /> +
+
+ $text ) : ?> + + +
+
+ + + + + + + +

+ +

+
+
+