From 84cc00a6e8696dfde4282c49eefb4da8044fc4d6 Mon Sep 17 00:00:00 2001 From: koopersmith Date: Thu, 24 May 2012 19:17:49 +0000 Subject: [PATCH] Theme Customizer: Improve accuracy of identifying internal urls. see #20507, #19910. The 'customize_preview_link' filter has been replaced by 'customize_allowed_urls'. Improved accuracy when checking for wp-admin. Improved accuracy when attempting to match the schemes of the control and preview frames. Improved accuracy of internal link whitelist. git-svn-id: http://core.svn.wordpress.org/trunk@20882 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/customize.php | 21 ++++++----- wp-includes/js/customize-controls.dev.js | 48 ++++++++++++++++++++---- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/wp-admin/customize.php b/wp-admin/customize.php index e2351d66a6..3b0b10045f 100644 --- a/wp-admin/customize.php +++ b/wp-admin/customize.php @@ -101,15 +101,17 @@ do_action( 'customize_controls_print_scripts' ); // preview over ssl if the customizer is being loaded over ssl. This avoids // insecure content warnings. This is not attempted if the admin and frontend // are on different domains to avoid the case where the frontend doesn't have - // ssl certs. Domain mapping plugins can force ssl in these conditions using - // the customize_preview_link filter. - $admin_origin = parse_url( admin_url() ); - $home_origin = parse_url( home_url() ); - $scheme = null; - if ( is_ssl() && ( $admin_origin[ 'host' ] == $home_origin[ 'host' ] ) ) - $scheme = 'https'; + // ssl certs. Domain mapping plugins can allow other urls in these conditions + // using the customize_allowed_urls filter. - $preview_url = apply_filters( 'customize_preview_link', home_url( '/', $scheme ) ); + $allowed_urls = array( home_url('/') ); + $admin_origin = parse_url( admin_url() ); + $home_origin = parse_url( home_url() ); + + if ( is_ssl() && ( $admin_origin[ 'host' ] == $home_origin[ 'host' ] ) ) + $allowed_urls[] = home_url( '/', 'https' ); + + $allowed_urls = array_unique( apply_filters( 'customize_allowed_urls', $allowed_urls ) ); $settings = array( 'theme' => array( @@ -117,9 +119,10 @@ do_action( 'customize_controls_print_scripts' ); 'active' => $wp_customize->is_theme_active(), ), 'url' => array( - 'preview' => esc_url( $preview_url ), + 'preview' => esc_url( home_url( '/' ) ), 'parent' => esc_url( admin_url() ), 'ajax' => esc_url( admin_url( 'admin-ajax.php', 'relative' ) ), + 'allowed' => array_map( 'esc_url', $allowed_urls ), ), 'settings' => array(), 'controls' => array(), diff --git a/wp-includes/js/customize-controls.dev.js b/wp-includes/js/customize-controls.dev.js index 811c7e91c1..f6a3a92e39 100644 --- a/wp-includes/js/customize-controls.dev.js +++ b/wp-includes/js/customize-controls.dev.js @@ -272,7 +272,8 @@ * - url - the URL of preview frame */ initialize: function( params, options ) { - var self = this; + var self = this, + rscheme = /^https?/; $.extend( this, options || {} ); @@ -314,7 +315,8 @@ }; })( this ); - this.container = api.ensure( params.container ); + this.container = api.ensure( params.container ); + this.allowedUrls = params.allowedUrls; api.Messenger.prototype.initialize.call( this, params.url ); @@ -322,13 +324,42 @@ // to the current window's location, not the url's. this.origin.unlink( this.url ).set( window.location.href ); + this.add( 'scheme', this.origin() ).link( this.origin ).setter( function( to ) { + var match = to.match( rscheme ); + return match ? match[0] : ''; + }); + // Limit the URL to internal, front-end links. + // + // If the frontend and the admin are served from the same domain, load the + // preview over ssl if the customizer is being loaded over ssl. This avoids + // insecure content warnings. This is not attempted if the admin and frontend + // are on different domains to avoid the case where the frontend doesn't have + // ssl certs. + this.url.setter( function( to ) { - // Bail if we're navigating to a different origin or wp-admin. - if ( 0 !== to.indexOf( self.origin() + '/' ) || -1 !== to.indexOf( 'wp-admin' ) ) + var result; + + // Check for URLs that include "/wp-admin/" or end in "/wp-admin". + // Strip hashes and query strings before testing. + if ( /\/wp-admin(\/|$)/.test( to.replace(/[#?].*$/, '') ) ) return null; - return to; + // Attempt to match the URL to the control frame's scheme + // and check if it's allowed. If not, try the original URL. + $.each([ to.replace( rscheme, self.scheme() ), to ], function( i, url ) { + $.each( self.allowedUrls, function( i, allowed ) { + if ( 0 === url.indexOf( allowed ) ) { + result = url; + return false; + } + }); + if ( result ) + return false; + }); + + // If we found a matching result, return it. If not, bail. + return result ? result : null; }); // Refresh the preview when the URL is changed. @@ -422,9 +453,10 @@ }); previewer = new api.Previewer({ - container: '#customize-preview', - form: '#customize-controls', - url: api.settings.url.preview + container: '#customize-preview', + form: '#customize-controls', + url: api.settings.url.preview, + allowedUrls: api.settings.url.allowed }, { query: function() { return {