Background Updates: Introduce support to take advantage of Group Writable (or World Writable) to Core Background updates.
This is only enabled when new files will not be installed during the update (as indicated by the WordPress.org API), and does not apply to Plugin/Theme/Translation Background Updates. Additionally, the code to determine if the 'direct' filesystem transport should be used has been tweaked for wider support (where getmyuid() was unavailalbe) which fixes #10424 See #10205, #30245 Built from https://develop.svn.wordpress.org/trunk@30384 git-svn-id: http://core.svn.wordpress.org/trunk@30381 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
d95b5196cc
commit
9b9289e0a3
|
@ -40,12 +40,18 @@ class WP_Upgrader_Skin {
|
||||||
$this->result = $result;
|
$this->result = $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function request_filesystem_credentials($error = false) {
|
public function request_filesystem_credentials( $error = false, $context = false, $allow_relaxed_file_ownership = false ) {
|
||||||
$url = $this->options['url'];
|
$url = $this->options['url'];
|
||||||
$context = $this->options['context'];
|
if ( ! $context ) {
|
||||||
if ( !empty($this->options['nonce']) )
|
$context = $this->options['context'];
|
||||||
|
}
|
||||||
|
if ( !empty($this->options['nonce']) ) {
|
||||||
$url = wp_nonce_url($url, $this->options['nonce']);
|
$url = wp_nonce_url($url, $this->options['nonce']);
|
||||||
return request_filesystem_credentials($url, '', $error, $context); //Possible to bring inline, Leaving as is for now.
|
}
|
||||||
|
|
||||||
|
$extra_fields = array();
|
||||||
|
|
||||||
|
return request_filesystem_credentials( $url, '', $error, $context, $extra_fields, $allow_relaxed_file_ownership );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function header() {
|
public function header() {
|
||||||
|
@ -699,13 +705,14 @@ class Language_Pack_Upgrader_Skin extends WP_Upgrader_Skin {
|
||||||
class Automatic_Upgrader_Skin extends WP_Upgrader_Skin {
|
class Automatic_Upgrader_Skin extends WP_Upgrader_Skin {
|
||||||
protected $messages = array();
|
protected $messages = array();
|
||||||
|
|
||||||
public function request_filesystem_credentials( $error = false, $context = '' ) {
|
public function request_filesystem_credentials( $error = false, $context = '', $allow_relaxed_file_ownership = false ) {
|
||||||
if ( $context )
|
if ( $context ) {
|
||||||
$this->options['context'] = $context;
|
$this->options['context'] = $context;
|
||||||
|
}
|
||||||
// TODO: fix up request_filesystem_credentials(), or split it, to allow us to request a no-output version
|
// TODO: fix up request_filesystem_credentials(), or split it, to allow us to request a no-output version
|
||||||
// This will output a credentials form in event of failure, We don't want that, so just hide with a buffer
|
// This will output a credentials form in event of failure, We don't want that, so just hide with a buffer
|
||||||
ob_start();
|
ob_start();
|
||||||
$result = parent::request_filesystem_credentials( $error );
|
$result = parent::request_filesystem_credentials( $error, $context, $allow_relaxed_file_ownership );
|
||||||
ob_end_clean();
|
ob_end_clean();
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,17 +61,19 @@ class WP_Upgrader {
|
||||||
$this->strings['maintenance_end'] = __('Disabling Maintenance mode…');
|
$this->strings['maintenance_end'] = __('Disabling Maintenance mode…');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fs_connect( $directories = array() ) {
|
public function fs_connect( $directories = array(), $allow_relaxed_file_ownership = false ) {
|
||||||
global $wp_filesystem;
|
global $wp_filesystem;
|
||||||
|
|
||||||
if ( false === ($credentials = $this->skin->request_filesystem_credentials()) )
|
if ( false === ( $credentials = $this->skin->request_filesystem_credentials( false, $directories[0], $allow_relaxed_file_ownership ) ) ) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! WP_Filesystem($credentials) ) {
|
if ( ! WP_Filesystem( $credentials, $directories[0], $allow_relaxed_file_ownership ) ) {
|
||||||
$error = true;
|
$error = true;
|
||||||
if ( is_object($wp_filesystem) && $wp_filesystem->errors->get_error_code() )
|
if ( is_object($wp_filesystem) && $wp_filesystem->errors->get_error_code() )
|
||||||
$error = $wp_filesystem->errors;
|
$error = $wp_filesystem->errors;
|
||||||
$this->skin->request_filesystem_credentials($error); //Failed to connect, Error and request again
|
// Failed to connect, Error and request again
|
||||||
|
$this->skin->request_filesystem_credentials( $error, $directories[0], $allow_relaxed_file_ownership );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1456,6 +1458,7 @@ class Core_Upgrader extends WP_Upgrader {
|
||||||
'pre_check_md5' => true,
|
'pre_check_md5' => true,
|
||||||
'attempt_rollback' => false,
|
'attempt_rollback' => false,
|
||||||
'do_rollback' => false,
|
'do_rollback' => false,
|
||||||
|
'allow_relaxed_file_ownership' => false,
|
||||||
);
|
);
|
||||||
$parsed_args = wp_parse_args( $args, $defaults );
|
$parsed_args = wp_parse_args( $args, $defaults );
|
||||||
|
|
||||||
|
@ -1466,7 +1469,7 @@ class Core_Upgrader extends WP_Upgrader {
|
||||||
if ( !isset( $current->response ) || $current->response == 'latest' )
|
if ( !isset( $current->response ) || $current->response == 'latest' )
|
||||||
return new WP_Error('up_to_date', $this->strings['up_to_date']);
|
return new WP_Error('up_to_date', $this->strings['up_to_date']);
|
||||||
|
|
||||||
$res = $this->fs_connect( array(ABSPATH, WP_CONTENT_DIR) );
|
$res = $this->fs_connect( array( ABSPATH, WP_CONTENT_DIR ), $parsed_args['allow_relaxed_file_ownership'] );
|
||||||
if ( ! $res || is_wp_error( $res ) ) {
|
if ( ! $res || is_wp_error( $res ) ) {
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
@ -1911,8 +1914,14 @@ class WP_Automatic_Updater {
|
||||||
if ( $this->is_disabled() )
|
if ( $this->is_disabled() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Only relax the filesystem checks when the update doesn't include new files
|
||||||
|
$allow_relaxed_file_ownership = false;
|
||||||
|
if ( 'core' == $type && isset( $item->new_files ) && ! $item->new_files ) {
|
||||||
|
$allow_relaxed_file_ownership = true;
|
||||||
|
}
|
||||||
|
|
||||||
// If we can't do an auto core update, we may still be able to email the user.
|
// If we can't do an auto core update, we may still be able to email the user.
|
||||||
if ( ! $skin->request_filesystem_credentials( false, $context ) || $this->is_vcs_checkout( $context ) ) {
|
if ( ! $skin->request_filesystem_credentials( false, $context, $allow_relaxed_file_ownership ) || $this->is_vcs_checkout( $context ) ) {
|
||||||
if ( 'core' == $type )
|
if ( 'core' == $type )
|
||||||
$this->send_core_update_notification_email( $item );
|
$this->send_core_update_notification_email( $item );
|
||||||
return false;
|
return false;
|
||||||
|
@ -2072,6 +2081,11 @@ class WP_Automatic_Updater {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$allow_relaxed_file_ownership = false;
|
||||||
|
if ( 'core' == $type && isset( $item->new_files ) && ! $item->new_files ) {
|
||||||
|
$allow_relaxed_file_ownership = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Boom, This sites about to get a whole new splash of paint!
|
// Boom, This sites about to get a whole new splash of paint!
|
||||||
$upgrade_result = $upgrader->upgrade( $upgrader_item, array(
|
$upgrade_result = $upgrader->upgrade( $upgrader_item, array(
|
||||||
'clear_update_cache' => false,
|
'clear_update_cache' => false,
|
||||||
|
@ -2079,6 +2093,9 @@ class WP_Automatic_Updater {
|
||||||
'pre_check_md5' => false,
|
'pre_check_md5' => false,
|
||||||
// Only available for core updates.
|
// Only available for core updates.
|
||||||
'attempt_rollback' => true,
|
'attempt_rollback' => true,
|
||||||
|
// Allow relaxed file ownership in some scenarios
|
||||||
|
'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership,
|
||||||
|
|
||||||
) );
|
) );
|
||||||
|
|
||||||
// If the filesystem is unavailable, false is returned.
|
// If the filesystem is unavailable, false is returned.
|
||||||
|
|
|
@ -809,14 +809,15 @@ function copy_dir($from, $to, $skip_list = array() ) {
|
||||||
*
|
*
|
||||||
* @param array $args (optional) Connection args, These are passed directly to the WP_Filesystem_*() classes.
|
* @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.
|
* @param string $context (optional) Context for get_filesystem_method(), See function declaration for more information.
|
||||||
|
* @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable.
|
||||||
* @return null|boolean false on failure, true on success
|
* @return null|boolean false on failure, true on success
|
||||||
*/
|
*/
|
||||||
function WP_Filesystem( $args = false, $context = false ) {
|
function WP_Filesystem( $args = false, $context = false, $allow_relaxed_file_ownership = false ) {
|
||||||
global $wp_filesystem;
|
global $wp_filesystem;
|
||||||
|
|
||||||
require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
|
require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
|
||||||
|
|
||||||
$method = get_filesystem_method($args, $context);
|
$method = get_filesystem_method( $args, $context, $allow_relaxed_file_ownership );
|
||||||
|
|
||||||
if ( ! $method )
|
if ( ! $method )
|
||||||
return false;
|
return false;
|
||||||
|
@ -879,25 +880,46 @@ function WP_Filesystem( $args = false, $context = false ) {
|
||||||
*
|
*
|
||||||
* @param array $args Connection details.
|
* @param array $args Connection details.
|
||||||
* @param string $context Full path to the directory that is tested for being writable.
|
* @param string $context Full path to the directory that is tested for being writable.
|
||||||
|
* @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable.
|
||||||
* @return string The transport to use, see description for valid return values.
|
* @return string The transport to use, see description for valid return values.
|
||||||
*/
|
*/
|
||||||
function get_filesystem_method($args = array(), $context = false) {
|
function get_filesystem_method( $args = array(), $context = false, $allow_relaxed_file_ownership = false ) {
|
||||||
$method = defined('FS_METHOD') ? FS_METHOD : false; // Please ensure that this is either 'direct', 'ssh2', 'ftpext' or 'ftpsockets'
|
$method = defined('FS_METHOD') ? FS_METHOD : false; // Please ensure that this is either 'direct', 'ssh2', 'ftpext' or 'ftpsockets'
|
||||||
|
|
||||||
if ( ! $method && function_exists('getmyuid') && function_exists('fileowner') ){
|
if ( ! $context ) {
|
||||||
if ( !$context )
|
$context = WP_CONTENT_DIR;
|
||||||
$context = WP_CONTENT_DIR;
|
}
|
||||||
|
|
||||||
// If the directory doesn't exist (wp-content/languages) then use the parent directory as we'll create it.
|
// If the directory doesn't exist (wp-content/languages) then use the parent directory as we'll create it.
|
||||||
if ( WP_LANG_DIR == $context && ! is_dir( $context ) )
|
if ( WP_LANG_DIR == $context && ! is_dir( $context ) ) {
|
||||||
$context = dirname( $context );
|
$context = dirname( $context );
|
||||||
|
}
|
||||||
|
|
||||||
|
$context = trailingslashit( $context );
|
||||||
|
|
||||||
|
if ( ! $method ) {
|
||||||
|
|
||||||
$context = trailingslashit($context);
|
|
||||||
$temp_file_name = $context . 'temp-write-test-' . time();
|
$temp_file_name = $context . 'temp-write-test-' . time();
|
||||||
$temp_handle = @fopen($temp_file_name, 'w');
|
$temp_handle = @fopen($temp_file_name, 'w');
|
||||||
if ( $temp_handle ) {
|
if ( $temp_handle ) {
|
||||||
if ( getmyuid() == @fileowner($temp_file_name) )
|
|
||||||
|
// Attempt to determine the file owner of the WordPress files, and that of newly created files
|
||||||
|
$wp_file_owner = $temp_file_owner = false;
|
||||||
|
if ( function_exists('fileowner') ) {
|
||||||
|
$wp_file_owner = @fileowner( __FILE__ );
|
||||||
|
$temp_file_owner = @fileowner( $temp_file_name );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $wp_file_owner !== false && $wp_file_owner === $temp_file_owner ) {
|
||||||
|
// WordPress is creating files as the same owner as the WordPress files,
|
||||||
|
// this means it's safe to modify & create new files via PHP.
|
||||||
$method = 'direct';
|
$method = 'direct';
|
||||||
|
} else if ( $allow_relaxed_file_ownership ) {
|
||||||
|
// The $context directory is writable, and $allow_relaxed_file_ownership is set, this means we can modify files
|
||||||
|
// safely in this directory. This mode doesn't create new files, only alter existing ones.
|
||||||
|
$method = 'direct';
|
||||||
|
}
|
||||||
|
|
||||||
@fclose($temp_handle);
|
@fclose($temp_handle);
|
||||||
@unlink($temp_file_name);
|
@unlink($temp_file_name);
|
||||||
}
|
}
|
||||||
|
@ -912,10 +934,12 @@ function get_filesystem_method($args = array(), $context = false) {
|
||||||
*
|
*
|
||||||
* @since 2.6.0
|
* @since 2.6.0
|
||||||
*
|
*
|
||||||
* @param string $method Filesystem method to return.
|
* @param string $method Filesystem method to return.
|
||||||
* @param array $args An array of connection details for the method.
|
* @param array $args An array of connection details for the method.
|
||||||
|
* @param string $context Full path to the directory that is tested for being writable.
|
||||||
|
* @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable.
|
||||||
*/
|
*/
|
||||||
return apply_filters( 'filesystem_method', $method, $args );
|
return apply_filters( 'filesystem_method', $method, $args, $context, $allow_relaxed_file_ownership );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -933,9 +957,10 @@ function get_filesystem_method($args = array(), $context = false) {
|
||||||
* @param boolean $error if the current request has failed to connect
|
* @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()
|
* @param string $context The directory which is needed access to, The write-test will be performed on this directory by get_filesystem_method()
|
||||||
* @param string $extra_fields Extra POST fields which should be checked for to be included in the post.
|
* @param string $extra_fields Extra POST fields which should be checked for to be included in the post.
|
||||||
|
* @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable.
|
||||||
* @return boolean False on failure. True on success.
|
* @return boolean False on failure. True on success.
|
||||||
*/
|
*/
|
||||||
function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null) {
|
function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null, $allow_relaxed_file_ownership = false ) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter the filesystem credentials form output.
|
* Filter the filesystem credentials form output.
|
||||||
|
@ -952,14 +977,16 @@ function request_filesystem_credentials($form_post, $type = '', $error = false,
|
||||||
* Default false.
|
* Default false.
|
||||||
* @param string $context Full path to the directory that is tested for
|
* @param string $context Full path to the directory that is tested for
|
||||||
* being writable.
|
* being writable.
|
||||||
|
* @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable.
|
||||||
* @param array $extra_fields Extra POST fields.
|
* @param array $extra_fields Extra POST fields.
|
||||||
*/
|
*/
|
||||||
$req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields );
|
$req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields, $allow_relaxed_file_ownership );
|
||||||
if ( '' !== $req_cred )
|
if ( '' !== $req_cred )
|
||||||
return $req_cred;
|
return $req_cred;
|
||||||
|
|
||||||
if ( empty($type) )
|
if ( empty($type) ) {
|
||||||
$type = get_filesystem_method(array(), $context);
|
$type = get_filesystem_method( array(), $context, $allow_relaxed_file_ownership );
|
||||||
|
}
|
||||||
|
|
||||||
if ( 'direct' == $type )
|
if ( 'direct' == $type )
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -381,19 +381,23 @@ function do_core_upgrade( $reinstall = false ) {
|
||||||
if ( !$update )
|
if ( !$update )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Allow relaxed file ownership writes for User-initiated upgrades when the API specifies
|
||||||
|
// that it's safe to do so. This only happens when there are no new files to create.
|
||||||
|
$allow_relaxed_file_ownership = ! $reinstall && isset( $update->new_files ) && ! $update->new_files;
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
<h2><?php _e('Update WordPress'); ?></h2>
|
<h2><?php _e('Update WordPress'); ?></h2>
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
if ( false === ( $credentials = request_filesystem_credentials( $url, '', false, ABSPATH ) ) ) {
|
if ( false === ( $credentials = request_filesystem_credentials( $url, '', false, ABSPATH, array(), $allow_relaxed_file_ownership ) ) ) {
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! WP_Filesystem( $credentials, ABSPATH ) ) {
|
if ( ! WP_Filesystem( $credentials, ABSPATH, $allow_relaxed_file_ownership ) ) {
|
||||||
// Failed to connect, Error and request again
|
// Failed to connect, Error and request again
|
||||||
request_filesystem_credentials( $url, '', true, ABSPATH );
|
request_filesystem_credentials( $url, '', true, ABSPATH, array(), $allow_relaxed_file_ownership );
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -411,7 +415,9 @@ function do_core_upgrade( $reinstall = false ) {
|
||||||
add_filter( 'update_feedback', 'show_message' );
|
add_filter( 'update_feedback', 'show_message' );
|
||||||
|
|
||||||
$upgrader = new Core_Upgrader();
|
$upgrader = new Core_Upgrader();
|
||||||
$result = $upgrader->upgrade( $update );
|
$result = $upgrader->upgrade( $update, array(
|
||||||
|
'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership
|
||||||
|
) );
|
||||||
|
|
||||||
if ( is_wp_error($result) ) {
|
if ( is_wp_error($result) ) {
|
||||||
show_message($result);
|
show_message($result);
|
||||||
|
|
|
@ -142,7 +142,7 @@ function wp_version_check( $extra_stats = array(), $force_check = false ) {
|
||||||
$offer[ $offer_key ] = esc_html( $value );
|
$offer[ $offer_key ] = esc_html( $value );
|
||||||
}
|
}
|
||||||
$offer = (object) array_intersect_key( $offer, array_fill_keys( array( 'response', 'download', 'locale',
|
$offer = (object) array_intersect_key( $offer, array_fill_keys( array( 'response', 'download', 'locale',
|
||||||
'packages', 'current', 'version', 'php_version', 'mysql_version', 'new_bundled', 'partial_version', 'notify_email', 'support_email' ), '' ) );
|
'packages', 'current', 'version', 'php_version', 'mysql_version', 'new_bundled', 'partial_version', 'notify_email', 'support_email', 'new_files' ), '' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
$updates = new stdClass();
|
$updates = new stdClass();
|
||||||
|
|
Loading…
Reference in New Issue