diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php
index dff74ec683..44958a070f 100644
--- a/src/wp-admin/includes/ajax-actions.php
+++ b/src/wp-admin/includes/ajax-actions.php
@@ -2547,17 +2547,50 @@ function wp_ajax_parse_embed() {
wp_send_json_error();
}
- if ( empty( $_POST['shortcode'] ) || ! current_user_can( 'read_post', $post->ID ) ) {
+ if ( empty( $_POST['shortcode'] ) || ! current_user_can( 'edit_post', $post->ID ) ) {
wp_send_json_error();
}
+ $shortcode = $_POST['shortcode'];
+ $url = str_replace( '[embed]', '', str_replace( '[/embed]', '', $shortcode ) );
+ $parsed = false;
setup_postdata( $post );
- // If the URL cannot be embedded, return an eror message with wp_send_json_error()
- add_filter( 'embed_maybe_make_link', '_wpview_embed_error', 20, 2 );
+ $wp_embed->return_false_on_fail = true;
- $parsed = $wp_embed->run_shortcode( $_POST['shortcode'] );
+ if ( is_ssl() && preg_match( '%^\\[embed\\]http://%i', $shortcode ) ) {
+ // Admin is ssl and the user pasted non-ssl URL.
+ // Check if the provider supports ssl embeds and use that for the preview.
+ $ssl_shortcode = preg_replace( '%^\\[embed\\]http://%i', '[embed]https://', $shortcode );
+ $parsed = $wp_embed->run_shortcode( $ssl_shortcode );
+
+ if ( ! $parsed ) {
+ $no_ssl_support = true;
+ }
+ }
+
+ if ( ! $parsed ) {
+ $parsed = $wp_embed->run_shortcode( $shortcode );
+ }
+
+ if ( ! $parsed ) {
+ wp_send_json_error( array(
+ 'type' => 'not-embeddable',
+ 'message' => sprintf( __( '%s failed to embed.' ), '' . esc_url( $url ) . '' ),
+ ) );
+ }
+
+ // TODO: needed?
$parsed = do_shortcode( $parsed );
+ if ( ! empty( $no_ssl_support ) || ( is_ssl() && ( preg_match( '%<(iframe|script|embed) [^>]*src="http://%', $parsed ) ||
+ preg_match( '%]*href="http://%', $parsed ) ) ) ) {
+ // Admin is ssl and the embed is not. Iframes, scripts, and other "active content" will be blocked.
+ wp_send_json_error( array(
+ 'type' => 'not-ssl',
+ 'message' => sprintf( __( 'Preview not available. %s cannot be embedded securely.' ), '' . esc_url( $url ) . '' ),
+ ) );
+ }
+
wp_send_json_success( $parsed );
}
diff --git a/src/wp-admin/includes/misc.php b/src/wp-admin/includes/misc.php
index 17ab62f1c8..9df880581f 100644
--- a/src/wp-admin/includes/misc.php
+++ b/src/wp-admin/includes/misc.php
@@ -824,15 +824,3 @@ function heartbeat_autosave( $response, $data ) {
}
// Run later as we have to set DOING_AUTOSAVE for back-compat
add_filter( 'heartbeat_received', 'heartbeat_autosave', 500, 2 );
-
-/**
- * Send error message when an URL cannot be embedded. Used in wp_ajax_parse_embed().
- *
- * @access private
- * @since 4.0
- */
-function _wpview_embed_error( $output, $url ) {
- wp_send_json_error( array(
- 'message' => sprintf( __( '%s failed to embed.' ), esc_url( $url ) ),
- ) );
-}
diff --git a/src/wp-includes/class-wp-embed.php b/src/wp-includes/class-wp-embed.php
index fbcd51713f..e959d93590 100644
--- a/src/wp-includes/class-wp-embed.php
+++ b/src/wp-includes/class-wp-embed.php
@@ -12,6 +12,12 @@ class WP_Embed {
public $usecache = true;
public $linkifunknown = true;
+ /**
+ * When an URL cannot be embedded, return false instead of returning a link
+ * or the URL. Bypasses the 'embed_maybe_make_link' filter.
+ */
+ public $return_false_on_fail = false;
+
/**
* Constructor
*/
@@ -322,6 +328,10 @@ class WP_Embed {
* @return string Linked URL or the original URL.
*/
public function maybe_make_link( $url ) {
+ if ( $this->return_false_on_fail ) {
+ return false;
+ }
+
$output = ( $this->linkifunknown ) ? '' . esc_html($url) . '' : $url;
/**
diff --git a/src/wp-includes/js/mce-view.js b/src/wp-includes/js/mce-view.js
index baaaf72928..cfdf2bd698 100644
--- a/src/wp-includes/js/mce-view.js
+++ b/src/wp-includes/js/mce-view.js
@@ -737,7 +737,9 @@ window.wp = window.wp || {};
} )
.fail( function( response ) {
if ( response && response.message ) {
- if ( self.type === 'embed' ) {
+ if ( ( response.type === 'not-embeddable' && self.type === 'embed' ) ||
+ response.type === 'not-ssl' ) {
+
self.setError( response.message, 'admin-media' );
} else {
self.setContent( '
' + self.original + '
', null, true );