From 7c7e0fb36d9c1249928d25f9e8665aa859b77240 Mon Sep 17 00:00:00 2001 From: michelvaldrighi Date: Fri, 17 Sep 2004 20:48:43 +0000 Subject: [PATCH] moved wp-admin/xmlrpc.php to the root dir git-svn-id: http://svn.automattic.com/wordpress/trunk@1684 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- xmlrpc.php | 2903 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 1714 insertions(+), 1189 deletions(-) diff --git a/xmlrpc.php b/xmlrpc.php index e3202157d..4738f0568 100644 --- a/xmlrpc.php +++ b/xmlrpc.php @@ -3,12 +3,14 @@ # fix for mozBlog and other cases where '$code"; - } - return $code; -} -function mkdir_p($target) { - // from php.net/mkdir user contributed notes - if (file_exists($target)) { - if (!is_dir($target)) { - return false; - } else { - return true; - } - } +/**** B2 API ****/ - // Attempting to create the directory may clutter up our display. - if (@mkdir($target)) { - return true; - } - // If the above failed, attempt to create the parent node, then try again. - if (mkdir_p(dirname($target))) { - return mkdir_p($target); - } +# note: the b2 API currently consists of the Blogger API, +# plus the following methods: +# +# b2.newPost , b2.getCategories - return false; +# Note: the b2 API will be replaced by the standard Weblogs.API once the specs are defined. + + +### b2.newPost ### + +$wpnewpost_sig=array(array($xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString)); + +$wpnewpost_doc='Adds a post, blogger-api like, +title +category +postdate'; + +function b2newpost($m) { + global $wpdb; + + global $xmlrpcerruser; // import user errcode value + global $blog_ID,$cache_userdata,$use_rss; + global $post_default_title,$post_default_category; + global $cafelogID, $sleep_after_edit; + $err=""; + + + $username=$m->getParam(2); + $password=$m->getParam(3); + $content=$m->getParam(4); + $title=$m->getParam(6); + $category=$m->getParam(7); + $postdate=$m->getParam(8); + + $username = $username->scalarval(); + $password = $password->scalarval(); + $content = $content->scalarval(); + $title = $title->scalarval(); + $post_category = $category->scalarval(); + $postdate = $postdate->scalarval(); + + + if (user_pass_ok($username,$password)) { + + $userdata = get_userdatabylogin($username); + $post_author = $userdata->ID; + $user_level = $userdata->user_level; + if ($user_level < 1) { + return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1 + "Sorry, level 0 users can not post"); + } + + + $post_content = format_to_post($content); + $post_title = addslashes($title); + + + if ($postdate != "") { + $post_date = $postdate; + $post_date_gmt = get_gmt_from_date($postdate); + } else { + $post_date = current_time('mysql'); + $post_date_gmt = current_time('mysql', 1); + } + + $post_data = compact('post_content','post_title','post_date','post_date_gmt','post_author','post_category'); + + $result = wp_insert_post($post_data); + + if (!$result) + return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2 + "For some strange yet very annoying reason, your entry couldn't be posted."); + + + $post_ID = $result; + + if (!isset($blog_ID)) { $blog_ID = 1; } + + if (isset($sleep_after_edit) && $sleep_after_edit > 0) { + sleep($sleep_after_edit); + } + + + + pingback($content, $post_ID); + + + return new xmlrpcresp(new xmlrpcval("$post_ID")); + + } else { + + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } } -class wp_xmlrpc_server extends IXR_Server { - function wp_xmlrpc_server() { - $this->methods = array( - // Blogger API - 'blogger.getUsersBlogs' => 'this:blogger_getUsersBlogs', - 'blogger.getUserInfo' => 'this:blogger_getUserInfo', - 'blogger.getPost' => 'this:blogger_getPost', - 'blogger.getRecentPosts' => 'this:blogger_getRecentPosts', - 'blogger.getTemplate' => 'this:blogger_getTemplate', - 'blogger.setTemplate' => 'this:blogger_setTemplate', - 'blogger.newPost' => 'this:blogger_newPost', - 'blogger.editPost' => 'this:blogger_editPost', - 'blogger.deletePost' => 'this:blogger_deletePost', +### b2.getCategories ### - // MetaWeblog API (with MT extensions to structs) - 'metaWeblog.newPost' => 'this:mw_newPost', - 'metaWeblog.editPost' => 'this:mw_editPost', - 'metaWeblog.getPost' => 'this:mw_getPost', - 'metaWeblog.getRecentPosts' => 'this:mw_getRecentPosts', - 'metaWeblog.getCategories' => 'this:mw_getCategories', - 'metaWeblog.newMediaObject' => 'this:mw_newMediaObject', +$wpgetcategories_sig=array(array($xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString)); - // MetaWeblog API aliases for Blogger API - // see http://www.xmlrpc.com/stories/storyReader$2460 - 'metaWeblog.deletePost' => 'this:blogger_deletePost', - 'metaWeblog.getTemplate' => 'this:blogger_getTemplate', - 'metaWeblog.setTemplate' => 'this:blogger_setTemplate', - 'metaWeblog.getUsersBlogs' => 'this:blogger_getUsersBlogs', +$wpgetcategories_doc='given a blogID, gives a struct that list categories in that blog, using categoryID and categoryName. categoryName is there so the user would choose a category name from the client, rather than just a number. however, when using b2.newPost, only the category ID number should be sent.'; - // MovableType API - 'mt.getCategoryList' => 'this:mt_getCategoryList', - 'mt.getRecentPostTitles' => 'this:mt_getRecentPostTitles', - 'mt.getPostCategories' => 'this:mt_getPostCategories', - 'mt.setPostCategories' => 'this:mt_setPostCategories', - 'mt.supportedMethods' => 'this:mt_supportedMethods', - 'mt.supportedTextFilters' => 'this:mt_supportedTextFilters', - 'mt.getTrackbackPings' => 'this:mt_getTrackbackPings', - 'mt.publishPost' => 'this:mt_publishPost', +function b2getcategories($m) { + global $wpdb; + global $xmlrpcerruser; - // PingBack - 'pingback.ping' => 'this:pingback_ping', - 'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks', - 'demo.sayHello' => 'this:sayHello', - 'demo.addTwoNumbers' => 'this:addTwoNumbers' - ); - $this->IXR_Server($this->methods); + $blogid=$m->getParam(0); + $blogid = $blogid->scalarval(); // we dot not use that yet, that will be used with multiple blogs + + $username=$m->getParam(1); + $username = $username->scalarval(); + + $password=$m->getParam(2); + $password = $password->scalarval(); + + $userdata = get_userdatabylogin($username); + + + if (user_pass_ok($username,$password)) { + + $results = $wpdb->get_results("SELECT * FROM $wpdb->categories ORDER BY cat_ID ASC"); + if (!$results) die("Error getting data"); + $i = 0; + foreach($results as $row) { + $cat_name = $row->cat_name; + $cat_ID = $row->cat_ID; + + $struct[$i] = new xmlrpcval(array("categoryID" => new xmlrpcval($cat_ID), + "categoryName" => new xmlrpcval($cat_name) + ),"struct"); + $i = $i + 1; + } + + $data = array($struct[0]); + for ($j=1; $j<$i; $j++) { + array_push($data, $struct[$j]); + } + + $resp = new xmlrpcval($data, "array"); + + return new xmlrpcresp($resp); + + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + + + +### b2.getPostURL ### + +$wp_getPostURL_sig = array(array($xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString)); + +$wp_getPostURL_doc = 'Given a blog ID, username, password, and a post ID, returns the URL to that post.'; + +function b2_getPostURL($m) { + global $wpdb; + global $xmlrpcerruser; + global $querystring_start, $querystring_equal, $querystring_separator; + + + // ideally, this would be used: + // $blog_ID = $m->getParam(0); + // $blog_ID = $blog_ID->scalarval(); + // but right now, b2 handles only one blog, so... :P + $blog_ID = 1; + + $username=$m->getParam(2); + $username = $username->scalarval(); + + $password=$m->getParam(3); + $password = $password->scalarval(); + + $post_ID = $m->getParam(4); + $post_ID = intval($post_ID->scalarval()); + + $userdata = get_userdatabylogin($username); + + if ($userdata->user_level < 1) { + return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1 + "Sorry, users whose level is zero, can not use this method."); } - function sayHello($args) { - return 'Hello!'; + if (user_pass_ok($username,$password)) { + $blog_URL = get_settings('home') .'/' . get_settings('blogfilename'); + $post_URL = get_permalink($post_ID); + + if ($err) { + return new xmlrpcresp(0, $xmlrpcerruser, $err); + } else { + return new xmlrpcresp(new xmlrpcval($post_URL));; + } + + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); } - function addTwoNumbers($args) { - $number1 = $args[0]; - $number2 = $args[1]; - return $number1 + $number2; - } +} - function login_pass_ok($user_login, $user_pass) { - if (!user_pass_ok($user_login, $user_pass)) { - $this->error = new IXR_Error(403, 'Bad login/pass combination.'); - return false; - } - return true; - } +/**** /B2 API ****/ +/**** Blogger API ****/ - /* Blogger API functions - * specs on http://plant.blogger.com/api and http://groups.yahoo.com/group/bloggerDev/ - */ +# as described on http://plant.blogger.com/api and in various messages in http://groups.yahoo.com/group/bloggerDev/ +# +# another list of these methods is there http://www.tswoam.co.uk/blogger_method_listing.html +# so you won't have to browse the eGroup to find all the methods +# +# special note: Evan please keep _your_ API page up to date :p - /* blogger.getUsersBlogs will make more sense once we support multiple blogs */ - function blogger_getUsersBlogs($args) { - $user_login = $args[1]; - $user_pass = $args[2]; +### blogger.newPost ### - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } +$bloggernewpost_sig=array(array($xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcBoolean)); - $user_data = get_userdatabylogin($user_login); - $is_admin = $user_data->user_level > 3; +$bloggernewpost_doc='Adds a post, blogger-api like'; - $struct = array( - 'isAdmin' => $is_admin, - 'url' => get_settings('home') .'/'.get_settings('blogfilename'), - 'blogid' => '1', - 'blogName' => get_settings('blogname') - ); +function bloggernewpost($m) { + global $wpdb; - return array($struct); - } + global $xmlrpcerruser; // import user errcode value + global $blog_ID,$cache_userdata,$use_rss; + global $post_default_title,$post_default_category; + global $cafelogID, $sleep_after_edit; + $err=""; - /* blogger.getUsersInfo gives your client some info about you, so you don't have to */ - function blogger_getUserInfo($args) { + $username=$m->getParam(2); + $password=$m->getParam(3); + $content=$m->getParam(4); + $publish=$m->getParam(5); - $user_login = $args[1]; - $user_pass = $args[2]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $user_data = get_userdatabylogin($user_login); - - $struct = array( - 'nickname' => $user_data->user_nickname, - 'userid' => $user_data->ID, - 'url' => $user_data->user_url, - 'email' => $user_data->user_email, - 'lastname' => $user_data->user_lastname, - 'firstname' => $user_data->user_firstname - ); - - return $struct; - } - - - /* blogger.getPost ...gets a post */ - function blogger_getPost($args) { - - $post_ID = $args[1]; - $user_login = $args[2]; - $user_pass = $args[3]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $user_data = get_userdatabylogin($user_login); - $post_data = wp_get_single_post($post_ID, ARRAY_A); - - $categories = implode(',', wp_get_post_cats(1, $post_ID)); - - $content = ''.stripslashes($post_data['post_title']).''; - $content .= ''.$categories.''; - $content .= stripslashes($post_data['post_content']); - - $struct = array( - 'userid' => $post_data['post_author'], - 'dateCreated' => new IXR_Date(mysql2date('Ymd\TH:i:s', $post_data['post_date'])), - 'content' => $content, - 'postid' => $post_data['ID'] - ); - - return $struct; - } - - - /* blogger.getRecentPosts ...gets recent posts */ - function blogger_getRecentPosts($args) { - - global $wpdb; - - $blog_ID = $args[1]; /* though we don't use it yet */ - $user_login = $args[2]; - $user_pass = $args[3]; - $num_posts = $args[4]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $posts_list = wp_get_recent_posts($num_posts); - - if (!$posts_list) { - $this->error = new IXR_Error(500, 'Either there are no posts, or something went wrong.'); - return $this->error; - } - - foreach ($posts_list as $entry) { - - $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']); - $categories = implode(',', wp_get_post_cats(1, $entry['ID'])); - - $content = ''.stripslashes($entry['post_itle']).''; - $content .= ''.$categories.''; - $content .= stripslashes($entry['post_content']); - - $struct[] = array( - 'userid' => $entry['post_author'], - 'dateCreated' => new IXR_Date($post_date), - 'content' => $content, - 'postid' => $entry['ID'], - ); - - } - - $recent_posts = array(); - for ($j=0; $jlogin_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $user_data = get_userdatabylogin($user_login); - - if ($user_data->user_level < 3) { - return new IXR_Error(401, 'Sorry, users whose level is less than 3, can not edit the template.'); - } - - /* warning: here we make the assumption that the weblog's URI is on the same server */ - $filename = get_settings('home').'/'.get_settings('blogfilename'); - $filename = preg_replace('#http://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename); - - $f = fopen($filename, 'r'); - $content = fread($f, filesize($filename)); - fclose($f); - - /* so it is actually editable with a windows/mac client */ - // FIXME: (or delete me) do we really want to cater to bad clients at the expense of good ones by BEEPing up their line breaks? commented. $content = str_replace("\n", "\r\n", $content); - - return $content; - } - - - /* blogger.setTemplate updates the content of blog_filename */ - function blogger_setTemplate($args) { - - $blog_ID = $args[1]; - $user_login = $args[2]; - $user_pass = $args[3]; - $content = $args[4]; - $template = $args[5]; /* could be 'main' or 'archiveIndex', but we don't use it */ - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $user_data = get_userdatabylogin($user_login); - - if ($user_data->user_level < 3) { - return new IXR_Error(401, 'Sorry, users whose level is less than 3, can not edit the template.'); - } - - /* warning: here we make the assumption that the weblog's URI is on the same server */ - $filename = get_settings('home').'/'.get_settings('blogfilename'); - $filename = preg_replace('#http://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename); - - if ($f = fopen($filename, 'w+')) { - fwrite($f, $content); - fclose($f); - } else { - return new IXR_Error(500, 'Either the file is not writable, or something wrong happened. The file has not been updated.'); - } - - return true; - } - - - /* blogger.newPost ...creates a new post */ - function blogger_newPost($args) { - - global $wpdb; - - $blog_ID = $args[1]; /* though we don't use it yet */ - $user_login = $args[2]; - $user_pass = $args[3]; - $content = $args[4]; - $publish = $args[5]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $user_data = get_userdatabylogin($user_login); - if (!user_can_create_post($user_data->ID, $blog_ID)) { - return new IXR_Error(401, 'Sorry, you can not post on this weblog or category.'); - } - - $post_status = ($publish) ? 'publish' : 'draft'; - - $post_author = $user_data->ID; - - $post_title = xmlrpc_getposttitle($content); - $post_category = xmlrpc_getpostcategory($content); - - $content = xmlrpc_removepostdata($content); - $post_content = format_to_post($content); - - $post_date = current_time('mysql'); - $post_date_gmt = current_time('mysql', 1); - - $post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status'); - - $post_ID = wp_insert_post($post_data); - - if (!$post_ID) { - return new IXR_Error(500, 'Sorry, your entry could not be posted. Something wrong happened.'); - } - - logIO('O', "Posted ! ID: $post_ID"); - - return $post_ID; - } - - - /* blogger.editPost ...edits a post */ - function blogger_editPost($args) { - - global $wpdb; - - $post_ID = $args[1]; - $user_login = $args[2]; - $user_pass = $args[3]; - $new_content = $args[4]; - $publish = $args[5]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $actual_post = wp_get_single_post($post_ID,ARRAY_A); - - if (!$actual_post) { - return new IXR_Error(404, 'Sorry, no such post.'); - } - - $post_author_data = get_userdata($actual_post['post_author']); - $user_data = get_userdatabylogin($user_login); - - if (!user_can_edit_post($user_data->ID, $post_ID)) { - return new IXR_Error(401, 'Sorry, you do not have the right to edit this post.'); - } - - extract($actual_post); - $content = $newcontent; - - $post_title = xmlrpc_getposttitle($content); - $post_category = xmlrpc_getpostcategory($content); - - $content = xmlrpc_removepostdata($content); - $post_content = format_to_post($content); - - $postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt'); - - $result = wp_update_post($postdata); - - if (!$result) { - return new IXR_Error(500, 'For some strange yet very annoying reason, this post could not be edited.'); - } - - return true; - } - - - /* blogger.deletePost ...deletes a post */ - function blogger_deletePost($args) { - - global $wpdb; - - $post_ID = $args[1]; - $user_login = $args[2]; - $user_pass = $args[3]; - $publish = $args[4]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $actual_post = wp_get_single_post($post_ID,ARRAY_A); - - if (!$actual_post) { - return new IXR_Error(404, 'Sorry, no such post.'); - } - - $user_data = get_userdatabylogin($user_login); - - if (!user_can_delete_post($user_data->ID, $post_ID)) { - return new IXR_Error(401, 'Sorry, you do not have the right to delete this post.'); - } - - $result = wp_delete_post($post_ID); - - if (!$result) { - return new IXR_Error(500, 'For some strange yet very annoying reason, this post could not be deleted.'); - } - - return true; - } - - - - /* MetaWeblog API functions - * specs on wherever Dave Winer wants them to be - */ - - /* metaweblog.newPost creates a post */ - function mw_newPost($args) { - - global $wpdb; - - $blog_ID = $args[0]; // we will support this in the near future - $user_login = $args[1]; - $user_pass = $args[2]; - $content_struct = $args[3]; - $publish = $args[4]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $user_data = get_userdatabylogin($user_login); - if (!user_can_create_post($user_data->ID, $blog_ID)) { - return new IXR_Error(401, 'Sorry, you can not post on this weblog or category.'); - } - - $post_author = $user_data->ID; - - $post_title = $content_struct['title']; - $post_content = format_to_post($content_struct['description']); - $post_status = $publish ? 'publish' : 'draft'; - - $post_excerpt = $content_struct['mt_excerpt']; - $post_more = $content_struct['mt_text_more']; - - $comment_status = (empty($content_struct['mt_allow_comments'])) ? - get_settings('default_comment_status') - : $content_struct['mt_allow_comments']; - - $ping_status = (empty($content_struct['mt_allow_pings'])) ? - get_settings('default_ping_status') - : $content_struct['mt_allow_pings']; - - if ($post_more) { - $post_content = $post_content . "\n\n" . $post_more; - } - - // Do some timestamp voodoo - $dateCreatedd = $content_struct['dateCreated']; - $dateCreated = $dateCreatedd->getIso(); - if (!empty($dateCreated)) { - $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); - $post_date_gmt = iso8601_to_datetime($dateCreated, GMT); - } else { - $post_date = current_time('mysql'); - $post_date_gmt = current_time('mysql', 1); - } - - $catnames = $content_struct['categories']; - logio('O', 'Post cats: ' . printr($catnames,true)); - $post_category = array(); - - if ($catnames) { - foreach ($catnames as $cat) { - $post_category[] = get_cat_ID($cat); - } - } else { - $post_category[] = 1; - } - - // We've got all the data -- post it: - $postdata = compact('post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status'); - - $post_ID = wp_insert_post($postdata); - - if (!$post_ID) { - return new IXR_Error(500, 'Sorry, your entry could not be posted. Something wrong happened.'); - } - - logIO('O', "Posted ! ID: $post_ID"); - - // FIXME: do we pingback always? pingback($content, $post_ID); - trackback_url_list($content_struct['mt_tb_ping_urls'],$post_ID); - - return strval($post_ID); - } - - - /* metaweblog.editPost ...edits a post */ - function mw_editPost($args) { - - global $wpdb; - - $post_ID = $args[0]; - $user_login = $args[1]; - $user_pass = $args[2]; - $content_struct = $args[3]; - $publish = $args[4]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $user_data = get_userdatabylogin($user_login); - if (!user_can_edit_post($user_data->ID, $post_ID)) { - return new IXR_Error(401, 'Sorry, you can not edit this post.'); - } - - $postdata = wp_get_single_post($post_ID, ARRAY_A); - extract($postdata); - - $post_title = $content_struct['title']; - $post_content = format_to_post($content_struct['description']); - $catnames = $content_struct['categories']; - - if ($catnames) { - foreach ($catnames as $cat) { - $post_category[] = get_cat_ID($cat); - } - } - - $post_excerpt = $content_struct['mt_excerpt']; - $post_more = $content_struct['mt_text_more']; - $post_status = $publish ? 'publish' : 'draft'; - - if ($post_more) { - $post_content = $post_content . "\n\n" . $post_more; - } - - $comment_status = (empty($content_struct['mt_allow_comments'])) ? - get_settings('default_comment_status') - : $content_struct['mt_allow_comments']; - - $ping_status = (empty($content_struct['mt_allow_pings'])) ? - get_settings('default_ping_status') - : $content_struct['mt_allow_pings']; - - // Do some timestamp voodoo - $dateCreated = $content_struct['dateCreated']; - $dateCreated = $dateCreated->getIso(); - if (!empty($dateCreated)) { - $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); - $post_date_gmt = iso8601_to_datetime($dateCreated, GMT); - } else { - $post_date = $postdata['post_date']; - $post_date_gmt = $postdata['post_date_gmt']; - } - - // We've got all the data -- post it: - $newpost = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'post_date', 'post_date_gmt'); - - $post_ID = wp_update_post($newpost); - if (!$post_ID) { - return new IXR_Error(500, 'Sorry, your entry could not be edited. Something wrong happened.'); - } - - logIO('O',"(MW) Edited ! ID: $post_ID"); - - // FIXME: do we pingback always? pingback($content, $post_ID); - trackback_url_list($content_struct['mt_tb_ping_urls'], $post_ID); - - return true; - } - - - /* metaweblog.getPost ...returns a post */ - function mw_getPost($args) { - - global $wpdb; - - $post_ID = $args[0]; - $user_login = $args[1]; - $user_pass = $args[2]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $postdata = wp_get_single_post($post_ID, ARRAY_A); - - if ($postdata['post_date'] != '') { - - $post_date = mysql2date('Ymd\TH:i:s', $postdata['post_date']); - - $categories = array(); - $catids = wp_get_post_cats('', $post_ID); - foreach($catids as $catid) { - $categories[] = get_cat_name($catid); - } - - $post = get_extended($postdata['post_content']); - $link = post_permalink($postdata['ID']); - - $allow_comments = ('open' == $postdata['comment_status']) ? 1 : 0; - $allow_pings = ('open' == $postdata['ping_status']) ? 1 : 0; - - $resp = array( - 'dateCreated' => new IXR_Date($post_date), - 'userid' => $postdata['post_author'], - 'postid' => $postdata['ID'], - 'description' => $post['main'], - 'title' => $postdata['post_title'], - 'link' => $link, - 'permaLink' => $link, -// commented out because no other tool seems to use this -// 'content' => $entry['post_content'], - 'categories' => $categories, - 'mt_excerpt' => $postdata['post_excerpt'], - 'mt_text_more' => $post['extended'], - 'mt_allow_comments' => $allow_comments, - 'mt_allow_pings' => $allow_pings - ); - - return $resp; - } else { - return new IXR_Error(404, 'Sorry, no such post.'); - } - } - - - /* metaweblog.getRecentPosts ...returns recent posts */ - function mw_getRecentPosts($args) { - - $blog_ID = $args[0]; - $user_login = $args[1]; - $user_pass = $args[2]; - $num_posts = $args[3]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $posts_list = wp_get_recent_posts($num_posts); - - if (!$posts_list) { - $this->error = new IXR_Error(500, 'Either there are no posts, or something went wrong.'); - return $this->error; - } - - foreach ($posts_list as $entry) { - - $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']); - $categories = array(); - $catids = wp_get_post_cats('', $entry['ID']); - foreach($catids as $catid) { - $categories[] = get_cat_name($catid); - } - - $post = get_extended($entry['post_content']); - $link = post_permalink($entry['ID']); - - $allow_comments = ('open' == $entry['comment_status']) ? 1 : 0; - $allow_pings = ('open' == $entry['ping_status']) ? 1 : 0; - - $struct[] = array( - 'dateCreated' => new IXR_Date($post_date), - 'userid' => $entry['post_author'], - 'postid' => $entry['ID'], - 'description' => $post['main'], - 'title' => $entry['post_title'], - 'link' => $link, - 'permaLink' => $link, -// commented out because no other tool seems to use this -// 'content' => $entry['post_content'], - 'categories' => $categories, - 'mt_excerpt' => $entry['post_excerpt'], - 'mt_text_more' => $post['extended'], - 'mt_allow_comments' => $allow_comments, - 'mt_allow_pings' => $allow_pings - ); - - } - - $recent_posts = array(); - for ($j=0; $jlogin_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $categories_struct = array(); - - // FIXME: can we avoid using direct SQL there? - if ($cats = $wpdb->get_results("SELECT cat_ID,cat_name FROM $wpdb->categories", ARRAY_A)) { - foreach ($cats as $cat) { - $struct['categoryId'] = $cat['cat_ID']; - $struct['description'] = $cat['cat_name']; - $struct['categoryName'] = $cat['cat_name']; - $struct['htmlUrl'] = htmlspecialchars(get_category_link(false, $cat['cat_ID'], $cat['cat_name'])); - $struct['rssUrl'] = htmlspecialchars(get_category_rss_link(false, $cat['cat_ID'], $cat['cat_name'])); - - $categories_struct[] = $struct; - } - } - - return $categories_struct; - } - - - /* metaweblog.newMediaObject uploads a file, following your settings */ - function mw_newMediaObject($args) { - // adapted from a patch by Johann Richard - // http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/ - - $blog_ID = $args[0]; - $user_login = $args[1]; - $user_pass = $args[2]; - $data = $args[3]; - - $name = $data['name']; - $type = $data['type']; - $bits = $data['bits']; - - $file_realpath = get_settings('fileupload_realpath'); - $file_url = get_settings('fileupload_url'); - - logIO('O', '(MW) Received '.strlen($bits).' bytes'); - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $user_data = get_userdatabylogin($user_login); - - if(!get_settings('use_fileupload')) { - // Uploads not allowed - logIO('O', '(MW) Uploads not allowed'); - $this->error = new IXR_Error(405, 'No uploads allowed for this site.'); - return $this->error; - } - - if(get_settings('fileupload_minlevel') > $user_data->user_level) { - // User has not enough privileges - logIO('O', '(MW) Not enough privilege: user level too low'); - $this->error = new IXR_Error(401, 'You are not allowed to upload files to this site.'); - return $this->error; - } - - if(trim($file_realpath) == '' || trim($file_url) == '' ) { - // WordPress is not correctly configured - logIO('O', '(MW) Bad configuration. Real/URL path not defined'); - $this->error = new IXR_Error(500, 'Please configure WordPress with valid paths for file upload.'); - return $this->error; - } - - $prefix = '/'; - - if(!empty($name)) { - // Create the path - $localpath = $file_realpath.$prefix.$name; - $url = $file_url.$prefix.$name; - - if (mkdir_p(dirname($localpath))) { - - /* encode & write data (binary) */ - $ifp = fopen($localpath, 'wb'); - $success = fwrite($ifp, $bits); - fclose($ifp); - @chmod($localpath, 0666); - - if($success) { - $resp = array('url' => $url); - return $resp; - } else { - logIO('O', '(MW) Could not write file '.$name.' to '.$localpath); - return new IXR_Error(500, 'Could not write file '.$name); - } - - } else { - return new IXR_Error(500, 'Could not create directories for '.$name); - } - } - } - - - - /* MovableType API functions - * specs on http://www.movabletype.org/docs/mtmanual_programmatic.html - */ - - /* mt.getRecentPostTitles ...returns recent posts' titles */ - function mt_getRecentPostTitles($args) { - - $blog_ID = $args[0]; - $user_login = $args[1]; - $user_pass = $args[2]; - $num_posts = $args[3]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $posts_list = wp_get_recent_posts($num_posts); - - if (!$posts_list) { - $this->error = new IXR_Error(500, 'Either there are no posts, or something went wrong.'); - return $this->error; - } - - foreach ($posts_list as $entry) { - - $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']); - - $struct[] = array( - 'dateCreated' => new IXR_Date($post_date), - 'userid' => $entry['post_author'], - 'postid' => $entry['ID'], - 'title' => $entry['post_title'], - ); - - } - - $recent_posts = array(); - for ($j=0; $jlogin_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $categories_struct = array(); - - // FIXME: can we avoid using direct SQL there? - if ($cats = $wpdb->get_results("SELECT cat_ID, cat_name FROM $wpdb->categories", ARRAY_A)) { - foreach ($cats as $cat) { - $struct['categoryId'] = $cat['cat_ID']; - $struct['categoryName'] = $cat['cat_name']; - - $categories_struct[] = $struct; - } - } - - return $categories_struct; - } - - - /* mt.getPostCategories ...returns a post's categories */ - function mt_getPostCategories($args) { - - $post_ID = $args[0]; - $user_login = $args[1]; - $user_pass = $args[2]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $categories = array(); - $catids = wp_get_post_cats('', intval($post_ID)); - // first listed category will be the primary category - $isPrimary = true; - foreach($catids as $catid) { - $categories[] = array( - 'categoryName' => get_cat_name($catid), - 'categoryId' => $catid, - 'isPrimary' => $isPrimary - ); - $isPrimary = false; - } - - return $categories; - } - - - /* mt.setPostCategories ...sets a post's categories */ - function mt_setPostCategories($args) { - - $post_ID = $args[0]; - $user_login = $args[1]; - $user_pass = $args[2]; - $categories = $args[3]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $user_data = get_userdatabylogin($user_login); - if (!user_can_edit_post($user_data->ID, $post_ID)) { - return new IXR_Error(401, 'Sorry, you can not edit this post.'); - } - - foreach($categories as $cat) { - $catids[] = $cat['categoryId']; - } + $username = $username->scalarval(); + $password = $password->scalarval(); + $content = $content->scalarval(); + // publish flag sets post status appropriately + $post_status = $publish->scalarval()?'publish':'draft'; - wp_set_post_cats('', $post_ID, $catids); + if (user_pass_ok($username,$password)) { - return true; - } - - - /* mt.supportedMethods ...returns an array of methods supported by this server */ - function mt_supportedMethods($args) { - - $supported_methods = array(); - foreach($this->methods as $key=>$value) { - $supported_methods[] = $key; - } - - return $supported_methods; - } - - - /* mt.supportedTextFilters ...returns an empty array because we don't - support per-post text filters yet */ - function mt_supportedTextFilters($args) { - return array(); - } - - - /* mt.getTrackbackPings ...returns trackbacks sent to a given post */ - function mt_getTrackbackPings($args) { - - global $wpdb; - - $post_ID = intval($args); - - $actual_post = wp_get_single_post($post_ID, ARRAY_A); - - if (!$actual_post) { - return new IXR_Error(404, 'Sorry, no such post.'); - } - - $comments = $wpdb->get_results("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = $post_ID"); - - if (!$comments) { - return array(); - } - - $trackback_pings = array(); - foreach($comments as $comment) { - if ((strpos($comment->comment_content, '') === 0) - || ('trackback' == $comment->comment_type)) { - // FIXME: would be nicer to have a comment_title field? - // FIXME: assumption: here we make the assumption that trackback - // titles are stored as title - $content = str_replace('', '', $comment->comment_content); - $title = substr($content, 8, (strpos($content, '') - 8)); - $trackback_pings[] = array( - 'pingTitle' => $title, - 'pingURL' => $comment->comment_author_url, - 'pingIP' => $comment->comment_author_IP - ); - } - } - - return $trackback_pings; - } - - - /* mt.publishPost ...sets a post's publish status to 'publish' */ - function mt_publishPost($args) { - - $post_ID = $args[0]; - $user_login = $args[1]; - $user_pass = $args[2]; - - if (!$this->login_pass_ok($user_login, $user_pass)) { - return $this->error; - } - - $user_data = get_userdatabylogin($user_login); - if (!user_can_edit_post($user_data->ID, $post_ID)) { - return new IXR_Error(401, 'Sorry, you can not edit this post.'); - } - - $postdata = wp_get_single_post($post_ID,ARRAY_A); - - $postdata['post_status'] = 'publish'; - - // retain old cats - $cats = wp_get_post_cats('',$post_ID); - $postdata['post_category'] = $cats; - - $result = wp_update_post($postdata); - - return $result; - } - - - - /* PingBack functions - * specs on www.hixie.ch/specs/pingback/pingback - */ - - /* pingback.ping gets a pingback and registers it */ - function pingback_ping($args) { - // original code by Mort (http://mort.mine.nu:8080 -- site seems dead) - // refactored to return error codes and avoid deep ifififif headaches - global $wpdb, $wp_version; - - $pagelinkedfrom = $args[0]; - $pagelinkedto = $args[1]; - - $title = ''; - - $pagelinkedfrom = str_replace('&', '&', $pagelinkedfrom); - $pagelinkedto = preg_replace('#&([^amp\;])#is', '&$1', $pagelinkedto); - - $error_code = -1; - - // Check if the page linked to is in our site - $pos1 = strpos($pagelinkedto, str_replace('http://', '', str_replace('www.', '', get_settings('home')))); - if(!$pos1) { - return new IXR_Error(0, ''); + $userdata = get_userdatabylogin($username); + $post_author = $userdata->ID; + $user_level = $userdata->user_level; + if ($user_level < 1) { + return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1 + "Sorry, level 0 users can not post"); } + $post_title = addslashes(xmlrpc_getposttitle($content)); + $post_category = xmlrpc_getpostcategory($content); + + $content = xmlrpc_removepostdata($content); + $post_content = format_to_post($content); + + $post_date = current_time('mysql'); + $post_date_gmt = current_time('mysql', 1); + + $postdata = compact('post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status'); + + $post_ID = wp_insert_post($postdata); + + if (!$post_ID) + return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2 + "For some strange yet very annoying reason, your entry couldn't be posted."); + + if (!isset($blog_ID)) { $blog_ID = 1; } + + if (isset($sleep_after_edit) && $sleep_after_edit > 0) { + sleep($sleep_after_edit); + } + + + pingback($content, $post_ID); + + logIO("O","Posted ! ID: $post_ID"); + return new xmlrpcresp(new xmlrpcval("$post_ID")); + + } else { + logIO("O","Wrong username/password combination $username / $password"); + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + + + +### blogger.editPost ### + +$bloggereditpost_sig=array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcBoolean)); + +$bloggereditpost_doc='Edits a post, blogger-api like'; + +function bloggereditpost($m) { + global $wpdb; + + global $xmlrpcerruser; // import user errcode value + global $blog_ID,$cache_userdata,$use_rss; + global $post_default_title,$post_default_category, $sleep_after_edit; + $err=""; + + + $post_ID=$m->getParam(1); + $username=$m->getParam(2); + $password=$m->getParam(3); + $newcontent=$m->getParam(4); + $publish=$m->getParam(5); + + $ID = $post_ID->scalarval(); + $username = $username->scalarval(); + $password = $password->scalarval(); + $newcontent = $newcontent->scalarval(); + $post_status = $publish->scalarval()?'publish':'draft'; + + $result = wp_get_single_post($ID,ARRAY_A); + + if (!$result) + return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2 + "No such post '$ID'."); + + $userdata = get_userdatabylogin($username); + $user_ID = $userdata->ID; + $user_level = $userdata->user_level; + + $postdata=get_postdata($ID); + $post_authordata=get_userdata($postdata["Author_ID"]); + $post_author_ID=$postdata["Author_ID"]; + + if (($user_ID != $post_author_ID) && ($user_level <= $post_authordata->user_level)) { + return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1 + "Sorry, you do not have the right to edit this post"); + } + + if (user_pass_ok($username,$password)) { + + if ($user_level < 1) { + return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1 + "Sorry, level 0 users can not edit posts"); + } + + extract($result); + + $content = $newcontent; + + $post_title = xmlrpc_getposttitle($content); + $post_category = xmlrpc_getpostcategory($content); + + $content = xmlrpc_removepostdata($content); + $post_content = format_to_post($content); + + $postdata = compact('ID','post_content','post_title','post_category','post_status','post_excerpt'); + + $result = wp_update_post($postdata); + + if (!$result) + return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2 + "For some strange yet very annoying reason, the entry couldn't be edited."); + + if (!isset($blog_ID)) { $blog_ID = 1; } + + if (isset($sleep_after_edit) && $sleep_after_edit > 0) { + sleep($sleep_after_edit); + } + + + + return new xmlrpcresp(new xmlrpcval(true, "boolean")); + + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + + + +### blogger.deletePost ### + +$bloggerdeletepost_sig=array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcBoolean)); + +$bloggerdeletepost_doc='Deletes a post, blogger-api like'; + +function bloggerdeletepost($m) { + global $wpdb; + + global $xmlrpcerruser; // import user errcode value + global $blog_ID,$cache_userdata,$use_rss; + global $post_default_title,$post_default_category, $sleep_after_edit; + $err=""; + + + $post_ID=$m->getParam(1); + $username=$m->getParam(2); + $password=$m->getParam(3); + $newcontent=$m->getParam(4); + + $post_ID = $post_ID->scalarval(); + $username = $username->scalarval(); + $password = $password->scalarval(); + $newcontent = $newcontent->scalarval(); + + $sql = "SELECT * FROM $wpdb->posts WHERE ID = '$post_ID'"; + $result = $wpdb->get_results($sql); + if (!$result) + return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2 + "No such post '$post_ID'."); + + $userdata = get_userdatabylogin($username); + $user_ID = $userdata->ID; + $user_level = $userdata->user_level; + + $postdata=get_postdata($post_ID); + $post_authordata=get_userdata($postdata["Author_ID"]); + $post_author_ID=$postdata["Author_ID"]; + + if (($user_ID != $post_author_ID) && ($user_level <= $post_authordata->user_level)) { + return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1 + "Sorry, you do not have the right to delete this post"); + } + + if (user_pass_ok($username,$password)) { + + if ($user_level < 1) { + return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1 + "Sorry, level 0 users can not delete posts"); + } + + $result = wp_delete_post($post_ID); + + if (!$result) + return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2 + "For some strange yet very annoying reason, the entry couldn't be deleted."); + + if (!isset($blog_ID)) { $blog_ID = 1; } + + if (isset($sleep_after_edit) && $sleep_after_edit > 0) { + sleep($sleep_after_edit); + } + + + + return new xmlrpcresp(new xmlrpcval(true,'boolean')); + + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + + + +### blogger.getUsersBlogs ### + +$bloggergetusersblogs_sig=array(array($xmlrpcArray, $xmlrpcString, $xmlrpcString, $xmlrpcString)); + +$bloggergetusersblogs_doc='returns the user\'s blogs - this is a dummy function, just so that BlogBuddy and other blogs-retrieving apps work'; + +function bloggergetusersblogs($m) { + global $wpdb; + // this function will have a real purpose with CafeLog's multiple blogs capability + + global $xmlrpcerruser; + + $user_login = $m->getParam(1); + $user_login = $user_login->scalarval(); + + + $sql = "SELECT user_level FROM $wpdb->users WHERE user_login = '$user_login' AND user_level > 3"; + $result = $wpdb->get_results($sql); + + + $is_admin = $wpdb->num_rows; + + $struct = new xmlrpcval(array("isAdmin" => new xmlrpcval($is_admin,"boolean"), + "url" => new xmlrpcval(get_settings('home') .'/'.get_settings('blogfilename')), + "blogid" => new xmlrpcval("1"), + "blogName" => new xmlrpcval(get_settings('blogname')) + ),"struct"); + $resp = new xmlrpcval(array($struct), "array"); + + return new xmlrpcresp($resp); +} + + + +### blogger.getUserInfo ### + +$bloggergetuserinfo_sig=array(array($xmlrpcStruct, $xmlrpcString, $xmlrpcString, $xmlrpcString)); + +$bloggergetuserinfo_doc='gives the info about a user'; + +function bloggergetuserinfo($m) { + global $xmlrpcerruser; + + + $username=$m->getParam(1); + $username = $username->scalarval(); + + $password=$m->getParam(2); + $password = $password->scalarval(); + + $userdata = get_userdatabylogin($username); + + if (user_pass_ok($username,$password)) { + $struct = new xmlrpcval(array("nickname" => new xmlrpcval($userdata->user_nickname), + "userid" => new xmlrpcval($userdata->ID), + "url" => new xmlrpcval($userdata->user_url), + "email" => new xmlrpcval($userdata->user_email), + "lastname" => new xmlrpcval($userdata->user_lastname), + "firstname" => new xmlrpcval($userdata->user_firstname) + ),"struct"); + $resp = $struct; + return new xmlrpcresp($resp); + + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + + + +### blogger.getPost ### + +$bloggergetpost_sig=array(array($xmlrpcStruct, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString)); + +$bloggergetpost_doc='fetches a post, blogger-api like'; + +function bloggergetpost($m) { + global $xmlrpcerruser; + + + $post_ID=$m->getParam(1); + $post_ID = $post_ID->scalarval(); + + $username=$m->getParam(2); + $username = $username->scalarval(); + + $password=$m->getParam(3); + $password = $password->scalarval(); + + if (user_pass_ok($username,$password)) { + $postdata = wp_get_single_post($post_ID); + + if ($postdata['post_date'] != '') { + $post_date = mysql2date('Ymd\TH:i:s\Z', $postdata['post_date_gmt']); + + $categories = implode(',', $postdata['post_category']); + + $content = ''.stripslashes($postdata['post_title']).''; + $content .= ''.$categories.''; + $content .= stripslashes($postdata['post_content']); + + $struct = new xmlrpcval(array('userid' => new xmlrpcval($postdata['post_author']), + "dateCreated" => new xmlrpcval($post_date,"dateTime.iso8601"), + "content" => new xmlrpcval($content), + "postid" => new xmlrpcval($postdata["ID"]) + ),"struct"); + + $resp = $struct; + return new xmlrpcresp($resp); + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 4 + "No such post #$post_ID"); + } + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + + + +### blogger.getRecentPosts ### + +$bloggergetrecentposts_sig=array(array($xmlrpcArray, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcInt)); + +$bloggergetrecentposts_doc='fetches X most recent posts, blogger-api like'; + +function bloggergetrecentposts($m) { + global $wpdb; + global $xmlrpcerruser; + + error_reporting(0); // there is a bug in phpxmlrpc that makes it say there are errors while the output is actually valid, so let's disable errors for that function + + + $blogid = 1; // we don't need that yet + + $numposts=$m->getParam(4); + $numposts = $numposts->scalarval(); + + if ($numposts > 0) { + $limit = " LIMIT $numposts"; + } else { + $limit = ""; + } + + $username=$m->getParam(2); + $username = $username->scalarval(); + + $password=$m->getParam(3); + $password = $password->scalarval(); + + if (user_pass_ok($username,$password)) { + + $sql = "SELECT * FROM $wpdb->posts ORDER BY post_date_gmt DESC".$limit; + $result = $wpdb->get_results($sql); + if (!$result) + return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2 + "For some strange yet very annoying reason, the entries couldn't be fetched."); + + $data = new xmlrpcval("","array"); + + $i = 0; + foreach ($result as $row) { + $postdata = array( + "ID" => $row->ID, + "Author_ID" => $row->post_author, + "Date" => $row->post_date_gmt, + "Content" => $row->post_content, + "Title" => $row->post_title, + "Category" => $row->post_category + ); + + $post_date = mysql2date('Ymd\TH:i:s\Z', $postdata['Date']); + + $categories = implode(',', wp_get_post_cats(1, $postdata['ID'])); + + $content = "".stripslashes($postdata["Title"]).""; + $content .= "".$categories.""; + $content .= stripslashes($postdata["Content"]); + +// $content = convert_chars($content,"html"); +// $content = $postdata["Title"]; + + $category = new xmlrpcval($postdata['Category']); + + $authordata = get_userdata($postdata["Author_ID"]); + switch($authordata["user_idmode"]) { + case "nickname": + $authorname = $authordata["user_nickname"]; + + case "login": + $authorname = $authordata["user_login"]; + break; + case "firstname": + $authorname = $authordata["user_firstname"]; + break; + case "lastname": + $authorname = $authordata["user_lastname"]; + break; + case "namefl": + $authorname = $authordata["user_firstname"]." ".$authordata["user_lastname"]; + break; + case "namelf": + $authorname = $authordata["user_lastname"]." ".$authordata["user_firstname"]; + break; + default: + $authorname = $authordata["user_nickname"]; + break; + } + + $struct[$i] = new xmlrpcval(array("authorName" => new xmlrpcval($authorname), + "userid" => new xmlrpcval($postdata["Author_ID"]), + "dateCreated" => new xmlrpcval($post_date,"dateTime.iso8601"), + "content" => new xmlrpcval($content), + "postid" => new xmlrpcval($postdata["ID"]), + 'category' => $category + ),"struct"); + $i = $i + 1; + } + + $data = array($struct[0]); + for ($j=1; $j<$i; $j++) { + array_push($data, $struct[$j]); + } + + $resp = new xmlrpcval($data, "array"); + + return new xmlrpcresp($resp); + + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + + + +### blogger.getTemplate ### + +# note: on b2, it fetches your $blogfilename, or b2.php if you didn't specify the variable + +$bloggergettemplate_sig=array(array($xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString)); + +$bloggergettemplate_doc='returns the default template file\'s code'; + +function bloggergettemplate($m) { + global $xmlrpcerruser; + + error_reporting(0); // there is a bug in phpxmlrpc that makes it say there are errors while the output is actually valid, so let's disable errors for that function + + + $blogid = 1; // we do not need this yet + + $templateType=$m->getParam(4); + $templateType = $templateType->scalarval(); + + $username=$m->getParam(2); + $username = $username->scalarval(); + + $password=$m->getParam(3); + $password = $password->scalarval(); + + $userdata = get_userdatabylogin($username); + + if ($userdata->user_level < 3) { + return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1 + "Sorry, users whose level is less than 3, can not edit the template."); + } + + if (user_pass_ok($username,$password)) { + + if ($templateType == "main") { + if (get_settings('blogfilename') != '') { + $file = get_settings('blogfilename'); + } else { + $file = "wp.php"; + } + } elseif ($templateType == "archiveIndex") { + $file = "wp.php"; + } + + $doc_root = preg_replace('#http://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', get_settings('home')); + $file = $doc_root.'/'.$file; + + $f = fopen($file,"r"); + $content = fread($f,filesize($file)); + fclose($f); + + $content = str_replace("\n","\r\n",$content); // so it is actually editable with a windows/mac client, instead of being returned as a looooooooooong line of code + + return new xmlrpcresp(new xmlrpcval("$content")); + + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + + + +### blogger.setTemplate ### + +# note: on b2, it saves that in your $blogfilename, or b2.php if you didn't specify the variable + +$bloggersettemplate_sig=array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString)); + +$bloggersettemplate_doc='saves the default template file\'s code'; + +function bloggersettemplate($m) { + global $xmlrpcerruser; + + error_reporting(0); // there is a bug in phpxmlrpc that makes it say there are errors while the output is actually valid, so let's disable errors for that function + + + $blogid = 1; // we do not need this yet + + $template=$m->getParam(4); + $template = $template->scalarval(); + + $templateType=$m->getParam(5); + $templateType = $templateType->scalarval(); + + $username=$m->getParam(2); + $username = $username->scalarval(); + + $password=$m->getParam(3); + $password = $password->scalarval(); + + $userdata = get_userdatabylogin($username); + + if ($userdata->user_level < 3) { + return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1 + "Sorry, users whose level is less than 3, can not edit the template."); + } + + if (user_pass_ok($username,$password)) { + + if ($templateType == 'main') { + if (get_settings('blogfilename') != '') { + $file = get_settings('blogfilename'); + } else { + $file = "wp.php"; + } + } elseif ($templateType == "archiveIndex") { + $file = "wp.php"; + } + + $doc_root = preg_replace('#http://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', get_settings('home')); + $file = $doc_root.'/'.$file; + + $f = fopen($file,"w+"); + fwrite($f, $template); + fclose($f); + + return new xmlrpcresp(new xmlrpcval(true, "boolean")); + + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + +/**** /Blogger API ****/ + + + +/**** metaWeblog API ****/ + +/********************** + * + * metaWeblog API extensions + * added by + * Dougal Campbell + * http://dougal.gunters.org/ + * + **********************/ + +$mwnewpost_sig = array(array($xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcStruct,$xmlrpcBoolean)); +$mwnewpost_doc = 'Add a post, MetaWeblog API-style'; + +function mwnewpost($params) { + global $xmlrpcerruser; + global $blog_ID, $cache_userdata; + global $use_rss, $post_default_title; + global $post_default_category,$cafelogID,$sleep_after_edit; + + $xblogid = $params->getParam(0); + $xuser = $params->getParam(1); + $xpass = $params->getParam(2); + $xcontent = $params->getParam(3); + $xpublish = $params->getParam(4); + + $blogid = $xblogid->scalarval(); + $username = $xuser->scalarval(); + $password = $xpass->scalarval(); + $contentstruct = phpxmlrpc_decode($xcontent); + $post_status = $xpublish->scalarval()?'publish':'draft'; + + // Check login + if (user_pass_ok($username,$password)) { + $userdata = get_userdatabylogin($username); + $post_author = $userdata->ID; + $user_level = $userdata->user_level; + if ($user_level < 1) { + return new xmlrpcresp(0, $xmlrpcerruser+1, + "Sorry, level 0 users cannot post"); + } + + + $post_title = $contentstruct['title']; + $post_content = format_to_post($contentstruct['description']); + + $post_excerpt = $contentstruct['mt_excerpt']; + $post_more = $contentstruct['mt_text_more']; + + $comment_status = $contentstruct['mt_allow_comments']?'open':'closed'; + $ping_status = $contentstruct['mt_allow_pings']?'open':'closed'; + + if ($post_more) { + $post_content = $post_content . "\n\n" . $post_more; + } + + // Do some timestamp voodoo + $dateCreated = $contentstruct['dateCreated']; + if (!empty($dateCreated)) { + $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); + $post_date_gmt = iso8601_to_datetime($dateCreated, GMT); + } else { + $post_date = current_time('mysql'); + $post_date_gmt = current_time('mysql', 1); + } + + $catnames = $contentstruct['categories']; + // FIXME: commented until proper fix // logio("O","Post cats: " . print_r($catnames,true)); + $post_category = array(); + if ($catnames) { + foreach ($catnames as $cat) { + $post_category[] = get_cat_ID($cat); + } + } else { + $post_category[] = 1; + } + + // We've got all the data -- post it: + $postarr = compact('post_author','post_date','post_date_gmt','post_content','post_title','post_category','post_status','post_excerpt','comment_status','ping_status'); + + $post_ID = wp_insert_post($postarr); + + if (!$post_ID) { + return new xmlrpcresp(0, $xmlrpcerruser+2, "For some strange yet very annoying reason, your entry could not be posted."); + } + + if (!isset($blog_ID)) { $blog_ID = 1; } + + if (isset($sleep_after_edit) && $sleep_after_edit > 0) { + sleep($sleep_after_edit); + } + + pingback($content, $post_ID); + trackback_url_list($contentstruct['mt_tb_ping_urls'],$post_ID); + + logIO("O","(MW) Posted ! ID: $post_ID"); + $myResp = new xmlrpcval($post_ID,"string"); + + return new xmlrpcresp($myResp); + + } else { + logIO("O","(MW) Wrong username/password combination $username / $password"); + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + +$mweditpost_sig = array(array($xmlrpcBoolean,$xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcStruct,$xmlrpcBoolean)); +$mweditpost_doc = 'Edit a post, MetaWeblog API-style'; + +function mweditpost ($params) { // ($postid, $user, $pass, $content, $publish) + global $xmlrpcerruser; + + $xpostid = $params->getParam(0); + $xuser = $params->getParam(1); + $xpass = $params->getParam(2); + $xcontent = $params->getParam(3); + $xpublish = $params->getParam(4); + + $ID = $xpostid->scalarval(); + $username = $xuser->scalarval(); + $password = $xpass->scalarval(); + $contentstruct = phpxmlrpc_decode($xcontent); + $postdata = wp_get_single_post($ID,ARRAY_A); + + if (!$postdata) + return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2 + "No such post $ID."); + + $userdata = get_userdatabylogin($username); + $user_ID = $userdata->ID; + $user_level = $userdata->user_level; + $time_difference = get_settings('gmt_offset'); + + $post_author_ID = $postdata['post_author']; + $post_authordata = get_userdata($post_author_ID); + + if (($user_ID != $post_author_ID) && ($user_level <= $post_authordata->user_level)) { + return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1 + "Sorry, you do not have the right to edit this post."); + } + + // Check login + if (user_pass_ok($username,$password)) { + if ($user_level < 1) { + return new xmlrpcresp(0, $xmlrpcerruser+1, + + "Sorry, level 0 users cannot edit posts"); + } + + extract($postdata); + + $post_title = $contentstruct['title']; + $post_content = format_to_post($contentstruct['description']); + $catnames = $contentstruct['categories']; + + if ($catnames) { + foreach ($catnames as $cat) { + $post_category[] = get_cat_ID($cat); + } + } + + $post_excerpt = $contentstruct['mt_excerpt']; + $post_more = $contentstruct['mt_text_more']; + $post_status = $xpublish->scalarval()?'publish':'draft'; + if ($post_more) { + $post_content = $post_content . "\n\n" . $post_more; + } + $comment_status = (1 == $contentstruct['mt_allow_comments'])?'open':'closed'; + $ping_status = $contentstruct['mt_allow_pings']?'open':'closed'; + + // Do some timestamp voodoo + $dateCreated = $contentstruct['dateCreated']; + if (!empty($dateCreated)) { + $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); + $post_date_gmt = iso8601_to_datetime($dateCreated, GMT); + } else { + $post_date = $postdata['post_date']; + $post_date_gmt = $postdata['post_date_gmt']; + } + + // We've got all the data -- post it: + $newpost = compact('ID','post_content','post_title','post_category','post_status','post_excerpt','comment_status','ping_status','post_date','post_date_gmt'); + + $post_ID = wp_update_post($newpost); + + if (!$post_ID) { + return new xmlrpcresp(0, $xmlrpcerruser+2, "For some strange yet very annoying reason, your entry could not be posted."); + } + + if (!isset($blog_ID)) { $blog_ID = 1; } + + if (isset($sleep_after_edit) && $sleep_after_edit > 0) { + sleep($sleep_after_edit); + } + + pingback($content, $post_ID); + trackback_url_list($contentstruct['mt_tb_ping_urls'],$post_ID); + + logIO("O","(MW) Edited ! ID: $post_ID"); + $myResp = new xmlrpcval(true,"boolean"); + + return new xmlrpcresp($myResp); + + } else { + logIO("O","(MW) Wrong username/password combination $username / $password"); + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + +$mwgetpost_sig = array(array($xmlrpcStruct,$xmlrpcString,$xmlrpcString,$xmlrpcString)); +$mwegetpost_doc = 'Get a post, MetaWeblog API-style'; + +function mwgetpost ($params) { // ($postid, $user, $pass) + global $xmlrpcerruser; + + $xpostid = $params->getParam(0); + $xuser = $params->getParam(1); + $xpass = $params->getParam(2); + + $post_ID = $xpostid->scalarval(); + $username = $xuser->scalarval(); + $password = $xpass->scalarval(); + + // Check login + if (user_pass_ok($username,$password)) { + $postdata = wp_get_single_post($post_ID, ARRAY_A); + + if ($postdata['post_date'] != '') { + + $post_date = mysql2date('Ymd\TH:i:s\Z', $postdata['post_date_gmt']); + + $catids = wp_get_post_cats('', $post_ID); + foreach($catids as $catid) { + $catname = get_cat_name($catid); + $catnameenc = new xmlrpcval($catname); + $catlist[] = $catnameenc; + } + $post = get_extended($postdata['post_content']); + $allow_comments = ('open' == $postdata['comment_status'])?1:0; + $allow_pings = ('open' == $postdata['ping_status'])?1:0; + + $resp = array( + 'link' => new xmlrpcval(post_permalink($post_ID)), + 'title' => new xmlrpcval($postdata['post_title']), + 'description' => new xmlrpcval($post['main']), + 'dateCreated' => new xmlrpcval($post_date,'dateTime.iso8601'), + 'userid' => new xmlrpcval($postdata['post_author']), + 'postid' => new xmlrpcval($postdata['ID']), + 'content' => new xmlrpcval($postdata['post_content']), + 'permalink' => new xmlrpcval(post_permalink($post_ID)), + 'categories' => new xmlrpcval($catlist,'array'), + 'mt_excerpt' => new xmlrpcval($postdata['post_excerpt']), + 'mt_allow_comments' => new xmlrpcval($allow_comments,'int'), + 'mt_allow_pings' => new xmlrpcval($allow_pings,'int'), + 'mt_text_more' => new xmlrpcval($post['extended']) + ); + + $resp = new xmlrpcval($resp,'struct'); + + return new xmlrpcresp($resp); + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 4 + "No such post #$post_ID"); + } + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } + +} + +$mwrecentposts_sig = array(array($xmlrpcArray,$xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcInt)); +$mwerecentposts_doc = 'Get recent posts, MetaWeblog API-style'; + +function mwrecentposts ($params) { // ($blogid, $user, $pass, $num) + global $xmlrpcerruser; + + $xblogid = $params->getParam(0); + $xuser = $params->getParam(1); + $xpass = $params->getParam(2); + $xnum = $params->getParam(3); + + $blogid = $xblogid->scalarval(); + $username = $xuser->scalarval(); + $password = $xpass->scalarval(); + $num = $xnum->scalarval(); + + // Check login + if (user_pass_ok($username,$password)) { + + $postlist = wp_get_recent_posts($num); + + // Build response packet. We can't just use xmlrpc_encode, + // because of the dateCreated field, which must be a date type. + + // Encode each entry of the array. + foreach($postlist as $entry) { + + $isoString = mysql2date('Ymd\TH:i:s\Z', $entry['post_date_gmt']); + $date = new xmlrpcval($isoString,"dateTime.iso8601"); + $userid = new xmlrpcval($entry['post_author']); + $content = new xmlrpcval($entry['post_content']); + $excerpt = new xmlrpcval($entry['post_excerpt']); + + // $pcat = stripslashes(get_cat_name($entry['post_category'])); + + $catlist = array(); + $catids = wp_get_post_cats('', $entry['ID']); + foreach($catids as $catid) { + $catname = get_cat_name($catid); + $catnameenc = new xmlrpcval($catname); + $catlist[] = $catnameenc; + } + + // For multiple cats, we might do something like + // this in the future: + //$catstruct['description'] = $pcat; + //$catstruct['categoryId'] = $entry['post_category']; + //$catstruct['categoryName'] = $pcat; + //$catstruct['isPrimary'] = TRUE; + + //$catstruct2 = phpxmlrpc_encode($catstruct); + + // $categories = new xmlrpcval(array(new xmlrpcval($pcat)),'array'); + $categories = new xmlrpcval($catlist, 'array'); + + $post = get_extended($entry['post_content']); + + $postid = new xmlrpcval($entry['ID']); + $title = new xmlrpcval(stripslashes($entry['post_title'])); + $description = new xmlrpcval(stripslashes($post['main'])); + $link = new xmlrpcval(post_permalink($entry['ID'])); + $permalink = $link; + + $extended = new xmlrpcval(stripslashes($post['extended'])); + + $allow_comments = new xmlrpcval((('open' == $entry['comment_status'])?1:0),'int'); + $allow_pings = new xmlrpcval((('open' == $entry['ping_status'])?1:0),'int'); + + $encode_arr = array( + 'dateCreated' => $date, + 'userid' => $userid, + 'postid' => $postid, + 'categories' => $categories, + 'title' => $title, + 'description' => $description, + 'link' => $link, + 'permalink' => $permalink, + 'mt_excerpt' => $excerpt, + 'mt_allow_comments' => $allow_comments, + 'mt_allow_pings' => $allow_pings, + 'mt_text_more' => $extended + ); + + $xmlrpcpostarr[] = new xmlrpcval($encode_arr,"struct"); + } + + // Now convert that to an xmlrpc array type + $myResp = new xmlrpcval($xmlrpcpostarr,"array"); + + return new xmlrpcresp($myResp); + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + + +$mwgetcats_sig = array(array($xmlrpcArray,$xmlrpcString,$xmlrpcString,$xmlrpcString)); +$mwgetcats_doc = 'Get a post, MetaWeblog API-style'; + +function mwgetcats ($params) { // ($blogid, $user, $pass) + global $xmlrpcerruser,$wpdb; + global $querystring_start, $querystring_equal, $querystring_separator; + + $blog_URL = get_settings('home') . '/' . get_settings('blogfilename'); + + $arr = array(); + + if ($cats = $wpdb->get_results("SELECT cat_ID,cat_name FROM $wpdb->categories",ARRAY_A)) { + foreach ($cats as $cat) { + $struct['categoryId'] = $cat['cat_ID']; + $struct['description'] = $cat['cat_name']; + $struct['categoryName'] = $cat['cat_name']; + $struct['htmlUrl'] = htmlspecialchars($blog_URL . $querystring_start . 'cat' . $querystring_equal . $cat['cat_ID']); + $struct['rssUrl'] = ''; // will probably hack alexking's stuff in here + + $arr[] = phpxmlrpc_encode($struct); + } + } + + $resp = new xmlrpcval($arr,'array'); + + return new xmlrpcresp($resp); +} + + +$mwnewmedia_sig = array(array($xmlrpcStruct,$xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcStruct)); +$mwnewmedia_doc = 'Upload image or other binary data, MetaWeblog API-style (unimplemented)'; + +function mwnewmedia($params) { // ($blogid, $user, $pass, $struct) + global $xmlrpcerruser; + + return new xmlrpcresp(0, $xmlrpcerruser+10, // user error 10 + 'metaWeblog.newMediaObject not implemented (yet)'); +} + + +/**** /MetaWeblog API ****/ + + +/**** MovableType API ****/ + +/********************** + * + * MovableType API extensions + * added by + * Dougal Campbell + * http://dougal.gunters.org/ + * + * DONE: + * mt.getCategoryList + * mt.setPostCategories + * mt.supportedMethods + * mt.getPostCategories + * mt.publishPost + * mt.getRecentPostTitles + * extend metaWeblog.newPost + * extend metaWeblog.editPost + * extend metaWeblog.getPost + * extend metaWeblog.getRecentPosts + * + * PARTIALLY DONE: + * mt.supportedTextFilters // empty stub, because WP doesn't support per-post text filters at this time + * mt.getTrackbackPings // another stub. + * metaWeblog.newMediaObject // ditto. For now. + * + **********************/ + +$mt_supportedMethods_sig = array(array($xmlrpcArray)); +$mt_supportedMethods_doc = 'Retrieve information about the XML-RPC methods supported by the server.'; + +// ripped out of system.listMethods +function mt_supportedMethods($params) { + global $dispatch_map, $xmlrpcerr, $xmlrpcstr, $_xmlrpcs_dmap; + $v=new xmlrpcval(); + $dmap=$dispatch_map; + $outAr=array(); + for(reset($dmap); list($key, $val)=each($dmap); ) { + $outAr[]=new xmlrpcval($key, "string"); + } + $dmap=$_xmlrpcs_dmap; + for(reset($dmap); list($key, $val)=each($dmap); ) { + $outAr[]=new xmlrpcval($key, "string"); + } + $v->addArray($outAr); + return new xmlrpcresp($v); + +} + +$mt_getPostCategories_sig = array(array($xmlrpcArray, $xmlrpcString, $xmlrpcString, $xmlrpcString)); +$mt_getPostCategories_doc = "Returns a list of all categories to which the post is assigned."; + +function mt_getPostCategories($params) { + global $xmlrpcusererr; + + $xpostid = $params->getParam(0); + $xuser = $params->getParam(1); + $xpass = $params->getParam(2); + + $post_ID = $xpostid->scalarval(); + $username = $xuser->scalarval(); + $password = $xpass->scalarval(); + + if (user_pass_ok($username,$password)) { + $catids = wp_get_post_cats('1', $post_ID); + + // The first category listed will be set as primary + $struct['isPrimary'] = true; + foreach($catids as $catid) { + $struct['categoryId'] = $catid; + $struct['categoryName'] = get_cat_name($catid); + + $resp_struct[] = phpxmlrpc_encode($struct); + $struct['isPrimary'] = false; + } + + // Return an array of structs + $resp_array = new xmlrpcval($resp_struct,'array'); + + return new xmlrpcresp($resp_array); + + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + +$mt_setPostCategories_sig = array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcArray)); +$mt_setPostCategories_doc = "Sets the categories for a post"; + +function mt_setPostCategories($params) { + global $xmlrpcusererr; + + $xpostid = $params->getParam(0); + $xuser = $params->getParam(1); + $xpass = $params->getParam(2); + $xcats = $params->getParam(3); + + $post_ID = $xpostid->scalarval(); + $username = $xuser->scalarval(); + $password = $xpass->scalarval(); + $cats = phpxmlrpc_decode($xcats); + + foreach($cats as $cat) { + $catids[] = $cat['categoryId']; + } + + if (user_pass_ok($username,$password)) { + wp_set_post_cats('', $post_ID, $catids); + + return new xmlrpcresp(new xmlrpcval(true,'boolean')); + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + +$mt_publishPost_sig = array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString)); +$mt_publishPost_doc = "Publish (rebuild) all of the static files related to an entry. Equivalent to saving an entry in the system (but without the ping)."; + +function mt_publishPost($params) { + global $xmlrpcusererr; + + $xpostid = $params->getParam(0); + $xuser = $params->getParam(1); + $xpass = $params->getParam(2); + + $post_ID = $xpostid->scalarval(); + $username = $xuser->scalarval(); + $password = $xpass->scalarval(); + + if (user_pass_ok($username,$password)) { + $postdata = wp_get_single_post($post_ID,ARRAY_A); + + $postdata['post_status'] = 'publish'; + + // retain old cats + $cats = wp_get_post_cats('',$post_ID); + $postdata['post_category'] = $cats; + + $result = wp_update_post($postdata); + + return new xmlrpcresp(new xmlrpcval($result,'boolean')); + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + +$mt_getRecentPostTitles_sig = array(array($xmlrpcArray,$xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcInt)); +$mt_getRecentPostTitles_doc = "Returns a bandwidth-friendly list of the most recent posts in the system."; + +function mt_getRecentPostTitles($params) { + global $xmlrpcusererr, $wpdb; + + $xblogid = $params->getParam(0); + $xuser = $params->getParam(1); + $xpass = $params->getParam(2); + $xnumposts = $params->getParam(3); + + $blogid = $xblogid->scalarval(); + $username = $xuser->scalarval(); + $password = $xpass->scalarval(); + $numposts = intval($xnumposts->scalarval()); + + if (user_pass_ok($username,$password)) { + $sql = "SELECT post_date, post_date_gmt, post_author, ID, post_title FROM $wpdb->posts ORDER BY post_date_gmt DESC LIMIT $numposts"; + $posts = $wpdb->get_results($sql,ARRAY_A); + + foreach($posts as $post) { + + $post_date = mysql2date('Ymd\TH:i:s\Z', $post['post_date_gmt']); + + $struct['dateCreated'] = new xmlrpcval($post_date, 'dateTime.iso8601'); + $struct['userid'] = new xmlrpcval($post['post_author'], 'string'); + $struct['postid'] = new xmlrpcval($post['ID'], 'string'); + $struct['title'] = new xmlrpcval($post['post_title'], 'string'); + + $result[] = $struct; + } + + return new xmlrpcresp(new xmlrpcval($results,'array')); + + } else { + return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3 + 'Wrong username/password combination '.$username.' / '.starify($password)); + } +} + + +$mt_supportedTextFilters_sig = array(array($xmlrpcArray)); +$mt_supportedTextFilters_doc = "Retrieve information about the text formatting plugins supported by the server. (not implemented)"; + +function mt_supportedTextFilters($params) { + // This should probably check the status of the 'use_bbcode' + // and 'use_gmcode' config options. + + return new xmlrpcresp(new xmlrpcval(array(),'array')); +} + + + +$mt_getTrackbackPings_sig = array(array($xmlrpcArray,$xmlrpcString)); +$mt_getTrackbackPings_doc = "Retrieve the list of Trackback pings posted to a particular entry. (not implemented)"; + +function mt_getTrackbackPings($params) { + $struct['pingTitle'] = ''; + $struct['pingURL'] = ''; + $struct['pingIP'] = ''; + + $xmlstruct = phpxmlrpc_encode($struct); + + return new xmlrpcresp(new xmlrpcval(array($xmlstruct),'array')); +} + + + +/**** /MovableType API ****/ + + +/**** PingBack functions ****/ + +$pingback_ping_sig = array(array($xmlrpcString, $xmlrpcString, $xmlrpcString)); + +$pingback_ping_doc = 'Gets a pingback and registers it as a comment prefixed by <pingback />'; + +function pingback_ping($m) { // original code by Mort + // (http://mort.mine.nu:8080) + global $wpdb, $wp_version; + + //$log = debug_fopen('./xmlrpc.log', 'w'); + + $title=''; + + $pagelinkedfrom = $m->getParam(0); + $pagelinkedfrom = $pagelinkedfrom->scalarval(); + + $pagelinkedto = $m->getParam(1); + $pagelinkedto = $pagelinkedto->scalarval(); + + $pagelinkedfrom = str_replace('&', '&', $pagelinkedfrom); + $pagelinkedto = preg_replace('#&([^amp\;])#is', '&$1', $pagelinkedto); + + //debug_fwrite($log, 'BEGIN '.time().' - '.date('Y-m-d H:i:s')."\n\n"); + //debug_fwrite($log, 'Page linked from: '.$pagelinkedfrom."\n"); + //debug_fwrite($log, 'Page linked to: '.$pagelinkedto."\n"); + + $messages = array( + htmlentities("Pingback from ".$pagelinkedfrom." to " + . $pagelinkedto . " registered. Keep the web talking! :-)"), + htmlentities("We can't find the URL to the post you are trying to " + . "link to in your entry. Please check how you wrote the post's permalink in your entry."), + htmlentities("We can't find the post you are trying to link to." + . " Please check the post's permalink.") + ); + + $message = $messages[0]; + + // Check if the page linked to is in our site + $pos1 = strpos($pagelinkedto, str_replace('http://', '', str_replace('www.', '', get_settings('home')))); + if($pos1) { // let's find which post is linked to - // FIXME: does url_to_postid() cover all these cases already? - // if so, then let's use it and drop the old code. $urltest = parse_url($pagelinkedto); if ($post_ID = url_to_postid($pagelinkedto)) { $way = 'url_to_postid()'; - } elseif (preg_match('#p/[0-9]{1,}#', $urltest['path'], $match)) { + } + elseif (preg_match('#p/[0-9]{1,}#', $urltest['path'], $match)) { // the path defines the post_ID (archives/p/XXXX) $blah = explode('/', $match[0]); $post_ID = $blah[1]; @@ -1140,173 +1567,271 @@ class wp_xmlrpc_server extends IXR_Server { // ...or a string #title, a little more complicated $title = preg_replace('/[^a-zA-Z0-9]/', '.', $urltest['fragment']); $sql = "SELECT ID FROM $wpdb->posts WHERE post_title RLIKE '$title'"; - if (! ($post_ID = $wpdb->get_var($sql)) ) { - // returning unknown error '0' is better than die()ing - return new IXR_Error(0, ''); - } + $post_ID = $wpdb->get_var($sql) or die("Query: $sql\n\nError: "); $way = 'from the fragment (title)'; } } else { // TODO: Attempt to extract a post ID from the given URL - return new IXR_Error(33, 'The specified target URI cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.'); + $post_ID = -1; + $way = 'no match'; } - logIO("O","(PB) URI='$pagelinkedto' ID='$post_ID' Found='$way'"); + //debug_fwrite($log, "Found post ID $way: $post_ID\n"); + $sql = 'SELECT post_author FROM '.$wpdb->posts.' WHERE ID = '.$post_ID; $result = $wpdb->get_results($sql); - if (!$wpdb->num_rows) { - // Post_ID not found - return new IXR_Error(33, 'The specified target URI cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.'); - } - - - // Let's check that the remote site didn't already pingback this entry - $sql = 'SELECT * FROM '.$wpdb->comments.' - WHERE comment_post_ID = '.$post_ID.' - AND comment_author_url = \''.$pagelinkedfrom.'\' - AND comment_type = \'pingback\''; - $result = $wpdb->get_results($sql); -//return($sql); - if ($wpdb->num_rows) { - // We already have a Pingback from this URL - return new IXR_Error(48, 'The pingback has already been registered.'); - } + //debug_fwrite($log, 'Post exists'."\n"); - // very stupid, but gives time to the 'from' server to publish ! - sleep(1); + // Let's check that the remote site didn't already pingback this entry + $sql = 'SELECT * FROM '.$wpdb->comments.' + WHERE comment_post_ID = '.$post_ID.' + AND comment_author_url = \''.$pagelinkedfrom.'\' + AND comment_content LIKE \'%%\''; + $result = $wpdb->get_results($sql); + + if ($wpdb->num_rows || (1==1)) { - // Let's check the remote site - $fp = @fopen($pagelinkedfrom, 'r'); - if (!$fp) { - // The source URI does not exist - return new IXR_Error(16, 'The source URI does not exist.'); - } + // very stupid, but gives time to the 'from' server to publish ! + sleep(1); - $puntero = 4096; - while($remote_read = fread($fp, $puntero)) { - $linea .= $remote_read; - } + // Let's check the remote site + $fp = @fopen($pagelinkedfrom, 'r'); - // Work around bug in strip_tags(): - $linea = str_replace(''); - $linea = strip_all_but_one_link($linea, $pagelinkedto); - // I don't think we need this? -- emc3 - //$linea = preg_replace('#&([^amp\;])#is', '&$1', $linea); - if (empty($matchtitle)) { - preg_match('|([^<]*?)|is', $linea, $matchtitle); - } - $pos2 = strpos($linea, $pagelinkedto); - $pos3 = strpos($linea, str_replace('http://www.', 'http://', $pagelinkedto)); - if (is_integer($pos2) || is_integer($pos3)) { - // The page really links to us :) - $pos4 = (is_integer($pos2)) ? $pos2 : $pos3; - $start = $pos4-100; - $context = substr($linea, $start, 250); - $context = str_replace("\n", ' ', $context); - $context = str_replace('&', '&', $context); - } - - fclose($fp); + $puntero = 4096; + while($remote_read = fread($fp, $puntero)) { + $linea .= $remote_read; + } + // Work around bug in strip_tags(): + $linea = str_replace(''); + $linea = strip_all_but_one_link($linea, $pagelinkedto); + // I don't think we need this? -- emc3 + //$linea = preg_replace('#&([^amp\;])#is', '&$1', $linea); + if (empty($matchtitle)) { + preg_match('|([^<]*?)|is', $linea, $matchtitle); + } + $pos2 = strpos($linea, $pagelinkedto); + $pos3 = strpos($linea, str_replace('http://www.', 'http://', $pagelinkedto)); + if (is_integer($pos2) || is_integer($pos3)) { + //debug_fwrite($log, 'The page really links to us :)'."\n"); + $pos4 = (is_integer($pos2)) ? $pos2 : $pos3; + $start = $pos4-100; + $context = substr($linea, $start, 250); + $context = str_replace("\n", ' ', $context); + $context = str_replace('&', '&', $context); + } else { + //debug_fwrite($log, 'The page doesn\'t link to us, here\'s an excerpt :'."\n\n".$linea."\n\n"); + } + //} + //debug_fwrite($log, '*****'."\n\n"); + fclose($fp); - if (empty($context)) { - // URL pattern not found - return new IXR_Error(17, 'The source URI does not contain a link to the target URI, and so cannot be used as a source.'); - } + if (!empty($context)) { + // Check if pings are on, inelegant exit + $pingstatus = $wpdb->get_var("SELECT ping_status FROM $wpdb->posts WHERE ID = $post_ID"); + if ('closed' == $pingstatus) die('Sorry, pings are turned off for this post.'); + $pagelinkedfrom = preg_replace('#&([^amp\;])#is', '&$1', $pagelinkedfrom); + $title = (!strlen($matchtitle[1])) ? $pagelinkedfrom : $matchtitle[1]; + $original_context = strip_tags($context); + $context = '[...] '; + $context = htmlspecialchars($original_context); + $context .= ' [...]'; + $original_pagelinkedfrom = $pagelinkedfrom; + $pagelinkedfrom = addslashes($pagelinkedfrom); + $original_title = $title; + $title = addslashes(strip_tags(trim($title))); + $user_ip = $_SERVER['REMOTE_ADDR']; + $user_agent = addslashes($_SERVER['HTTP_USER_AGENT']); + $now = current_time('mysql'); + $now_gmt = current_time('mysql', 1); + if( check_comment($title, '', $pagelinkedfrom, $context, $user_ip, $user_agent) ) { + $approved = 1; + } else { + $approved = 0; + } + $consulta = $wpdb->query("INSERT INTO $wpdb->comments + (comment_post_ID, comment_author, comment_author_url, comment_author_IP, comment_date, comment_date_gmt, comment_content, comment_approved, comment_agent) + VALUES + ($post_ID, '$title', '$pagelinkedfrom', '$user_ip', $now', '$now_gmt', '$context', '$approved', '$user_agent') + "); - // Check if pings are on, inelegant exit - $pingstatus = $wpdb->get_var("SELECT ping_status FROM $wpdb->posts WHERE ID = $post_ID"); - if ('closed' == $pingstatus) { - return new IXR_Error(33, 'The specified target URI cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.'); - } - - - $pagelinkedfrom = preg_replace('#&([^amp\;])#is', '&$1', $pagelinkedfrom); - $title = (!strlen($matchtitle[1])) ? $pagelinkedfrom : $matchtitle[1]; - $original_context = strip_tags($context); - $context = '[...] '; - $context = htmlspecialchars($original_context); - $context .= ' [...]'; - $original_pagelinkedfrom = $pagelinkedfrom; - $pagelinkedfrom = addslashes($pagelinkedfrom); - $original_title = $title; - $title = addslashes(strip_tags(trim($title))); - $user_ip = $_SERVER['REMOTE_ADDR']; - $user_agent = addslashes($_SERVER['HTTP_USER_AGENT']); - $now = current_time('mysql'); - $now_gmt = current_time('mysql', 1); - - // Check if the entry allows pings - if( !check_comment($title, '', $pagelinkedfrom, $context, $user_ip, $user_agent) ) { - return new IXR_Error(49, 'Pingbacks not allowed on this entry.'); - } - - - $consulta = $wpdb->query("INSERT INTO $wpdb->comments - (comment_post_ID, comment_author, comment_author_url, comment_author_IP, comment_date, comment_date_gmt, comment_content, comment_approved, comment_agent, comment_type) - VALUES - ($post_ID, '$title', '$pagelinkedfrom', '$user_ip', '$now', '$now_gmt', '$context', '1', '$user_agent', 'pingback') - "); - - $comment_ID = $wpdb->get_var('SELECT last_insert_id()'); - - if (get_settings('comments_notify')) { - wp_notify_postauthor($comment_ID, 'pingback'); - } - - do_action('pingback_post', $comment_ID); - - return "Pingback from $pagelinkedfrom to $pagelinkedto registered. Keep the web talking! :-)"; - } - - - /* pingback.extensions.getPingbacks returns an array of URLs - that pingbacked the given URL - specs on http://www.aquarionics.com/misc/archives/blogite/0198.html */ - function pingback_extensions_getPingbacks($args) { - - global $wpdb; - - $url = $args; - - $post_ID = url_to_postid($url); - if (!$post_ID) { - // We aren't sure that the resource is available and/or pingback enabled - return new IXR_Error(33, 'The specified target URI cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.'); - } - - $actual_post = wp_get_single_post($post_ID, ARRAY_A); - - if (!$actual_post) { - // No such post = resource not found - return new IXR_Error(32, 'The specified target URI does not exist.'); - } - - $comments = $wpdb->get_results("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = $post_ID"); - - if (!$comments) { - return array(); - } - - $pingbacks = array(); - foreach($comments as $comment) { - if ((strpos($comment->comment_content, '') === 0) - || ('pingback' == $comment->comment_type)) { - $pingbacks[] = $comment->comment_author_url; + $comment_ID = $wpdb->get_var('SELECT last_insert_id()'); + if (get_settings('comments_notify')) + wp_notify_postauthor($comment_ID, 'pingback'); + do_action('pingback_post', $comment_ID); + } else { + // URL pattern not found + $message = "Page linked to: $pagelinkedto\nPage linked from:" + . " $pagelinkedfrom\nTitle: $title\nContext: $context\n\n".$messages[1]; + } + } else { + // We already have a Pingback from this URL + $message = "Sorry, you already did a pingback to $pagelinkedto" + . " from $pagelinkedfrom."; } + } else { + // Post_ID not found + $message = $messages[2]; + //debug_fwrite($log, 'Post doesn\'t exist'."\n"); } - - return $pingbacks; } + return new xmlrpcresp(new xmlrpcval($message)); } +/**** /PingBack functions ****/ -$wp_xmlrpc_server = new wp_xmlrpc_server(); +/**** SERVER FUNCTIONS ARRAY ****/ -?> \ No newline at end of file +$dispatch_map = +array( "blogger.newPost" => +array("function" => "bloggernewpost", + "signature" => $bloggernewpost_sig, + "docstring" => $bloggernewpost_doc), + + +"blogger.editPost" => +array("function" => "bloggereditpost", + "signature" => $bloggereditpost_sig, + "docstring" => $bloggereditpost_doc), + + +"blogger.deletePost" => +array("function" => "bloggerdeletepost", + "signature" => $bloggerdeletepost_sig, + "docstring" => $bloggerdeletepost_doc), + + +"blogger.getUsersBlogs" => +array("function" => "bloggergetusersblogs", + "signature" => $bloggergetusersblogs_sig, + "docstring" => $bloggergetusersblogs_doc), + +"blogger.getUserInfo" => +array("function" => "bloggergetuserinfo", + "signature" => $bloggergetuserinfo_sig, + "docstring" => $bloggergetuserinfo_doc), + +"blogger.getPost" => +array("function" => "bloggergetpost", + "signature" => $bloggergetpost_sig, + "docstring" => $bloggergetpost_doc), + +"blogger.getRecentPosts" => +array("function" => "bloggergetrecentposts", + "signature" => $bloggergetrecentposts_sig, + "docstring" => $bloggergetrecentposts_doc), + +"blogger.getTemplate" => +array("function" => "bloggergettemplate", + "signature" => $bloggergettemplate_sig, + "docstring" => $bloggergettemplate_doc), + +"blogger.setTemplate" => +array("function" => "bloggersettemplate", + "signature" => $bloggersettemplate_sig, + "docstring" => $bloggersettemplate_doc), + +"metaWeblog.newPost" => +array("function" => "mwnewpost", + "signature" => $mwnewpost_sig, + "docstring" => $mwnewpost_doc), + +"metaWeblog.editPost" => +array("function" => "mweditpost", + "signature" => $mweditpost_sig, + "docstring" => $mweditpost_doc), + +"metaWeblog.getPost" => +array("function" => "mwgetpost", + "signature" => $mwgetpost_sig, + "docstring" => $mwgetpost_doc), + +"metaWeblog.getRecentPosts" => +array("function" => "mwrecentposts", + "signature" => $mwrecentposts_sig, + "docstring" => $mwrecentposts_doc), + +"metaWeblog.getCategories" => +array("function" => "mwgetcats", + "signature" => $mwgetcats_sig, + "docstring" => $mwgetcats_doc), + +"metaWeblog.newMediaObject" => +array("function" => "mwnewmedia", + "signature" => $mwnewmedia_sig, + "docstring" => $mwnewmedia_doc), + +"mt.getCategoryList" => +array("function" => "mwgetcats", + "signature" => $mwgetcats_sig, + "docstring" => $mwgetcats_doc), + +"mt.getPostCategories" => +array("function" => "mt_getPostCategories", + "signature" => $mt_getPostCategories_sig, + "docstring" => $mt_getPostCategories_doc), + +"mt.setPostCategories" => +array("function" => "mt_setPostCategories", + "signature" => $mt_setPostCategories_sig, + "docstring" => $mt_setPostCategories_doc), + +"mt.publishPost" => +array("function" => "mt_publishPost", + "signature" => $mt_publishPost_sig, + "docstring" => $mt_publishPost_doc), + +"mt.supportedMethods" => +array("function" => "mt_supportedMethods", + "signature" => $mt_supportedMethods_sig, + "docstring" => $mt_supportedMethods_doc), + +"mt.supportedTextFilters" => +array("function" => "mt_supportedTextFilters", + "signature" => $mt_supportedTextFilters_sig, + "docstring" => $mt_supportedTextFilters_doc), + +"mt.getRecentPostTitles" => +array("function" => "mt_getRecentPostTitles", + "signature" => $mt_getRecentPostTitles_sig, + "docstring" => $mt_getRecentPostTitles_doc), + +"mt.getTrackbackPings" => +array("function" => "mt_getTrackbackPings", + "signature" => $mt_getTrackbackPings_sig, + "docstring" => $mt_getTrackbackPings_doc), + +"b2.newPost" => +array("function" => "b2newpost", + "signature" => $wpnewpost_sig, + "docstring" => $wpnewpost_doc), +"b2.getCategories" => +array("function" => "b2getcategories", + "signature" => $wpgetcategories_sig, + "docstring" => $wpgetcategories_doc), + +"b2.ping" => +array("function" => "b2ping", + "signature" => $wpping_sig, + "docstring" => $wpping_doc), + +"pingback.ping" => +array("function" => "pingback_ping", + "signature" => $pingback_ping_sig, + "docstring" => $pingback_ping_doc), + +"b2.getPostURL" => +array("function" => "pingback_getPostURL", + "signature" => $wp_getPostURL_sig, + "docstring" => $wp_getPostURL_doc), +); + +$s = new xmlrpc_server($dispatch_map); + +?>