Ticket #30245: 30245.2.diff
File 30245.2.diff, 20.9 KB (added by , 10 years ago) |
---|
-
src/wp-admin/includes/class-wp-upgrader-skins.php
28 28 } 29 29 30 30 public function set_upgrader(&$upgrader) { 31 31 if ( is_object($upgrader) ) 32 32 $this->upgrader =& $upgrader; 33 33 $this->add_strings(); 34 34 } 35 35 36 36 public function add_strings() { 37 37 } 38 38 39 39 public function set_result($result) { 40 40 $this->result = $result; 41 41 } 42 42 43 public function request_filesystem_credentials( $error = false) {43 public function request_filesystem_credentials( $error = false, $context = false, $allow_relaxed_file_ownership = false ) { 44 44 $url = $this->options['url']; 45 $context = $this->options['context']; 46 if ( !empty($this->options['nonce']) ) 45 if ( ! $context ) { 46 $context = $this->options['context']; 47 } 48 if ( !empty($this->options['nonce']) ) { 47 49 $url = wp_nonce_url($url, $this->options['nonce']); 48 return request_filesystem_credentials($url, '', $error, $context); //Possible to bring inline, Leaving as is for now. 50 } 51 52 $extra_fields = array(); 53 54 return request_filesystem_credentials( $url, '', $error, $context, $extra_fields, $allow_relaxed_file_ownership ); 49 55 } 50 56 51 57 public function header() { 52 58 if ( $this->done_header ) { 53 59 return; 54 60 } 55 61 $this->done_header = true; 56 62 echo '<div class="wrap">'; 57 63 echo '<h2>' . $this->options['title'] . '</h2>'; 58 64 } 59 65 public function footer() { 60 66 if ( $this->done_footer ) { 61 67 return; 62 68 } 63 69 $this->done_footer = true; … … 687 693 } 688 694 689 695 /** 690 696 * Upgrader Skin for Automatic WordPress Upgrades 691 697 * 692 698 * This skin is designed to be used when no output is intended, all output 693 699 * is captured and stored for the caller to process and log/email/discard. 694 700 * 695 701 * @package WordPress 696 702 * @subpackage Upgrader 697 703 * @since 3.7.0 698 704 */ 699 705 class Automatic_Upgrader_Skin extends WP_Upgrader_Skin { 700 706 protected $messages = array(); 701 707 702 public function request_filesystem_credentials( $error = false, $context = '' ) {703 if ( $context ) 708 public function request_filesystem_credentials( $error = false, $context = '', $allow_relaxed_file_ownership = false ) { 709 if ( $context ) { 704 710 $this->options['context'] = $context; 711 } 705 712 // TODO: fix up request_filesystem_credentials(), or split it, to allow us to request a no-output version 706 713 // This will output a credentials form in event of failure, We don't want that, so just hide with a buffer 707 714 ob_start(); 708 $result = parent::request_filesystem_credentials( $error );715 $result = parent::request_filesystem_credentials( $error, $context, $allow_relaxed_file_ownership ); 709 716 ob_end_clean(); 710 717 return $result; 711 718 } 712 719 713 720 public function get_upgrade_messages() { 714 721 return $this->messages; 715 722 } 716 723 717 724 public function feedback( $data ) { 718 725 if ( is_wp_error( $data ) ) 719 726 $string = $data->get_error_message(); 720 727 else if ( is_array( $data ) ) 721 728 return; 722 729 else 723 730 $string = $data; -
src/wp-admin/includes/class-wp-upgrader.php
49 49 $this->strings['fs_no_themes_dir'] = __('Unable to locate WordPress Theme directory.'); 50 50 /* translators: %s: directory name */ 51 51 $this->strings['fs_no_folder'] = __('Unable to locate needed folder (%s).'); 52 52 53 53 $this->strings['download_failed'] = __('Download failed.'); 54 54 $this->strings['installing_package'] = __('Installing the latest version…'); 55 55 $this->strings['no_files'] = __('The package contains no files.'); 56 56 $this->strings['folder_exists'] = __('Destination folder already exists.'); 57 57 $this->strings['mkdir_failed'] = __('Could not create directory.'); 58 58 $this->strings['incompatible_archive'] = __('The package could not be installed.'); 59 59 60 60 $this->strings['maintenance_start'] = __('Enabling Maintenance mode…'); 61 61 $this->strings['maintenance_end'] = __('Disabling Maintenance mode…'); 62 62 } 63 63 64 public function fs_connect( $directories = array() ) {64 public function fs_connect( $directories = array(), $allow_relaxed_file_ownership = false ) { 65 65 global $wp_filesystem; 66 66 67 if ( false === ( $credentials = $this->skin->request_filesystem_credentials()) )67 if ( false === ( $credentials = $this->skin->request_filesystem_credentials( false, $directories[0], $allow_relaxed_file_ownership ) ) ) { 68 68 return false; 69 } 69 70 70 if ( ! WP_Filesystem( $credentials) ) {71 if ( ! WP_Filesystem( $credentials, $directories[0], $allow_relaxed_file_ownership ) ) { 71 72 $error = true; 72 73 if ( is_object($wp_filesystem) && $wp_filesystem->errors->get_error_code() ) 73 74 $error = $wp_filesystem->errors; 74 $this->skin->request_filesystem_credentials($error); //Failed to connect, Error and request again 75 // Failed to connect, Error and request again 76 $this->skin->request_filesystem_credentials( $error, $directories[0], $allow_relaxed_file_ownership ); 75 77 return false; 76 78 } 77 79 78 80 if ( ! is_object($wp_filesystem) ) 79 81 return new WP_Error('fs_unavailable', $this->strings['fs_unavailable'] ); 80 82 81 83 if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() ) 82 84 return new WP_Error('fs_error', $this->strings['fs_error'], $wp_filesystem->errors); 83 85 84 86 foreach ( (array)$directories as $dir ) { 85 87 switch ( $dir ) { 86 88 case ABSPATH: 87 89 if ( ! $wp_filesystem->abspath() ) 88 90 return new WP_Error('fs_no_root_dir', $this->strings['fs_no_root_dir']); 89 91 break; … … 1444 1446 $this->strings['start_rollback'] = __( 'Attempting to roll back to previous version.' ); 1445 1447 $this->strings['rollback_was_required'] = __( 'Due to an error during updating, WordPress has rolled back to your previous version.' ); 1446 1448 } 1447 1449 1448 1450 public function upgrade( $current, $args = array() ) { 1449 1451 global $wp_filesystem; 1450 1452 1451 1453 include( ABSPATH . WPINC . '/version.php' ); // $wp_version; 1452 1454 1453 1455 $start_time = time(); 1454 1456 1455 1457 $defaults = array( 1456 1458 'pre_check_md5' => true, 1457 1459 'attempt_rollback' => false, 1458 1460 'do_rollback' => false, 1461 'allow_relaxed_file_ownership' => false, 1459 1462 ); 1460 1463 $parsed_args = wp_parse_args( $args, $defaults ); 1461 1464 1462 1465 $this->init(); 1463 1466 $this->upgrade_strings(); 1464 1467 1465 1468 // Is an update available? 1466 1469 if ( !isset( $current->response ) || $current->response == 'latest' ) 1467 1470 return new WP_Error('up_to_date', $this->strings['up_to_date']); 1468 1471 1469 $res = $this->fs_connect( array( ABSPATH, WP_CONTENT_DIR));1472 $res = $this->fs_connect( array( ABSPATH, WP_CONTENT_DIR ), $parsed_args['allow_relaxed_file_ownership'] ); 1470 1473 if ( ! $res || is_wp_error( $res ) ) { 1471 1474 return $res; 1472 1475 } 1473 1476 1474 1477 $wp_dir = trailingslashit($wp_filesystem->abspath()); 1475 1478 1476 1479 $partial = true; 1477 1480 if ( $parsed_args['do_rollback'] ) 1478 1481 $partial = false; 1479 1482 elseif ( $parsed_args['pre_check_md5'] && ! $this->check_files() ) 1480 1483 $partial = false; 1481 1484 1482 1485 /* 1483 1486 * If partial update is returned from the API, use that, unless we're doing 1484 1487 * a reinstall. If we cross the new_bundled version number, then use … … 1899 1902 * @since 3.7.0 1900 1903 * 1901 1904 * @param string $type The type of update being checked: 'core', 'theme', 1902 1905 * 'plugin', 'translation'. 1903 1906 * @param object $item The update offer. 1904 1907 * @param string $context The filesystem context (a path) against which filesystem 1905 1908 * access and status should be checked. 1906 1909 */ 1907 1910 public function should_update( $type, $item, $context ) { 1908 1911 // Used to see if WP_Filesystem is set up to allow unattended updates. 1909 1912 $skin = new Automatic_Upgrader_Skin; 1910 1913 1911 1914 if ( $this->is_disabled() ) 1912 1915 return false; 1913 1916 1917 // Only relax the filesystem checks when the update doesn't include new files 1918 $allow_relaxed_file_ownership = false; 1919 if ( 'core' == $type && isset( $item->new_files ) && ! $item->new_files ) { 1920 $allow_relaxed_file_ownership = true; 1921 } /* elseif ( 'translation' == $type && $translation_is_installed ) { 1922 $allow_relaxed_file_ownership = true; 1923 }*/ 1924 1914 1925 // If we can't do an auto core update, we may still be able to email the user. 1915 if ( ! $skin->request_filesystem_credentials( false, $context ) || $this->is_vcs_checkout( $context ) ) {1926 if ( ! $skin->request_filesystem_credentials( false, $context, $allow_relaxed_file_ownership ) || $this->is_vcs_checkout( $context ) ) { 1916 1927 if ( 'core' == $type ) 1917 1928 $this->send_core_update_notification_email( $item ); 1918 1929 return false; 1919 1930 } 1920 1931 1921 1932 // Next up, is this an item we can update? 1922 1933 if ( 'core' == $type ) 1923 1934 $update = Core_Upgrader::should_update_to_version( $item->current ); 1924 1935 else 1925 1936 $update = ! empty( $item->autoupdate ); 1926 1937 1927 1938 /** 1928 1939 * Filter whether to automatically update core, a plugin, a theme, or a language. 1929 1940 * 1930 1941 * The dynamic portion of the hook name, $type, refers to the type of update … … 2060 2071 $skin->feedback( __( 'Updating theme: %s' ), $item_name ); 2061 2072 break; 2062 2073 case 'plugin': 2063 2074 $upgrader_item = $item->plugin; 2064 2075 $plugin_data = get_plugin_data( $context . '/' . $upgrader_item ); 2065 2076 $item_name = $plugin_data['Name']; 2066 2077 $skin->feedback( __( 'Updating plugin: %s' ), $item_name ); 2067 2078 break; 2068 2079 case 'translation': 2069 2080 $language_item_name = $upgrader->get_name_for_update( $item ); 2070 2081 $item_name = sprintf( __( 'Translations for %s' ), $language_item_name ); 2071 2082 $skin->feedback( sprintf( __( 'Updating translations for %1$s (%2$s)…' ), $language_item_name, $item->language ) ); 2072 2083 break; 2073 2084 } 2074 2085 2086 $allow_relaxed_file_ownership = false; 2087 if ( 'core' == $type && isset( $item->new_files ) && ! $item->new_files ) { 2088 $allow_relaxed_file_ownership = true; 2089 }/* elseif ( 'translation' == $type && $translation_is_installed ) { 2090 $allow_relaxed_file_ownership = true; 2091 }*/ 2092 2075 2093 // Boom, This sites about to get a whole new splash of paint! 2076 2094 $upgrade_result = $upgrader->upgrade( $upgrader_item, array( 2077 2095 'clear_update_cache' => false, 2078 2096 // Always use partial builds if possible for core updates. 2079 2097 'pre_check_md5' => false, 2080 2098 // Only available for core updates. 2081 2099 'attempt_rollback' => true, 2100 // Allow relaxed file ownership in some scenarios 2101 'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership, 2102 2082 2103 ) ); 2083 2104 2084 2105 // If the filesystem is unavailable, false is returned. 2085 2106 if ( false === $upgrade_result ) { 2086 2107 $upgrade_result = new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) ); 2087 2108 } 2088 2109 2089 2110 // Core doesn't output this, so lets append it so we don't get confused. 2090 2111 if ( 'core' == $type ) { 2091 2112 if ( is_wp_error( $upgrade_result ) ) { 2092 2113 $skin->error( __( 'Installation Failed' ), $upgrade_result ); 2093 2114 } else { 2094 2115 $skin->feedback( __( 'WordPress updated successfully' ) ); 2095 2116 } 2096 2117 } -
src/wp-admin/includes/file.php
797 797 } 798 798 } 799 799 return true; 800 800 } 801 801 802 802 /** 803 803 * Initialises and connects the WordPress Filesystem Abstraction classes. 804 804 * This function will include the chosen transport and attempt connecting. 805 805 * 806 806 * Plugins may add extra transports, And force WordPress to use them by returning the filename via the 'filesystem_method_file' filter. 807 807 * 808 808 * @since 2.5.0 809 809 * 810 810 * @param array $args (optional) Connection args, These are passed directly to the WP_Filesystem_*() classes. 811 811 * @param string $context (optional) Context for get_filesystem_method(), See function declaration for more information. 812 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. 812 813 * @return null|boolean false on failure, true on success 813 814 */ 814 function WP_Filesystem( $args = false, $context = false ) {815 function WP_Filesystem( $args = false, $context = false, $allow_relaxed_file_ownership = false ) { 815 816 global $wp_filesystem; 816 817 817 818 require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php'); 818 819 819 $method = get_filesystem_method( $args, $context);820 $method = get_filesystem_method( $args, $context, $allow_relaxed_file_ownership ); 820 821 821 822 if ( ! $method ) 822 823 return false; 823 824 824 825 if ( ! class_exists("WP_Filesystem_$method") ) { 825 826 826 827 /** 827 828 * Filter the path for a specific filesystem method class file. 828 829 * 829 830 * @since 2.6.0 830 831 * 831 832 * @see get_filesystem_method() 832 833 * 833 834 * @param string $path Path to the specific filesystem method class file. 834 835 * @param string $method The filesystem method to use. … … 867 868 868 869 /** 869 870 * Determines which Filesystem Method to use. 870 871 * The priority of the Transports are: Direct, SSH2, FTP PHP Extension, FTP Sockets (Via Sockets class, or fsockopen()) 871 872 * 872 873 * Note that the return value of this function can be overridden in 2 ways 873 874 * - By defining FS_METHOD in your <code>wp-config.php</code> file 874 875 * - By using the filesystem_method filter 875 876 * Valid values for these are: 'direct', 'ssh2', 'ftpext' or 'ftpsockets' 876 877 * Plugins may also define a custom transport handler, See the WP_Filesystem function for more information. 877 878 * 878 879 * @since 2.5.0 879 880 * 880 881 * @param array $args Connection details. 881 882 * @param string $context Full path to the directory that is tested for being writable. 883 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. 882 884 * @return string The transport to use, see description for valid return values. 883 885 */ 884 function get_filesystem_method( $args = array(), $context = false) {886 function get_filesystem_method( $args = array(), $context = false, $allow_relaxed_file_ownership = false ) { 885 887 $method = defined('FS_METHOD') ? FS_METHOD : false; // Please ensure that this is either 'direct', 'ssh2', 'ftpext' or 'ftpsockets' 886 888 887 if ( ! $method && function_exists('getmyuid') && function_exists('fileowner') ){888 if ( !$context ) 889 if ( ! $method ) { 890 if ( !$context ) { 889 891 $context = WP_CONTENT_DIR; 892 } 890 893 891 894 // If the directory doesn't exist (wp-content/languages) then use the parent directory as we'll create it. 892 if ( WP_LANG_DIR == $context && ! is_dir( $context ) ) 895 if ( WP_LANG_DIR == $context && ! is_dir( $context ) ) { 893 896 $context = dirname( $context ); 897 } 894 898 895 899 $context = trailingslashit($context); 900 896 901 $temp_file_name = $context . 'temp-write-test-' . time(); 897 902 $temp_handle = @fopen($temp_file_name, 'w'); 898 903 if ( $temp_handle ) { 899 if ( getmyuid() == @fileowner($temp_file_name) ) 904 /** 905 * getmyuid() will return the User ID of the current script, equiv to fileowner( __FILE__ ). 906 * getmygid() will return the Group ID of the current script, equiv to filegroup( __FILE__ ). 907 * 908 * The below tests are used to select the appropriate WP_Filesystem_* class, allowing for 909 * created files to be owned by the correct user. If no new files are being created, then 910 * group / world writable is enough to modify core files. 911 */ 912 913 $owner_writable_functions_exist = function_exists('getmyuid') && function_exists('fileowner'); 914 $group_writable_functions_exist = function_exists('getmygid') && function_exists('filegroup'); 915 916 if ( $owner_writable_functions_exist && getmyuid() == @fileowner( $temp_file_name ) ) { 917 $method = 'direct'; 918 } elseif ( $allow_relaxed_file_ownership && $group_writable_functions_exist && getmygid() === @filegroup( $temp_file_name ) ) { 900 919 $method = 'direct'; 920 } elseif ( $allow_relaxed_file_ownership ) { 921 // wp_is_writable( $context ) is assumed based on fopen() suceeding. 922 $method = 'direct'; 923 } 901 924 @fclose($temp_handle); 902 925 @unlink($temp_file_name); 903 926 } 904 927 } 905 928 906 929 if ( ! $method && isset($args['connection_type']) && 'ssh' == $args['connection_type'] && extension_loaded('ssh2') && function_exists('stream_get_contents') ) $method = 'ssh2'; 907 930 if ( ! $method && extension_loaded('ftp') ) $method = 'ftpext'; 908 931 if ( ! $method && ( extension_loaded('sockets') || function_exists('fsockopen') ) ) $method = 'ftpsockets'; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread 909 932 910 933 /** 911 934 * Filter the filesystem method to use. 912 935 * 913 936 * @since 2.6.0 914 937 * 915 938 * @param string $method Filesystem method to return. … … 921 944 /** 922 945 * Displays a form to the user to request for their FTP/SSH details in order to connect to the filesystem. 923 946 * All chosen/entered details are saved, Excluding the Password. 924 947 * 925 948 * Hostnames may be in the form of hostname:portnumber (eg: wordpress.org:2467) to specify an alternate FTP/SSH port. 926 949 * 927 950 * Plugins may override this form by returning true|false via the <code>request_filesystem_credentials</code> filter. 928 951 * 929 952 * @since 2.5.0 930 953 * 931 954 * @param string $form_post the URL to post the form to 932 955 * @param string $type the chosen Filesystem method in use 933 956 * @param boolean $error if the current request has failed to connect 934 957 * @param string $context The directory which is needed access to, The write-test will be performed on this directory by get_filesystem_method() 935 958 * @param string $extra_fields Extra POST fields which should be checked for to be included in the post. 959 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. 936 960 * @return boolean False on failure. True on success. 937 961 */ 938 function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null ) {962 function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null, $allow_relaxed_file_ownership = false ) { 939 963 940 964 /** 941 965 * Filter the filesystem credentials form output. 942 966 * 943 967 * Returning anything other than an empty string will effectively short-circuit 944 968 * output of the filesystem credentials form, returning that value instead. 945 969 * 946 970 * @since 2.5.0 947 971 * 948 972 * @param mixed $output Form output to return instead. Default empty. 949 973 * @param string $form_post URL to POST the form to. 950 974 * @param string $type Chosen type of filesystem. 951 975 * @param bool $error Whether the current request has failed to connect. 952 976 * Default false. 953 977 * @param string $context Full path to the directory that is tested for 954 978 * being writable. 979 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. 955 980 * @param array $extra_fields Extra POST fields. 956 981 */ 957 $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields );982 $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields, $allow_relaxed_file_ownership ); 958 983 if ( '' !== $req_cred ) 959 984 return $req_cred; 960 985 961 if ( empty($type) ) 962 $type = get_filesystem_method(array(), $context); 986 if ( empty($type) ) { 987 $type = get_filesystem_method( array(), $context, $allow_relaxed_file_ownership ); 988 } 963 989 964 990 if ( 'direct' == $type ) 965 991 return true; 966 992 967 993 if ( is_null( $extra_fields ) ) 968 994 $extra_fields = array( 'version', 'locale' ); 969 995 970 996 $credentials = get_option('ftp_credentials', array( 'hostname' => '', 'username' => '')); 971 997 972 998 // 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) 973 999 $credentials['hostname'] = defined('FTP_HOST') ? FTP_HOST : (!empty($_POST['hostname']) ? wp_unslash( $_POST['hostname'] ) : $credentials['hostname']); 974 1000 $credentials['username'] = defined('FTP_USER') ? FTP_USER : (!empty($_POST['username']) ? wp_unslash( $_POST['username'] ) : $credentials['username']); 975 1001 $credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($_POST['password']) ? wp_unslash( $_POST['password'] ) : ''); 976 1002 977 1003 // Check to see if we are setting the public/private keys for ssh -
src/wp-includes/update.php
130 130 return false; 131 131 132 132 $offers = $body['offers']; 133 133 134 134 foreach ( $offers as &$offer ) { 135 135 foreach ( $offer as $offer_key => $value ) { 136 136 if ( 'packages' == $offer_key ) 137 137 $offer['packages'] = (object) array_intersect_key( array_map( 'esc_url', $offer['packages'] ), 138 138 array_fill_keys( array( 'full', 'no_content', 'new_bundled', 'partial', 'rollback' ), '' ) ); 139 139 elseif ( 'download' == $offer_key ) 140 140 $offer['download'] = esc_url( $value ); 141 141 else 142 142 $offer[ $offer_key ] = esc_html( $value ); 143 143 } 144 144 $offer = (object) array_intersect_key( $offer, array_fill_keys( array( 'response', 'download', 'locale', 145 'packages', 'current', 'version', 'php_version', 'mysql_version', 'new_bundled', 'partial_version', 'notify_email', 'support_email' ), '' ) );145 'packages', 'current', 'version', 'php_version', 'mysql_version', 'new_bundled', 'partial_version', 'notify_email', 'support_email', 'new_files' ), '' ) ); 146 146 } 147 147 148 148 $updates = new stdClass(); 149 149 $updates->updates = $offers; 150 150 $updates->last_checked = time(); 151 151 $updates->version_checked = $wp_version; 152 152 153 153 if ( isset( $body['translations'] ) ) 154 154 $updates->translations = $body['translations']; 155 155 156 156 set_site_transient( 'update_core', $updates ); 157 157 158 158 if ( ! empty( $body['ttl'] ) ) { 159 159 $ttl = (int) $body['ttl']; 160 160 if ( $ttl && ( time() + $ttl < wp_next_scheduled( 'wp_version_check' ) ) ) {