Commit 58c21501 authored by lucha's avatar lucha

Wordpress 4.7.5

parent dce2634c
......@@ -45,6 +45,10 @@ include( ABSPATH . 'wp-admin/admin-header.php' );
<div class="changelog point-releases">
<h3><?php _e( 'Maintenance and Security Releases' ); ?></h3>
<p><?php printf( _n( '<strong>Version %1$s</strong> addressed some security issues and fixed %2$s bug.',
'<strong>Version %1$s</strong> addressed some security issues and fixed %2$s bugs.', 3 ), '4.7.5', number_format_i18n( 3 ) ); ?>
<?php printf( __( 'For more information, see <a href="%s">the release notes</a>.' ), 'https://codex.wordpress.org/Version_4.7.5' ); ?>
</p>
<p><?php printf( _n( '<strong>Version %1$s</strong> addressed %2$s bug.',
'<strong>Version %1$s</strong> addressed %2$s bugs.', 47 ), '4.7.4', number_format_i18n( 47 ) ); ?>
<?php printf( __( 'For more information, see <a href="%s">the release notes</a>.' ), 'https://codex.wordpress.org/Version_4.7.4' ); ?>
......
......@@ -155,7 +155,7 @@ do_action( 'customize_controls_print_scripts' );
<div id="customize-info" class="accordion-section customize-info">
<div class="accordion-section-title">
<span class="preview-notice"><?php
echo sprintf( __( 'You are customizing %s' ), '<strong class="panel-title site-title">' . get_bloginfo( 'name' ) . '</strong>' );
echo sprintf( __( 'You are customizing %s' ), '<strong class="panel-title site-title">' . get_bloginfo( 'name', 'display' ) . '</strong>' );
?></span>
<button type="button" class="customize-help-toggle dashicons dashicons-editor-help" aria-expanded="false"><span class="screen-reader-text"><?php _e( 'Help' ); ?></span></button>
</div>
......
......@@ -1091,14 +1091,28 @@ function request_filesystem_credentials( $form_post, $type = '', $error = false,
$credentials = get_option('ftp_credentials', array( 'hostname' => '', 'username' => ''));
$submitted_form = wp_unslash( $_POST );
// Verify nonce, or unset submitted form field values on failure
if ( ! isset( $_POST['_fs_nonce'] ) || ! wp_verify_nonce( $_POST['_fs_nonce'], 'filesystem-credentials' ) ) {
unset(
$submitted_form['hostname'],
$submitted_form['username'],
$submitted_form['password'],
$submitted_form['public_key'],
$submitted_form['private_key'],
$submitted_form['connection_type']
);
}
// If defined, set it to that, Else, If POST'd, set it to that, If not, Set it to whatever it previously was(saved details in option)
$credentials['hostname'] = defined('FTP_HOST') ? FTP_HOST : (!empty($_POST['hostname']) ? wp_unslash( $_POST['hostname'] ) : $credentials['hostname']);
$credentials['username'] = defined('FTP_USER') ? FTP_USER : (!empty($_POST['username']) ? wp_unslash( $_POST['username'] ) : $credentials['username']);
$credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($_POST['password']) ? wp_unslash( $_POST['password'] ) : '');
$credentials['hostname'] = defined('FTP_HOST') ? FTP_HOST : (!empty($submitted_form['hostname']) ? $submitted_form['hostname'] : $credentials['hostname']);
$credentials['username'] = defined('FTP_USER') ? FTP_USER : (!empty($submitted_form['username']) ? $submitted_form['username'] : $credentials['username']);
$credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($submitted_form['password']) ? $submitted_form['password'] : '');
// Check to see if we are setting the public/private keys for ssh
$credentials['public_key'] = defined('FTP_PUBKEY') ? FTP_PUBKEY : (!empty($_POST['public_key']) ? wp_unslash( $_POST['public_key'] ) : '');
$credentials['private_key'] = defined('FTP_PRIKEY') ? FTP_PRIKEY : (!empty($_POST['private_key']) ? wp_unslash( $_POST['private_key'] ) : '');
$credentials['public_key'] = defined('FTP_PUBKEY') ? FTP_PUBKEY : (!empty($submitted_form['public_key']) ? $submitted_form['public_key'] : '');
$credentials['private_key'] = defined('FTP_PRIKEY') ? FTP_PRIKEY : (!empty($submitted_form['private_key']) ? $submitted_form['private_key'] : '');
// Sanitize the hostname, Some people might pass in odd-data:
$credentials['hostname'] = preg_replace('|\w+://|', '', $credentials['hostname']); //Strip any schemes off
......@@ -1115,8 +1129,8 @@ function request_filesystem_credentials( $form_post, $type = '', $error = false,
$credentials['connection_type'] = 'ssh';
} elseif ( ( defined( 'FTP_SSL' ) && FTP_SSL ) && 'ftpext' == $type ) { //Only the FTP Extension understands SSL
$credentials['connection_type'] = 'ftps';
} elseif ( ! empty( $_POST['connection_type'] ) ) {
$credentials['connection_type'] = wp_unslash( $_POST['connection_type'] );
} elseif ( ! empty( $submitted_form['connection_type'] ) ) {
$credentials['connection_type'] = $submitted_form['connection_type'];
} elseif ( ! isset( $credentials['connection_type'] ) ) { //All else fails (And it's not defaulted to something else saved), Default to FTP
$credentials['connection_type'] = 'ftp';
}
......@@ -1255,11 +1269,12 @@ if ( isset( $types['ssh'] ) ) {
}
foreach ( (array) $extra_fields as $field ) {
if ( isset( $_POST[ $field ] ) )
echo '<input type="hidden" name="' . esc_attr( $field ) . '" value="' . esc_attr( wp_unslash( $_POST[ $field ] ) ) . '" />';
if ( isset( $submitted_form[ $field ] ) )
echo '<input type="hidden" name="' . esc_attr( $field ) . '" value="' . esc_attr( $submitted_form[ $field ] ) . '" />';
}
?>
<p class="request-filesystem-credentials-action-buttons">
<?php wp_nonce_field( 'filesystem-credentials', '_fs_nonce', false, true ); ?>
<button class="button cancel-button" data-js-action="close" type="button"><?php _e( 'Cancel' ); ?></button>
<?php submit_button( __( 'Proceed' ), '', 'upgrade', false ); ?>
</p>
......
......@@ -418,7 +418,7 @@ $document.ready( function() {
screenMeta.init();
// This event needs to be delegated. Ticket #37973.
$body.on( 'click', 'tbody > .check-column :checkbox', function( event ) {
$body.on( 'click', 'tbody > tr > .check-column :checkbox', function( event ) {
// Shift click to select a range of checkboxes.
if ( 'undefined' == event.shiftKey ) { return true; }
if ( event.shiftKey ) {
......
This diff is collapsed.
......@@ -4579,6 +4579,16 @@
}
});
// Ensure preview nonce is included with every customized request, to allow post data to be read.
$.ajaxPrefilter( function injectPreviewNonce( options ) {
if ( ! /wp_customize=on/.test( options.data ) ) {
return;
}
options.data += '&' + $.param({
customize_preview_nonce: api.settings.nonce.preview
});
});
// Refresh the nonces if the preview sends updated nonces over.
api.previewer.bind( 'nonce', function( nonce ) {
$.extend( this.nonce, nonce );
......
This diff is collapsed.
......@@ -94,6 +94,7 @@
* @type {object} filesystemCredentials.ssh Holds SSH credentials.
* @type {string} filesystemCredentials.ssh.publicKey The public key. Default empty string.
* @type {string} filesystemCredentials.ssh.privateKey The private key. Default empty string.
* @type {string} filesystemCredentials.fsNonce Filesystem credentials form nonce.
* @type {bool} filesystemCredentials.available Whether filesystem credentials have been provided.
* Default 'false'.
*/
......@@ -108,6 +109,7 @@
publicKey: '',
privateKey: ''
},
fsNonce: '',
available: false
};
......@@ -225,6 +227,7 @@
options.data = _.extend( data, {
action: action,
_ajax_nonce: wp.updates.ajaxNonce,
_fs_nonce: wp.updates.filesystemCredentials.fsNonce,
username: wp.updates.filesystemCredentials.ftp.username,
password: wp.updates.filesystemCredentials.ftp.password,
hostname: wp.updates.filesystemCredentials.ftp.hostname,
......@@ -1705,6 +1708,7 @@
wp.updates.filesystemCredentials.ftp.connectionType = $( 'input[name="connection_type"]:checked' ).val();
wp.updates.filesystemCredentials.ssh.publicKey = $( '#public_key' ).val();
wp.updates.filesystemCredentials.ssh.privateKey = $( '#private_key' ).val();
wp.updates.filesystemCredentials.fsNonce = $( '#_fs_nonce' ).val();
wp.updates.filesystemCredentials.available = true;
// Unlock and invoke the queue.
......
This diff is collapsed.
......@@ -16,12 +16,12 @@
text-decoration: inherit;
color: inherit;
}
#the-comment-list .remove_url {
#the-comment-list .akismet_remove_url {
margin-left: 3px;
color: #999;
padding: 2px 3px 2px 0;
}
#the-comment-list .remove_url:hover {
#the-comment-list .akismet_remove_url:hover {
color: #A7301F;
font-weight: bold;
padding: 2px 2px 2px 0;
......
......@@ -11,31 +11,10 @@ jQuery( function ( $ ) {
var thisId = $(this).attr('commentid');
$(this).insertAfter('#comment-' + thisId + ' .author strong:first').show();
});
$('#the-comment-list')
.find('tr.comment, tr[id ^= "comment-"]')
.find('.column-author a[href^="http"]:first') // Ignore mailto: links, which would be the comment author's email.
.each(function () {
var linkHref = $(this).attr( 'href' );
// Ignore any links to the current domain, which are diagnostic tools, like the IP address link
// or any other links another plugin might add.
var currentHostParts = document.location.href.split( '/' );
var currentHost = currentHostParts[0] + '//' + currentHostParts[2] + '/';
if ( linkHref.indexOf( currentHost ) != 0 ) {
var thisCommentId = $(this).parents('tr:first').attr('id').split("-");
$(this)
.attr("id", "author_comment_url_"+ thisCommentId[1])
.after(
$( '<a href="#" class="remove_url">x</a>' )
.attr( 'commentid', thisCommentId[1] )
.attr( 'title', WPAkismet.strings['Remove this URL'] )
);
}
});
akismet_enable_comment_author_url_removal();
$( '#the-comment-list' ).on( 'click', '.remove_url', function () {
$( '#the-comment-list' ).on( 'click', '.akismet_remove_url', function () {
var thisId = $(this).attr('commentid');
var data = {
action: 'comment_author_deurl',
......@@ -103,7 +82,7 @@ jQuery( function ( $ ) {
});
// Show a preview image of the hovered URL. Applies to author URLs and URLs inside the comments.
$( 'a[id^="author_comment_url"], tr.pingback td.column-author a:first-of-type, table.comments td.comment p a' ).mouseover( function () {
$( '#the-comment-list' ).on( 'mouseover', 'a[id^="author_comment_url"], tr.pingback td.column-author a:first-of-type, td.comment p a', function () {
clearTimeout( mshotRemovalTimer );
if ( $( '.akismet-mshot' ).length > 0 ) {
......@@ -120,7 +99,7 @@ jQuery( function ( $ ) {
clearTimeout( mshotSecondTryTimer );
clearTimeout( mshotThirdTryTimer );
var thisHref = $.URLEncode( $( this ).attr( 'href' ) );
var thisHref = encodeURIComponent( $( this ).attr( 'href' ) );
var mShot = $( '<div class="akismet-mshot mshot-container"><div class="mshot-arrow"></div><img src="//s0.wordpress.com/mshots/v1/' + thisHref + '?w=450" width="450" height="338" class="mshot-image" /></div>' );
mShot.data( 'link', this );
......@@ -141,7 +120,7 @@ jQuery( function ( $ ) {
}, 12000 );
$( 'body' ).append( mShot );
} ).mouseout( function () {
} ).on( 'mouseout', 'a[id^="author_comment_url"], tr.pingback td.column-author a:first-of-type, td.comment p a', function () {
mshotRemovalTimer = setTimeout( function () {
clearTimeout( mshotSecondTryTimer );
clearTimeout( mshotThirdTryTimer );
......@@ -194,11 +173,54 @@ jQuery( function ( $ ) {
if ( "start_recheck" in WPAkismet && WPAkismet.start_recheck ) {
$( '.checkforspam' ).click();
}
});
// URL encode plugin
jQuery.extend({URLEncode:function(c){var o='';var x=0;c=c.toString();var r=/(^[a-zA-Z0-9_.]*)/;
while(x<c.length){var m=r.exec(c.substr(x));
if(m!=null && m.length>1 && m[1]!=''){o+=m[1];x+=m[1].length;
}else{if(c[x]==' ')o+='+';else{var d=c.charCodeAt(x);var h=d.toString(16);
o+='%'+(h.length<2?'0':'')+h.toUpperCase();}x++;}}return o;}
});
if ( typeof MutationObserver !== 'undefined' ) {
// Dynamically add the "X" next the the author URL links when a comment is quick-edited.
var comment_list_container = document.getElementById( 'the-comment-list' );
if ( comment_list_container ) {
var observer = new MutationObserver( function ( mutations ) {
for ( var i = 0, _len = mutations.length; i < _len; i++ ) {
if ( mutations[i].addedNodes.length > 0 ) {
akismet_enable_comment_author_url_removal();
// Once we know that we'll have to check for new author links, skip the rest of the mutations.
break;
}
}
} );
observer.observe( comment_list_container, { attributes: true, childList: true, characterData: true } );
}
}
function akismet_enable_comment_author_url_removal() {
$( '#the-comment-list' )
.find( 'tr.comment, tr[id ^= "comment-"]' )
.find( '.column-author a[href^="http"]:first' ) // Ignore mailto: links, which would be the comment author's email.
.each(function () {
if ( $( this ).parent().find( '.akismet_remove_url' ).length > 0 ) {
return;
}
var linkHref = $(this).attr( 'href' );
// Ignore any links to the current domain, which are diagnostic tools, like the IP address link
// or any other links another plugin might add.
var currentHostParts = document.location.href.split( '/' );
var currentHost = currentHostParts[0] + '//' + currentHostParts[2] + '/';
if ( linkHref.indexOf( currentHost ) != 0 ) {
var thisCommentId = $(this).parents('tr:first').attr('id').split("-");
$(this)
.attr("id", "author_comment_url_"+ thisCommentId[1])
.after(
$( '<a href="#" class="akismet_remove_url">x</a>' )
.attr( 'commentid', thisCommentId[1] )
.attr( 'title', WPAkismet.strings['Remove this URL'] )
);
}
});
}
});
\ No newline at end of file
......@@ -6,7 +6,7 @@
Plugin Name: Akismet Anti-Spam
Plugin URI: https://akismet.com/
Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from spam</strong>. It keeps your site protected even while you sleep. To get started: activate the Akismet plugin and then go to your Akismet Settings page to set up your API key.
Version: 3.3
Version: 3.3.2
Author: Automattic
Author URI: https://automattic.com/wordpress-plugins/
License: GPLv2 or later
......@@ -37,7 +37,7 @@ if ( !function_exists( 'add_action' ) ) {
exit;
}
define( 'AKISMET_VERSION', '3.3' );
define( 'AKISMET_VERSION', '3.3.2' );
define( 'AKISMET__MINIMUM_WP_VERSION', '3.7' );
define( 'AKISMET__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'AKISMET_DELETE_LIMIT', 100000 );
......
......@@ -29,18 +29,7 @@ class Akismet {
add_action( 'akismet_scheduled_delete', array( 'Akismet', 'delete_old_comments_meta' ) );
add_action( 'akismet_schedule_cron_recheck', array( 'Akismet', 'cron_recheck' ) );
/**
* To disable the Akismet comment nonce, add a filter for the 'akismet_comment_nonce' tag
* and return any string value that is not 'true' or '' (empty string).
*
* Don't return boolean false, because that implies that the 'akismet_comment_nonce' option
* has not been set and that Akismet should just choose the default behavior for that
* situation.
*/
$akismet_comment_nonce_option = apply_filters( 'akismet_comment_nonce', get_option( 'akismet_comment_nonce' ) );
if ( $akismet_comment_nonce_option == 'true' || $akismet_comment_nonce_option == '' )
add_action( 'comment_form', array( 'Akismet', 'add_comment_nonce' ), 1 );
add_action( 'comment_form', array( 'Akismet', 'add_comment_nonce' ), 1 );
add_action( 'admin_head-edit-comments.php', array( 'Akismet', 'load_form_js' ) );
add_action( 'comment_form', array( 'Akismet', 'load_form_js' ) );
......@@ -171,7 +160,11 @@ class Akismet {
}
$post = get_post( $comment['comment_post_ID'] );
$comment[ 'comment_post_modified_gmt' ] = $post->post_modified_gmt;
if ( ! is_null( $post ) ) {
// $post can technically be null, although in the past, it's always been an indicator of another plugin interfering.
$comment[ 'comment_post_modified_gmt' ] = $post->post_modified_gmt;
}
$response = self::http_post( Akismet::build_query( $comment ), 'comment-check' );
......@@ -200,7 +193,9 @@ class Akismet {
// akismet_result_spam() won't be called so bump the counter here
if ( $incr = apply_filters('akismet_spam_count_incr', 1) )
update_option( 'akismet_spam_count', get_option('akismet_spam_count') + $incr );
$redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : get_permalink( $post );
// The spam is obvious, so we're bailing out early. Redirect back to the previous page,
// or failing that, the post permalink, or failing that, the homepage of the blog.
$redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : ( $post ? get_permalink( $post ) : home_url() );
wp_safe_redirect( esc_url_raw( $redirect_to ) );
die();
}
......@@ -266,9 +261,6 @@ class Akismet {
if ( !function_exists('add_comment_meta') )
return false;
if ( !isset( self::$last_comment['comment_author_email'] ) )
self::$last_comment['comment_author_email'] = '';
// wp_insert_comment() might be called in other contexts, so make sure this is the same comment
// as was checked by auto_check_comment
if ( is_object( $comment ) && !empty( self::$last_comment ) && is_array( self::$last_comment ) ) {
......@@ -355,6 +347,7 @@ class Akismet {
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->commentmeta} WHERE comment_id IN ( " . $format_string . " )", $comment_ids ) );
clean_comment_cache( $comment_ids );
do_action( 'akismet_delete_comment_batch', count( $comment_ids ) );
}
if ( apply_filters( 'akismet_optimize_table', ( mt_rand(1, 5000) == 11), $wpdb->comments ) ) // lucky number
......@@ -382,6 +375,8 @@ class Akismet {
foreach ( $comment_ids as $comment_id ) {
delete_comment_meta( $comment_id, 'akismet_as_submitted' );
}
do_action( 'akismet_delete_commentmeta_batch', count( $comment_ids ) );
}
if ( apply_filters( 'akismet_optimize_table', ( mt_rand(1, 5000) == 11), $wpdb->commentmeta ) ) // lucky number
......@@ -606,7 +601,10 @@ class Akismet {
$comment->is_test = 'true';
$post = get_post( $comment->comment_post_ID );
$comment->comment_post_modified_gmt = $post->post_modified_gmt;
if ( ! is_null( $post ) ) {
$comment->comment_post_modified_gmt = $post->post_modified_gmt;
}
$response = Akismet::http_post( Akismet::build_query( $comment ), 'submit-spam' );
if ( $comment->reporter ) {
......@@ -653,7 +651,10 @@ class Akismet {
$comment->is_test = 'true';
$post = get_post( $comment->comment_post_ID );
$comment->comment_post_modified_gmt = $post->post_modified_gmt;
if ( ! is_null( $post ) ) {
$comment->comment_post_modified_gmt = $post->post_modified_gmt;
}
$response = self::http_post( Akismet::build_query( $comment ), 'submit-ham' );
if ( $comment->reporter ) {
......@@ -768,9 +769,21 @@ class Akismet {
}
public static function add_comment_nonce( $post_id ) {
echo '<p style="display: none;">';
wp_nonce_field( 'akismet_comment_nonce_' . $post_id, 'akismet_comment_nonce', FALSE );
echo '</p>';
/**
* To disable the Akismet comment nonce, add a filter for the 'akismet_comment_nonce' tag
* and return any string value that is not 'true' or '' (empty string).
*
* Don't return boolean false, because that implies that the 'akismet_comment_nonce' option
* has not been set and that Akismet should just choose the default behavior for that
* situation.
*/
$akismet_comment_nonce_option = apply_filters( 'akismet_comment_nonce', get_option( 'akismet_comment_nonce' ) );
if ( $akismet_comment_nonce_option == 'true' || $akismet_comment_nonce_option == '' ) {
echo '<p style="display: none;">';
wp_nonce_field( 'akismet_comment_nonce_' . $post_id, 'akismet_comment_nonce', FALSE );
echo '</p>';
}
}
public static function is_test_mode() {
......@@ -800,7 +813,25 @@ class Akismet {
private static function comments_match( $comment1, $comment2 ) {
$comment1 = (array) $comment1;
$comment2 = (array) $comment2;
// Set default values for these strings that we check in order to simplify
// the checks and avoid PHP warnings.
if ( ! isset( $comment1['comment_author'] ) ) {
$comment1['comment_author'] = '';
}
if ( ! isset( $comment2['comment_author'] ) ) {
$comment2['comment_author'] = '';
}
if ( ! isset( $comment1['comment_author_email'] ) ) {
$comment1['comment_author_email'] = '';
}
if ( ! isset( $comment2['comment_author_email'] ) ) {
$comment2['comment_author_email'] = '';
}
$comments_match = (
isset( $comment1['comment_post_ID'], $comment2['comment_post_ID'] )
&& intval( $comment1['comment_post_ID'] ) == intval( $comment2['comment_post_ID'] )
......@@ -834,9 +865,6 @@ class Akismet {
// Does the supplied comment match the details of the one most recently stored in self::$last_comment?
public static function matches_last_comment( $comment ) {
if ( is_object( $comment ) )
$comment = (array) $comment;
return self::comments_match( self::$last_comment, $comment );
}
......
......@@ -2,8 +2,8 @@
Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eoigal, cfinke, automattic, jgs
Tags: akismet, comments, spam, antispam, anti-spam, anti spam, comment moderation, comment spam, contact form spam, spam comments
Requires at least: 3.7
Tested up to: 4.7.2
Stable tag: 3.3
Tested up to: 4.7.4
Stable tag: 3.3.2
License: GPLv2 or later
Akismet checks your comments and contact form submissions against our global database of spam to protect you and your site from malicious content.
......@@ -30,6 +30,19 @@ Upload the Akismet plugin to your blog, Activate it, then enter your [Akismet.co
== Changelog ==
= 3.3.2 =
*Release Date - 10 May 2017*
* Fixed a bug causing JavaScript errors in some browsers.
= 3.3.1 =
*Release Date - 2 May 2017*
* Improve performance by only requesting the akismet_comment_nonce option when absolutely necessary.
* Fixed two bugs that could cause PHP warnings.
* Fixed a bug that was preventing the "Remove author URL" feature from working after a comment was edited using "Quick Edit."
* Fixed a bug that was preventing the URL preview feature from working after a comment was edited using "Quick Edit."
= 3.3 =
*Release Date - 23 February 2017*
......
......@@ -306,6 +306,11 @@ class WP_Http {
// Ensure redirects follow browser behaviour.
$options['hooks']->register( 'requests.before_redirect', array( get_class(), 'browser_redirect_compatibility' ) );
// Validate redirected URLs.
if ( function_exists( 'wp_kses_bad_protocol' ) && $r['reject_unsafe_urls'] ) {
$options['hooks']->register( 'requests.before_redirect', array( get_class(), 'validate_redirects' ) );
}
if ( $r['stream'] ) {
$options['filename'] = $r['filename'];
}
......@@ -466,6 +471,20 @@ class WP_Http {
}
}
/**
* Validate redirected URLs.
*
* @since 4.7.5
*
* @throws Requests_Exception On unsuccessful URL validation
* @param string $location URL to redirect to.
*/
public static function validate_redirects( $location ) {
if ( ! wp_http_validate_url( $location ) ) {
throw new Requests_Exception( __('A valid URL was not provided.'), 'wp_http.redirect_failed_validation' );
}
}
/**
* Tests which transports are capable of supporting the request.
*
......
......@@ -484,6 +484,24 @@ final class WP_Customize_Manager {
$this->wp_die( -1, __( 'Invalid changeset UUID' ) );
}
/*
* Clear incoming post data if the user lacks a CSRF token (nonce). Note that the customizer
* application will inject the customize_preview_nonce query parameter into all Ajax requests.
* For similar behavior elsewhere in WordPress, see rest_cookie_check_errors() which logs out
* a user when a valid nonce isn't present.
*/
$has_post_data_nonce = (
check_ajax_referer( 'preview-customize_' . $this->get_stylesheet(), 'nonce', false )
||
check_ajax_referer( 'save-customize_' . $this->get_stylesheet(), 'nonce', false )
||
check_ajax_referer( 'preview-customize_' . $this->get_stylesheet(), 'customize_preview_nonce', false )
);
if ( ! current_user_can( 'customize' ) || ! $has_post_data_nonce ) {
unset( $_POST['customized'] );
unset( $_REQUEST['customized'] );
}
/*
* If unauthenticated then require a valid changeset UUID to load the preview.
* In this way, the UUID serves as a secret key. If the messenger channel is present,
......
......@@ -382,6 +382,11 @@ class wp_xmlrpc_server extends IXR_Server {
if ( isset($meta['id']) ) {
$meta['id'] = (int) $meta['id'];
$pmeta = get_metadata_by_mid( 'post', $meta['id'] );
if ( ! $pmeta || $pmeta->post_id != $post_id ) {
continue;
}
if ( isset($meta['key']) ) {
$meta['key'] = wp_unslash( $meta['key'] );
if ( $meta['key'] !== $pmeta->meta_key )
......@@ -1295,10 +1300,31 @@ class wp_xmlrpc_server extends IXR_Server {
* @return IXR_Error|string
*/
protected function _insert_post( $user, $content_struct ) {
$defaults = array( 'post_status' => 'draft', 'post_type' => 'post', 'post_author' => 0,
'post_password' => '', 'post_excerpt' => '', 'post_content' => '', 'post_title' => '' );
$defaults = array(
'post_status' => 'draft',
'post_type' => 'post',
'post_author' => null,
'post_password' => null,
'post_excerpt' => null,
'post_content' => null,
'post_title' => null,
'post_date' => null,
'post_date_gmt' => null,
'post_format' => null,
'post_name' => null,
'post_thumbnail' => null,
'post_parent' => null,
'ping_status' => null,
'comment_status' => null,
'custom_fields' => null,
'terms_names' => null,
'terms' => null,
'sticky' => null,
'enclosure' => null,
'ID' => null,
);
$post_data = wp_parse_args( $content_struct, $defaults );
$post_data = wp_parse_args( array_intersect_key( $content_struct, $defaults ), $defaults );
$post_type = get_post_type_object( $post_data['post_type'] );
if ( ! $post_type )
......@@ -1488,9 +1514,6 @@ class wp_xmlrpc_server extends IXR_Server {
$post_data['tax_input'] = $terms;
unset( $post_data['terms'], $post_data['terms_names'] );
} else {
// Do not allow direct submission of 'tax_input', clients must use 'terms' and/or 'terms_names'.
unset( $post_data['tax_input'], $post_data['post_category'], $post_data['tags_input'] );
}
if ( isset( $post_data['post_format'] ) ) {
......