No scolding, but why hack xmlrpc.php when wordpress already offers hooks to modify or install additional xmlrpc calls?
add_filter(‘xmlrpc_methods’, ‘patch_xmlrpc_methods’);
Note: This post is over 2 years old. You may want to check later in this blog to see if there is new information.
The following links are auto-generated but may help you locate newer content:
I’ve been hacking around with the xmlrpc.php file that Wordpress uses to interface with various clients. Primarily, I’ve been working to improve integration with TextMate, which my more regular readers will be coming to recognize as one of my obsessions. I’ve put together a full bundle that integrates Ultimate Tag Warrior functionality with TextMate’s blogging bundle. It even incorporates a slightly dumbed down version of my AutoTag mod (it doesn’t account for synonyms or suggest new tags based on repitition yet.) If anyone reading this has an express interest in this bundle, let me know, but I’m hesitant to release it to the general public because of the amount of hacking of support files it requires and my concerns about what security holes this process might open up…
But I want to go into a few things I learned playing around with the xmlrpc.php file and TextMate…
XMLRPC is the interface that TextMate and other blogging clients use to interface with your blog. They have a limited number of functions and can’t by nature include support for third-party plugins (like tagging plugins). But with a little hacking, you can customize your XMLRPC interface to suit your needs.
Download your xmlrpc.php file from the root directory of your Wordpress blog to your local drive. Rename the file to anything else, and upload the renamed version. Then set up a new blog in TextMate, or modify an existing blog, to point to that file instead of xmlrpc.php:
Example Blog UTW http://username@exampleblog.com/xmlrpcUTW.php
Note: I use Transmit and mirror my directory structure locally so I can set up “Docksend“. Then I built a quick override for the save command that will automatically docksend the current file on save. That way, if the file is part of a Transmit favorite with Docksend enabled, it will go to the right website in the right directory automatically.
The first thing we want to do is set up some new hooks in the API. This is easily done by adding them into the wp_xmlrpc_server function starting around line 100 of the xmlrpc.php file. TextMate\Wordpress use the metaWeblog interface, so that’s where I added my functions. Just add the names of the hooks and the functions they’ll call into the array:
…,
'metaWeblog.getTags' => 'this:mw_getTags',
'metaWeblog.AutoTag' => 'this:mw_AutoTag',
…
Next you’ll want to define the functions that the hooks are calling. The beauty of this is that you have access to the entire WP database, and can really glean any information that you want to. I’m sure there are some security issues to be concerned about, but I stuck to using the already established database calls and didn’t modify the credential verification process at all, so it shouldn’t create any new holes.
I added functions mw_getTags and mw_AutoTag. By doing a require() in the file to include my UltimateTagWarriorCore.php file, I was able to directly use all of the functions and hooks in that file to access the tag database and my own Autotag mod for Ultimate Tag Warrior. I created a stripped down version of the Autotag and included it in the xmlrpc.php file so that the returned information could be put into a multi-select menu in TextMate.
To keep things organized, I added the functions in the metaWeblog section and put them after the mw_getCategories function, to which they are somewhat related, at least for my purposes.
The beginning of the functions needs to include the arguments that will be passed by the client. You can steal the code from any of the surrounding functions. In my case, the AutoTag function began like this:
global $wpdb, $tabletags, $tabletag_synonyms;
$this->escape($args);
$blog_ID = $args[0];
$user_login = $args[1];
$user_pass = $args[2];
$body = $args[3];
So let’s take a look at where those variables are coming from.
What I did was create a new TextMate bundle, and copy the blogging bundle’s support files into it so that I could modify them without changing the original or losing them to updates. After creating a new bundle, switch the current selection in the bundle editor to a different bundle and come back and it should create the bundle in your home directory. Load up Terminal and do this:
mkdir ~/Library/Application\ Support/TextMate/Bundles/yourbundle.tmbundle/Support
mkdir ~/Library/Application\ Support/TextMate/Bundles/yourbundle.tmbundle/Support/lib
cd ~/Library/Application\ Support/TextMate/Bundles/yourbundle.tmbundle/Support/lib
cp /Library/Application\ Support/TextMate/Bundles/Blogging.tmbundle/Support/lib/* .
What I eventually did for the purpose of this little exercise was create a project in TextMate and add the support files mentioned above, the xmlrpcUTW.php file that I created before, and all of the Wordpress files and plugins that I planned to include in the process. Then I set up Transmit with the Docksend trick mentioned previously and started hacking away.
Since we’re working backwards, we’ll start with metaweblog.rb, to which you’ll need to add the calls to the hooks we created. Make sure you open the metaweblog.rb that you copied into your bundle in your home directory. Adding the calls just means a simple one-line Ruby function for each new call.
def getTags(blog_id, username, password)
call("metaWeblog.getTags", "#{blog_id}", "#{username}", "#{password}")
end
def AutoTag(blog_id, username, password, content='')
call("metaWeblog.AutoTag", "#{blog_id}", "#{username}", "#{password}", content)
end
Note that you’ll need to define and pass the appropriate number of parameters for your function. Whatever you set up in $args will need to be accounted for here.
Since we’re editing support files anyway, I’ve found it a lot simpler to create the commands in the file than in the bundle editor. This is what the autotag function looks like in the blogging.rb file:
1 2 begin 3 # Makes sure endpoint is determined and elements are parsed 4 current_password = self.password 5 result = nil 6 7 TextMate.call_with_progress(:title => “Fetch Tags”, :message => “Contacting Server “â€?…”) do 8 result = self.client.AutoTag(self.blog_id, self.username, current_password, content) 9 end 10 11 if !result || !result.length 12 TextMate.exit_show_tool_tip(“No tags are available!”) 13 end 14 select_from_tags(result.split(‘,’)) 15 end 16 end
This won’t do you a lot of good without the select_from_tags function that gets called, which formats the tags and puts them into a multi-select menu using a little Applescript. But I’m only trying to share the basics of what I learned… most of you won’t have the Autotag mod installed anyway, so the actual source will be of little use. It’s the line:
self.client.AutoTag(self.blog_id, self.username, current_password, content)
that calls the hook and associated function that we set up previously. The client call runs through the Ruby XMLRPC library and sets up the connection using the provided credentials. The content is passed from the TextMate command to the function and passed on as an argument.
The command in TextMate, of course, has to reside inside the bundle we created for this project. A call to TM_BUNDLE_SUPPORT will automatically call the copied support files in your home directory rather than the originals. I set up the command to save nothing, take the entire document as input and insert as text. I put it on a tab trigger (auto->) that I call from within the header of the blog post. Here’s the way the autotag command looks:
#!/usr/bin/env ruby -rjcode -Ku
require “#{ENV[’TM_BUNDLE_SUPPORT’]}/lib/blogging.rb”
Blogging.new.autotag(STDIN.read)
So that’s it. I’ve added the autotag function to the xmlrpc.php, modified the local files to recognize the change and created a custom interface for my blogging client. The sky seems to be the limit and I’m not constrained to the limits of the basic xmlrpc interface. I am curious about what problems this is going to cause, and what security holes it will open up, so if someone wants to scold me, please do. 
No scolding, but why hack xmlrpc.php when wordpress already offers hooks to modify or install additional xmlrpc calls?
add_filter(‘xmlrpc_methods’, ‘patch_xmlrpc_methods’);
Scolding accepted, I actually had no idea. I’ll have to research that a little better and see if I can make it work as a plugin. A textmate plugin would be a much better solution…
Thanks much for the tip!
i would like to use pocket sharpmt to blog wordpress. sharpmt uses movable type as i know. it allready works with my standard xmlrpc.php.
but now my problem: as i’m using the showonfrontpage-plugin, all my posts via xmlrpc won’t show on frontpage as its standard value is ‘false’. now im looking for the right way to have this value set as ‘true’ in xmlprc.php. and my php-knowledge is not enough to get it right.
this is how showonfrontpage updates the post’s meta information. do you have any hints how to hack this functionality into xmlprc?
function showfrontpage_editpost($id) {
global $wpdb, $FrontPage_checkbox;
if (!isset($id))
$id = $_REQUEST['post_ID'];
if(isset($_REQUEST['FrontPage_checkbox']))
{
$qry = "delete from {$wpdb->postmeta} WHERE Post_ID = {$id} AND meta_key = 'showfrontpage';";
$wpdb->query($qry);
}
else
{
// Delete any meta data for this post (sgc)
// Fixed problem where we just kept getting new showfrontpage meta data
// Can we fix this with an update instead of deleting each time?
$qry = "delete from {$wpdb->postmeta} WHERE Post_ID = {$id} AND meta_key = 'showfrontpage';";
$wpdb->query($qry);
// Add new meta data
$qry = "INSERT INTO {$wpdb->postmeta} (Post_ID, meta_key, meta_value) VALUES ({$id}, 'showfrontpage', 'true');";
$wpdb->query($qry);
}
any idea??
I don’t have any experience with SharpMT, but you’re going to have to be able to modify the headers it sends in addition to the xmlrpc.php (or hooks added by the plugin). Do you know if you have access to add headers or any of the source files?
Hi Brett
I am very interested in trying out your bundle!
I would appreciate it if you could email it to me.
Thanks. Wayne
Any updates on this? I’d really like to use this bundle, so if you could email it to me, I’d greatly appreciate it!
Here’s the update. My files are so hacked and so customized that I don’t want to share them. But that makes me feel bad so I started working on a way to make them available to more people. I’m currently working on a plugin for Wordpress that provides xmlrpc functionality for regular UTW tags and the autotag feature, as well as a bundle for TextMate that doesn’t require hacking any core files. I will release it as soon as I can. I’m also trying to get Christine to add a hook into Ultimate Tag Warrior to allow for external plugins so I can stop modding her original files.
I currently have a Wordpress plugin finished that interfaces with TextMate and allows you to search for posts based on a phrase or word, and open the post or create a link to it with a title. It’s really handy for linking to articles you’ve written in the past. My next blog entry will be about that.
So keep checking back, and I’ll email the people who’ve responded in the comments here when it’s ready. If you’re adventurous, everything you need to know is either in this post or on the net… and that’s the thing. If you don’t know how to do it then I’m scared that I’ll break something on your blog with all the hacks involved. Best to wait for a more tamed down release ;-).
Comments are closed
Comments are currently closed on this entry.