Using MetaWebLog with PHP-XMLRPC
Due to the fact that there is virtually no documentation available on how to get the MetaWebLog API working with the PHP-XMLRPC library, I decided to write this post. The MetaWebLog API is an application programming interface that allows data to be passed from a client to a server, and vice versa. It is used by all of the most popular blogging software, allowing the user to post blog entries from software like Microsoft Word or Windows Live Writer.
If you want to add MetaWebLog functionality to your custom blog or CMS, then this post will really help you. First off, download the PHP-XMLRPC library and upload the three files - xmlrpc.inc, xmlrpcs.inc, xmlrpc_wrappers.inc - found within the lib folder to your web server.
With that done, you can now start implementing the MetaWebLog functions. The first one you’ll need to implement is blogger.getUsersBlogs, otherwise software like Microsoft Word won’t recognise it as a valid MetaWebLog implementation. With that done, you can then start working on the functions that you might need to use.
To debug your code, make sure you take advantage of the XMLRPC debugger. And for more information on what each function is supposed to accept and return, check out Microsoft’s MSDN.
Below is the MetaWebLog implementation I developed to work with the PHP-XMLRPC library:
<?php // These three files are from the PHP-XMLRPC library.
include(“xmlrpc.inc”);
include(“xmlrpcs.inc”);
include(“xmlrpc_wrappers.inc”);
/**
* Used to test usage of object methods in dispatch maps
*/
class xmlrpc_server_methods_container
{
}
function
userLogin($username, $password, $area) {
// This is where you would check to see if the username and password are valid
// and whether the user has rights to perform this action ($area)
// Return true if so. Or false if the login info is wrong.
}
$getUsersBlogs_sig=array(array($xmlrpcArray, $xmlrpcString, $xmlrpcString, $xmlrpcString));
$getUsersBlogs_doc=‘Returns a list of weblogs to which an author has posting privileges.’;
function getUsersBlogs($xmlrpcmsg)
{
$structArray = array();
$structArray[] = new xmlrpcval(array(
‘isAdmin’ => new xmlrpcval(true, ‘boolean’),
‘url’ => new xmlrpcval(‘http://blogurl’, ’string’),
‘blogid’ => new xmlrpcval(“The Blog ID”, ’string’),
‘blogName’ => new xmlrpcval(‘The Blog Name’, ’string’),
‘xmlrpc’ => new xmlrpcval(‘http://LocationOfThisFile’, ’string’)
), ’struct’);
return new xmlrpcresp(new xmlrpcval($structArray,‘array’));
}
$newPost_sig=array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcStruct, $xmlrpcBoolean));
$newPost_doc=‘Post a new item to the blog.’;
function newPost($xmlrpcmsg)
{
$blogid=$xmlrpcmsg->getParam(0)->scalarval();
$username=$xmlrpcmsg->getParam(1)->scalarval();
$password=$xmlrpcmsg->getParam(2)->scalarval();
if(userLogin($username, $password, ‘addnews’) == true) {
$content=$xmlrpcmsg->getParam(3);
$title = $content->structMem(‘title’)->scalarval();
$description = $content->structMem(‘description’)->scalarval();
//$dateCreated = $content->structMem(’dateCreated’)->serialize(); // Not all clients send dateCreated info. So add if statement here if you want to use it.
//$timestamp = iso8601_decode($dateCreated); // To convert to unix timestamp
if($content->structMem(‘categories’)->arraySize() > 0) {
$categories = $content->structMem(‘categories’)->arrayMem(0)->scalarval();
}
$published=$xmlrpcmsg->getParam(4)->scalarval();
// Put your DB queries in here to store the new post.
return new
xmlrpcresp(new xmlrpcval($postid,’string’)); // Return the id of the post just inserted into the DB. See mysql_insert_id() in the PHP manual.
} else {
return new xmlrpcresp(0, $xmlrpcerruser+1, “Login Failed”);
}
}
$editPost_sig=array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcStruct, $xmlrpcBoolean));
$editPost_doc=‘Edit an item on the blog.’;
function editPost($xmlrpcmsg)
{
$postid=$xmlrpcmsg->getParam(0)->scalarval();
$username=$xmlrpcmsg->getParam(1)->scalarval();
$password=$xmlrpcmsg->getParam(2)->scalarval();
if(userLogin($username, $password, ‘editnews’) == true) {
$content=$xmlrpcmsg->getParam(3);
$title = $content->structMem(‘title’)->scalarval();
$description = $content->structMem(‘description’)->scalarval();
//$dateCreated = $content->structMem(’dateCreated’)->serialize(); // Not all clients send dateCreated info. So add if statement here if you want to use it.
//$timestamp = iso8601_decode($dateCreated); // To convert to unix timestamp
if($content->structMem(‘categories’)->arraySize() > 0) {
$categories = $content->structMem(‘categories’)->arrayMem(0)->scalarval();
}
$published=$xmlrpcmsg->getParam(4)->scalarval();
// Put your DB queries in here to update the post corresponding to the $postid.
return new
xmlrpcresp(new xmlrpcval(true,‘boolean’));
} else {
return new xmlrpcresp(0, $xmlrpcerruser+1, “Login Failed”);
}
}
$getPost_sig=array(array($xmlrpcStruct, $xmlrpcString, $xmlrpcString, $xmlrpcString));
$getPost_doc=‘Get an item on the blog.’;
function getPost($xmlrpcmsg)
{
$postid=$xmlrpcmsg->getParam(0)->scalarval();
$username=$xmlrpcmsg->getParam(1)->scalarval();
$password=$xmlrpcmsg->getParam(2)->scalarval();
if(userLogin($username, $password, ‘editnews’) == true) {
$result = mysql_query(“SELECT * FROM sometable WHERE id=’$postid’ LIMIT 1″);
while ($row = mysql_fetch_assoc($result)) {
return new xmlrpcresp(new xmlrpcval(array(
‘postid’ => new xmlrpcval($row[‘id’], ’string’),
‘dateCreated’ => new xmlrpcval(iso8601_encode($row[‘timestamp’]), ‘dateTime.iso8601′),
‘title’ => new xmlrpcval($row[‘title’], ’string’),
‘description’ => new xmlrpcval($row[‘content’], ’string’),
‘categories’ => new xmlrpcval(array(new xmlrpcval($row[‘category’], ’string’)), ‘array’),
‘publish’ => new xmlrpcval($row[‘published’], ‘boolean’)
), ’struct’));
}
} else {
return new xmlrpcresp(0, $xmlrpcerruser+1, “Login Failed”);
}
}
function
deletePost($xmlrpcmsg)
{
$postid=$xmlrpcmsg->getParam(1)->scalarval();
$username=$xmlrpcmsg->getParam(2)->scalarval();
$password=$xmlrpcmsg->getParam(3)->scalarval();
if(userLogin($username, $password, ‘editnews’) == true) {
$query = “DELETE FROM sometable WHERE id=$postid LIMIT 1″;
mysql_query($query) or die (mail(“your@email.com”,“Error with MetaWebLog deleting new post”,$query . ‘ | ’ . mysql_error()));
return new xmlrpcresp(new xmlrpcval(true,‘boolean’));
} else {
return new xmlrpcresp(0, $xmlrpcerruser+1, “Login Failed”);
}
}
$getRecentPosts_sig=array(array($xmlrpcArray, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcInt));
$getRecentPosts_doc=‘Get the recent posts on the blog.’;
function getRecentPosts($xmlrpcmsg)
{
$blogid=$xmlrpcmsg->getParam(0)->scalarval();
$username=$xmlrpcmsg->getParam(1)->scalarval();
$password=$xmlrpcmsg->getParam(2)->scalarval();
if(userLogin($username, $password, ‘addnews’) == true) {
$numposts=$xmlrpcmsg->getParam(3)->scalarval();
$structArray = array();
$result = mysql_query(“SELECT * FROM sometable ORDER BY timestamp DESC LIMIT $numposts”);
while ($row = mysql_fetch_assoc($result)) {
$structArray[] = new xmlrpcval(array(
‘postid’ => new xmlrpcval($row[‘id’], ’string’),
‘dateCreated’ => new xmlrpcval(iso8601_encode($row[‘timestamp’]), ‘dateTime.iso8601′),
‘title’ => new xmlrpcval($row[‘title’], ’string’),
‘description’ => new xmlrpcval($row[‘content’]),
‘categories’ => new xmlrpcval(array(new xmlrpcval($row[‘category’], ’string’)), ‘array’),
‘publish’ => new xmlrpcval($row[‘published’], ‘boolean’)
), ’struct’);
}
return new xmlrpcresp(new xmlrpcval($structArray , ‘array’)); // Return type is struct[] (array of struct)
} else {
return new xmlrpcresp(0, $xmlrpcerruser+1, “Login Failed”);
}
}
$getCategories_sig=array(array($xmlrpcArray, $xmlrpcString, $xmlrpcString, $xmlrpcString));
$getCategories_doc=‘Get the categories on the blog.’;
function getCategories($xmlrpcmsg) {
$username=$xmlrpcmsg->getParam(1)->scalarval();
$password=$xmlrpcmsg->getParam(2)->scalarval();
if(userLogin($username, $password, ‘addnews’) == true) {
$structArray = array();
$result = mysql_query(“SELECT * FROM categories”);
while ($row = mysql_fetch_assoc($result)) {
$structArray[] = new xmlrpcval(array(
‘title’ => new xmlrpcval($row[‘title’], ’string’),
‘description’ => new xmlrpcval($row[‘description’], ’string’)
), ’struct’);
}
return new xmlrpcresp(new xmlrpcval($structArray , ‘array’)); // Return type is struct[] (array of struct)
} else {
return new xmlrpcresp(0, $xmlrpcerruser+1, “Login Failed”);
}
}
$newMediaObject_sig=array(array($xmlrpcStruct, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcStruct));
$newMediaObject_doc=‘Upload media files onto the blog server.’;
function newMediaObject($xmlrpcmsg)
{
$username=$xmlrpcmsg->getParam(1)->scalarval();
$password=$xmlrpcmsg->getParam(2)->scalarval();
if(userLogin($username, $password, ‘addnews’) == true) {
$file=$xmlrpcmsg->getParam(3);
$filename = $file->structMem(‘name’)->scalarval();
$filename = substr($filename, (strrpos($filename,“/”)+1));
//$type = $file->structMem(’type’)->scalarval(); // The type of the file
$bits = $file->structMem(‘bits’)->serialize();
$bits = str_replace(“<value><base64>”,“”,$bits);
$bits = str_replace(“</base64></value>”,“”,$bits);
$uploaddir = ‘/home/yourhostingusername/public_html/uploads/’; // Make sure this folder has been chmoded to 777.
if(fwrite(fopen($uploaddir . $filename, “xb”), base64_decode($bits)) == false) {
return new xmlrpcresp(0, $xmlrpcerruser+1, “File Failed to Write”);
} else {
return new xmlrpcresp(new xmlrpcval(array(‘url’ => new xmlrpcval(‘http://blogurl.com/uploads/’.$filename, ’string’)),’struct’));
}
} else {
return new xmlrpcresp(0, $xmlrpcerruser+1, “Login Failed”);
}
}
$o=new xmlrpc_server_methods_container;
$a=array(
‘blogger.getUsersBlogs’ => array(
‘function’ => ‘getUsersBlogs’,
‘docstring’ => $getUsersBlogs_doc,
’signature’ => $getUsersBlogs_sig
),
“metaWeblog.newPost” => array(
“function” => “newPost”,
“signature” => $newPost_sig,
“docstring” => $newPost_doc
),
“metaWeblog.editPost” => array(
“function” => “editPost”,
“signature” => $editPost_sig,
“docstring” => $editPost_doc
),
“metaWeblog.getPost” => array(
“function” => “getPost”,
“signature” => $getPost_sig,
“docstring” => $getPost_doc
),
“metaWeblog.getRecentPosts” => array(
“function” => “getRecentPosts”,
“signature” => $getRecentPosts_sig,
“docstring” => $getRecentPosts_doc
),
“metaWeblog.getCategories” => array(
“function” => “getCategories”,
“signature” => $getCategories_sig,
“docstring” => $getCategories_doc
),
“metaWeblog.newMediaObject” => array(
“function” => “newMediaObject”,
“signature” => $newMediaObject_sig,
“docstring” => $newMediaObject_doc
),/*
’blogger.getUserInfo’ => array(
’function’ => ’getUserInfo’,
’docstring’ => ”Returns information about an author in the system.”,
’signature’ => array(array($xmlrpcStruct, $xmlrpcString, $xmlrpcString, $xmlrpcString))
)*/
‘blogger.deletePost’ => array(
‘function’ => ‘deletePost’,
‘docstring’ => ‘Deletes a post.’,
’signature’ => array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcBoolean))
)
);
$s=new xmlrpc_server($a, false);
$s->setdebug(2);
$s->service();
// that should do all we need!
?>
I hope that helps you.




