diff --git a/includes/sanitizers/class-amp-form-sanitizer.php b/includes/sanitizers/class-amp-form-sanitizer.php index 03b5a183965..872f64dd9f6 100644 --- a/includes/sanitizers/class-amp-form-sanitizer.php +++ b/includes/sanitizers/class-amp-form-sanitizer.php @@ -115,6 +115,8 @@ public function sanitize() { /** * Get the action URL for the form element. * + * @todo De-duplicate with AMP_Style_Sanitizer::normalize_stylesheet_url(). + * * @param string $action_url Action URL. * @return string Action URL. */ @@ -143,28 +145,25 @@ protected function get_action_url( $action_url ) { return $action_url; } - // Make URL protocol relative. - $parsed_url['scheme'] = '//'; - // Set an empty path if none is defined but there is a host. if ( ! isset( $parsed_url['path'] ) && isset( $parsed_url['host'] ) ) { $parsed_url['path'] = ''; } if ( ! isset( $parsed_url['host'] ) ) { - $parsed_url['host'] = $_SERVER['HTTP_HOST']; + $parsed_url['host'] = $_SERVER['HTTP_HOST']; // @todo Use home_url() instead? } if ( ! isset( $parsed_url['path'] ) ) { // If there is action URL path, use the one from the request. - $parsed_url['path'] = trailingslashit( wp_unslash( $_SERVER['REQUEST_URI'] ) ); + $parsed_url['path'] = trailingslashit( wp_unslash( $_SERVER['REQUEST_URI'] ) ); // @todo This is wrong because it includes the path. } elseif ( '' !== $parsed_url['path'] && '/' !== $parsed_url['path'][0] ) { // If the path is relative, append it to the current request path. - $parsed_url['path'] = trailingslashit( wp_unslash( $_SERVER['REQUEST_URI'] ) ) . trailingslashit( $parsed_url['path'] ); + $parsed_url['path'] = trailingslashit( wp_unslash( $_SERVER['REQUEST_URI'] ) ) . trailingslashit( $parsed_url['path'] ); // @todo This is wrong because it includes the path. } // Rebuild the URL. - $action_url = $parsed_url['scheme']; + $action_url = '//'; if ( isset( $parsed_url['user'] ) ) { $action_url .= $parsed_url['user']; if ( isset( $parsed_url['pass'] ) ) { diff --git a/includes/sanitizers/class-amp-style-sanitizer.php b/includes/sanitizers/class-amp-style-sanitizer.php index f323e745932..43563665ffc 100644 --- a/includes/sanitizers/class-amp-style-sanitizer.php +++ b/includes/sanitizers/class-amp-style-sanitizer.php @@ -1417,6 +1417,75 @@ private function get_stylesheet_from_url( $stylesheet_url ) { return $this->fetch_external_stylesheet( $stylesheet_url ); } + /** + * Get the action URL for the form element. + * + * @todo De-duplicate with \AMP_Form_Sanitizer::get_action_url(). + * + * @param string $stylesheet_url Stylesheet URL. + * @return string|WP_Error Stylesheet URL. + */ + protected function normalize_stylesheet_url( $stylesheet_url ) { + if ( ! $stylesheet_url ) { + return new WP_Error( 'empty_stylesheet_url', __( 'Empty stylesheet URL', 'amp' ) ); + } + + $parsed_url = wp_parse_url( $stylesheet_url ); + if ( ! $parsed_url ) { + return new WP_Error( 'stylesheet_url_parse_error', __( 'Stylesheet URL parse error', 'amp' ) ); + } + + // If a scheme was provided, there's nothing to do. + if ( ! empty( $parsed_url['scheme'] ) ) { + return $stylesheet_url; + } + + $parsed_home_url = wp_parse_url( home_url() ); + + // Supply the same scheme as the site. + $parsed_url['scheme'] = $parsed_home_url['scheme']; + + // Set an empty path if none is defined but there is a host. + if ( ! isset( $parsed_url['path'] ) && isset( $parsed_url['host'] ) ) { + $parsed_url['path'] = ''; + } + + if ( ! isset( $parsed_url['host'] ) ) { + $parsed_url['host'] = $parsed_home_url['host']; + } + + if ( ! isset( $parsed_url['path'] ) ) { + // If there is action URL path, use the one from the request. + $parsed_url['path'] = trailingslashit( wp_unslash( $_SERVER['REQUEST_URI'] ) ); // @todo This is wrong because it includes the path. + } elseif ( '' !== $parsed_url['path'] && '/' !== $parsed_url['path'][0] ) { + // If the path is relative, append it to the current request path. + $parsed_url['path'] = trailingslashit( wp_unslash( $_SERVER['REQUEST_URI'] ) ) . trailingslashit( $parsed_url['path'] ); // @todo This is wrong because it includes the path. + } + + // Rebuild the URL. + $stylesheet_url = $parsed_url['scheme'] . '://'; + if ( isset( $parsed_url['user'] ) ) { + $stylesheet_url .= $parsed_url['user']; + if ( isset( $parsed_url['pass'] ) ) { + $stylesheet_url .= ':' . $parsed_url['pass']; + } + $stylesheet_url .= '@'; + } + $stylesheet_url .= $parsed_url['host']; + if ( isset( $parsed_url['port'] ) ) { + $stylesheet_url .= ':' . $parsed_url['port']; + } + $stylesheet_url .= $parsed_url['path']; + if ( isset( $parsed_url['query'] ) ) { + $stylesheet_url .= '?' . $parsed_url['query']; + } + if ( isset( $parsed_url['fragment'] ) ) { + $stylesheet_url .= '#' . $parsed_url['fragment']; + } + + return esc_url_raw( $stylesheet_url ); + } + /** * Fetch external stylesheet. * @@ -1427,9 +1496,9 @@ private function get_stylesheet_from_url( $stylesheet_url ) { */ private function fetch_external_stylesheet( $url ) { - // Prepend schemeless stylesheet URL with the same URL scheme as the current site. - if ( '//' === substr( $url, 0, 2 ) ) { - $url = wp_parse_url( home_url(), PHP_URL_SCHEME ) . ':' . $url; + $url = $this->normalize_stylesheet_url( $url ); + if ( is_wp_error( $url ) ) { + return $url; } try { diff --git a/includes/validation/class-amp-validated-url-post-type.php b/includes/validation/class-amp-validated-url-post-type.php index 822f6fcb061..519fa2b228c 100644 --- a/includes/validation/class-amp-validated-url-post-type.php +++ b/includes/validation/class-amp-validated-url-post-type.php @@ -1553,7 +1553,7 @@ public static function handle_validate_request() { throw new Exception( 'invalid_post' ); } if ( ! current_user_can( 'edit_post', $post->ID ) ) { - throw new Exception( 'unauthorized' ); + throw new Exception( __( 'Unable to access validated URL screen.', 'amp' ) ); } $url = self::get_url_from_post( $post ); } elseif ( isset( $_GET['url'] ) ) { @@ -1562,8 +1562,8 @@ public static function handle_validate_request() { throw new Exception( 'illegal_url' ); } // Don't let non-admins create new amp_validated_url posts. - if ( ! current_user_can( 'manage_options' ) ) { - throw new Exception( 'unauthorized' ); + if ( ! current_user_can( get_post_type_object( self::POST_TYPE_SLUG )->cap->edit_posts ) ) { + throw new Exception( __( 'Unable to access validated URL screen.', 'amp' ) ); } } @@ -1591,6 +1591,9 @@ public static function handle_validate_request() { throw new Exception( AMP_Validation_Manager::get_validate_url_error_message( $stored->get_error_code(), $stored->get_error_message() ) ); } $redirect = get_edit_post_link( $stored, 'raw' ); + if ( empty( $redirect ) ) { + throw new Exception( __( 'Unable to access validated URL screen.', 'amp' ) ); + } $error_count = count( array_filter( diff --git a/includes/validation/class-amp-validation-manager.php b/includes/validation/class-amp-validation-manager.php index 804a049f5f4..2e6b5a419b6 100644 --- a/includes/validation/class-amp-validation-manager.php +++ b/includes/validation/class-amp-validation-manager.php @@ -836,7 +836,7 @@ public static function get_amp_validity_rest_field( $post_data, $field_name, $re * @return boolean $has_cap Whether the current user has the capability. */ public static function has_cap() { - return current_user_can( 'edit_posts' ); + return current_user_can( get_post_type_object( AMP_Validated_URL_Post_Type::POST_TYPE_SLUG )->cap->edit_posts ); } /**