X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/wordpress.git/blobdiff_plain/76aea3697c6043c1613370f172395b4f65ee71f0..d3b1ea255664edd2deef17f900a655613d20820d:/xmlrpc.php diff --git a/xmlrpc.php b/xmlrpc.php index e52e4546..55279426 100644 --- a/xmlrpc.php +++ b/xmlrpc.php @@ -99,14 +99,32 @@ if ( isset($HTTP_RAW_POST_DATA) ) logIO("I", $HTTP_RAW_POST_DATA); /** - * @internal - * Left undocumented to work on later. If you want to finish, then please do so. + * WordPress XMLRPC server implementation. + * + * Implements compatability for Blogger API, MetaWeblog API, MovableType, and + * pingback. Additional WordPress API for managing comments, pages, posts, + * options, etc. + * + * Since WordPress 2.6.0, WordPress XMLRPC server can be disabled in the + * administration panels. * * @package WordPress * @subpackage Publishing + * @since 1.5.0 */ class wp_xmlrpc_server extends IXR_Server { + /** + * Register all of the XMLRPC methods that XMLRPC server understands. + * + * PHP4 constructor and sets up server and method property. Passes XMLRPC + * methods through the 'xmlrpc_methods' filter to allow plugins to extend + * or replace XMLRPC methods. + * + * @since 1.5.0 + * + * @return wp_xmlrpc_server + */ function wp_xmlrpc_server() { $this->methods = array( // WordPress API @@ -119,6 +137,7 @@ class wp_xmlrpc_server extends IXR_Server { 'wp.getPageList' => 'this:wp_getPageList', 'wp.getAuthors' => 'this:wp_getAuthors', 'wp.getCategories' => 'this:mw_getCategories', // Alias + 'wp.getTags' => 'this:wp_getTags', 'wp.newCategory' => 'this:wp_newCategory', 'wp.deleteCategory' => 'this:wp_deleteCategory', 'wp.suggestCategories' => 'this:wp_suggestCategories', @@ -129,6 +148,12 @@ class wp_xmlrpc_server extends IXR_Server { 'wp.getPageTemplates' => 'this:wp_getPageTemplates', 'wp.getOptions' => 'this:wp_getOptions', 'wp.setOptions' => 'this:wp_setOptions', + 'wp.getComment' => 'this:wp_getComment', + 'wp.getComments' => 'this:wp_getComments', + 'wp.deleteComment' => 'this:wp_deleteComment', + 'wp.editComment' => 'this:wp_editComment', + 'wp.newComment' => 'this:wp_newComment', + 'wp.getCommentStatusList' => 'this:wp_getCommentStatusList', // Blogger API 'blogger.getUsersBlogs' => 'this:blogger_getUsersBlogs', @@ -179,16 +204,43 @@ class wp_xmlrpc_server extends IXR_Server { $this->IXR_Server($this->methods); } + /** + * Test XMLRPC API by saying, "Hello!" to client. + * + * @since 1.5.0 + * + * @param array $args Method Parameters. + * @return string + */ function sayHello($args) { return 'Hello!'; } + /** + * Test XMLRPC API by adding two numbers for client. + * + * @since 1.5.0 + * + * @param array $args Method Parameters. + * @return int + */ function addTwoNumbers($args) { $number1 = $args[0]; $number2 = $args[1]; return $number1 + $number2; } + /** + * Check user's credentials. + * + * @since 1.5.0 + * + * @param string $user_login User's username. + * @param string $user_pass User's password. + * @return bool Whether authentication passed. + * @deprecated use wp_xmlrpc_server::login + * @see wp_xmlrpc_server::login + */ function login_pass_ok($user_login, $user_pass) { if ( !get_option( 'enable_xmlrpc' ) ) { $this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this blog. An admin user can enable them at %s'), admin_url('options-writing.php') ) ); @@ -202,6 +254,40 @@ class wp_xmlrpc_server extends IXR_Server { return true; } + /** + * Log user in. + * + * @since 2.8 + * + * @param string $username User's username. + * @param string $password User's password. + * @return mixed WP_User object if authentication passed, false otherwise + */ + function login($username, $password) { + if ( !get_option( 'enable_xmlrpc' ) ) { + $this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this blog. An admin user can enable them at %s'), admin_url('options-writing.php') ) ); + return false; + } + + $user = wp_authenticate($username, $password); + + if (is_wp_error($user)) { + $this->error = new IXR_Error(403, __('Bad login/pass combination.')); + return false; + } + + set_current_user( $user->ID ); + return $user; + } + + /** + * Sanitize string or array of strings for database. + * + * @since 1.5.2 + * + * @param string|array $array Sanitize single string or array of strings. + * @return string|array Type matches $array and sanitized for the database. + */ function escape(&$array) { global $wpdb; @@ -221,6 +307,14 @@ class wp_xmlrpc_server extends IXR_Server { } } + /** + * Retrieve custom fields for post. + * + * @since 2.5.0 + * + * @param int $post_id Post ID. + * @return array Custom fields, if exist. + */ function get_custom_fields($post_id) { $post_id = (int) $post_id; @@ -242,6 +336,14 @@ class wp_xmlrpc_server extends IXR_Server { return $custom_fields; } + /** + * Set custom fields for post. + * + * @since 2.5.0 + * + * @param int $post_id Post ID. + * @param array $fields Custom fields. + */ function set_custom_fields($post_id, $fields) { $post_id = (int) $post_id; @@ -264,6 +366,13 @@ class wp_xmlrpc_server extends IXR_Server { } } + /** + * Setup blog options property. + * + * Passes property through 'xmlrpc_blog_options' filter. + * + * @since 2.6.0 + */ function initialise_blog_option_info( ) { global $wp_version; @@ -317,8 +426,12 @@ class wp_xmlrpc_server extends IXR_Server { } /** - * WordPress XML-RPC API - * wp_getUsersBlogs + * Retrieve the blogs of the user. + * + * @since 2.6.0 + * + * @param array $args Method parameters. + * @return array */ function wp_getUsersBlogs( $args ) { // If this isn't on WPMU then just use blogger_getUsersBlogs @@ -332,19 +445,18 @@ class wp_xmlrpc_server extends IXR_Server { $username = $args[0]; $password = $args[1]; - if( !$this->login_pass_ok( $username, $password ) ) + if ( !$user = $this->login($username, $password) ) { return $this->error; + } do_action( 'xmlrpc_call', 'wp.getUsersBlogs' ); - $user = set_current_user( 0, $username ); - $blogs = (array) get_blogs_of_user( $user->ID ); $struct = array( ); foreach( $blogs as $blog ) { // Don't include blogs that aren't hosted at this site - if( $blog->site_id != 1 ) + if( $blog->site_id != $current_site->id ) continue; $blog_id = $blog->userblog_id; @@ -356,16 +468,22 @@ class wp_xmlrpc_server extends IXR_Server { 'url' => get_option( 'home' ) . '/', 'blogid' => $blog_id, 'blogName' => get_option( 'blogname' ), - 'xmlrpc' => get_option( 'home' ) . '/xmlrpc.php' + 'xmlrpc' => site_url( 'xmlrpc.php' ) ); + + restore_current_blog( ); } return $struct; } /** - * WordPress XML-RPC API - * wp_getPage + * Retrieve page. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return array */ function wp_getPage($args) { $this->escape($args); @@ -375,13 +493,12 @@ class wp_xmlrpc_server extends IXR_Server { $username = $args[2]; $password = $args[3]; - if(!$this->login_pass_ok($username, $password)) { - return($this->error); + if ( !$user = $this->login($username, $password) ) { + return $this->error; } - set_current_user( 0, $username ); if( !current_user_can( 'edit_page', $page_id ) ) - return new IXR_Error( 401, __( 'Sorry, you can not edit this page.' ) ); + return new IXR_Error( 401, __( 'Sorry, you cannot edit this page.' ) ); do_action('xmlrpc_call', 'wp.getPage'); @@ -402,12 +519,12 @@ class wp_xmlrpc_server extends IXR_Server { } // Determine comment and ping settings. - $allow_comments = ("open" == $page->comment_status) ? 1 : 0; - $allow_pings = ("open" == $page->ping_status) ? 1 : 0; + $allow_comments = comments_open($page->ID) ? 1 : 0; + $allow_pings = pings_open($page->ID) ? 1 : 0; // Format page date. - $page_date = mysql2date("Ymd\TH:i:s", $page->post_date); - $page_date_gmt = mysql2date("Ymd\TH:i:s", $page->post_date_gmt); + $page_date = mysql2date("Ymd\TH:i:s", $page->post_date, false); + $page_date_gmt = mysql2date("Ymd\TH:i:s", $page->post_date_gmt, false); // Pull the categories info together. $categories = array(); @@ -458,8 +575,12 @@ class wp_xmlrpc_server extends IXR_Server { } /** - * WordPress XML-RPC API - * wp_getPages + * Retrieve Pages. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return array */ function wp_getPages($args) { $this->escape($args); @@ -467,19 +588,23 @@ class wp_xmlrpc_server extends IXR_Server { $blog_id = (int) $args[0]; $username = $args[1]; $password = $args[2]; + $num_pages = (int) $args[3]; - if(!$this->login_pass_ok($username, $password)) { - return($this->error); + if ( !$user = $this->login($username, $password) ) { + return $this->error; } - set_current_user( 0, $username ); if( !current_user_can( 'edit_pages' ) ) - return new IXR_Error( 401, __( 'Sorry, you can not edit pages.' ) ); + return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) ); do_action('xmlrpc_call', 'wp.getPages'); - // Lookup info on pages. - $pages = get_pages(); + $page_limit = 10; + if( isset( $num_pages ) ) { + $page_limit = $num_pages; + } + + $pages = get_posts( array('post_type' => 'page', 'post_status' => 'all', 'numberposts' => $page_limit) ); $num_pages = count($pages); // If we have pages, put together their info. @@ -502,8 +627,12 @@ class wp_xmlrpc_server extends IXR_Server { } /** - * WordPress XML-RPC API - * wp_newPage + * Create new page. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return unknown */ function wp_newPage($args) { // Items not escaped here will be escaped in newPost. @@ -512,17 +641,15 @@ class wp_xmlrpc_server extends IXR_Server { $page = $args[3]; $publish = $args[4]; - if(!$this->login_pass_ok($username, $password)) { - return($this->error); + if ( !$user = $this->login($username, $password) ) { + return $this->error; } do_action('xmlrpc_call', 'wp.newPage'); - // Set the user context and check if they are allowed - // to add new pages. - $user = set_current_user(0, $username); + // Make sure the user is allowed to add new pages. if(!current_user_can("publish_pages")) { - return(new IXR_Error(401, __("Sorry, you can not add new pages."))); + return(new IXR_Error(401, __("Sorry, you cannot add new pages."))); } // Mark this as content for a page. @@ -533,8 +660,12 @@ class wp_xmlrpc_server extends IXR_Server { } /** - * WordPress XML-RPC API - * wp_deletePage + * Delete page. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return bool True, if success. */ function wp_deletePage($args) { $this->escape($args); @@ -544,8 +675,8 @@ class wp_xmlrpc_server extends IXR_Server { $password = $args[2]; $page_id = (int) $args[3]; - if(!$this->login_pass_ok($username, $password)) { - return($this->error); + if ( !$user = $this->login($username, $password) ) { + return $this->error; } do_action('xmlrpc_call', 'wp.deletePage'); @@ -560,8 +691,7 @@ class wp_xmlrpc_server extends IXR_Server { return(new IXR_Error(404, __("Sorry, no such page."))); } - // Set the user context and make sure they can delete pages. - set_current_user(0, $username); + // Make sure the user can delete pages. if(!current_user_can("delete_page", $page_id)) { return(new IXR_Error(401, __("Sorry, you do not have the right to delete this page."))); } @@ -576,8 +706,12 @@ class wp_xmlrpc_server extends IXR_Server { } /** - * WordPress XML-RPC API - * wp_editPage + * Edit page. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return unknown */ function wp_editPage($args) { // Items not escaped here will be escaped in editPost. @@ -588,8 +722,8 @@ class wp_xmlrpc_server extends IXR_Server { $content = $args[4]; $publish = $args[5]; - if(!$this->login_pass_ok($username, $password)) { - return($this->error); + if ( !$user = $this->login($username, $password) ) { + return $this->error; } do_action('xmlrpc_call', 'wp.editPage'); @@ -603,8 +737,7 @@ class wp_xmlrpc_server extends IXR_Server { return(new IXR_Error(404, __("Sorry, no such page."))); } - // Set the user context and make sure they are allowed to edit pages. - set_current_user(0, $username); + // Make sure the user is allowed to edit pages. if(!current_user_can("edit_page", $page_id)) { return(new IXR_Error(401, __("Sorry, you do not have the right to edit this page."))); } @@ -626,8 +759,12 @@ class wp_xmlrpc_server extends IXR_Server { } /** - * WordPress XML-RPC API - * wp_getPageList + * Retrieve page list. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return unknown */ function wp_getPageList($args) { global $wpdb; @@ -638,13 +775,12 @@ class wp_xmlrpc_server extends IXR_Server { $username = $args[1]; $password = $args[2]; - if(!$this->login_pass_ok($username, $password)) { - return($this->error); + if ( !$user = $this->login($username, $password) ) { + return $this->error; } - set_current_user( 0, $username ); if( !current_user_can( 'edit_pages' ) ) - return new IXR_Error( 401, __( 'Sorry, you can not edit pages.' ) ); + return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) ); do_action('xmlrpc_call', 'wp.getPageList'); @@ -663,8 +799,8 @@ class wp_xmlrpc_server extends IXR_Server { // The date needs to be formated properly. $num_pages = count($page_list); for($i = 0; $i < $num_pages; $i++) { - $post_date = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date); - $post_date_gmt = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date_gmt); + $post_date = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date, false); + $post_date_gmt = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date_gmt, false); $page_list[$i]->dateCreated = new IXR_Date($post_date); $page_list[$i]->date_created_gmt = new IXR_Date($post_date_gmt); @@ -677,8 +813,12 @@ class wp_xmlrpc_server extends IXR_Server { } /** - * WordPress XML-RPC API - * wp_getAuthors + * Retrieve authors list. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return array */ function wp_getAuthors($args) { @@ -688,14 +828,13 @@ class wp_xmlrpc_server extends IXR_Server { $username = $args[1]; $password = $args[2]; - if(!$this->login_pass_ok($username, $password)) { - return($this->error); + if ( !$user = $this->login($username, $password) ) { + return $this->error; } - set_current_user(0, $username); if(!current_user_can("edit_posts")) { - return(new IXR_Error(401, __("Sorry, you can not edit posts on this blog."))); - } + return(new IXR_Error(401, __("Sorry, you cannot edit posts on this blog."))); + } do_action('xmlrpc_call', 'wp.getAuthors'); @@ -712,8 +851,55 @@ class wp_xmlrpc_server extends IXR_Server { } /** - * WordPress XML-RPC API - * wp_newCategory + * Get list of all tags + * + * @since 2.7 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getTags( $args ) { + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) { + return $this->error; + } + + if( !current_user_can( 'edit_posts' ) ) { + return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this blog in order to view tags.' ) ); + } + + do_action( 'xmlrpc_call', 'wp.getKeywords' ); + + $tags = array( ); + + if( $all_tags = get_tags( ) ) { + foreach( (array) $all_tags as $tag ) { + $struct['tag_id'] = $tag->term_id; + $struct['name'] = $tag->name; + $struct['count'] = $tag->count; + $struct['slug'] = $tag->slug; + $struct['html_url'] = esc_html( get_tag_link( $tag->term_id ) ); + $struct['rss_url'] = esc_html( get_tag_feed_link( $tag->term_id ) ); + + $tags[] = $struct; + } + } + + return $tags; + } + + /** + * Create new category. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return int Category ID. */ function wp_newCategory($args) { $this->escape($args); @@ -723,15 +909,13 @@ class wp_xmlrpc_server extends IXR_Server { $password = $args[2]; $category = $args[3]; - if(!$this->login_pass_ok($username, $password)) { - return($this->error); + if ( !$user = $this->login($username, $password) ) { + return $this->error; } do_action('xmlrpc_call', 'wp.newCategory'); - // Set the user context and make sure they are - // allowed to add a category. - set_current_user(0, $username); + // Make sure the user is allowed to add a category. if(!current_user_can("manage_categories")) { return(new IXR_Error(401, __("Sorry, you do not have the right to add a category."))); } @@ -768,8 +952,12 @@ class wp_xmlrpc_server extends IXR_Server { } /** - * WordPress XML-RPC API - * wp_deleteCategory + * Remove category. + * + * @since 2.5.0 + * + * @param array $args Method parameters. + * @return mixed See {@link wp_delete_category()} for return info. */ function wp_deleteCategory($args) { $this->escape($args); @@ -779,13 +967,12 @@ class wp_xmlrpc_server extends IXR_Server { $password = $args[2]; $category_id = (int) $args[3]; - if( !$this->login_pass_ok( $username, $password ) ) { + if ( !$user = $this->login($username, $password) ) { return $this->error; } do_action('xmlrpc_call', 'wp.deleteCategory'); - set_current_user(0, $username); if( !current_user_can("manage_categories") ) { return new IXR_Error( 401, __( "Sorry, you do not have the right to delete a category." ) ); } @@ -793,10 +980,13 @@ class wp_xmlrpc_server extends IXR_Server { return wp_delete_category( $category_id ); } - /** - * WordPress XML-RPC API - * wp_suggestCategories + * Retrieve category list. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return array */ function wp_suggestCategories($args) { $this->escape($args); @@ -807,11 +997,10 @@ class wp_xmlrpc_server extends IXR_Server { $category = $args[3]; $max_results = (int) $args[4]; - if(!$this->login_pass_ok($username, $password)) { - return($this->error); + if ( !$user = $this->login($username, $password) ) { + return $this->error; } - set_current_user(0, $username); if( !current_user_can( 'edit_posts' ) ) return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts to this blog in order to view categories.' ) ); @@ -829,6 +1018,348 @@ class wp_xmlrpc_server extends IXR_Server { return($category_suggestions); } + /** + * Retrieve comment. + * + * @since 2.7.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getComment($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $comment_id = (int) $args[3]; + + if ( !$user = $this->login($username, $password) ) { + return $this->error; + } + + if ( !current_user_can( 'moderate_comments' ) ) + return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this blog.' ) ); + + do_action('xmlrpc_call', 'wp.getComment'); + + if ( ! $comment = get_comment($comment_id) ) + return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); + + // Format page date. + $comment_date = mysql2date("Ymd\TH:i:s", $comment->comment_date, false); + $comment_date_gmt = mysql2date("Ymd\TH:i:s", $comment->comment_date_gmt, false); + + if ( 0 == $comment->comment_approved ) + $comment_status = 'hold'; + else if ( 'spam' == $comment->comment_approved ) + $comment_status = 'spam'; + else if ( 1 == $comment->comment_approved ) + $comment_status = 'approve'; + else + $comment_status = $comment->comment_approved; + + $link = get_comment_link($comment); + + $comment_struct = array( + "date_created_gmt" => new IXR_Date($comment_date_gmt), + "user_id" => $comment->user_id, + "comment_id" => $comment->comment_ID, + "parent" => $comment->comment_parent, + "status" => $comment_status, + "content" => $comment->comment_content, + "link" => $link, + "post_id" => $comment->comment_post_ID, + "post_title" => get_the_title($comment->comment_post_ID), + "author" => $comment->comment_author, + "author_url" => $comment->comment_author_url, + "author_email" => $comment->comment_author_email, + "author_ip" => $comment->comment_author_IP, + "type" => $comment->comment_type, + ); + + return $comment_struct; + } + + /** + * Retrieve comments. + * + * @since 2.7.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getComments($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $struct = $args[3]; + + if ( !$user = $this->login($username, $password) ) { + return $this->error; + } + + if ( !current_user_can( 'moderate_comments' ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit comments.' ) ); + + do_action('xmlrpc_call', 'wp.getComments'); + + if ( isset($struct['status']) ) + $status = $struct['status']; + else + $status = ''; + + $post_id = ''; + if ( isset($struct['post_id']) ) + $post_id = absint($struct['post_id']); + + $offset = 0; + if ( isset($struct['offset']) ) + $offset = absint($struct['offset']); + + $number = 10; + if ( isset($struct['number']) ) + $number = absint($struct['number']); + + $comments = get_comments( array('status' => $status, 'post_id' => $post_id, 'offset' => $offset, 'number' => $number ) ); + $num_comments = count($comments); + + if ( ! $num_comments ) + return array(); + + $comments_struct = array(); + + for ( $i = 0; $i < $num_comments; $i++ ) { + $comment = wp_xmlrpc_server::wp_getComment(array( + $blog_id, $username, $password, $comments[$i]->comment_ID, + )); + $comments_struct[] = $comment; + } + + return $comments_struct; + } + + /** + * Remove comment. + * + * @since 2.7.0 + * + * @param array $args Method parameters. + * @return mixed {@link wp_delete_comment()} + */ + function wp_deleteComment($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $comment_ID = (int) $args[3]; + + if ( !$user = $this->login($username, $password) ) { + return $this->error; + } + + if ( !current_user_can( 'moderate_comments' ) ) + return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this blog.' ) ); + + do_action('xmlrpc_call', 'wp.deleteComment'); + + if ( ! get_comment($comment_ID) ) + return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); + + return wp_delete_comment($comment_ID); + } + + /** + * Edit comment. + * + * @since 2.7.0 + * + * @param array $args Method parameters. + * @return bool True, on success. + */ + function wp_editComment($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $comment_ID = (int) $args[3]; + $content_struct = $args[4]; + + if ( !$user = $this->login($username, $password) ) { + return $this->error; + } + + if ( !current_user_can( 'moderate_comments' ) ) + return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this blog.' ) ); + + do_action('xmlrpc_call', 'wp.editComment'); + + if ( ! get_comment($comment_ID) ) + return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); + + if ( isset($content_struct['status']) ) { + $statuses = get_comment_statuses(); + $statuses = array_keys($statuses); + + if ( ! in_array($content_struct['status'], $statuses) ) + return new IXR_Error( 401, __( 'Invalid comment status.' ) ); + $comment_approved = $content_struct['status']; + } + + // Do some timestamp voodoo + if ( !empty( $content_struct['date_created_gmt'] ) ) { + $dateCreated = str_replace( 'Z', '', $content_struct['date_created_gmt']->getIso() ) . 'Z'; // We know this is supposed to be GMT, so we're going to slap that Z on there by force + $comment_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); + $comment_date_gmt = iso8601_to_datetime($dateCreated, GMT); + } + + if ( isset($content_struct['content']) ) + $comment_content = $content_struct['content']; + + if ( isset($content_struct['author']) ) + $comment_author = $content_struct['author']; + + if ( isset($content_struct['author_url']) ) + $comment_author_url = $content_struct['author_url']; + + if ( isset($content_struct['author_email']) ) + $comment_author_email = $content_struct['author_email']; + + // We've got all the data -- post it: + $comment = compact('comment_ID', 'comment_content', 'comment_approved', 'comment_date', 'comment_date_gmt', 'comment_author', 'comment_author_email', 'comment_author_url'); + + $result = wp_update_comment($comment); + if ( is_wp_error( $result ) ) + return new IXR_Error(500, $result->get_error_message()); + + if ( !$result ) + return new IXR_Error(500, __('Sorry, the comment could not be edited. Something wrong happened.')); + + return true; + } + + /** + * Create new comment. + * + * @since 2.7.0 + * + * @param array $args Method parameters. + * @return mixed {@link wp_new_comment()} + */ + function wp_newComment($args) { + global $wpdb; + + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $post = $args[3]; + $content_struct = $args[4]; + + $allow_anon = apply_filters('xmlrpc_allow_anonymous_comments', false); + + $user = $this->login($username, $password); + + if ( !$user ) { + $logged_in = false; + if ( $allow_anon && get_option('comment_registration') ) + return new IXR_Error( 403, __( 'You must be registered to comment' ) ); + else if ( !$allow_anon ) + return $this->error; + } else { + $logged_in = true; + } + + if ( is_numeric($post) ) + $post_id = absint($post); + else + $post_id = url_to_postid($post); + + if ( ! $post_id ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( ! get_post($post_id) ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + $comment['comment_post_ID'] = $post_id; + + if ( $logged_in ) { + $comment['comment_author'] = $wpdb->escape( $user->display_name ); + $comment['comment_author_email'] = $wpdb->escape( $user->user_email ); + $comment['comment_author_url'] = $wpdb->escape( $user->user_url ); + $comment['user_ID'] = $user->ID; + } else { + $comment['comment_author'] = ''; + if ( isset($content_struct['author']) ) + $comment['comment_author'] = $content_struct['author']; + + $comment['comment_author_email'] = ''; + if ( isset($content_struct['author_email']) ) + $comment['comment_author_email'] = $content_struct['author_email']; + + $comment['comment_author_url'] = ''; + if ( isset($content_struct['author_url']) ) + $comment['comment_author_url'] = $content_struct['author_url']; + + $comment['user_ID'] = 0; + + if ( get_option('require_name_email') ) { + if ( 6 > strlen($comment['comment_author_email']) || '' == $comment['comment_author'] ) + return new IXR_Error( 403, __( 'Comment author name and email are required' ) ); + elseif ( !is_email($comment['comment_author_email']) ) + return new IXR_Error( 403, __( 'A valid email address is required' ) ); + } + } + + $comment['comment_parent'] = isset($content_struct['comment_parent']) ? absint($content_struct['comment_parent']) : 0; + + $comment['comment_content'] = $content_struct['content']; + + do_action('xmlrpc_call', 'wp.newComment'); + + return wp_new_comment($comment); + } + + /** + * Retrieve all of the comment status. + * + * @since 2.7.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getCommentStatusList($args) { + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) { + return $this->error; + } + + if ( !current_user_can( 'moderate_comments' ) ) + return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) ); + + do_action('xmlrpc_call', 'wp.getCommentStatusList'); + + return get_comment_statuses( ); + } + + /** + * Retrieve comment count. + * + * @since 2.5.0 + * + * @param array $args Method parameters. + * @return array + */ function wp_getCommentCount( $args ) { $this->escape($args); @@ -837,11 +1368,10 @@ class wp_xmlrpc_server extends IXR_Server { $password = $args[2]; $post_id = (int) $args[3]; - if( !$this->login_pass_ok( $username, $password ) ) { + if ( !$user = $this->login($username, $password) ) { return $this->error; } - set_current_user( 0, $username ); if( !current_user_can( 'edit_posts' ) ) { return new IXR_Error( 403, __( 'You are not allowed access to details about comments.' ) ); } @@ -857,7 +1387,14 @@ class wp_xmlrpc_server extends IXR_Server { ); } - + /** + * Retrieve post statuses. + * + * @since 2.5.0 + * + * @param array $args Method parameters. + * @return array + */ function wp_getPostStatusList( $args ) { $this->escape( $args ); @@ -865,11 +1402,10 @@ class wp_xmlrpc_server extends IXR_Server { $username = $args[1]; $password = $args[2]; - if( !$this->login_pass_ok( $username, $password ) ) { + if ( !$user = $this->login($username, $password) ) { return $this->error; } - set_current_user( 0, $username ); if( !current_user_can( 'edit_posts' ) ) { return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) ); } @@ -879,7 +1415,14 @@ class wp_xmlrpc_server extends IXR_Server { return get_post_statuses( ); } - + /** + * Retrieve page statuses. + * + * @since 2.5.0 + * + * @param array $args Method parameters. + * @return array + */ function wp_getPageStatusList( $args ) { $this->escape( $args ); @@ -887,11 +1430,10 @@ class wp_xmlrpc_server extends IXR_Server { $username = $args[1]; $password = $args[2]; - if( !$this->login_pass_ok( $username, $password ) ) { + if ( !$user = $this->login($username, $password) ) { return $this->error; } - set_current_user( 0, $username ); if( !current_user_can( 'edit_posts' ) ) { return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) ); } @@ -901,6 +1443,14 @@ class wp_xmlrpc_server extends IXR_Server { return get_page_statuses( ); } + /** + * Retrieve page templates. + * + * @since 2.6.0 + * + * @param array $args Method parameters. + * @return array + */ function wp_getPageTemplates( $args ) { $this->escape( $args ); @@ -908,11 +1458,10 @@ class wp_xmlrpc_server extends IXR_Server { $username = $args[1]; $password = $args[2]; - if( !$this->login_pass_ok( $username, $password ) ) { + if ( !$user = $this->login($username, $password) ) { return $this->error; } - set_current_user( 0, $username ); if( !current_user_can( 'edit_pages' ) ) { return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) ); } @@ -923,6 +1472,14 @@ class wp_xmlrpc_server extends IXR_Server { return $templates; } + /** + * Retrieve blog options. + * + * @since 2.6.0 + * + * @param array $args Method parameters. + * @return array + */ function wp_getOptions( $args ) { $this->escape( $args ); @@ -931,10 +1488,9 @@ class wp_xmlrpc_server extends IXR_Server { $password = $args[2]; $options = (array) $args[3]; - if( !$this->login_pass_ok( $username, $password ) ) + if ( !$user = $this->login($username, $password) ) { return $this->error; - - $user = set_current_user( 0, $username ); + } // If no specific options where asked for, return all of them if (count( $options ) == 0 ) { @@ -944,6 +1500,14 @@ class wp_xmlrpc_server extends IXR_Server { return $this->_getOptions($options); } + /** + * Retrieve blog options value from list. + * + * @since 2.6.0 + * + * @param array $options Options to retrieve. + * @return array + */ function _getOptions($options) { $data = array( ); @@ -962,6 +1526,14 @@ class wp_xmlrpc_server extends IXR_Server { return $data; } + /** + * Update blog options. + * + * @since 2.6.0 + * + * @param array $args Method parameters. + * @return unknown + */ function wp_setOptions( $args ) { $this->escape( $args ); @@ -970,10 +1542,10 @@ class wp_xmlrpc_server extends IXR_Server { $password = $args[2]; $options = (array) $args[3]; - if( !$this->login_pass_ok( $username, $password ) ) + if ( !$user = $this->login($username, $password) ) { return $this->error; + } - $user = set_current_user( 0, $username ); if( !current_user_can( 'manage_options' ) ) return new IXR_Error( 403, __( 'You are not allowed to update options.' ) ); @@ -995,26 +1567,33 @@ class wp_xmlrpc_server extends IXR_Server { return $this->_getOptions($option_names); } - /* Blogger API functions + /* Blogger API functions. * specs on http://plant.blogger.com/api and http://groups.yahoo.com/group/bloggerDev/ */ - - /* blogger.getUsersBlogs will make more sense once we support multiple blogs */ + /** + * Retrieve blogs that user owns. + * + * Will make more sense once we support multiple blogs. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ function blogger_getUsersBlogs($args) { $this->escape($args); - $user_login = $args[1]; - $user_pass = $args[2]; + $username = $args[1]; + $password = $args[2]; - if (!$this->login_pass_ok($user_login, $user_pass)) { + if ( !$user = $this->login($username, $password) ) { return $this->error; } do_action('xmlrpc_call', 'blogger.getUsersBlogs'); - set_current_user(0, $user_login); $is_admin = current_user_can('manage_options'); $struct = array( @@ -1022,61 +1601,71 @@ class wp_xmlrpc_server extends IXR_Server { 'url' => get_option('home') . '/', 'blogid' => '1', 'blogName' => get_option('blogname'), - 'xmlrpc' => get_option('home') . '/xmlrpc.php', + 'xmlrpc' => site_url( 'xmlrpc.php' ) ); return array($struct); } - - /* blogger.getUsersInfo gives your client some info about you, so you don't have to */ + /** + * Retrieve user's data. + * + * Gives your client some info about you, so you don't have to. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ function blogger_getUserInfo($args) { $this->escape($args); - $user_login = $args[1]; - $user_pass = $args[2]; + $username = $args[1]; + $password = $args[2]; - if (!$this->login_pass_ok($user_login, $user_pass)) { + if ( !$user = $this->login($username, $password) ) { return $this->error; } - set_current_user( 0, $user_login ); if( !current_user_can( 'edit_posts' ) ) return new IXR_Error( 401, __( 'Sorry, you do not have access to user data on this blog.' ) ); do_action('xmlrpc_call', 'blogger.getUserInfo'); - $user_data = get_userdatabylogin($user_login); - $struct = array( - 'nickname' => $user_data->nickname, - 'userid' => $user_data->ID, - 'url' => $user_data->user_url, - 'lastname' => $user_data->last_name, - 'firstname' => $user_data->first_name + 'nickname' => $user->nickname, + 'userid' => $user->ID, + 'url' => $user->user_url, + 'lastname' => $user->last_name, + 'firstname' => $user->first_name ); return $struct; } - - /* blogger.getPost ...gets a post */ + /** + * Retrieve post. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ function blogger_getPost($args) { $this->escape($args); $post_ID = (int) $args[1]; - $user_login = $args[2]; - $user_pass = $args[3]; + $username = $args[2]; + $password = $args[3]; - if (!$this->login_pass_ok($user_login, $user_pass)) { + if ( !$user = $this->login($username, $password) ) { return $this->error; } - set_current_user( 0, $user_login ); if( !current_user_can( 'edit_post', $post_ID ) ) - return new IXR_Error( 401, __( 'Sorry, you can not edit this post.' ) ); + return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) ); do_action('xmlrpc_call', 'blogger.getPost'); @@ -1090,7 +1679,7 @@ class wp_xmlrpc_server extends IXR_Server { $struct = array( 'userid' => $post_data['post_author'], - 'dateCreated' => new IXR_Date(mysql2date('Ymd\TH:i:s', $post_data['post_date'])), + 'dateCreated' => new IXR_Date(mysql2date('Ymd\TH:i:s', $post_data['post_date'], false)), 'content' => $content, 'postid' => $post_data['ID'] ); @@ -1098,18 +1687,24 @@ class wp_xmlrpc_server extends IXR_Server { return $struct; } - - /* blogger.getRecentPosts ...gets recent posts */ + /** + * Retrieve list of recent posts. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ function blogger_getRecentPosts($args) { $this->escape($args); $blog_ID = (int) $args[1]; /* though we don't use it yet */ - $user_login = $args[2]; - $user_pass = $args[3]; + $username = $args[2]; + $password = $args[3]; $num_posts = $args[4]; - if (!$this->login_pass_ok($user_login, $user_pass)) { + if ( !$user = $this->login($username, $password) ) { return $this->error; } @@ -1117,8 +1712,6 @@ class wp_xmlrpc_server extends IXR_Server { $posts_list = wp_get_recent_posts($num_posts); - set_current_user( 0, $user_login ); - if (!$posts_list) { $this->error = new IXR_Error(500, __('Either there are no posts, or something went wrong.')); return $this->error; @@ -1128,7 +1721,7 @@ class wp_xmlrpc_server extends IXR_Server { if( !current_user_can( 'edit_post', $entry['ID'] ) ) continue; - $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']); + $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date'], false); $categories = implode(',', wp_get_post_categories($entry['ID'])); $content = '