<!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>[21031] trunk: Customizer: Gravefully handle cookie expipration.</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, #logmsg > ol { margin-left: 0; 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">
<dt>Revision</dt> <dd><a href="http://core.trac.wordpress.org/changeset/21031">21031</a></dd>
<dt>Author</dt> <dd>ryan</dd>
<dt>Date</dt> <dd>2012-06-08 19:22:11 +0000 (Fri, 08 Jun 2012)</dd>
</dl>
<h3>Log Message</h3>
<pre>Customizer: Gravefully handle cookie expipration. Prompt for log in in the preview. Props ocean90, koopersmith, nacin. fixes <a href="http://core.trac.wordpress.org/ticket/20876">#20876</a></pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpadmincsscustomizecontrolsdevcss">trunk/wp-admin/css/customize-controls.dev.css</a></li>
<li><a href="#trunkwpadmincustomizephp">trunk/wp-admin/customize.php</a></li>
<li><a href="#trunkwpadminjscustomizecontrolsdevjs">trunk/wp-admin/js/customize-controls.dev.js</a></li>
<li><a href="#trunkwpincludesclasswpcustomizemanagerphp">trunk/wp-includes/class-wp-customize-manager.php</a></li>
<li><a href="#trunkwpincludesscriptloaderphp">trunk/wp-includes/script-loader.php</a></li>
<li><a href="#trunkwploginphp">trunk/wp-login.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpadmincsscustomizecontrolsdevcss"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/css/customize-controls.dev.css (21030 => 21031)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/css/customize-controls.dev.css        2012-06-08 18:58:24 UTC (rev 21030)
+++ trunk/wp-admin/css/customize-controls.dev.css        2012-06-08 19:22:11 UTC (rev 21031)
</span><span class="lines">@@ -514,3 +514,24 @@
</span><span class="cx">         -webkit-overflow-scrolling: touch;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+/**
+ * Handle cheaters.
+ */
+body.cheatin {
+        min-width: 0;
+        background: #f9f9f9;
+        padding: 50px;
+}
+
+body.cheatin p {
+        max-width: 700px;
+        margin: 0 auto;
+        padding: 2em;
+        font-size: 14px;
+
+        background: #fff;
+        border: 1px solid #dfdfdf;
+
+        -webkit-border-radius: 3px;
+        border-radius: 3px;
+}
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpadmincustomizephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/customize.php (21030 => 21031)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/customize.php        2012-06-08 18:58:24 UTC (rev 21030)
+++ trunk/wp-admin/customize.php        2012-06-08 19:22:11 UTC (rev 21031)
</span><span class="lines">@@ -148,6 +148,11 @@
</span><span class="cx">                 'TB_iframe' => 'true'
</span><span class="cx">         ), home_url( '/' ) );
</span><span class="cx">
</span><ins>+        $login_url = add_query_arg( array(
+                'interim-login' => 1,
+                'customize-login' => 1
+        ), wp_login_url() );
+
</ins><span class="cx">         $settings = array(
</span><span class="cx">                 'theme' => array(
</span><span class="cx">                         'stylesheet' => $wp_customize->get_stylesheet(),
</span><span class="lines">@@ -162,6 +167,7 @@
</span><span class="cx">                         'isCrossDomain' => $cross_domain,
</span><span class="cx">                         'fallback' => $fallback_url,
</span><span class="cx">                         'home' => esc_url( home_url( '/' ) ),
</span><ins>+                        'login' => $login_url,
</ins><span class="cx">                 ),
</span><span class="cx">                 'browser' => array(
</span><span class="cx">                         'mobile' => wp_is_mobile(),
</span></span></pre></div>
<a id="trunkwpadminjscustomizecontrolsdevjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/js/customize-controls.dev.js (21030 => 21031)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/js/customize-controls.dev.js        2012-06-08 18:58:24 UTC (rev 21030)
+++ trunk/wp-admin/js/customize-controls.dev.js        2012-06-08 19:22:11 UTC (rev 21031)
</span><span class="lines">@@ -334,6 +334,18 @@
</span><span class="cx">                                         return;
</span><span class="cx">                                 }
</span><span class="cx">
</span><ins>+                                // Check if the user is not logged in.
+                                if ( '0' === response ) {
+                                        deferred.rejectWith( self, [ 'logged out' ] );
+                                        return;
+                                }
+
+                                // Check for cheaters.
+                                if ( '-1' === response ) {
+                                        deferred.rejectWith( self, [ 'cheatin' ] );
+                                        return;
+                                }
+
</ins><span class="cx">                                 // Check for a signature in the request.
</span><span class="cx">                                 index = response.lastIndexOf( signature );
</span><span class="cx">                                 if ( -1 === index || index < response.lastIndexOf('</html>') ) {
</span><span class="lines">@@ -548,7 +560,52 @@
</span><span class="cx">                         this.loading.fail( function( reason, location ) {
</span><span class="cx">                                 if ( 'redirect' === reason && location )
</span><span class="cx">                                         self.url( location );
</span><ins>+
+                                if ( 'logged out' === reason ) {
+                                        if ( self.iframe ) {
+                                                self.iframe.destroy();
+                                                delete self.iframe;
+                                        }
+
+                                        self.login().done( self.refresh );
+                                }
+
+                                if ( 'cheatin' === reason )
+                                        self.cheatin();
</ins><span class="cx">                         });
</span><ins>+                },
+
+                login: function() {
+                        var previewer = this,
+                                deferred, messenger, iframe;
+
+                        if ( this._login )
+                                return this._login;
+
+                        deferred = $.Deferred();
+                        this._login = deferred.promise();
+
+                        messenger = new api.Messenger({
+                                channel: 'login',
+                                url: api.settings.url.login
+                        });
+
+                        iframe = $('<iframe src="' + api.settings.url.login + '" />').appendTo( this.container );
+
+                        messenger.targetWindow( iframe[0].contentWindow );
+
+                        messenger.bind( 'login', function() {
+                                iframe.remove();
+                                messenger.destroy();
+                                delete previewer._login;
+                                deferred.resolve();
+                        });
+
+                        return this._login;
+                },
+
+                cheatin: function() {
+                        $( document.body ).empty().addClass('cheatin').append( '<p>' + api.l10n.cheatin + '</p>' );
</ins><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx">
</span><span class="lines">@@ -605,7 +662,8 @@
</span><span class="cx">                         nonce: $('#_wpnonce').val(),
</span><span class="cx">
</span><span class="cx">                         save: function() {
</span><del>-                                var query = $.extend( this.query(), {
</del><ins>+                                var self = this,
+                                        query = $.extend( this.query(), {
</ins><span class="cx">                                                 action: 'customize_save',
</span><span class="cx">                                                 nonce: this.nonce
</span><span class="cx">                                         }),
</span><span class="lines">@@ -619,7 +677,23 @@
</span><span class="cx">                                         body.removeClass('saving');
</span><span class="cx">                                 });
</span><span class="cx">
</span><del>-                                request.done( function() {
</del><ins>+                                request.done( function( response ) {
+                                        // Check if the user is logged out.
+                                        if ( '0' === response ) {
+                                                self.iframe.iframe.hide();
+                                                self.login().done( function() {
+                                                        self.save();
+                                                        self.iframe.iframe.show();
+                                                });
+                                                return;
+                                        }
+
+                                        // Check for cheaters.
+                                        if ( '-1' === response ) {
+                                                self.cheatin();
+                                                return;
+                                        }
+
</ins><span class="cx">                                         api.trigger( 'saved' );
</span><span class="cx">                                 });
</span><span class="cx">                         }
</span></span></pre></div>
<a id="trunkwpincludesclasswpcustomizemanagerphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/class-wp-customize-manager.php (21030 => 21031)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/class-wp-customize-manager.php        2012-06-08 18:58:24 UTC (rev 21030)
+++ trunk/wp-includes/class-wp-customize-manager.php        2012-06-08 19:22:11 UTC (rev 21031)
</span><span class="lines">@@ -31,6 +31,8 @@
</span><span class="cx">                 require( ABSPATH . WPINC . '/class-wp-customize-section.php' );
</span><span class="cx">                 require( ABSPATH . WPINC . '/class-wp-customize-control.php' );
</span><span class="cx">
</span><ins>+                add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) );
+
</ins><span class="cx">                 add_action( 'setup_theme', array( $this, 'setup_theme' ) );
</span><span class="cx">                 add_action( 'wp_loaded', array( $this, 'wp_loaded' ) );
</span><span class="cx">
</span><span class="lines">@@ -52,16 +54,54 @@
</span><span class="cx">                 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_control_scripts' ) );
</span><span class="cx">         }
</span><span class="cx">
</span><ins>+         /**
+         * Return true if it's an AJAX request.
+         *
+         * @since 3.4.0
+         */
+        public function doing_ajax() {
+                return isset( $_POST['customized'] ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX );
+        }
+
</ins><span class="cx">         /**
</span><del>-         * Start preview and customize theme.
</del><ins>+         * Custom wp_die wrapper. Returns either the standard message for UI
+         * or the AJAX message.
</ins><span class="cx">          *
</span><del>-         * Check if customize query variable exist. Init filters to filter the current theme.
</del><ins>+         * @param mixed $ajax_message AJAX return
+         * @param mixed $message UI message
</ins><span class="cx">          *
</span><span class="cx">          * @since 3.4.0
</span><span class="cx">          */
</span><ins>+        private function wp_die( $ajax_message, $message ) {
+                if ( $this->doing_ajax() )
+                        wp_die( $ajax_message );
+
+                wp_die( $message );
+        }
+
+        /**
+         * Return the AJAX wp_die() handler if it's a customized request.
+         *
+         * @since 3.4.0
+         */
+        public function wp_die_handler() {
+                if ( $this->doing_ajax() )
+                        return '_ajax_wp_die_handler';
+
+                return '_default_wp_die_handler';
+        }
+        /**
+        * Start preview and customize theme.
+        *
+        * Check if customize query variable exist. Init filters to filter the current theme.
+         *
+         * @since 3.4.0
+         */
</ins><span class="cx">         public function setup_theme() {
</span><del>-                if ( is_admin() && ! defined( 'DOING_AJAX' ) )
-                        auth_redirect();
</del><ins>+                if ( is_admin() && ! $this->doing_ajax() )
+                 auth_redirect();
+                elseif ( $this->doing_ajax() && ! is_user_logged_in())
+                 wp_die( 0 );
</ins><span class="cx">
</span><span class="cx">                 send_origin_headers();
</span><span class="cx">
</span><span class="lines">@@ -71,13 +111,13 @@
</span><span class="cx">
</span><span class="cx">                 // You can't preview a theme if it doesn't exist, or if it is not allowed (unless active).
</span><span class="cx">                 if ( ! $this->theme->exists() )
</span><del>-                        wp_die( __( 'Cheatin&#8217; uh?' ) );
</del><ins>+                        $this->wp_die( -1, __( 'Cheatin&#8217; uh?' ) );
</ins><span class="cx">
</span><span class="cx">                 if ( $this->theme->get_stylesheet() != get_stylesheet() && ( ! $this->theme()->is_allowed() || ! current_user_can( 'switch_themes' ) ) )
</span><del>-                        wp_die( __( 'Cheatin&#8217; uh?' ) );
</del><ins>+                        $this->wp_die( -1, __( 'Cheatin&#8217; uh?' ) );
</ins><span class="cx">
</span><span class="cx">                 if ( ! current_user_can( 'edit_theme_options' ) )
</span><del>-                        wp_die( __( 'Cheatin&#8217; uh?' ) );
</del><ins>+                        $this->wp_die( -1, __( 'Cheatin&#8217; uh?' ) );
</ins><span class="cx">
</span><span class="cx">                 $this->start_previewing_theme();
</span><span class="cx">                 show_admin_bar( false );
</span><span class="lines">@@ -949,4 +989,4 @@
</span><span class="cx">                 return '#' . $unhashed;
</span><span class="cx">
</span><span class="cx">         return $color;
</span><del>-}
</del><span class="cx">\ No newline at end of file
</span><ins>+}
</ins></span></pre></div>
<a id="trunkwpincludesscriptloaderphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/script-loader.php (21030 => 21031)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/script-loader.php        2012-06-08 18:58:24 UTC (rev 21030)
+++ trunk/wp-includes/script-loader.php        2012-06-08 19:22:11 UTC (rev 21031)
</span><span class="lines">@@ -305,6 +305,7 @@
</span><span class="cx">                 'saved' => __( 'Saved' ),
</span><span class="cx">                 'cancel' => __( 'Cancel' ),
</span><span class="cx">                 'close' => __( 'Close' ),
</span><ins>+                'cheatin' => __( 'Cheatin&#8217; uh?' ),
</ins><span class="cx">         ) );
</span><span class="cx">
</span><span class="cx">         if ( is_admin() ) {
</span></span></pre></div>
<a id="trunkwploginphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-login.php (21030 => 21031)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-login.php        2012-06-08 18:58:24 UTC (rev 21030)
+++ trunk/wp-login.php        2012-06-08 19:22:11 UTC (rev 21031)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> * @param WP_Error $wp_error Optional. WordPress Error Object
</span><span class="cx"> */
</span><span class="cx"> function login_header($title = 'Log In', $message = '', $wp_error = '') {
</span><del>-        global $error, $interim_login, $current_site;
</del><ins>+        global $error, $interim_login, $current_site, $customize_login;
</ins><span class="cx">
</span><span class="cx">         // Don't index any of these forms
</span><span class="cx">         add_action( 'login_head', 'wp_no_robots' );
</span><span class="lines">@@ -68,6 +68,9 @@
</span><span class="cx">                 <meta name="viewport" content="width=320; initial-scale=0.9; maximum-scale=1.0; user-scalable=0;" /><?php
</span><span class="cx">         }
</span><span class="cx">
</span><ins>+        if ( $customize_login )
+                wp_enqueue_script( 'customize-base' );
+
</ins><span class="cx">         do_action( 'login_enqueue_scripts' );
</span><span class="cx">         do_action( 'login_head' );
</span><span class="cx">
</span><span class="lines">@@ -82,6 +85,10 @@
</span><span class="cx">         $login_header_url = apply_filters( 'login_headerurl', $login_header_url );
</span><span class="cx">         $login_header_title = apply_filters( 'login_headertitle', $login_header_title );
</span><span class="cx">
</span><ins>+        // Don't allow interim logins to navigate away from the page.
+        if ( $interim_login )
+                $login_header_url = '#';
+
</ins><span class="cx">         ?>
</span><span class="cx">         </head>
</span><span class="cx">         <body class="login<?php if ( wp_is_mobile() ) echo ' mobile'; ?>">
</span><span class="lines">@@ -126,8 +133,13 @@
</span><span class="cx"> * @param string $input_id Which input to auto-focus
</span><span class="cx"> */
</span><span class="cx"> function login_footer($input_id = '') {
</span><del>-        ?>
</del><ins>+        global $interim_login;
+
+        // Don't allow interim logins to navigate away from the page.
+        if ( ! $interim_login ): ?>
</ins><span class="cx">         <p id="backtoblog"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php esc_attr_e( 'Are you lost?' ); ?>"><?php printf( __( '&larr; Back to %s' ), get_bloginfo( 'title', 'display' ) ); ?></a></p>
</span><ins>+        <?php endif; ?>
+
</ins><span class="cx">         </div>
</span><span class="cx">
</span><span class="cx">         <?php if ( !empty($input_id) ) : ?>
</span><span class="lines">@@ -555,6 +567,7 @@
</span><span class="cx"> default:
</span><span class="cx">         $secure_cookie = '';
</span><span class="cx">         $interim_login = isset($_REQUEST['interim-login']);
</span><ins>+        $customize_login = isset( $_REQUEST['customize-login'] );
</ins><span class="cx">
</span><span class="cx">         // If the user wants ssl but the session is not ssl, force a secure cookie.
</span><span class="cx">         if ( !empty($_POST['log']) && !force_ssl_admin() ) {
</span><span class="lines">@@ -591,11 +604,22 @@
</span><span class="cx">         if ( !is_wp_error($user) && !$reauth ) {
</span><span class="cx">                 if ( $interim_login ) {
</span><span class="cx">                         $message = '<p class="message">' . __('You have logged in successfully.') . '</p>';
</span><del>-                        login_header( '', $message ); ?>
-                        <script type="text/javascript">setTimeout( function(){window.close()}, 8000);</script>
-                        <p class="alignright">
-                        <input type="button" class="button-primary" value="<?php esc_attr_e('Close'); ?>" onclick="window.close()" /></p>
-                        </div></body></html>
</del><ins>+                        login_header( '', $message );
+
+                        if ( ! $customize_login ) : ?>
+                                <script type="text/javascript">setTimeout( function(){window.close()}, 8000);</script>
+                                <p class="alignright">
+                                <input type="button" class="button-primary" value="<?php esc_attr_e('Close'); ?>" onclick="window.close()" /></p>
+<?php                endif;
+
+                        ?></div><?php
+
+                        do_action('login_footer');
+
+                        if ( $customize_login ) : ?>
+                                <script type="text/javascript">setTimeout( function(){ new wp.customize.Messenger({ url: '<?php echo wp_customize_url(); ?>', channel: 'login' }).send('login') }, 1000 );</script>
+<?php                endif; ?>
+                        </body></html>
</ins><span class="cx"> <?php                exit;
</span><span class="cx">                 }
</span><span class="cx">
</span><span class="lines">@@ -666,6 +690,9 @@
</span><span class="cx"> <?php        } else { ?>
</span><span class="cx">                 <input type="hidden" name="redirect_to" value="<?php echo esc_attr($redirect_to); ?>" />
</span><span class="cx"> <?php         } ?>
</span><ins>+<?php if ( $customize_login ) : ?>
+                <input type="hidden" name="customize-login" value="1" />
+<?php endif; ?>
</ins><span class="cx">                 <input type="hidden" name="testcookie" value="1" />
</span><span class="cx">         </p>
</span><span class="cx"> </form>
</span></span></pre>
</div>
</div>
</body>
</html>