<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[30384] trunk/src: Background Updates: Introduce support to take advantage of Group Writable (or World Writable) to Core Background updates.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/30384">30384</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/30384","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>dd32</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2014-11-19 05:39:52 +0000 (Wed, 19 Nov 2014)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>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 <a href="https://core.trac.wordpress.org/ticket/10424">#10424</a>

See <a href="https://core.trac.wordpress.org/ticket/10205">#10205</a>, <a href="https://core.trac.wordpress.org/ticket/30245">#30245</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadminincludesclasswpupgraderskinsphp">trunk/src/wp-admin/includes/class-wp-upgrader-skins.php</a></li>
<li><a href="#trunksrcwpadminincludesclasswpupgraderphp">trunk/src/wp-admin/includes/class-wp-upgrader.php</a></li>
<li><a href="#trunksrcwpadminincludesfilephp">trunk/src/wp-admin/includes/file.php</a></li>
<li><a href="#trunksrcwpadminupdatecorephp">trunk/src/wp-admin/update-core.php</a></li>
<li><a href="#trunksrcwpincludesupdatephp">trunk/src/wp-includes/update.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadminincludesclasswpupgraderskinsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/class-wp-upgrader-skins.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/class-wp-upgrader-skins.php   2014-11-19 01:52:57 UTC (rev 30383)
+++ trunk/src/wp-admin/includes/class-wp-upgrader-skins.php     2014-11-19 05:39:52 UTC (rev 30384)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -40,12 +40,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->result = $result;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function request_filesystem_credentials($error = false) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function request_filesystem_credentials( $error = false, $context = false, $allow_relaxed_file_ownership = false ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 $url = $this->options['url'];
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $context = $this->options['context'];
-               if ( !empty($this->options['nonce']) )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( ! $context ) {
+                       $context = $this->options['context'];
+               }
+               if ( !empty($this->options['nonce']) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         $url = wp_nonce_url($url, $this->options['nonce']);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return request_filesystem_credentials($url, '', $error, $context); //Possible to bring inline, Leaving as is for now.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         }
+
+               $extra_fields = array();
+
+               return request_filesystem_credentials( $url, '', $error, $context, $extra_fields, $allow_relaxed_file_ownership );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        public function header() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -699,13 +705,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> class Automatic_Upgrader_Skin extends WP_Upgrader_Skin {
</span><span class="cx" style="display: block; padding: 0 10px">        protected $messages = array();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function request_filesystem_credentials( $error = false, $context = '' ) {
-               if ( $context )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function request_filesystem_credentials( $error = false, $context = '', $allow_relaxed_file_ownership = false ) {
+               if ( $context ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         $this->options['context'] = $context;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                }
</ins><span class="cx" style="display: block; padding: 0 10px">                 // TODO: fix up request_filesystem_credentials(), or split it, to allow us to request a no-output version
</span><span class="cx" style="display: block; padding: 0 10px">                // This will output a credentials form in event of failure, We don't want that, so just hide with a buffer
</span><span class="cx" style="display: block; padding: 0 10px">                ob_start();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $result = parent::request_filesystem_credentials( $error );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $result = parent::request_filesystem_credentials( $error, $context, $allow_relaxed_file_ownership );
</ins><span class="cx" style="display: block; padding: 0 10px">                 ob_end_clean();
</span><span class="cx" style="display: block; padding: 0 10px">                return $result;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span></span></pre></div>
<a id="trunksrcwpadminincludesclasswpupgraderphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/class-wp-upgrader.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/class-wp-upgrader.php 2014-11-19 01:52:57 UTC (rev 30383)
+++ trunk/src/wp-admin/includes/class-wp-upgrader.php   2014-11-19 05:39:52 UTC (rev 30384)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -61,17 +61,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->strings['maintenance_end'] = __('Disabling Maintenance mode&#8230;');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function fs_connect( $directories = array() ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function fs_connect( $directories = array(), $allow_relaxed_file_ownership = false ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 global $wp_filesystem;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( false === ($credentials = $this->skin->request_filesystem_credentials()) )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( false === ( $credentials = $this->skin->request_filesystem_credentials( false, $directories[0], $allow_relaxed_file_ownership ) ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         return false;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( ! WP_Filesystem($credentials) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( ! WP_Filesystem( $credentials, $directories[0], $allow_relaxed_file_ownership ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         $error = true;
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( is_object($wp_filesystem) && $wp_filesystem->errors->get_error_code() )
</span><span class="cx" style="display: block; padding: 0 10px">                                $error = $wp_filesystem->errors;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $this->skin->request_filesystem_credentials($error); //Failed to connect, Error and request again
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // Failed to connect, Error and request again
+                       $this->skin->request_filesystem_credentials( $error, $directories[0], $allow_relaxed_file_ownership );
</ins><span class="cx" style="display: block; padding: 0 10px">                         return false;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1456,6 +1458,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        'pre_check_md5'    => true,
</span><span class="cx" style="display: block; padding: 0 10px">                        'attempt_rollback' => false,
</span><span class="cx" style="display: block; padding: 0 10px">                        'do_rollback'      => false,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        'allow_relaxed_file_ownership' => false,
</ins><span class="cx" style="display: block; padding: 0 10px">                 );
</span><span class="cx" style="display: block; padding: 0 10px">                $parsed_args = wp_parse_args( $args, $defaults );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1466,7 +1469,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if ( !isset( $current->response ) || $current->response == 'latest' )
</span><span class="cx" style="display: block; padding: 0 10px">                        return new WP_Error('up_to_date', $this->strings['up_to_date']);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $res = $this->fs_connect( array(ABSPATH, WP_CONTENT_DIR) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $res = $this->fs_connect( array( ABSPATH, WP_CONTENT_DIR ), $parsed_args['allow_relaxed_file_ownership'] );
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ( ! $res || is_wp_error( $res ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return $res;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1911,8 +1914,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if ( $this->is_disabled() )
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // 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;
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // If we can't do an auto core update, we may still be able to email the user.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( ! $skin->request_filesystem_credentials( false, $context ) || $this->is_vcs_checkout( $context ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( ! $skin->request_filesystem_credentials( false, $context, $allow_relaxed_file_ownership ) || $this->is_vcs_checkout( $context ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ( 'core' == $type )
</span><span class="cx" style="display: block; padding: 0 10px">                                $this->send_core_update_notification_email( $item );
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2072,6 +2081,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $allow_relaxed_file_ownership = false;
+               if ( 'core' == $type && isset( $item->new_files ) && ! $item->new_files ) {
+                       $allow_relaxed_file_ownership = true;
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // Boom, This sites about to get a whole new splash of paint!
</span><span class="cx" style="display: block; padding: 0 10px">                $upgrade_result = $upgrader->upgrade( $upgrader_item, array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'clear_update_cache' => false,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2079,6 +2093,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        'pre_check_md5'      => false,
</span><span class="cx" style="display: block; padding: 0 10px">                        // Only available for core updates.
</span><span class="cx" style="display: block; padding: 0 10px">                        'attempt_rollback'   => true,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        // Allow relaxed file ownership in some scenarios
+                       'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership,
+                       
</ins><span class="cx" style="display: block; padding: 0 10px">                 ) );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // If the filesystem is unavailable, false is returned.
</span></span></pre></div>
<a id="trunksrcwpadminincludesfilephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/file.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/file.php      2014-11-19 01:52:57 UTC (rev 30383)
+++ trunk/src/wp-admin/includes/file.php        2014-11-19 05:39:52 UTC (rev 30384)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -809,14 +809,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @param array $args (optional) Connection args, These are passed directly to the WP_Filesystem_*() classes.
</span><span class="cx" style="display: block; padding: 0 10px">  * @param string $context (optional) Context for get_filesystem_method(), See function declaration for more information.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable.
</ins><span class="cx" style="display: block; padding: 0 10px">  * @return null|boolean false on failure, true on success
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function WP_Filesystem( $args = false, $context = false ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function WP_Filesystem( $args = false, $context = false, $allow_relaxed_file_ownership = false ) {
</ins><span class="cx" style="display: block; padding: 0 10px">         global $wp_filesystem;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $method = get_filesystem_method($args, $context);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $method = get_filesystem_method( $args, $context, $allow_relaxed_file_ownership );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        if ( ! $method )
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -879,25 +880,46 @@
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @param array $args Connection details.
</span><span class="cx" style="display: block; padding: 0 10px">  * @param string $context Full path to the directory that is tested for being writable.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable.
</ins><span class="cx" style="display: block; padding: 0 10px">  * @return string The transport to use, see description for valid return values.
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function get_filesystem_method($args = array(), $context = false) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function get_filesystem_method( $args = array(), $context = false, $allow_relaxed_file_ownership = false ) {
</ins><span class="cx" style="display: block; padding: 0 10px">         $method = defined('FS_METHOD') ? FS_METHOD : false; // Please ensure that this is either 'direct', 'ssh2', 'ftpext' or 'ftpsockets'
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( ! $method && function_exists('getmyuid') && function_exists('fileowner') ){
-               if ( !$context )
-                       $context = WP_CONTENT_DIR;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! $context ) {
+               $context = WP_CONTENT_DIR;
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // 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 ) )
-                       $context = dirname( $context );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // 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 ) ) {
+               $context = dirname( $context );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $context = trailingslashit($context);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $context = trailingslashit( $context );
+
+       if ( ! $method ) {
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 $temp_file_name = $context . 'temp-write-test-' . time();
</span><span class="cx" style="display: block; padding: 0 10px">                $temp_handle = @fopen($temp_file_name, 'w');
</span><span class="cx" style="display: block; padding: 0 10px">                if ( $temp_handle ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ( getmyuid() == @fileowner($temp_file_name) )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                       // 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.
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $method = 'direct';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        } 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';
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         @fclose($temp_handle);
</span><span class="cx" style="display: block; padding: 0 10px">                        @unlink($temp_file_name);
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -912,10 +934,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 2.6.0
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @param string $method Filesystem method to return.
-        * @param array  $args   An array of connection details for the method.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * @param string $method  Filesystem method to return.
+        * @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.
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        return apply_filters( 'filesystem_method', $method, $args );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return apply_filters( 'filesystem_method', $method, $args, $context, $allow_relaxed_file_ownership );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -933,9 +957,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * @param boolean $error if the current request has failed to connect
</span><span class="cx" style="display: block; padding: 0 10px">  * @param string $context The directory which is needed access to, The write-test will be performed on this directory by get_filesystem_method()
</span><span class="cx" style="display: block; padding: 0 10px">  * @param string $extra_fields Extra POST fields which should be checked for to be included in the post.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable.
</ins><span class="cx" style="display: block; padding: 0 10px">  * @return boolean False on failure. True on success.
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null, $allow_relaxed_file_ownership = false ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="cx" style="display: block; padding: 0 10px">         * Filter the filesystem credentials form output.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -952,14 +977,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *                             Default false.
</span><span class="cx" style="display: block; padding: 0 10px">         * @param string $context      Full path to the directory that is tested for
</span><span class="cx" style="display: block; padding: 0 10px">         *                             being writable.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable.
</ins><span class="cx" style="display: block; padding: 0 10px">          * @param array  $extra_fields Extra POST fields.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields, $allow_relaxed_file_ownership );
</ins><span class="cx" style="display: block; padding: 0 10px">         if ( '' !== $req_cred )
</span><span class="cx" style="display: block; padding: 0 10px">                return $req_cred;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( empty($type) )
-               $type = get_filesystem_method(array(), $context);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( empty($type) ) {
+               $type = get_filesystem_method( array(), $context, $allow_relaxed_file_ownership );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        if ( 'direct' == $type )
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span></span></pre></div>
<a id="trunksrcwpadminupdatecorephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/update-core.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/update-core.php        2014-11-19 01:52:57 UTC (rev 30383)
+++ trunk/src/wp-admin/update-core.php  2014-11-19 05:39:52 UTC (rev 30384)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -381,19 +381,23 @@
</span><span class="cx" style="display: block; padding: 0 10px">        if ( !$update )
</span><span class="cx" style="display: block; padding: 0 10px">                return;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        // 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;
+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px">        <div class="wrap">
</span><span class="cx" style="display: block; padding: 0 10px">        <h2><?php _e('Update WordPress'); ?></h2>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( false === ( $credentials = request_filesystem_credentials( $url, '', false, ABSPATH ) ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( false === ( $credentials = request_filesystem_credentials( $url, '', false, ABSPATH, array(), $allow_relaxed_file_ownership ) ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 echo '</div>';
</span><span class="cx" style="display: block; padding: 0 10px">                return;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( ! WP_Filesystem( $credentials, ABSPATH ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! WP_Filesystem( $credentials, ABSPATH, $allow_relaxed_file_ownership ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 // Failed to connect, Error and request again
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                request_filesystem_credentials( $url, '', true, ABSPATH );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         request_filesystem_credentials( $url, '', true, ABSPATH, array(), $allow_relaxed_file_ownership );
</ins><span class="cx" style="display: block; padding: 0 10px">                 echo '</div>';
</span><span class="cx" style="display: block; padding: 0 10px">                return;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -411,7 +415,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">        add_filter( 'update_feedback', 'show_message' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $upgrader = new Core_Upgrader();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $result = $upgrader->upgrade( $update );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $result = $upgrader->upgrade( $update, array(
+               'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership
+       ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        if ( is_wp_error($result) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                show_message($result);
</span></span></pre></div>
<a id="trunksrcwpincludesupdatephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/update.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/update.php  2014-11-19 01:52:57 UTC (rev 30383)
+++ trunk/src/wp-includes/update.php    2014-11-19 05:39:52 UTC (rev 30384)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -142,7 +142,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $offer[ $offer_key ] = esc_html( $value );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                $offer = (object) array_intersect_key( $offer, array_fill_keys( array( 'response', 'download', 'locale',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'packages', 'current', 'version', 'php_version', 'mysql_version', 'new_bundled', 'partial_version', 'notify_email', 'support_email' ), '' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'packages', 'current', 'version', 'php_version', 'mysql_version', 'new_bundled', 'partial_version', 'notify_email', 'support_email', 'new_files' ), '' ) );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $updates = new stdClass();
</span></span></pre>
</div>
</div>

</body>
</html>