Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 74 additions & 10 deletions src/wp-includes/class-wp-xmlrpc-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,30 @@ protected function _convert_date_gmt( $date_gmt, $date ) {
return $this->_convert_date( $date_gmt );
}

/**
* Converts a client-supplied date value to an IXR_Date object.
*
* XML-RPC clients may send a date either as a dateTime.iso8601 value, which
* arrives as an IXR_Date object, or as a plain string. Any other type cannot
* be a date and results in an error.
*
* @since 7.2.0
*
* @param mixed $date Client-supplied date value.
* @return IXR_Date|IXR_Error IXR_Date object on success, IXR_Error if the value is not a date.
*/
protected function _convert_client_date( $date ) {
if ( $date instanceof IXR_Date ) {
return $date;
}

if ( is_string( $date ) ) {
return $this->_convert_date( $date );
}

return new IXR_Error( 400, __( 'Dates must be a dateTime.iso8601 value or a string.' ) );
}

/**
* Prepares post data for return in an XML-RPC object.
*
Expand Down Expand Up @@ -1365,15 +1389,15 @@ public function wp_newPost( $args ) {
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this warrants adding a type check for the $content_struct. Something like this:

Suggested change
}
}
if ( ! is_array( $content_struct ) ) {
return new IXR_Error( 400, __( 'Invalid parameters.', 'xmlrpc-server' ) );
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same goes for wp_editPost below.


// Convert the date field back to IXR form.
if ( isset( $content_struct['post_date'] ) && ! ( $content_struct['post_date'] instanceof IXR_Date ) ) {
if ( isset( $content_struct['post_date'] ) && is_string( $content_struct['post_date'] ) ) {
$content_struct['post_date'] = $this->_convert_date( $content_struct['post_date'] );
}

/*
* Ignore the existing GMT date if it is empty or a non-GMT date was supplied in $content_struct,
* since _insert_post() will ignore the non-GMT date if the GMT date is set.
*/
if ( isset( $content_struct['post_date_gmt'] ) && ! ( $content_struct['post_date_gmt'] instanceof IXR_Date ) ) {
if ( isset( $content_struct['post_date_gmt'] ) && is_string( $content_struct['post_date_gmt'] ) ) {
if ( '0000-00-00 00:00:00' === $content_struct['post_date_gmt'] || isset( $content_struct['post_date'] ) ) {
unset( $content_struct['post_date_gmt'] );
} else {
Expand Down Expand Up @@ -1550,10 +1574,20 @@ protected function _insert_post( $user, $content_struct ) {

// Do some timestamp voodoo.
if ( ! empty( $post_data['post_date_gmt'] ) ) {
$post_date_gmt = $this->_convert_client_date( $post_data['post_date_gmt'] );
if ( $post_date_gmt instanceof IXR_Error ) {
return $post_date_gmt;
}

// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
$date_created = rtrim( $post_data['post_date_gmt']->getIso(), 'Z' ) . 'Z';
$date_created = rtrim( $post_date_gmt->getIso(), 'Z' ) . 'Z';
} elseif ( ! empty( $post_data['post_date'] ) ) {
$date_created = $post_data['post_date']->getIso();
$post_date = $this->_convert_client_date( $post_data['post_date'] );
if ( $post_date instanceof IXR_Error ) {
return $post_date;
}

$date_created = $post_date->getIso();
}

// Default to not flagging the post date to be edited unless it's intentional.
Expand Down Expand Up @@ -1792,8 +1826,13 @@ public function wp_editPost( $args ) {
}

if ( isset( $content_struct['if_not_modified_since'] ) ) {
$if_not_modified_since = $this->_convert_client_date( $content_struct['if_not_modified_since'] );
if ( $if_not_modified_since instanceof IXR_Error ) {
return $if_not_modified_since;
}

// If the post has been modified since the date provided, return an error.
if ( mysql2date( 'U', $post['post_modified_gmt'] ) > $content_struct['if_not_modified_since']->getTimestamp() ) {
if ( mysql2date( 'U', $post['post_modified_gmt'] ) > $if_not_modified_since->getTimestamp() ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, what if $post['post_modified_gmt'] is not a string?

return new IXR_Error( 409, __( 'There is a revision of this post that is more recent.' ) );
}
}
Expand Down Expand Up @@ -3913,8 +3952,13 @@ public function wp_editComment( $args ) {

// Do some timestamp voodoo.
if ( ! empty( $content_struct['date_created_gmt'] ) ) {
$date_created_gmt = $this->_convert_client_date( $content_struct['date_created_gmt'] );
if ( $date_created_gmt instanceof IXR_Error ) {
return $date_created_gmt;
}

// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
$date_created = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
$date_created = rtrim( $date_created_gmt->getIso(), 'Z' ) . 'Z';

$comment['comment_date'] = get_date_from_gmt( $date_created );
$comment['comment_date_gmt'] = iso8601_to_datetime( $date_created, 'gmt' );
Expand Down Expand Up @@ -5671,10 +5715,20 @@ public function mw_newPost( $args ) {

// Do some timestamp voodoo.
if ( ! empty( $content_struct['date_created_gmt'] ) ) {
$date_created_gmt = $this->_convert_client_date( $content_struct['date_created_gmt'] );
if ( $date_created_gmt instanceof IXR_Error ) {
return $date_created_gmt;
}

// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
$date_created = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
$date_created = rtrim( $date_created_gmt->getIso(), 'Z' ) . 'Z';
} elseif ( ! empty( $content_struct['dateCreated'] ) ) {
$date_created = $content_struct['dateCreated']->getIso();
$date_created_object = $this->_convert_client_date( $content_struct['dateCreated'] );
if ( $date_created_object instanceof IXR_Error ) {
return $date_created_object;
}

$date_created = $date_created_object->getIso();
}

$post_date = '';
Expand Down Expand Up @@ -6077,10 +6131,20 @@ public function mw_editPost( $args ) {

// Do some timestamp voodoo.
if ( ! empty( $content_struct['date_created_gmt'] ) ) {
$date_created_gmt = $this->_convert_client_date( $content_struct['date_created_gmt'] );
if ( $date_created_gmt instanceof IXR_Error ) {
return $date_created_gmt;
}

// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
$date_created = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
$date_created = rtrim( $date_created_gmt->getIso(), 'Z' ) . 'Z';
} elseif ( ! empty( $content_struct['dateCreated'] ) ) {
$date_created = $content_struct['dateCreated']->getIso();
$date_created_object = $this->_convert_client_date( $content_struct['dateCreated'] );
if ( $date_created_object instanceof IXR_Error ) {
return $date_created_object;
}

$date_created = $date_created_object->getIso();
}

// Default to not flagging the post date to be edited unless it's intentional.
Expand Down
14 changes: 14 additions & 0 deletions tests/phpunit/tests/xmlrpc/mw/editPost.php
Original file line number Diff line number Diff line change
Expand Up @@ -335,4 +335,18 @@ public function test_draft_not_prematurely_published() {
$future_date_string = date_format( date_create( "@{$future_time}" ), 'Y-m-d H:i:s' );
$this->assertSame( $future_date_string, $after->post_date );
}

/**
* @ticket 66107
*/
public function test_string_date_created_is_accepted(): void {
$editor_id = $this->make_user_by_role( 'editor' );
$post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );

$date_string = '1984-01-11 05:00:00';
$result = $this->myxmlrpcserver->mw_editPost( array( $post_id, 'editor', 'editor', array( 'dateCreated' => $date_string ) ) );
$this->assertNotIXRError( $result );
$this->assertTrue( $result );
$this->assertSame( $date_string, get_post( $post_id )->post_date );
}
}
16 changes: 16 additions & 0 deletions tests/phpunit/tests/xmlrpc/mw/newPost.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,20 @@ public function test_draft_post_date() {
$this->assertSame( 'draft', $out->post_status );
$this->assertSame( '0000-00-00 00:00:00', $out->post_date_gmt );
}

/**
* @ticket 66107
*/
public function test_string_date_created_is_accepted(): void {
$this->make_user_by_role( 'author' );

$date_string = '1984-01-11 05:00:00';
$post = array(
'title' => 'Test',
'dateCreated' => $date_string,
);
$result = $this->myxmlrpcserver->mw_newPost( array( 1, 'author', 'author', $post ) );
$this->assertNotIXRError( $result );
$this->assertSame( $date_string, get_post( $result )->post_date );
}
}
17 changes: 17 additions & 0 deletions tests/phpunit/tests/xmlrpc/wp/editComment.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,21 @@ public function test_trash_comment() {

$this->assertSame( 'trash', get_comment( $comment_id )->comment_approved );
}

/**
* @ticket 66107
* @ticket 42995
*/
public function test_string_date_created_gmt_is_accepted(): void {
$this->make_user_by_role( 'administrator' );
$comment_id = self::factory()->comment->create();

$date_string = '1984-01-11 05:00:00';
$result = $this->myxmlrpcserver->wp_editComment(
array( 1, 'administrator', 'administrator', $comment_id, array( 'date_created_gmt' => $date_string ) )
);
$this->assertNotIXRError( $result );
$this->assertTrue( $result );
$this->assertSame( $date_string, get_comment( $comment_id )->comment_date_gmt );
}
}
58 changes: 58 additions & 0 deletions tests/phpunit/tests/xmlrpc/wp/editPost.php
Original file line number Diff line number Diff line change
Expand Up @@ -528,4 +528,62 @@ public function test_draft_not_assigned_published_date() {
$after = get_post( $post_id );
$this->assertSame( '0000-00-00 00:00:00', $after->post_date_gmt );
}

/**
* @ticket 66107
*/
public function test_string_post_date_is_accepted(): void {
$editor_id = $this->make_user_by_role( 'editor' );
$post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );

$date_string = '1984-01-11 05:00:00';
$result = $this->myxmlrpcserver->wp_editPost( array( 1, 'editor', 'editor', $post_id, array( 'post_date' => $date_string ) ) );
$this->assertNotIXRError( $result );
$this->assertTrue( $result );
$this->assertSame( $date_string, get_post( $post_id )->post_date );
}

/**
* @ticket 66107
*/
public function test_string_post_date_gmt_is_accepted(): void {
$editor_id = $this->make_user_by_role( 'editor' );
$post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );

$date_string = '1984-01-11 05:00:00';
$result = $this->myxmlrpcserver->wp_editPost( array( 1, 'editor', 'editor', $post_id, array( 'post_date_gmt' => $date_string ) ) );
$this->assertNotIXRError( $result );
$this->assertTrue( $result );
$this->assertSame( $date_string, get_post( $post_id )->post_date_gmt );
}

/**
* @ticket 66107
*/
public function test_string_if_not_modified_since_is_accepted(): void {
$editor_id = $this->make_user_by_role( 'editor' );
$post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );

$struct = array(
'post_title' => 'Updated',
'if_not_modified_since' => gmdate( 'Y-m-d H:i:s', strtotime( '+1 day' ) ),
);
$result = $this->myxmlrpcserver->wp_editPost( array( 1, 'editor', 'editor', $post_id, $struct ) );
$this->assertNotIXRError( $result );
$this->assertTrue( $result );
$this->assertSame( 'Updated', get_post( $post_id )->post_title );
}

/**
* @ticket 66107
*/
public function test_non_date_post_date_returns_error(): void {
$editor_id = $this->make_user_by_role( 'editor' );
$post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );

$struct = array( 'post_date' => array( '1984-01-11 05:00:00' ) );
$result = $this->myxmlrpcserver->wp_editPost( array( 1, 'editor', 'editor', $post_id, $struct ) );
$this->assertIXRError( $result );
$this->assertSame( 400, $result->code );
}
}
15 changes: 15 additions & 0 deletions tests/phpunit/tests/xmlrpc/wp/newPost.php
Original file line number Diff line number Diff line change
Expand Up @@ -446,4 +446,19 @@ public function test_valid_IXR_post_date_gmt() {
$this->assertStringMatchesFormat( '%d', $result );
$this->assertSame( $date_string, $fetched_post->post_date_gmt );
}

/**
* @ticket 66107
*/
public function test_non_date_post_date_returns_error(): void {
$this->make_user_by_role( 'author' );

$post = array(
'post_title' => 'test',
'post_date' => array( '1984-01-11 05:00:00' ),
);
$result = $this->myxmlrpcserver->wp_newPost( array( 1, 'author', 'author', $post ) );
$this->assertIXRError( $result );
$this->assertSame( 400, $result->code );
}
}
Loading