Make WordPress Core

Opened 8 years ago

Last modified 4 days ago

#39699 new enhancement

Filter to check XML-RPC data before any DB insertion

Reported by: enricosorcinelli's profile enrico.sorcinelli Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version: 4.8
Component: XML-RPC Keywords: has-patch has-unit-tests dev-feedback
Focuses: Cc:

Description

After searching into XML-RPC server class code, I realized that it seems that there isn't way to check XML-RPC input data before starting to insert/update any rows to database nor to return an IXR custom error message.
For example for new post, in order to check custom fields, a possible workaround is to use wp_insert_post_empty_content filter, but we are unable to customize the error message. Moreover at this point some DB rows are inserted, so inside the filter above we have to call wp_delete_post manually in order to clean DB (taking care to check auto-draft post status).
In the case of editing post, things get a bit more complicated, so we could use transactions with the help of xmlrpc_call/wp_insert_post actions.

So, the patch aims to add a new filter named xmlrpc_before_insert_post that allows to do this check in a more robust manner (for wp.newPost and wp.editPost XML-RCP methods).

Typical usage:

<?php

if ( defined( 'XMLRPC_REQUEST' ) ) {
   add_filter( 'xmlrpc_before_insert_post', 'my_filter_xmlrpc_before_insert_post', 10, 3 );
}
function my_filter_xmlrpc_before_insert_post ( $post_data, $content_struct, $user  ) {
   // do checks with $post_data, i.e:
   if ( title_contains_stop_words( $post_data['post_title'] ) )
      return new IXR_Error( 500, 'Post title contains invalid words' );
   return $post_data,
}

The filter is placed inside _insert_post helper function before get_default_post_to_edit() that isthe first statement that adds a new DB row.

Regards

Attachments (1)

39699.patch (4.2 KB) - added by enrico.sorcinelli 8 years ago.

Download all attachments as: .zip

Change History (8)

#1 @SergeyBiryukov
8 years ago

  • Milestone changed from Awaiting Review to 4.9

#2 @jbpaul17
7 years ago

  • Keywords has-patch needs-testing added

This ticket was mentioned in Slack in #core by jeffpaul. View the logs.


7 years ago

This ticket was mentioned in Slack in #core by jeffpaul. View the logs.


7 years ago

#5 @jbpaul17
7 years ago

  • Milestone changed from 4.9 to Future Release

Punting to Future Release per today's 4.8 bug scrub.

This ticket was mentioned in PR #8494 on WordPress/wordpress-develop by @SirLouen.


4 days ago
#6

  • Keywords has-unit-tests added

This patch is an adaptation of the original patch made 8 years ago in the ticket
It adds some corrections + sorting of PHPCS issues.

More info about this patch in Trac.

Trac ticket: [](https://core.trac.wordpress.org/ticket/39699)

#7 @SirLouen
4 days ago

  • Keywords dev-feedback added; needs-testing removed

Test Report

Description

This report validates that the indicated patch works as expected.
Given that the patch is 8 years old, I have uploaded a new patch to Github, adding some PHPCS corrections and fixing the merging process that slightly failed.

Patch tested: https://patch-diff.githubusercontent.com/raw/WordPress/wordpress-develop/pull/8494.diff

Environment

  • WordPress: 6.8-beta2-59971-src
  • PHP: 8.2.27
  • Server: nginx/1.27.4
  • Database: mysqli (Server: 8.4.4 / Client: mysqlnd 8.2.27)
  • Browser: Firefox 136.0
  • OS: Windows 10/11
  • Theme: Twenty Twenty-Five 1.1
  • MU Plugins: None activated
  • Plugins:
    • Test Reports 1.2.0

Testing Instructions

  1. Run the code below adding before to functions.php or a custom plugin the filter hook proposed also there
  2. The post should be published without issues
  3. Apply the patch
  4. Run the code again
  5. It throws an error like: Error: 500 - Post title too short.

Actual Results

  1. ✅ Issue resolved with patch.
  2. ✅ Both tests pass with the two asserts each correctly

Additional Notes

I doubt that anyone in the world is still using RPC, but I have admit that this adds a fun filter for those who needs some extra limitations when publishing content.

Supplemental Artifacts

I'm using this script to test it manually with an external PHP library. It basically replicates a similar example to the one exposed in the tests:

<?php
// First Run: composer require phpxmlrpc/phpxmlrpc
require_once 'vendor/autoload.php';

use PhpXmlRpc\Client;
use PhpXmlRpc\Value;
use PhpXmlRpc\Request;

// Create a new XML-RPC client
$client = new Client('http://localhost:8889/xmlrpc.php');

// Create custom fields array
$customFields = new Value(
    array(
        new Value(
            array(
                 'key' => new Value('custom_field_to_create', 'string'),
                 'value' => new Value('123456789', 'string')
            ),
            'struct'
        )
    ),
    'array'
);

// Create post data
$postData = new Value(
    array(
        'post_title' => new Value('This title is too long', 'string'),
        'custom_fields' => $customFields
     ),
    'struct'
);

// Create parameters for the request
$params = array(
    new Value(1, 'int'),            // Blog ID
    new Value('testuser', 'string'), // Username
    new Value('password', 'string'), // Password
    $postData
);

// Create and send the request
$request = new Request('wp.newPost', $params);
$response = $client->send($request);

// Check for errors and display result
if ($response->faultCode()) {
    echo "Error: " . $response->faultCode() . " - " . $response->faultString();
} else {
    echo "Post created with ID: " . $response->value()->scalarval();
}

Plus we can use this code in a plugin or in the functions.php:

<?php
function filter_xmlrpc_before_insert_post ( $post_data, $content_struct, $user  ) {     
        if ( strlen( $post_data['post_title'] ) > 10 ) {
                return new \IXR_Error( 500, 'Post title too long.' );
        }
        return $post_data;
}

add_filter( 'xmlrpc_before_insert_post', 'filter_xmlrpc_before_insert_post', 10, 3 );
Note: See TracTickets for help on using tickets.