Opened 8 years ago
Last modified 4 days ago
#39699 new enhancement
Filter to check XML-RPC data before any DB insertion
Reported by: |
|
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)
Change History (8)
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
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
@
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
- Run the code below adding before to
functions.php
or a custom plugin the filter hook proposed also there - The post should be published without issues
- Apply the patch
- Run the code again
- It throws an error like:
Error: 500 - Post title too short.
Actual Results
- ✅ Issue resolved with patch.
- ✅ 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 );
Punting to Future Release per today's 4.8 bug scrub.