From 9c3ce8628020e25399ffc8a079a509617302e127 Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 15 May 2012 18:46:03 +0000 Subject: [PATCH] API for allowing cross origin resource sharing. * Allowed origin whitelist that can be altered by plugins * Validation of the request origin against the whitelist * Send Access-Control-Allow-Origin if origin allowed * get_http_origin(), get_allowed_http_origins(), is_allowed_http_origin(), send_origin_headers() See #20681 git-svn-id: http://core.svn.wordpress.org/trunk@20794 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/class-wp-customize.php | 12 +---- wp-includes/http.php | 77 ++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 11 deletions(-) diff --git a/wp-includes/class-wp-customize.php b/wp-includes/class-wp-customize.php index 198d979bf..ffae10619 100644 --- a/wp-includes/class-wp-customize.php +++ b/wp-includes/class-wp-customize.php @@ -71,17 +71,7 @@ final class WP_Customize { if ( ! isset( $_REQUEST['customize'] ) || 'on' != $_REQUEST['customize'] ) return; - $url = parse_url( admin_url() ); - $allowed_origins = array( 'http://' . $url[ 'host' ], 'https://' . $url[ 'host' ] ); - // @todo preserve port? - if ( isset( $_SERVER[ 'HTTP_ORIGIN' ] ) && in_array( $_SERVER[ 'HTTP_ORIGIN' ], $allowed_origins ) ) { - $origin = $_SERVER[ 'HTTP_ORIGIN' ]; - } else { - $origin = $url[ 'scheme' ] . '://' . $url[ 'host' ]; - } - - @header( 'Access-Control-Allow-Origin: ' . $origin ); - @header( 'Access-Control-Allow-Credentials: true' ); + send_origin_headers(); $this->start_previewing_theme(); show_admin_bar( false ); diff --git a/wp-includes/http.php b/wp-includes/http.php index 6d3dcffa6..dd9df6e73 100644 --- a/wp-includes/http.php +++ b/wp-includes/http.php @@ -222,3 +222,80 @@ function wp_http_supports( $capabilities = array(), $url = null ) { return (bool) $objFetchSite->_get_first_available_transport( $capabilities ); } + +/** + * Get the HTTP Origin of the current request. + * + * @since 3.4.0 + * + * @return string URL of the origin. Empty string if no origin. + */ +function get_http_origin() { + $origin = ''; + if ( ! empty ( $_SERVER[ 'HTTP_ORIGIN' ] ) ) + $origin = $_SERVER[ 'HTTP_ORIGIN' ]; + + return apply_filters( 'http_origin', $origin ); +} + +/** + * Retrieve list of allowed http origins. + * + * @since 3.4.0 + * + * @return array Array of origin URLs. + */ +function get_allowed_http_origins() { + $admin_origin = parse_url( admin_url() ); + $home_origin = parse_url( home_url() ); + + // @todo preserve port? + $allowed_origins = array_unique( array( + 'http://' . $admin_origin[ 'host' ], + 'https://' . $admin_origin[ 'host' ], + 'http://' . $home_origin[ 'host' ], + 'https://' . $home_origin[ 'host' ], + ) ); + + return apply_filters( 'allowed_http_origins' , $allowed_origins ); +} + +/** + * Determines if the http origin is an authorized one. + * + * @since 3.4.0 + * + * @param string Origin URL. If not provided, the value of get_http_origin() is used. + * @return bool True if the origin is allowed. False otherwise. + */ +function is_allowed_http_origin( $origin = null ) { + $origin_arg = $origin; + + if ( null === $origin ) + $origin = get_http_origin(); + + if ( $origin && ! in_array( $origin, get_allowed_http_origins() ) ) + $origin = ''; + + return apply_filters( 'allowed_http_origin', $origin, $origin_arg ); +} + +/** + * Send Access-Control-Allow-Origin and related headers if the current request + * is from an allowed origin. + * + * @since 3.4.0 + * + * @return bool|string Returns the origin URL if headers are sent. Returns false + * if headers are not sent. + */ +function send_origin_headers() { + $origin = get_http_origin(); + if ( ! is_allowed_http_origin( $origin ) ) + return false; + + @header( 'Access-Control-Allow-Origin: ' . $origin ); + @header( 'Access-Control-Allow-Credentials: true' ); + + return $origin; +} \ No newline at end of file