web/xmlrpc.php
branchwordpress
changeset 109 03b0d1493584
child 132 4d4862461b8d
equal deleted inserted replaced
-1:000000000000 109:03b0d1493584
       
     1 <?php
       
     2 /**
       
     3  * XML-RPC protocol support for WordPress
       
     4  *
       
     5  * @license GPL v2 <./license.txt>
       
     6  * @package WordPress
       
     7  */
       
     8 
       
     9 /**
       
    10  * Whether this is a XMLRPC Request
       
    11  *
       
    12  * @var bool
       
    13  */
       
    14 define('XMLRPC_REQUEST', true);
       
    15 
       
    16 // Some browser-embedded clients send cookies. We don't want them.
       
    17 $_COOKIE = array();
       
    18 
       
    19 // A bug in PHP < 5.2.2 makes $HTTP_RAW_POST_DATA not set by default,
       
    20 // but we can do it ourself.
       
    21 if ( !isset( $HTTP_RAW_POST_DATA ) ) {
       
    22 	$HTTP_RAW_POST_DATA = file_get_contents( 'php://input' );
       
    23 }
       
    24 
       
    25 // fix for mozBlog and other cases where '<?xml' isn't on the very first line
       
    26 if ( isset($HTTP_RAW_POST_DATA) )
       
    27 	$HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA);
       
    28 
       
    29 /** Include the bootstrap for setting up WordPress environment */
       
    30 include('./wp-load.php');
       
    31 
       
    32 if ( isset( $_GET['rsd'] ) ) { // http://archipelago.phrasewise.com/rsd
       
    33 header('Content-Type: text/xml; charset=' . get_option('blog_charset'), true);
       
    34 ?>
       
    35 <?php echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; ?>
       
    36 <rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">
       
    37   <service>
       
    38     <engineName>WordPress</engineName>
       
    39     <engineLink>http://wordpress.org/</engineLink>
       
    40     <homePageLink><?php bloginfo_rss('url') ?></homePageLink>
       
    41     <apis>
       
    42       <api name="WordPress" blogID="1" preferred="true" apiLink="<?php echo site_url('xmlrpc.php', 'rpc') ?>" />
       
    43       <api name="Movable Type" blogID="1" preferred="false" apiLink="<?php echo site_url('xmlrpc.php', 'rpc') ?>" />
       
    44       <api name="MetaWeblog" blogID="1" preferred="false" apiLink="<?php echo site_url('xmlrpc.php', 'rpc') ?>" />
       
    45       <api name="Blogger" blogID="1" preferred="false" apiLink="<?php echo site_url('xmlrpc.php', 'rpc') ?>" />
       
    46       <api name="Atom" blogID="" preferred="false" apiLink="<?php echo apply_filters('atom_service_url', site_url('wp-app.php/service', 'rpc') ) ?>" />
       
    47     </apis>
       
    48   </service>
       
    49 </rsd>
       
    50 <?php
       
    51 exit;
       
    52 }
       
    53 
       
    54 include_once(ABSPATH . 'wp-admin/includes/admin.php');
       
    55 include_once(ABSPATH . WPINC . '/class-IXR.php');
       
    56 
       
    57 // Turn off all warnings and errors.
       
    58 // error_reporting(0);
       
    59 
       
    60 /**
       
    61  * Posts submitted via the xmlrpc interface get that title
       
    62  * @name post_default_title
       
    63  * @var string
       
    64  */
       
    65 $post_default_title = "";
       
    66 
       
    67 /**
       
    68  * Whether to enable XMLRPC Logging.
       
    69  *
       
    70  * @name xmlrpc_logging
       
    71  * @var int|bool
       
    72  */
       
    73 $xmlrpc_logging = 0;
       
    74 
       
    75 /**
       
    76  * logIO() - Writes logging info to a file.
       
    77  *
       
    78  * @uses $xmlrpc_logging
       
    79  * @package WordPress
       
    80  * @subpackage Logging
       
    81  *
       
    82  * @param string $io Whether input or output
       
    83  * @param string $msg Information describing logging reason.
       
    84  * @return bool Always return true
       
    85  */
       
    86 function logIO($io,$msg) {
       
    87 	global $xmlrpc_logging;
       
    88 	if ($xmlrpc_logging) {
       
    89 		$fp = fopen("../xmlrpc.log","a+");
       
    90 		$date = gmdate("Y-m-d H:i:s ");
       
    91 		$iot = ($io == "I") ? " Input: " : " Output: ";
       
    92 		fwrite($fp, "\n\n".$date.$iot.$msg);
       
    93 		fclose($fp);
       
    94 	}
       
    95 	return true;
       
    96 }
       
    97 
       
    98 if ( isset($HTTP_RAW_POST_DATA) )
       
    99 	logIO("I", $HTTP_RAW_POST_DATA);
       
   100 
       
   101 /**
       
   102  * WordPress XMLRPC server implementation.
       
   103  *
       
   104  * Implements compatability for Blogger API, MetaWeblog API, MovableType, and
       
   105  * pingback. Additional WordPress API for managing comments, pages, posts,
       
   106  * options, etc.
       
   107  *
       
   108  * Since WordPress 2.6.0, WordPress XMLRPC server can be disabled in the
       
   109  * administration panels.
       
   110  *
       
   111  * @package WordPress
       
   112  * @subpackage Publishing
       
   113  * @since 1.5.0
       
   114  */
       
   115 class wp_xmlrpc_server extends IXR_Server {
       
   116 
       
   117 	/**
       
   118 	 * Register all of the XMLRPC methods that XMLRPC server understands.
       
   119 	 *
       
   120 	 * PHP4 constructor and sets up server and method property. Passes XMLRPC
       
   121 	 * methods through the 'xmlrpc_methods' filter to allow plugins to extend
       
   122 	 * or replace XMLRPC methods.
       
   123 	 *
       
   124 	 * @since 1.5.0
       
   125 	 *
       
   126 	 * @return wp_xmlrpc_server
       
   127 	 */
       
   128 	function wp_xmlrpc_server() {
       
   129 		$this->methods = array(
       
   130 			// WordPress API
       
   131 			'wp.getUsersBlogs'		=> 'this:wp_getUsersBlogs',
       
   132 			'wp.getPage'			=> 'this:wp_getPage',
       
   133 			'wp.getPages'			=> 'this:wp_getPages',
       
   134 			'wp.newPage'			=> 'this:wp_newPage',
       
   135 			'wp.deletePage'			=> 'this:wp_deletePage',
       
   136 			'wp.editPage'			=> 'this:wp_editPage',
       
   137 			'wp.getPageList'		=> 'this:wp_getPageList',
       
   138 			'wp.getAuthors'			=> 'this:wp_getAuthors',
       
   139 			'wp.getCategories'		=> 'this:mw_getCategories',		// Alias
       
   140 			'wp.getTags'			=> 'this:wp_getTags',
       
   141 			'wp.newCategory'		=> 'this:wp_newCategory',
       
   142 			'wp.deleteCategory'		=> 'this:wp_deleteCategory',
       
   143 			'wp.suggestCategories'	=> 'this:wp_suggestCategories',
       
   144 			'wp.uploadFile'			=> 'this:mw_newMediaObject',	// Alias
       
   145 			'wp.getCommentCount'	=> 'this:wp_getCommentCount',
       
   146 			'wp.getPostStatusList'	=> 'this:wp_getPostStatusList',
       
   147 			'wp.getPageStatusList'	=> 'this:wp_getPageStatusList',
       
   148 			'wp.getPageTemplates'	=> 'this:wp_getPageTemplates',
       
   149 			'wp.getOptions'			=> 'this:wp_getOptions',
       
   150 			'wp.setOptions'			=> 'this:wp_setOptions',
       
   151 			'wp.getComment'			=> 'this:wp_getComment',
       
   152 			'wp.getComments'		=> 'this:wp_getComments',
       
   153 			'wp.deleteComment'		=> 'this:wp_deleteComment',
       
   154 			'wp.editComment'		=> 'this:wp_editComment',
       
   155 			'wp.newComment'			=> 'this:wp_newComment',
       
   156 			'wp.getCommentStatusList' => 'this:wp_getCommentStatusList',
       
   157 
       
   158 			// Blogger API
       
   159 			'blogger.getUsersBlogs' => 'this:blogger_getUsersBlogs',
       
   160 			'blogger.getUserInfo' => 'this:blogger_getUserInfo',
       
   161 			'blogger.getPost' => 'this:blogger_getPost',
       
   162 			'blogger.getRecentPosts' => 'this:blogger_getRecentPosts',
       
   163 			'blogger.getTemplate' => 'this:blogger_getTemplate',
       
   164 			'blogger.setTemplate' => 'this:blogger_setTemplate',
       
   165 			'blogger.newPost' => 'this:blogger_newPost',
       
   166 			'blogger.editPost' => 'this:blogger_editPost',
       
   167 			'blogger.deletePost' => 'this:blogger_deletePost',
       
   168 
       
   169 			// MetaWeblog API (with MT extensions to structs)
       
   170 			'metaWeblog.newPost' => 'this:mw_newPost',
       
   171 			'metaWeblog.editPost' => 'this:mw_editPost',
       
   172 			'metaWeblog.getPost' => 'this:mw_getPost',
       
   173 			'metaWeblog.getRecentPosts' => 'this:mw_getRecentPosts',
       
   174 			'metaWeblog.getCategories' => 'this:mw_getCategories',
       
   175 			'metaWeblog.newMediaObject' => 'this:mw_newMediaObject',
       
   176 
       
   177 			// MetaWeblog API aliases for Blogger API
       
   178 			// see http://www.xmlrpc.com/stories/storyReader$2460
       
   179 			'metaWeblog.deletePost' => 'this:blogger_deletePost',
       
   180 			'metaWeblog.getTemplate' => 'this:blogger_getTemplate',
       
   181 			'metaWeblog.setTemplate' => 'this:blogger_setTemplate',
       
   182 			'metaWeblog.getUsersBlogs' => 'this:blogger_getUsersBlogs',
       
   183 
       
   184 			// MovableType API
       
   185 			'mt.getCategoryList' => 'this:mt_getCategoryList',
       
   186 			'mt.getRecentPostTitles' => 'this:mt_getRecentPostTitles',
       
   187 			'mt.getPostCategories' => 'this:mt_getPostCategories',
       
   188 			'mt.setPostCategories' => 'this:mt_setPostCategories',
       
   189 			'mt.supportedMethods' => 'this:mt_supportedMethods',
       
   190 			'mt.supportedTextFilters' => 'this:mt_supportedTextFilters',
       
   191 			'mt.getTrackbackPings' => 'this:mt_getTrackbackPings',
       
   192 			'mt.publishPost' => 'this:mt_publishPost',
       
   193 
       
   194 			// PingBack
       
   195 			'pingback.ping' => 'this:pingback_ping',
       
   196 			'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks',
       
   197 
       
   198 			'demo.sayHello' => 'this:sayHello',
       
   199 			'demo.addTwoNumbers' => 'this:addTwoNumbers'
       
   200 		);
       
   201 
       
   202 		$this->initialise_blog_option_info( );
       
   203 		$this->methods = apply_filters('xmlrpc_methods', $this->methods);
       
   204 		$this->IXR_Server($this->methods);
       
   205 	}
       
   206 
       
   207 	/**
       
   208 	 * Test XMLRPC API by saying, "Hello!" to client.
       
   209 	 *
       
   210 	 * @since 1.5.0
       
   211 	 *
       
   212 	 * @param array $args Method Parameters.
       
   213 	 * @return string
       
   214 	 */
       
   215 	function sayHello($args) {
       
   216 		return 'Hello!';
       
   217 	}
       
   218 
       
   219 	/**
       
   220 	 * Test XMLRPC API by adding two numbers for client.
       
   221 	 *
       
   222 	 * @since 1.5.0
       
   223 	 *
       
   224 	 * @param array $args Method Parameters.
       
   225 	 * @return int
       
   226 	 */
       
   227 	function addTwoNumbers($args) {
       
   228 		$number1 = $args[0];
       
   229 		$number2 = $args[1];
       
   230 		return $number1 + $number2;
       
   231 	}
       
   232 
       
   233 	/**
       
   234 	 * Check user's credentials.
       
   235 	 *
       
   236 	 * @since 1.5.0
       
   237 	 *
       
   238 	 * @param string $user_login User's username.
       
   239 	 * @param string $user_pass User's password.
       
   240 	 * @return bool Whether authentication passed.
       
   241 	 * @deprecated use wp_xmlrpc_server::login
       
   242 	 * @see wp_xmlrpc_server::login
       
   243 	 */
       
   244 	function login_pass_ok($user_login, $user_pass) {
       
   245 		if ( !get_option( 'enable_xmlrpc' ) ) {
       
   246 			$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') ) );
       
   247 			return false;
       
   248 		}
       
   249 
       
   250 		if (!user_pass_ok($user_login, $user_pass)) {
       
   251 			$this->error = new IXR_Error(403, __('Bad login/pass combination.'));
       
   252 			return false;
       
   253 		}
       
   254 		return true;
       
   255 	}
       
   256 
       
   257 	/**
       
   258 	 * Log user in.
       
   259 	 *
       
   260 	 * @since 2.8
       
   261 	 *
       
   262 	 * @param string $username User's username.
       
   263 	 * @param string $password User's password.
       
   264 	 * @return mixed WP_User object if authentication passed, false otherwise
       
   265 	 */
       
   266 	function login($username, $password) {
       
   267 		if ( !get_option( 'enable_xmlrpc' ) ) {
       
   268 			$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') ) );
       
   269 			return false;
       
   270 		}
       
   271 
       
   272 		$user = wp_authenticate($username, $password);
       
   273 
       
   274 		if (is_wp_error($user)) {
       
   275 			$this->error = new IXR_Error(403, __('Bad login/pass combination.'));
       
   276 			return false;
       
   277 		}
       
   278 
       
   279 		set_current_user( $user->ID );
       
   280 		return $user;
       
   281 	}
       
   282 
       
   283 	/**
       
   284 	 * Sanitize string or array of strings for database.
       
   285 	 *
       
   286 	 * @since 1.5.2
       
   287 	 *
       
   288 	 * @param string|array $array Sanitize single string or array of strings.
       
   289 	 * @return string|array Type matches $array and sanitized for the database.
       
   290 	 */
       
   291 	function escape(&$array) {
       
   292 		global $wpdb;
       
   293 
       
   294 		if(!is_array($array)) {
       
   295 			return($wpdb->escape($array));
       
   296 		}
       
   297 		else {
       
   298 			foreach ( (array) $array as $k => $v ) {
       
   299 				if (is_array($v)) {
       
   300 					$this->escape($array[$k]);
       
   301 				} else if (is_object($v)) {
       
   302 					//skip
       
   303 				} else {
       
   304 					$array[$k] = $wpdb->escape($v);
       
   305 				}
       
   306 			}
       
   307 		}
       
   308 	}
       
   309 
       
   310 	/**
       
   311 	 * Retrieve custom fields for post.
       
   312 	 *
       
   313 	 * @since 2.5.0
       
   314 	 *
       
   315 	 * @param int $post_id Post ID.
       
   316 	 * @return array Custom fields, if exist.
       
   317 	 */
       
   318 	function get_custom_fields($post_id) {
       
   319 		$post_id = (int) $post_id;
       
   320 
       
   321 		$custom_fields = array();
       
   322 
       
   323 		foreach ( (array) has_meta($post_id) as $meta ) {
       
   324 			// Don't expose protected fields.
       
   325 			if ( strpos($meta['meta_key'], '_wp_') === 0 ) {
       
   326 				continue;
       
   327 			}
       
   328 
       
   329 			$custom_fields[] = array(
       
   330 				"id"    => $meta['meta_id'],
       
   331 				"key"   => $meta['meta_key'],
       
   332 				"value" => $meta['meta_value']
       
   333 			);
       
   334 		}
       
   335 
       
   336 		return $custom_fields;
       
   337 	}
       
   338 
       
   339 	/**
       
   340 	 * Set custom fields for post.
       
   341 	 *
       
   342 	 * @since 2.5.0
       
   343 	 *
       
   344 	 * @param int $post_id Post ID.
       
   345 	 * @param array $fields Custom fields.
       
   346 	 */
       
   347 	function set_custom_fields($post_id, $fields) {
       
   348 		$post_id = (int) $post_id;
       
   349 
       
   350 		foreach ( (array) $fields as $meta ) {
       
   351 			if ( isset($meta['id']) ) {
       
   352 				$meta['id'] = (int) $meta['id'];
       
   353 
       
   354 				if ( isset($meta['key']) ) {
       
   355 					update_meta($meta['id'], $meta['key'], $meta['value']);
       
   356 				}
       
   357 				else {
       
   358 					delete_meta($meta['id']);
       
   359 				}
       
   360 			}
       
   361 			else {
       
   362 				$_POST['metakeyinput'] = $meta['key'];
       
   363 				$_POST['metavalue'] = $meta['value'];
       
   364 				add_meta($post_id);
       
   365 			}
       
   366 		}
       
   367 	}
       
   368 
       
   369 	/**
       
   370 	 * Setup blog options property.
       
   371 	 *
       
   372 	 * Passes property through 'xmlrpc_blog_options' filter.
       
   373 	 *
       
   374 	 * @since 2.6.0
       
   375 	 */
       
   376 	function initialise_blog_option_info( ) {
       
   377 		global $wp_version;
       
   378 
       
   379 		$this->blog_options = array(
       
   380 			// Read only options
       
   381 			'software_name'		=> array(
       
   382 				'desc'			=> __( 'Software Name' ),
       
   383 				'readonly'		=> true,
       
   384 				'value'			=> 'WordPress'
       
   385 			),
       
   386 			'software_version'	=> array(
       
   387 				'desc'			=> __( 'Software Version' ),
       
   388 				'readonly'		=> true,
       
   389 				'value'			=> $wp_version
       
   390 			),
       
   391 			'blog_url'			=> array(
       
   392 				'desc'			=> __( 'Blog URL' ),
       
   393 				'readonly'		=> true,
       
   394 				'option'		=> 'siteurl'
       
   395 			),
       
   396 
       
   397 			// Updatable options
       
   398 			'time_zone'			=> array(
       
   399 				'desc'			=> __( 'Time Zone' ),
       
   400 				'readonly'		=> false,
       
   401 				'option'		=> 'gmt_offset'
       
   402 			),
       
   403 			'blog_title'		=> array(
       
   404 				'desc'			=> __( 'Blog Title' ),
       
   405 				'readonly'		=> false,
       
   406 				'option'			=> 'blogname'
       
   407 			),
       
   408 			'blog_tagline'		=> array(
       
   409 				'desc'			=> __( 'Blog Tagline' ),
       
   410 				'readonly'		=> false,
       
   411 				'option'		=> 'blogdescription'
       
   412 			),
       
   413 			'date_format'		=> array(
       
   414 				'desc'			=> __( 'Date Format' ),
       
   415 				'readonly'		=> false,
       
   416 				'option'		=> 'date_format'
       
   417 			),
       
   418 			'time_format'		=> array(
       
   419 				'desc'			=> __( 'Time Format' ),
       
   420 				'readonly'		=> false,
       
   421 				'option'		=> 'time_format'
       
   422 			)
       
   423 		);
       
   424 
       
   425 		$this->blog_options = apply_filters( 'xmlrpc_blog_options', $this->blog_options );
       
   426 	}
       
   427 
       
   428 	/**
       
   429 	 * Retrieve the blogs of the user.
       
   430 	 *
       
   431 	 * @since 2.6.0
       
   432 	 *
       
   433 	 * @param array $args Method parameters.
       
   434 	 * @return array
       
   435 	 */
       
   436 	function wp_getUsersBlogs( $args ) {
       
   437 		// If this isn't on WPMU then just use blogger_getUsersBlogs
       
   438 		if( !function_exists( 'is_site_admin' ) ) {
       
   439 			array_unshift( $args, 1 );
       
   440 			return $this->blogger_getUsersBlogs( $args );
       
   441 		}
       
   442 
       
   443 		$this->escape( $args );
       
   444 
       
   445 		$username = $args[0];
       
   446 		$password = $args[1];
       
   447 
       
   448 		if ( !$user = $this->login($username, $password) ) {
       
   449 			return $this->error;
       
   450 		}
       
   451 
       
   452 		do_action( 'xmlrpc_call', 'wp.getUsersBlogs' );
       
   453 
       
   454 		$blogs = (array) get_blogs_of_user( $user->ID );
       
   455 		$struct = array( );
       
   456 
       
   457 		foreach( $blogs as $blog ) {
       
   458 			// Don't include blogs that aren't hosted at this site
       
   459 			if( $blog->site_id != $current_site->id )
       
   460 				continue;
       
   461 
       
   462 			$blog_id = $blog->userblog_id;
       
   463 			switch_to_blog($blog_id);
       
   464 			$is_admin = current_user_can('level_8');
       
   465 
       
   466 			$struct[] = array(
       
   467 				'isAdmin'		=> $is_admin,
       
   468 				'url'			=> get_option( 'home' ) . '/',
       
   469 				'blogid'		=> $blog_id,
       
   470 				'blogName'		=> get_option( 'blogname' ),
       
   471 				'xmlrpc'		=> site_url( 'xmlrpc.php' )
       
   472 			);
       
   473 
       
   474 			restore_current_blog( );
       
   475 		}
       
   476 
       
   477 		return $struct;
       
   478 	}
       
   479 
       
   480 	/**
       
   481 	 * Retrieve page.
       
   482 	 *
       
   483 	 * @since 2.2.0
       
   484 	 *
       
   485 	 * @param array $args Method parameters.
       
   486 	 * @return array
       
   487 	 */
       
   488 	function wp_getPage($args) {
       
   489 		$this->escape($args);
       
   490 
       
   491 		$blog_id	= (int) $args[0];
       
   492 		$page_id	= (int) $args[1];
       
   493 		$username	= $args[2];
       
   494 		$password	= $args[3];
       
   495 
       
   496 		if ( !$user = $this->login($username, $password) ) {
       
   497 			return $this->error;
       
   498 		}
       
   499 
       
   500 		if( !current_user_can( 'edit_page', $page_id ) )
       
   501 			return new IXR_Error( 401, __( 'Sorry, you cannot edit this page.' ) );
       
   502 
       
   503 		do_action('xmlrpc_call', 'wp.getPage');
       
   504 
       
   505 		// Lookup page info.
       
   506 		$page = get_page($page_id);
       
   507 
       
   508 		// If we found the page then format the data.
       
   509 		if($page->ID && ($page->post_type == "page")) {
       
   510 			// Get all of the page content and link.
       
   511 			$full_page = get_extended($page->post_content);
       
   512 			$link = post_permalink($page->ID);
       
   513 
       
   514 			// Get info the page parent if there is one.
       
   515 			$parent_title = "";
       
   516 			if(!empty($page->post_parent)) {
       
   517 				$parent = get_page($page->post_parent);
       
   518 				$parent_title = $parent->post_title;
       
   519 			}
       
   520 
       
   521 			// Determine comment and ping settings.
       
   522 			$allow_comments = comments_open($page->ID) ? 1 : 0;
       
   523 			$allow_pings = pings_open($page->ID) ? 1 : 0;
       
   524 
       
   525 			// Format page date.
       
   526 			$page_date = mysql2date("Ymd\TH:i:s", $page->post_date, false);
       
   527 			$page_date_gmt = mysql2date("Ymd\TH:i:s", $page->post_date_gmt, false);
       
   528 
       
   529 			// For drafts use the GMT version of the date
       
   530 			if ( $page->post_status == 'draft' ) {
       
   531 				$page_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $page->post_date ), 'Ymd\TH:i:s' );
       
   532 			}
       
   533 
       
   534 			// Pull the categories info together.
       
   535 			$categories = array();
       
   536 			foreach(wp_get_post_categories($page->ID) as $cat_id) {
       
   537 				$categories[] = get_cat_name($cat_id);
       
   538 			}
       
   539 
       
   540 			// Get the author info.
       
   541 			$author = get_userdata($page->post_author);
       
   542 
       
   543 			$page_template = get_post_meta( $page->ID, '_wp_page_template', true );
       
   544 			if( empty( $page_template ) )
       
   545 				$page_template = 'default';
       
   546 
       
   547 			$page_struct = array(
       
   548 				"dateCreated"			=> new IXR_Date($page_date),
       
   549 				"userid"				=> $page->post_author,
       
   550 				"page_id"				=> $page->ID,
       
   551 				"page_status"			=> $page->post_status,
       
   552 				"description"			=> $full_page["main"],
       
   553 				"title"					=> $page->post_title,
       
   554 				"link"					=> $link,
       
   555 				"permaLink"				=> $link,
       
   556 				"categories"			=> $categories,
       
   557 				"excerpt"				=> $page->post_excerpt,
       
   558 				"text_more"				=> $full_page["extended"],
       
   559 				"mt_allow_comments"		=> $allow_comments,
       
   560 				"mt_allow_pings"		=> $allow_pings,
       
   561 				"wp_slug"				=> $page->post_name,
       
   562 				"wp_password"			=> $page->post_password,
       
   563 				"wp_author"				=> $author->display_name,
       
   564 				"wp_page_parent_id"		=> $page->post_parent,
       
   565 				"wp_page_parent_title"	=> $parent_title,
       
   566 				"wp_page_order"			=> $page->menu_order,
       
   567 				"wp_author_id"			=> $author->ID,
       
   568 				"wp_author_display_name"	=> $author->display_name,
       
   569 				"date_created_gmt"		=> new IXR_Date($page_date_gmt),
       
   570 				"custom_fields"			=> $this->get_custom_fields($page_id),
       
   571 				"wp_page_template"		=> $page_template
       
   572 			);
       
   573 
       
   574 			return($page_struct);
       
   575 		}
       
   576 		// If the page doesn't exist indicate that.
       
   577 		else {
       
   578 			return(new IXR_Error(404, __("Sorry, no such page.")));
       
   579 		}
       
   580 	}
       
   581 
       
   582 	/**
       
   583 	 * Retrieve Pages.
       
   584 	 *
       
   585 	 * @since 2.2.0
       
   586 	 *
       
   587 	 * @param array $args Method parameters.
       
   588 	 * @return array
       
   589 	 */
       
   590 	function wp_getPages($args) {
       
   591 		$this->escape($args);
       
   592 
       
   593 		$blog_id	= (int) $args[0];
       
   594 		$username	= $args[1];
       
   595 		$password	= $args[2];
       
   596 		$num_pages	= (int) $args[3];
       
   597 
       
   598 		if ( !$user = $this->login($username, $password) ) {
       
   599 			return $this->error;
       
   600 		}
       
   601 
       
   602 		if( !current_user_can( 'edit_pages' ) )
       
   603 			return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) );
       
   604 
       
   605 		do_action('xmlrpc_call', 'wp.getPages');
       
   606 
       
   607 		$page_limit = 10;
       
   608 		if( isset( $num_pages ) ) {
       
   609 			$page_limit = $num_pages;
       
   610 		}
       
   611 
       
   612 		$pages = get_posts( array('post_type' => 'page', 'post_status' => 'all', 'numberposts' => $page_limit) );
       
   613 		$num_pages = count($pages);
       
   614 
       
   615 		// If we have pages, put together their info.
       
   616 		if($num_pages >= 1) {
       
   617 			$pages_struct = array();
       
   618 
       
   619 			for($i = 0; $i < $num_pages; $i++) {
       
   620 				$page = wp_xmlrpc_server::wp_getPage(array(
       
   621 					$blog_id, $pages[$i]->ID, $username, $password
       
   622 				));
       
   623 				$pages_struct[] = $page;
       
   624 			}
       
   625 
       
   626 			return($pages_struct);
       
   627 		}
       
   628 		// If no pages were found return an error.
       
   629 		else {
       
   630 			return(array());
       
   631 		}
       
   632 	}
       
   633 
       
   634 	/**
       
   635 	 * Create new page.
       
   636 	 *
       
   637 	 * @since 2.2.0
       
   638 	 *
       
   639 	 * @param array $args Method parameters.
       
   640 	 * @return unknown
       
   641 	 */
       
   642 	function wp_newPage($args) {
       
   643 		// Items not escaped here will be escaped in newPost.
       
   644 		$username	= $this->escape($args[1]);
       
   645 		$password	= $this->escape($args[2]);
       
   646 		$page		= $args[3];
       
   647 		$publish	= $args[4];
       
   648 
       
   649 		if ( !$user = $this->login($username, $password) ) {
       
   650 			return $this->error;
       
   651 		}
       
   652 
       
   653 		do_action('xmlrpc_call', 'wp.newPage');
       
   654 
       
   655 		// Make sure the user is allowed to add new pages.
       
   656 		if(!current_user_can("publish_pages")) {
       
   657 			return(new IXR_Error(401, __("Sorry, you cannot add new pages.")));
       
   658 		}
       
   659 
       
   660 		// Mark this as content for a page.
       
   661 		$args[3]["post_type"] = "page";
       
   662 
       
   663 		// Let mw_newPost do all of the heavy lifting.
       
   664 		return($this->mw_newPost($args));
       
   665 	}
       
   666 
       
   667 	/**
       
   668 	 * Delete page.
       
   669 	 *
       
   670 	 * @since 2.2.0
       
   671 	 *
       
   672 	 * @param array $args Method parameters.
       
   673 	 * @return bool True, if success.
       
   674 	 */
       
   675 	function wp_deletePage($args) {
       
   676 		$this->escape($args);
       
   677 
       
   678 		$blog_id	= (int) $args[0];
       
   679 		$username	= $args[1];
       
   680 		$password	= $args[2];
       
   681 		$page_id	= (int) $args[3];
       
   682 
       
   683 		if ( !$user = $this->login($username, $password) ) {
       
   684 			return $this->error;
       
   685 		}
       
   686 
       
   687 		do_action('xmlrpc_call', 'wp.deletePage');
       
   688 
       
   689 		// Get the current page based on the page_id and
       
   690 		// make sure it is a page and not a post.
       
   691 		$actual_page = wp_get_single_post($page_id, ARRAY_A);
       
   692 		if(
       
   693 			!$actual_page
       
   694 			|| ($actual_page["post_type"] != "page")
       
   695 		) {
       
   696 			return(new IXR_Error(404, __("Sorry, no such page.")));
       
   697 		}
       
   698 
       
   699 		// Make sure the user can delete pages.
       
   700 		if(!current_user_can("delete_page", $page_id)) {
       
   701 			return(new IXR_Error(401, __("Sorry, you do not have the right to delete this page.")));
       
   702 		}
       
   703 
       
   704 		// Attempt to delete the page.
       
   705 		$result = wp_delete_post($page_id);
       
   706 		if(!$result) {
       
   707 			return(new IXR_Error(500, __("Failed to delete the page.")));
       
   708 		}
       
   709 
       
   710 		return(true);
       
   711 	}
       
   712 
       
   713 	/**
       
   714 	 * Edit page.
       
   715 	 *
       
   716 	 * @since 2.2.0
       
   717 	 *
       
   718 	 * @param array $args Method parameters.
       
   719 	 * @return unknown
       
   720 	 */
       
   721 	function wp_editPage($args) {
       
   722 		// Items not escaped here will be escaped in editPost.
       
   723 		$blog_id	= (int) $args[0];
       
   724 		$page_id	= (int) $this->escape($args[1]);
       
   725 		$username	= $this->escape($args[2]);
       
   726 		$password	= $this->escape($args[3]);
       
   727 		$content	= $args[4];
       
   728 		$publish	= $args[5];
       
   729 
       
   730 		if ( !$user = $this->login($username, $password) ) {
       
   731 			return $this->error;
       
   732 		}
       
   733 
       
   734 		do_action('xmlrpc_call', 'wp.editPage');
       
   735 
       
   736 		// Get the page data and make sure it is a page.
       
   737 		$actual_page = wp_get_single_post($page_id, ARRAY_A);
       
   738 		if(
       
   739 			!$actual_page
       
   740 			|| ($actual_page["post_type"] != "page")
       
   741 		) {
       
   742 			return(new IXR_Error(404, __("Sorry, no such page.")));
       
   743 		}
       
   744 
       
   745 		// Make sure the user is allowed to edit pages.
       
   746 		if(!current_user_can("edit_page", $page_id)) {
       
   747 			return(new IXR_Error(401, __("Sorry, you do not have the right to edit this page.")));
       
   748 		}
       
   749 
       
   750 		// Mark this as content for a page.
       
   751 		$content["post_type"] = "page";
       
   752 
       
   753 		// Arrange args in the way mw_editPost understands.
       
   754 		$args = array(
       
   755 			$page_id,
       
   756 			$username,
       
   757 			$password,
       
   758 			$content,
       
   759 			$publish
       
   760 		);
       
   761 
       
   762 		// Let mw_editPost do all of the heavy lifting.
       
   763 		return($this->mw_editPost($args));
       
   764 	}
       
   765 
       
   766 	/**
       
   767 	 * Retrieve page list.
       
   768 	 *
       
   769 	 * @since 2.2.0
       
   770 	 *
       
   771 	 * @param array $args Method parameters.
       
   772 	 * @return unknown
       
   773 	 */
       
   774 	function wp_getPageList($args) {
       
   775 		global $wpdb;
       
   776 
       
   777 		$this->escape($args);
       
   778 
       
   779 		$blog_id				= (int) $args[0];
       
   780 		$username				= $args[1];
       
   781 		$password				= $args[2];
       
   782 
       
   783 		if ( !$user = $this->login($username, $password) ) {
       
   784 			return $this->error;
       
   785 		}
       
   786 
       
   787 		if( !current_user_can( 'edit_pages' ) )
       
   788 			return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) );
       
   789 
       
   790 		do_action('xmlrpc_call', 'wp.getPageList');
       
   791 
       
   792 		// Get list of pages ids and titles
       
   793 		$page_list = $wpdb->get_results("
       
   794 			SELECT ID page_id,
       
   795 				post_title page_title,
       
   796 				post_parent page_parent_id,
       
   797 				post_date_gmt,
       
   798 				post_date,
       
   799 				post_status
       
   800 			FROM {$wpdb->posts}
       
   801 			WHERE post_type = 'page'
       
   802 			ORDER BY ID
       
   803 		");
       
   804 
       
   805 		// The date needs to be formated properly.
       
   806 		$num_pages = count($page_list);
       
   807 		for($i = 0; $i < $num_pages; $i++) {
       
   808 			$post_date = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date, false);
       
   809 			$post_date_gmt = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date_gmt, false);
       
   810 
       
   811 			$page_list[$i]->dateCreated = new IXR_Date($post_date);
       
   812 			$page_list[$i]->date_created_gmt = new IXR_Date($post_date_gmt);
       
   813 
       
   814 			// For drafts use the GMT version of the date
       
   815 			if ( $page_list[$i]->post_status == 'draft' ) {
       
   816 				$page_list[$i]->date_created_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $page_list[$i]->post_date ), 'Ymd\TH:i:s' );
       
   817 				$page_list[$i]->date_created_gmt = new IXR_Date( $page_list[$i]->date_created_gmt );
       
   818 			}
       
   819 
       
   820 			unset($page_list[$i]->post_date_gmt);
       
   821 			unset($page_list[$i]->post_date);
       
   822 			unset($page_list[$i]->post_status);
       
   823 		}
       
   824 
       
   825 		return($page_list);
       
   826 	}
       
   827 
       
   828 	/**
       
   829 	 * Retrieve authors list.
       
   830 	 *
       
   831 	 * @since 2.2.0
       
   832 	 *
       
   833 	 * @param array $args Method parameters.
       
   834 	 * @return array
       
   835 	 */
       
   836 	function wp_getAuthors($args) {
       
   837 
       
   838 		$this->escape($args);
       
   839 
       
   840 		$blog_id	= (int) $args[0];
       
   841 		$username	= $args[1];
       
   842 		$password	= $args[2];
       
   843 
       
   844 		if ( !$user = $this->login($username, $password) ) {
       
   845 			return $this->error;
       
   846 		}
       
   847 
       
   848 		if(!current_user_can("edit_posts")) {
       
   849 			return(new IXR_Error(401, __("Sorry, you cannot edit posts on this blog.")));
       
   850 		}
       
   851 
       
   852 		do_action('xmlrpc_call', 'wp.getAuthors');
       
   853 
       
   854 		$authors = array();
       
   855 		foreach( (array) get_users_of_blog() as $row ) {
       
   856 			$authors[] = array(
       
   857 				"user_id"       => $row->user_id,
       
   858 				"user_login"    => $row->user_login,
       
   859 				"display_name"  => $row->display_name
       
   860 			);
       
   861 		}
       
   862 
       
   863 		return($authors);
       
   864 	}
       
   865 
       
   866 	/**
       
   867 	 * Get list of all tags
       
   868 	 *
       
   869 	 * @since 2.7
       
   870 	 *
       
   871 	 * @param array $args Method parameters.
       
   872 	 * @return array
       
   873 	 */
       
   874 	function wp_getTags( $args ) {
       
   875 		$this->escape( $args );
       
   876 
       
   877 		$blog_id		= (int) $args[0];
       
   878 		$username		= $args[1];
       
   879 		$password		= $args[2];
       
   880 
       
   881 		if ( !$user = $this->login($username, $password) ) {
       
   882 			return $this->error;
       
   883 		}
       
   884 
       
   885 		if( !current_user_can( 'edit_posts' ) ) {
       
   886 			return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this blog in order to view tags.' ) );
       
   887 		}
       
   888 
       
   889 		do_action( 'xmlrpc_call', 'wp.getKeywords' );
       
   890 
       
   891 		$tags = array( );
       
   892 
       
   893 		if( $all_tags = get_tags( ) ) {
       
   894 			foreach( (array) $all_tags as $tag ) {
       
   895 				$struct['tag_id']			= $tag->term_id;
       
   896 				$struct['name']				= $tag->name;
       
   897 				$struct['count']			= $tag->count;
       
   898 				$struct['slug']				= $tag->slug;
       
   899 				$struct['html_url']			= esc_html( get_tag_link( $tag->term_id ) );
       
   900 				$struct['rss_url']			= esc_html( get_tag_feed_link( $tag->term_id ) );
       
   901 
       
   902 				$tags[] = $struct;
       
   903 			}
       
   904 		}
       
   905 
       
   906 		return $tags;
       
   907 	}
       
   908 
       
   909 	/**
       
   910 	 * Create new category.
       
   911 	 *
       
   912 	 * @since 2.2.0
       
   913 	 *
       
   914 	 * @param array $args Method parameters.
       
   915 	 * @return int Category ID.
       
   916 	 */
       
   917 	function wp_newCategory($args) {
       
   918 		$this->escape($args);
       
   919 
       
   920 		$blog_id				= (int) $args[0];
       
   921 		$username				= $args[1];
       
   922 		$password				= $args[2];
       
   923 		$category				= $args[3];
       
   924 
       
   925 		if ( !$user = $this->login($username, $password) ) {
       
   926 			return $this->error;
       
   927 		}
       
   928 
       
   929 		do_action('xmlrpc_call', 'wp.newCategory');
       
   930 
       
   931 		// Make sure the user is allowed to add a category.
       
   932 		if(!current_user_can("manage_categories")) {
       
   933 			return(new IXR_Error(401, __("Sorry, you do not have the right to add a category.")));
       
   934 		}
       
   935 
       
   936 		// If no slug was provided make it empty so that
       
   937 		// WordPress will generate one.
       
   938 		if(empty($category["slug"])) {
       
   939 			$category["slug"] = "";
       
   940 		}
       
   941 
       
   942 		// If no parent_id was provided make it empty
       
   943 		// so that it will be a top level page (no parent).
       
   944 		if ( !isset($category["parent_id"]) )
       
   945 			$category["parent_id"] = "";
       
   946 
       
   947 		// If no description was provided make it empty.
       
   948 		if(empty($category["description"])) {
       
   949 			$category["description"] = "";
       
   950 		}
       
   951 
       
   952 		$new_category = array(
       
   953 			"cat_name"				=> $category["name"],
       
   954 			"category_nicename"		=> $category["slug"],
       
   955 			"category_parent"		=> $category["parent_id"],
       
   956 			"category_description"	=> $category["description"]
       
   957 		);
       
   958 
       
   959 		$cat_id = wp_insert_category($new_category);
       
   960 		if(!$cat_id) {
       
   961 			return(new IXR_Error(500, __("Sorry, the new category failed.")));
       
   962 		}
       
   963 
       
   964 		return($cat_id);
       
   965 	}
       
   966 
       
   967 	/**
       
   968 	 * Remove category.
       
   969 	 *
       
   970 	 * @since 2.5.0
       
   971 	 *
       
   972 	 * @param array $args Method parameters.
       
   973 	 * @return mixed See {@link wp_delete_category()} for return info.
       
   974 	 */
       
   975 	function wp_deleteCategory($args) {
       
   976 		$this->escape($args);
       
   977 
       
   978 		$blog_id		= (int) $args[0];
       
   979 		$username		= $args[1];
       
   980 		$password		= $args[2];
       
   981 		$category_id	= (int) $args[3];
       
   982 
       
   983 		if ( !$user = $this->login($username, $password) ) {
       
   984 			return $this->error;
       
   985 		}
       
   986 
       
   987 		do_action('xmlrpc_call', 'wp.deleteCategory');
       
   988 
       
   989 		if( !current_user_can("manage_categories") ) {
       
   990 			return new IXR_Error( 401, __( "Sorry, you do not have the right to delete a category." ) );
       
   991 		}
       
   992 
       
   993 		return wp_delete_category( $category_id );
       
   994 	}
       
   995 
       
   996 	/**
       
   997 	 * Retrieve category list.
       
   998 	 *
       
   999 	 * @since 2.2.0
       
  1000 	 *
       
  1001 	 * @param array $args Method parameters.
       
  1002 	 * @return array
       
  1003 	 */
       
  1004 	function wp_suggestCategories($args) {
       
  1005 		$this->escape($args);
       
  1006 
       
  1007 		$blog_id				= (int) $args[0];
       
  1008 		$username				= $args[1];
       
  1009 		$password				= $args[2];
       
  1010 		$category				= $args[3];
       
  1011 		$max_results			= (int) $args[4];
       
  1012 
       
  1013 		if ( !$user = $this->login($username, $password) ) {
       
  1014 			return $this->error;
       
  1015 		}
       
  1016 
       
  1017 		if( !current_user_can( 'edit_posts' ) )
       
  1018 			return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts to this blog in order to view categories.' ) );
       
  1019 
       
  1020 		do_action('xmlrpc_call', 'wp.suggestCategories');
       
  1021 
       
  1022 		$category_suggestions = array();
       
  1023 		$args = array('get' => 'all', 'number' => $max_results, 'name__like' => $category);
       
  1024 		foreach ( (array) get_categories($args) as $cat ) {
       
  1025 			$category_suggestions[] = array(
       
  1026 				"category_id"	=> $cat->cat_ID,
       
  1027 				"category_name"	=> $cat->cat_name
       
  1028 			);
       
  1029 		}
       
  1030 
       
  1031 		return($category_suggestions);
       
  1032 	}
       
  1033 
       
  1034 	/**
       
  1035 	 * Retrieve comment.
       
  1036 	 *
       
  1037 	 * @since 2.7.0
       
  1038 	 *
       
  1039 	 * @param array $args Method parameters.
       
  1040 	 * @return array
       
  1041 	 */
       
  1042 	function wp_getComment($args) {
       
  1043 		$this->escape($args);
       
  1044 
       
  1045 		$blog_id	= (int) $args[0];
       
  1046 		$username	= $args[1];
       
  1047 		$password	= $args[2];
       
  1048 		$comment_id	= (int) $args[3];
       
  1049 
       
  1050 		if ( !$user = $this->login($username, $password) ) {
       
  1051 			return $this->error;
       
  1052 		}
       
  1053 
       
  1054 		if ( !current_user_can( 'moderate_comments' ) )
       
  1055 			return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this blog.' ) );
       
  1056 
       
  1057 		do_action('xmlrpc_call', 'wp.getComment');
       
  1058 
       
  1059 		if ( ! $comment = get_comment($comment_id) )
       
  1060 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
       
  1061 
       
  1062 		// Format page date.
       
  1063 		$comment_date = mysql2date("Ymd\TH:i:s", $comment->comment_date, false);
       
  1064 		$comment_date_gmt = mysql2date("Ymd\TH:i:s", $comment->comment_date_gmt, false);
       
  1065 
       
  1066 		if ( 0 == $comment->comment_approved )
       
  1067 			$comment_status = 'hold';
       
  1068 		else if ( 'spam' == $comment->comment_approved )
       
  1069 			$comment_status = 'spam';
       
  1070 		else if ( 1 == $comment->comment_approved )
       
  1071 			$comment_status = 'approve';
       
  1072 		else
       
  1073 			$comment_status = $comment->comment_approved;
       
  1074 
       
  1075 		$link = get_comment_link($comment);
       
  1076 
       
  1077 		$comment_struct = array(
       
  1078 			"date_created_gmt"		=> new IXR_Date($comment_date_gmt),
       
  1079 			"user_id"				=> $comment->user_id,
       
  1080 			"comment_id"			=> $comment->comment_ID,
       
  1081 			"parent"				=> $comment->comment_parent,
       
  1082 			"status"				=> $comment_status,
       
  1083 			"content"				=> $comment->comment_content,
       
  1084 			"link"					=> $link,
       
  1085 			"post_id"				=> $comment->comment_post_ID,
       
  1086 			"post_title"			=> get_the_title($comment->comment_post_ID),
       
  1087 			"author"				=> $comment->comment_author,
       
  1088 			"author_url"			=> $comment->comment_author_url,
       
  1089 			"author_email"			=> $comment->comment_author_email,
       
  1090 			"author_ip"				=> $comment->comment_author_IP,
       
  1091 			"type"					=> $comment->comment_type,
       
  1092 		);
       
  1093 
       
  1094 		return $comment_struct;
       
  1095 	}
       
  1096 
       
  1097 	/**
       
  1098 	 * Retrieve comments.
       
  1099 	 *
       
  1100 	 * @since 2.7.0
       
  1101 	 *
       
  1102 	 * @param array $args Method parameters.
       
  1103 	 * @return array
       
  1104 	 */
       
  1105 	function wp_getComments($args) {
       
  1106 		$this->escape($args);
       
  1107 
       
  1108 		$blog_id	= (int) $args[0];
       
  1109 		$username	= $args[1];
       
  1110 		$password	= $args[2];
       
  1111 		$struct		= $args[3];
       
  1112 
       
  1113 		if ( !$user = $this->login($username, $password) ) {
       
  1114 			return $this->error;
       
  1115 		}
       
  1116 
       
  1117 		if ( !current_user_can( 'moderate_comments' ) )
       
  1118 			return new IXR_Error( 401, __( 'Sorry, you cannot edit comments.' ) );
       
  1119 
       
  1120 		do_action('xmlrpc_call', 'wp.getComments');
       
  1121 
       
  1122 		if ( isset($struct['status']) )
       
  1123 			$status = $struct['status'];
       
  1124 		else
       
  1125 			$status = '';
       
  1126 
       
  1127 		$post_id = '';
       
  1128 		if ( isset($struct['post_id']) )
       
  1129 			$post_id = absint($struct['post_id']);
       
  1130 
       
  1131 		$offset = 0;
       
  1132 		if ( isset($struct['offset']) )
       
  1133 			$offset = absint($struct['offset']);
       
  1134 
       
  1135 		$number = 10;
       
  1136 		if ( isset($struct['number']) )
       
  1137 			$number = absint($struct['number']);
       
  1138 
       
  1139 		$comments = get_comments( array('status' => $status, 'post_id' => $post_id, 'offset' => $offset, 'number' => $number ) );
       
  1140 		$num_comments = count($comments);
       
  1141 
       
  1142 		if ( ! $num_comments )
       
  1143 			return array();
       
  1144 
       
  1145 		$comments_struct = array();
       
  1146 
       
  1147 		for ( $i = 0; $i < $num_comments; $i++ ) {
       
  1148 			$comment = wp_xmlrpc_server::wp_getComment(array(
       
  1149 				$blog_id, $username, $password, $comments[$i]->comment_ID,
       
  1150 			));
       
  1151 			$comments_struct[] = $comment;
       
  1152 		}
       
  1153 
       
  1154 		return $comments_struct;
       
  1155 	}
       
  1156 
       
  1157 	/**
       
  1158 	 * Remove comment.
       
  1159 	 *
       
  1160 	 * @since 2.7.0
       
  1161 	 *
       
  1162 	 * @param array $args Method parameters.
       
  1163 	 * @return mixed {@link wp_delete_comment()}
       
  1164 	 */
       
  1165 	function wp_deleteComment($args) {
       
  1166 		$this->escape($args);
       
  1167 
       
  1168 		$blog_id	= (int) $args[0];
       
  1169 		$username	= $args[1];
       
  1170 		$password	= $args[2];
       
  1171 		$comment_ID	= (int) $args[3];
       
  1172 
       
  1173 		if ( !$user = $this->login($username, $password) ) {
       
  1174 			return $this->error;
       
  1175 		}
       
  1176 
       
  1177 		if ( !current_user_can( 'moderate_comments' ) )
       
  1178 			return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this blog.' ) );
       
  1179 
       
  1180 		do_action('xmlrpc_call', 'wp.deleteComment');
       
  1181 
       
  1182 		if ( ! get_comment($comment_ID) )
       
  1183 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
       
  1184 
       
  1185 		return wp_delete_comment($comment_ID);
       
  1186 	}
       
  1187 
       
  1188 	/**
       
  1189 	 * Edit comment.
       
  1190 	 *
       
  1191 	 * @since 2.7.0
       
  1192 	 *
       
  1193 	 * @param array $args Method parameters.
       
  1194 	 * @return bool True, on success.
       
  1195 	 */
       
  1196 	function wp_editComment($args) {
       
  1197 		$this->escape($args);
       
  1198 
       
  1199 		$blog_id	= (int) $args[0];
       
  1200 		$username	= $args[1];
       
  1201 		$password	= $args[2];
       
  1202 		$comment_ID	= (int) $args[3];
       
  1203 		$content_struct = $args[4];
       
  1204 
       
  1205 		if ( !$user = $this->login($username, $password) ) {
       
  1206 			return $this->error;
       
  1207 		}
       
  1208 
       
  1209 		if ( !current_user_can( 'moderate_comments' ) )
       
  1210 			return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this blog.' ) );
       
  1211 
       
  1212 		do_action('xmlrpc_call', 'wp.editComment');
       
  1213 
       
  1214 		if ( ! get_comment($comment_ID) )
       
  1215 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
       
  1216 
       
  1217 		if ( isset($content_struct['status']) ) {
       
  1218 			$statuses = get_comment_statuses();
       
  1219 			$statuses = array_keys($statuses);
       
  1220 
       
  1221 			if ( ! in_array($content_struct['status'], $statuses) )
       
  1222 				return new IXR_Error( 401, __( 'Invalid comment status.' ) );
       
  1223 			$comment_approved = $content_struct['status'];
       
  1224 		}
       
  1225 
       
  1226 		// Do some timestamp voodoo
       
  1227 		if ( !empty( $content_struct['date_created_gmt'] ) ) {
       
  1228 			$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
       
  1229 			$comment_date = get_date_from_gmt(iso8601_to_datetime($dateCreated));
       
  1230 			$comment_date_gmt = iso8601_to_datetime($dateCreated, GMT);
       
  1231 		}
       
  1232 
       
  1233 		if ( isset($content_struct['content']) )
       
  1234 			$comment_content = $content_struct['content'];
       
  1235 
       
  1236 		if ( isset($content_struct['author']) )
       
  1237 			$comment_author = $content_struct['author'];
       
  1238 
       
  1239 		if ( isset($content_struct['author_url']) )
       
  1240 			$comment_author_url = $content_struct['author_url'];
       
  1241 
       
  1242 		if ( isset($content_struct['author_email']) )
       
  1243 			$comment_author_email = $content_struct['author_email'];
       
  1244 
       
  1245 		// We've got all the data -- post it:
       
  1246 		$comment = compact('comment_ID', 'comment_content', 'comment_approved', 'comment_date', 'comment_date_gmt', 'comment_author', 'comment_author_email', 'comment_author_url');
       
  1247 
       
  1248 		$result = wp_update_comment($comment);
       
  1249 		if ( is_wp_error( $result ) )
       
  1250 			return new IXR_Error(500, $result->get_error_message());
       
  1251 
       
  1252 		if ( !$result )
       
  1253 			return new IXR_Error(500, __('Sorry, the comment could not be edited. Something wrong happened.'));
       
  1254 
       
  1255 		return true;
       
  1256 	}
       
  1257 
       
  1258 	/**
       
  1259 	 * Create new comment.
       
  1260 	 *
       
  1261 	 * @since 2.7.0
       
  1262 	 *
       
  1263 	 * @param array $args Method parameters.
       
  1264 	 * @return mixed {@link wp_new_comment()}
       
  1265 	 */
       
  1266 	function wp_newComment($args) {
       
  1267 		global $wpdb;
       
  1268 
       
  1269 		$this->escape($args);
       
  1270 
       
  1271 		$blog_id	= (int) $args[0];
       
  1272 		$username	= $args[1];
       
  1273 		$password	= $args[2];
       
  1274 		$post		= $args[3];
       
  1275 		$content_struct = $args[4];
       
  1276 
       
  1277 		$allow_anon = apply_filters('xmlrpc_allow_anonymous_comments', false);
       
  1278 
       
  1279 		$user = $this->login($username, $password);
       
  1280 
       
  1281 		if ( !$user ) {
       
  1282 			$logged_in = false;
       
  1283 			if ( $allow_anon && get_option('comment_registration') )
       
  1284 				return new IXR_Error( 403, __( 'You must be registered to comment' ) );
       
  1285 			else if ( !$allow_anon )
       
  1286 				return $this->error;
       
  1287 		} else {
       
  1288 			$logged_in = true;
       
  1289 		}
       
  1290 
       
  1291 		if ( is_numeric($post) )
       
  1292 			$post_id = absint($post);
       
  1293 		else
       
  1294 			$post_id = url_to_postid($post);
       
  1295 
       
  1296 		if ( ! $post_id )
       
  1297 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
       
  1298 
       
  1299 		if ( ! get_post($post_id) )
       
  1300 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
       
  1301 
       
  1302 		$comment['comment_post_ID'] = $post_id;
       
  1303 
       
  1304 		if ( $logged_in ) {
       
  1305 			$comment['comment_author'] = $wpdb->escape( $user->display_name );
       
  1306 			$comment['comment_author_email'] = $wpdb->escape( $user->user_email );
       
  1307 			$comment['comment_author_url'] = $wpdb->escape( $user->user_url );
       
  1308 			$comment['user_ID'] = $user->ID;
       
  1309 		} else {
       
  1310 			$comment['comment_author'] = '';
       
  1311 			if ( isset($content_struct['author']) )
       
  1312 				$comment['comment_author'] = $content_struct['author'];
       
  1313 
       
  1314 			$comment['comment_author_email'] = '';
       
  1315 			if ( isset($content_struct['author_email']) )
       
  1316 				$comment['comment_author_email'] = $content_struct['author_email'];
       
  1317 
       
  1318 			$comment['comment_author_url'] = '';
       
  1319 			if ( isset($content_struct['author_url']) )
       
  1320 				$comment['comment_author_url'] = $content_struct['author_url'];
       
  1321 
       
  1322 			$comment['user_ID'] = 0;
       
  1323 
       
  1324 			if ( get_option('require_name_email') ) {
       
  1325 				if ( 6 > strlen($comment['comment_author_email']) || '' == $comment['comment_author'] )
       
  1326 					return new IXR_Error( 403, __( 'Comment author name and email are required' ) );
       
  1327 				elseif ( !is_email($comment['comment_author_email']) )
       
  1328 					return new IXR_Error( 403, __( 'A valid email address is required' ) );
       
  1329 			}
       
  1330 		}
       
  1331 
       
  1332 		$comment['comment_parent'] = isset($content_struct['comment_parent']) ? absint($content_struct['comment_parent']) : 0;
       
  1333 
       
  1334 		$comment['comment_content'] = $content_struct['content'];
       
  1335 
       
  1336 		do_action('xmlrpc_call', 'wp.newComment');
       
  1337 
       
  1338 		return wp_new_comment($comment);
       
  1339 	}
       
  1340 
       
  1341 	/**
       
  1342 	 * Retrieve all of the comment status.
       
  1343 	 *
       
  1344 	 * @since 2.7.0
       
  1345 	 *
       
  1346 	 * @param array $args Method parameters.
       
  1347 	 * @return array
       
  1348 	 */
       
  1349 	function wp_getCommentStatusList($args) {
       
  1350 		$this->escape( $args );
       
  1351 
       
  1352 		$blog_id	= (int) $args[0];
       
  1353 		$username	= $args[1];
       
  1354 		$password	= $args[2];
       
  1355 
       
  1356 		if ( !$user = $this->login($username, $password) ) {
       
  1357 			return $this->error;
       
  1358 		}
       
  1359 
       
  1360 		if ( !current_user_can( 'moderate_comments' ) )
       
  1361 			return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) );
       
  1362 
       
  1363 		do_action('xmlrpc_call', 'wp.getCommentStatusList');
       
  1364 
       
  1365 		return get_comment_statuses( );
       
  1366 	}
       
  1367 
       
  1368 	/**
       
  1369 	 * Retrieve comment count.
       
  1370 	 *
       
  1371 	 * @since 2.5.0
       
  1372 	 *
       
  1373 	 * @param array $args Method parameters.
       
  1374 	 * @return array
       
  1375 	 */
       
  1376 	function wp_getCommentCount( $args ) {
       
  1377 		$this->escape($args);
       
  1378 
       
  1379 		$blog_id	= (int) $args[0];
       
  1380 		$username	= $args[1];
       
  1381 		$password	= $args[2];
       
  1382 		$post_id	= (int) $args[3];
       
  1383 
       
  1384 		if ( !$user = $this->login($username, $password) ) {
       
  1385 			return $this->error;
       
  1386 		}
       
  1387 
       
  1388 		if( !current_user_can( 'edit_posts' ) ) {
       
  1389 			return new IXR_Error( 403, __( 'You are not allowed access to details about comments.' ) );
       
  1390 		}
       
  1391 
       
  1392 		do_action('xmlrpc_call', 'wp.getCommentCount');
       
  1393 
       
  1394 		$count = wp_count_comments( $post_id );
       
  1395 		return array(
       
  1396 			"approved" => $count->approved,
       
  1397 			"awaiting_moderation" => $count->moderated,
       
  1398 			"spam" => $count->spam,
       
  1399 			"total_comments" => $count->total_comments
       
  1400 		);
       
  1401 	}
       
  1402 
       
  1403 	/**
       
  1404 	 * Retrieve post statuses.
       
  1405 	 *
       
  1406 	 * @since 2.5.0
       
  1407 	 *
       
  1408 	 * @param array $args Method parameters.
       
  1409 	 * @return array
       
  1410 	 */
       
  1411 	function wp_getPostStatusList( $args ) {
       
  1412 		$this->escape( $args );
       
  1413 
       
  1414 		$blog_id	= (int) $args[0];
       
  1415 		$username	= $args[1];
       
  1416 		$password	= $args[2];
       
  1417 
       
  1418 		if ( !$user = $this->login($username, $password) ) {
       
  1419 			return $this->error;
       
  1420 		}
       
  1421 
       
  1422 		if( !current_user_can( 'edit_posts' ) ) {
       
  1423 			return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) );
       
  1424 		}
       
  1425 
       
  1426 		do_action('xmlrpc_call', 'wp.getPostStatusList');
       
  1427 
       
  1428 		return get_post_statuses( );
       
  1429 	}
       
  1430 
       
  1431 	/**
       
  1432 	 * Retrieve page statuses.
       
  1433 	 *
       
  1434 	 * @since 2.5.0
       
  1435 	 *
       
  1436 	 * @param array $args Method parameters.
       
  1437 	 * @return array
       
  1438 	 */
       
  1439 	function wp_getPageStatusList( $args ) {
       
  1440 		$this->escape( $args );
       
  1441 
       
  1442 		$blog_id	= (int) $args[0];
       
  1443 		$username	= $args[1];
       
  1444 		$password	= $args[2];
       
  1445 
       
  1446 		if ( !$user = $this->login($username, $password) ) {
       
  1447 			return $this->error;
       
  1448 		}
       
  1449 
       
  1450 		if( !current_user_can( 'edit_posts' ) ) {
       
  1451 			return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) );
       
  1452 		}
       
  1453 
       
  1454 		do_action('xmlrpc_call', 'wp.getPageStatusList');
       
  1455 
       
  1456 		return get_page_statuses( );
       
  1457 	}
       
  1458 
       
  1459 	/**
       
  1460 	 * Retrieve page templates.
       
  1461 	 *
       
  1462 	 * @since 2.6.0
       
  1463 	 *
       
  1464 	 * @param array $args Method parameters.
       
  1465 	 * @return array
       
  1466 	 */
       
  1467 	function wp_getPageTemplates( $args ) {
       
  1468 		$this->escape( $args );
       
  1469 
       
  1470 		$blog_id	= (int) $args[0];
       
  1471 		$username	= $args[1];
       
  1472 		$password	= $args[2];
       
  1473 
       
  1474 		if ( !$user = $this->login($username, $password) ) {
       
  1475 			return $this->error;
       
  1476 		}
       
  1477 
       
  1478 		if( !current_user_can( 'edit_pages' ) ) {
       
  1479 			return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) );
       
  1480 		}
       
  1481 
       
  1482 		$templates = get_page_templates( );
       
  1483 		$templates['Default'] = 'default';
       
  1484 
       
  1485 		return $templates;
       
  1486 	}
       
  1487 
       
  1488 	/**
       
  1489 	 * Retrieve blog options.
       
  1490 	 *
       
  1491 	 * @since 2.6.0
       
  1492 	 *
       
  1493 	 * @param array $args Method parameters.
       
  1494 	 * @return array
       
  1495 	 */
       
  1496 	function wp_getOptions( $args ) {
       
  1497 		$this->escape( $args );
       
  1498 
       
  1499 		$blog_id	= (int) $args[0];
       
  1500 		$username	= $args[1];
       
  1501 		$password	= $args[2];
       
  1502 		$options	= (array) $args[3];
       
  1503 
       
  1504 		if ( !$user = $this->login($username, $password) ) {
       
  1505 			return $this->error;
       
  1506 		}
       
  1507 
       
  1508 		// If no specific options where asked for, return all of them
       
  1509 		if (count( $options ) == 0 ) {
       
  1510 			$options = array_keys($this->blog_options);
       
  1511 		}
       
  1512 
       
  1513 		return $this->_getOptions($options);
       
  1514 	}
       
  1515 
       
  1516 	/**
       
  1517 	 * Retrieve blog options value from list.
       
  1518 	 *
       
  1519 	 * @since 2.6.0
       
  1520 	 *
       
  1521 	 * @param array $options Options to retrieve.
       
  1522 	 * @return array
       
  1523 	 */
       
  1524 	function _getOptions($options)
       
  1525 	{
       
  1526 		$data = array( );
       
  1527 		foreach( $options as $option ) {
       
  1528 			if( array_key_exists( $option, $this->blog_options ) )
       
  1529 			{
       
  1530 				$data[$option] = $this->blog_options[$option];
       
  1531 				//Is the value static or dynamic?
       
  1532 				if( isset( $data[$option]['option'] ) ) {
       
  1533 					$data[$option]['value'] = get_option( $data[$option]['option'] );
       
  1534 					unset($data[$option]['option']);
       
  1535 				}
       
  1536 			}
       
  1537 		}
       
  1538 
       
  1539 		return $data;
       
  1540 	}
       
  1541 
       
  1542 	/**
       
  1543 	 * Update blog options.
       
  1544 	 *
       
  1545 	 * @since 2.6.0
       
  1546 	 *
       
  1547 	 * @param array $args Method parameters.
       
  1548 	 * @return unknown
       
  1549 	 */
       
  1550 	function wp_setOptions( $args ) {
       
  1551 		$this->escape( $args );
       
  1552 
       
  1553 		$blog_id	= (int) $args[0];
       
  1554 		$username	= $args[1];
       
  1555 		$password	= $args[2];
       
  1556 		$options	= (array) $args[3];
       
  1557 
       
  1558 		if ( !$user = $this->login($username, $password) ) {
       
  1559 			return $this->error;
       
  1560 		}
       
  1561 
       
  1562 		if( !current_user_can( 'manage_options' ) )
       
  1563 			return new IXR_Error( 403, __( 'You are not allowed to update options.' ) );
       
  1564 
       
  1565 		foreach( $options as $o_name => $o_value ) {
       
  1566 			$option_names[] = $o_name;
       
  1567 			if( empty( $o_value ) )
       
  1568 				continue;
       
  1569 
       
  1570 			if( !array_key_exists( $o_name, $this->blog_options ) )
       
  1571 				continue;
       
  1572 
       
  1573 			if( $this->blog_options[$o_name]['readonly'] == true )
       
  1574 				continue;
       
  1575 
       
  1576 			update_option( $this->blog_options[$o_name]['option'], $o_value );
       
  1577 		}
       
  1578 
       
  1579 		//Now return the updated values
       
  1580 		return $this->_getOptions($option_names);
       
  1581 	}
       
  1582 
       
  1583 	/* Blogger API functions.
       
  1584 	 * specs on http://plant.blogger.com/api and http://groups.yahoo.com/group/bloggerDev/
       
  1585 	 */
       
  1586 
       
  1587 	/**
       
  1588 	 * Retrieve blogs that user owns.
       
  1589 	 *
       
  1590 	 * Will make more sense once we support multiple blogs.
       
  1591 	 *
       
  1592 	 * @since 1.5.0
       
  1593 	 *
       
  1594 	 * @param array $args Method parameters.
       
  1595 	 * @return array
       
  1596 	 */
       
  1597 	function blogger_getUsersBlogs($args) {
       
  1598 
       
  1599 		$this->escape($args);
       
  1600 
       
  1601 		$username = $args[1];
       
  1602 		$password  = $args[2];
       
  1603 
       
  1604 		if ( !$user = $this->login($username, $password) ) {
       
  1605 			return $this->error;
       
  1606 		}
       
  1607 
       
  1608 		do_action('xmlrpc_call', 'blogger.getUsersBlogs');
       
  1609 
       
  1610 		$is_admin = current_user_can('manage_options');
       
  1611 
       
  1612 		$struct = array(
       
  1613 			'isAdmin'  => $is_admin,
       
  1614 			'url'      => get_option('home') . '/',
       
  1615 			'blogid'   => '1',
       
  1616 			'blogName' => get_option('blogname'),
       
  1617 			'xmlrpc'   => site_url( 'xmlrpc.php' )
       
  1618 		);
       
  1619 
       
  1620 		return array($struct);
       
  1621 	}
       
  1622 
       
  1623 	/**
       
  1624 	 * Retrieve user's data.
       
  1625 	 *
       
  1626 	 * Gives your client some info about you, so you don't have to.
       
  1627 	 *
       
  1628 	 * @since 1.5.0
       
  1629 	 *
       
  1630 	 * @param array $args Method parameters.
       
  1631 	 * @return array
       
  1632 	 */
       
  1633 	function blogger_getUserInfo($args) {
       
  1634 
       
  1635 		$this->escape($args);
       
  1636 
       
  1637 		$username = $args[1];
       
  1638 		$password  = $args[2];
       
  1639 
       
  1640 		if ( !$user = $this->login($username, $password) ) {
       
  1641 			return $this->error;
       
  1642 		}
       
  1643 
       
  1644 		if( !current_user_can( 'edit_posts' ) )
       
  1645 			return new IXR_Error( 401, __( 'Sorry, you do not have access to user data on this blog.' ) );
       
  1646 
       
  1647 		do_action('xmlrpc_call', 'blogger.getUserInfo');
       
  1648 
       
  1649 		$struct = array(
       
  1650 			'nickname'  => $user->nickname,
       
  1651 			'userid'    => $user->ID,
       
  1652 			'url'       => $user->user_url,
       
  1653 			'lastname'  => $user->last_name,
       
  1654 			'firstname' => $user->first_name
       
  1655 		);
       
  1656 
       
  1657 		return $struct;
       
  1658 	}
       
  1659 
       
  1660 	/**
       
  1661 	 * Retrieve post.
       
  1662 	 *
       
  1663 	 * @since 1.5.0
       
  1664 	 *
       
  1665 	 * @param array $args Method parameters.
       
  1666 	 * @return array
       
  1667 	 */
       
  1668 	function blogger_getPost($args) {
       
  1669 
       
  1670 		$this->escape($args);
       
  1671 
       
  1672 		$post_ID    = (int) $args[1];
       
  1673 		$username = $args[2];
       
  1674 		$password  = $args[3];
       
  1675 
       
  1676 		if ( !$user = $this->login($username, $password) ) {
       
  1677 			return $this->error;
       
  1678 		}
       
  1679 
       
  1680 		if( !current_user_can( 'edit_post', $post_ID ) )
       
  1681 			return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) );
       
  1682 
       
  1683 		do_action('xmlrpc_call', 'blogger.getPost');
       
  1684 
       
  1685 		$post_data = wp_get_single_post($post_ID, ARRAY_A);
       
  1686 
       
  1687 		$categories = implode(',', wp_get_post_categories($post_ID));
       
  1688 
       
  1689 		$content  = '<title>'.stripslashes($post_data['post_title']).'</title>';
       
  1690 		$content .= '<category>'.$categories.'</category>';
       
  1691 		$content .= stripslashes($post_data['post_content']);
       
  1692 
       
  1693 		$struct = array(
       
  1694 			'userid'    => $post_data['post_author'],
       
  1695 			'dateCreated' => new IXR_Date(mysql2date('Ymd\TH:i:s', $post_data['post_date'], false)),
       
  1696 			'content'     => $content,
       
  1697 			'postid'  => $post_data['ID']
       
  1698 		);
       
  1699 
       
  1700 		return $struct;
       
  1701 	}
       
  1702 
       
  1703 	/**
       
  1704 	 * Retrieve list of recent posts.
       
  1705 	 *
       
  1706 	 * @since 1.5.0
       
  1707 	 *
       
  1708 	 * @param array $args Method parameters.
       
  1709 	 * @return array
       
  1710 	 */
       
  1711 	function blogger_getRecentPosts($args) {
       
  1712 
       
  1713 		$this->escape($args);
       
  1714 
       
  1715 		$blog_ID    = (int) $args[1]; /* though we don't use it yet */
       
  1716 		$username = $args[2];
       
  1717 		$password  = $args[3];
       
  1718 		$num_posts  = $args[4];
       
  1719 
       
  1720 		if ( !$user = $this->login($username, $password) ) {
       
  1721 			return $this->error;
       
  1722 		}
       
  1723 
       
  1724 		do_action('xmlrpc_call', 'blogger.getRecentPosts');
       
  1725 
       
  1726 		$posts_list = wp_get_recent_posts($num_posts);
       
  1727 
       
  1728 		if (!$posts_list) {
       
  1729 			$this->error = new IXR_Error(500, __('Either there are no posts, or something went wrong.'));
       
  1730 			return $this->error;
       
  1731 		}
       
  1732 
       
  1733 		foreach ($posts_list as $entry) {
       
  1734 			if( !current_user_can( 'edit_post', $entry['ID'] ) )
       
  1735 				continue;
       
  1736 
       
  1737 			$post_date = mysql2date('Ymd\TH:i:s', $entry['post_date'], false);
       
  1738 			$categories = implode(',', wp_get_post_categories($entry['ID']));
       
  1739 
       
  1740 			$content  = '<title>'.stripslashes($entry['post_title']).'</title>';
       
  1741 			$content .= '<category>'.$categories.'</category>';
       
  1742 			$content .= stripslashes($entry['post_content']);
       
  1743 
       
  1744 			$struct[] = array(
       
  1745 				'userid' => $entry['post_author'],
       
  1746 				'dateCreated' => new IXR_Date($post_date),
       
  1747 				'content' => $content,
       
  1748 				'postid' => $entry['ID'],
       
  1749 			);
       
  1750 
       
  1751 		}
       
  1752 
       
  1753 		$recent_posts = array();
       
  1754 		for ($j=0; $j<count($struct); $j++) {
       
  1755 			array_push($recent_posts, $struct[$j]);
       
  1756 		}
       
  1757 
       
  1758 		return $recent_posts;
       
  1759 	}
       
  1760 
       
  1761 	/**
       
  1762 	 * Retrieve blog_filename content.
       
  1763 	 *
       
  1764 	 * @since 1.5.0
       
  1765 	 *
       
  1766 	 * @param array $args Method parameters.
       
  1767 	 * @return string
       
  1768 	 */
       
  1769 	function blogger_getTemplate($args) {
       
  1770 
       
  1771 		$this->escape($args);
       
  1772 
       
  1773 		$blog_ID    = (int) $args[1];
       
  1774 		$username = $args[2];
       
  1775 		$password  = $args[3];
       
  1776 		$template   = $args[4]; /* could be 'main' or 'archiveIndex', but we don't use it */
       
  1777 
       
  1778 		if ( !$user = $this->login($username, $password) ) {
       
  1779 			return $this->error;
       
  1780 		}
       
  1781 
       
  1782 		do_action('xmlrpc_call', 'blogger.getTemplate');
       
  1783 
       
  1784 		if ( !current_user_can('edit_themes') ) {
       
  1785 			return new IXR_Error(401, __('Sorry, this user can not edit the template.'));
       
  1786 		}
       
  1787 
       
  1788 		/* warning: here we make the assumption that the blog's URL is on the same server */
       
  1789 		$filename = get_option('home') . '/';
       
  1790 		$filename = preg_replace('#https?://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename);
       
  1791 
       
  1792 		$f = fopen($filename, 'r');
       
  1793 		$content = fread($f, filesize($filename));
       
  1794 		fclose($f);
       
  1795 
       
  1796 		/* so it is actually editable with a windows/mac client */
       
  1797 		// 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);
       
  1798 
       
  1799 		return $content;
       
  1800 	}
       
  1801 
       
  1802 	/**
       
  1803 	 * Updates the content of blog_filename.
       
  1804 	 *
       
  1805 	 * @since 1.5.0
       
  1806 	 *
       
  1807 	 * @param array $args Method parameters.
       
  1808 	 * @return bool True when done.
       
  1809 	 */
       
  1810 	function blogger_setTemplate($args) {
       
  1811 
       
  1812 		$this->escape($args);
       
  1813 
       
  1814 		$blog_ID    = (int) $args[1];
       
  1815 		$username = $args[2];
       
  1816 		$password  = $args[3];
       
  1817 		$content    = $args[4];
       
  1818 		$template   = $args[5]; /* could be 'main' or 'archiveIndex', but we don't use it */
       
  1819 
       
  1820 		if ( !$user = $this->login($username, $password) ) {
       
  1821 			return $this->error;
       
  1822 		}
       
  1823 
       
  1824 		do_action('xmlrpc_call', 'blogger.setTemplate');
       
  1825 
       
  1826 		if ( !current_user_can('edit_themes') ) {
       
  1827 			return new IXR_Error(401, __('Sorry, this user cannot edit the template.'));
       
  1828 		}
       
  1829 
       
  1830 		/* warning: here we make the assumption that the blog's URL is on the same server */
       
  1831 		$filename = get_option('home') . '/';
       
  1832 		$filename = preg_replace('#https?://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename);
       
  1833 
       
  1834 		if ($f = fopen($filename, 'w+')) {
       
  1835 			fwrite($f, $content);
       
  1836 			fclose($f);
       
  1837 		} else {
       
  1838 			return new IXR_Error(500, __('Either the file is not writable, or something wrong happened. The file has not been updated.'));
       
  1839 		}
       
  1840 
       
  1841 		return true;
       
  1842 	}
       
  1843 
       
  1844 	/**
       
  1845 	 * Create new post.
       
  1846 	 *
       
  1847 	 * @since 1.5.0
       
  1848 	 *
       
  1849 	 * @param array $args Method parameters.
       
  1850 	 * @return int
       
  1851 	 */
       
  1852 	function blogger_newPost($args) {
       
  1853 
       
  1854 		$this->escape($args);
       
  1855 
       
  1856 		$blog_ID    = (int) $args[1]; /* though we don't use it yet */
       
  1857 		$username = $args[2];
       
  1858 		$password  = $args[3];
       
  1859 		$content    = $args[4];
       
  1860 		$publish    = $args[5];
       
  1861 
       
  1862 		if ( !$user = $this->login($username, $password) ) {
       
  1863 			return $this->error;
       
  1864 		}
       
  1865 
       
  1866 		do_action('xmlrpc_call', 'blogger.newPost');
       
  1867 
       
  1868 		$cap = ($publish) ? 'publish_posts' : 'edit_posts';
       
  1869 		if ( !current_user_can($cap) )
       
  1870 			return new IXR_Error(401, __('Sorry, you are not allowed to post on this blog.'));
       
  1871 
       
  1872 		$post_status = ($publish) ? 'publish' : 'draft';
       
  1873 
       
  1874 		$post_author = $user->ID;
       
  1875 
       
  1876 		$post_title = xmlrpc_getposttitle($content);
       
  1877 		$post_category = xmlrpc_getpostcategory($content);
       
  1878 		$post_content = xmlrpc_removepostdata($content);
       
  1879 
       
  1880 		$post_date = current_time('mysql');
       
  1881 		$post_date_gmt = current_time('mysql', 1);
       
  1882 
       
  1883 		$post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status');
       
  1884 
       
  1885 		$post_ID = wp_insert_post($post_data);
       
  1886 		if ( is_wp_error( $post_ID ) )
       
  1887 			return new IXR_Error(500, $post_ID->get_error_message());
       
  1888 
       
  1889 		if (!$post_ID)
       
  1890 			return new IXR_Error(500, __('Sorry, your entry could not be posted. Something wrong happened.'));
       
  1891 
       
  1892 		$this->attach_uploads( $post_ID, $post_content );
       
  1893 
       
  1894 		logIO('O', "Posted ! ID: $post_ID");
       
  1895 
       
  1896 		return $post_ID;
       
  1897 	}
       
  1898 
       
  1899 	/**
       
  1900 	 * Edit a post.
       
  1901 	 *
       
  1902 	 * @since 1.5.0
       
  1903 	 *
       
  1904 	 * @param array $args Method parameters.
       
  1905 	 * @return bool true when done.
       
  1906 	 */
       
  1907 	function blogger_editPost($args) {
       
  1908 
       
  1909 		$this->escape($args);
       
  1910 
       
  1911 		$post_ID     = (int) $args[1];
       
  1912 		$username  = $args[2];
       
  1913 		$password   = $args[3];
       
  1914 		$content     = $args[4];
       
  1915 		$publish     = $args[5];
       
  1916 
       
  1917 		if ( !$user = $this->login($username, $password) ) {
       
  1918 			return $this->error;
       
  1919 		}
       
  1920 
       
  1921 		do_action('xmlrpc_call', 'blogger.editPost');
       
  1922 
       
  1923 		$actual_post = wp_get_single_post($post_ID,ARRAY_A);
       
  1924 
       
  1925 		if (!$actual_post || $actual_post['post_type'] != 'post') {
       
  1926 			return new IXR_Error(404, __('Sorry, no such post.'));
       
  1927 		}
       
  1928 
       
  1929 		$this->escape($actual_post);
       
  1930 
       
  1931 		if ( !current_user_can('edit_post', $post_ID) )
       
  1932 			return new IXR_Error(401, __('Sorry, you do not have the right to edit this post.'));
       
  1933 
       
  1934 		extract($actual_post, EXTR_SKIP);
       
  1935 
       
  1936 		if ( ('publish' == $post_status) && !current_user_can('publish_posts') )
       
  1937 			return new IXR_Error(401, __('Sorry, you do not have the right to publish this post.'));
       
  1938 
       
  1939 		$post_title = xmlrpc_getposttitle($content);
       
  1940 		$post_category = xmlrpc_getpostcategory($content);
       
  1941 		$post_content = xmlrpc_removepostdata($content);
       
  1942 
       
  1943 		$postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt');
       
  1944 
       
  1945 		$result = wp_update_post($postdata);
       
  1946 
       
  1947 		if (!$result) {
       
  1948 			return new IXR_Error(500, __('For some strange yet very annoying reason, this post could not be edited.'));
       
  1949 		}
       
  1950 		$this->attach_uploads( $ID, $post_content );
       
  1951 
       
  1952 		return true;
       
  1953 	}
       
  1954 
       
  1955 	/**
       
  1956 	 * Remove a post.
       
  1957 	 *
       
  1958 	 * @since 1.5.0
       
  1959 	 *
       
  1960 	 * @param array $args Method parameters.
       
  1961 	 * @return bool True when post is deleted.
       
  1962 	 */
       
  1963 	function blogger_deletePost($args) {
       
  1964 		$this->escape($args);
       
  1965 
       
  1966 		$post_ID     = (int) $args[1];
       
  1967 		$username  = $args[2];
       
  1968 		$password   = $args[3];
       
  1969 		$publish     = $args[4];
       
  1970 
       
  1971 		if ( !$user = $this->login($username, $password) ) {
       
  1972 			return $this->error;
       
  1973 		}
       
  1974 
       
  1975 		do_action('xmlrpc_call', 'blogger.deletePost');
       
  1976 
       
  1977 		$actual_post = wp_get_single_post($post_ID,ARRAY_A);
       
  1978 
       
  1979 		if (!$actual_post || $actual_post['post_type'] != 'post') {
       
  1980 			return new IXR_Error(404, __('Sorry, no such post.'));
       
  1981 		}
       
  1982 
       
  1983 		if ( !current_user_can('edit_post', $post_ID) )
       
  1984 			return new IXR_Error(401, __('Sorry, you do not have the right to delete this post.'));
       
  1985 
       
  1986 		$result = wp_delete_post($post_ID);
       
  1987 
       
  1988 		if (!$result) {
       
  1989 			return new IXR_Error(500, __('For some strange yet very annoying reason, this post could not be deleted.'));
       
  1990 		}
       
  1991 
       
  1992 		return true;
       
  1993 	}
       
  1994 
       
  1995 	/* MetaWeblog API functions
       
  1996 	 * specs on wherever Dave Winer wants them to be
       
  1997 	 */
       
  1998 
       
  1999 	/**
       
  2000 	 * Create a new post.
       
  2001 	 *
       
  2002 	 * @since 1.5.0
       
  2003 	 *
       
  2004 	 * @param array $args Method parameters.
       
  2005 	 * @return int
       
  2006 	 */
       
  2007 	function mw_newPost($args) {
       
  2008 		$this->escape($args);
       
  2009 
       
  2010 		$blog_ID     = (int) $args[0]; // we will support this in the near future
       
  2011 		$username  = $args[1];
       
  2012 		$password   = $args[2];
       
  2013 		$content_struct = $args[3];
       
  2014 		$publish     = $args[4];
       
  2015 
       
  2016 		if ( !$user = $this->login($username, $password) ) {
       
  2017 			return $this->error;
       
  2018 		}
       
  2019 
       
  2020 		do_action('xmlrpc_call', 'metaWeblog.newPost');
       
  2021 
       
  2022 		$cap = ( $publish ) ? 'publish_posts' : 'edit_posts';
       
  2023 		$error_message = __( 'Sorry, you are not allowed to publish posts on this blog.' );
       
  2024 		$post_type = 'post';
       
  2025 		$page_template = '';
       
  2026 		if( !empty( $content_struct['post_type'] ) ) {
       
  2027 			if( $content_struct['post_type'] == 'page' ) {
       
  2028 				$cap = ( $publish ) ? 'publish_pages' : 'edit_pages';
       
  2029 				$error_message = __( 'Sorry, you are not allowed to publish pages on this blog.' );
       
  2030 				$post_type = 'page';
       
  2031 				if( !empty( $content_struct['wp_page_template'] ) )
       
  2032 					$page_template = $content_struct['wp_page_template'];
       
  2033 			}
       
  2034 			elseif( $content_struct['post_type'] == 'post' ) {
       
  2035 				// This is the default, no changes needed
       
  2036 			}
       
  2037 			else {
       
  2038 				// No other post_type values are allowed here
       
  2039 				return new IXR_Error( 401, __( 'Invalid post type.' ) );
       
  2040 			}
       
  2041 		}
       
  2042 
       
  2043 		if( !current_user_can( $cap ) ) {
       
  2044 			return new IXR_Error( 401, $error_message );
       
  2045 		}
       
  2046 
       
  2047 		// Let WordPress generate the post_name (slug) unless
       
  2048 		// one has been provided.
       
  2049 		$post_name = "";
       
  2050 		if(isset($content_struct["wp_slug"])) {
       
  2051 			$post_name = $content_struct["wp_slug"];
       
  2052 		}
       
  2053 
       
  2054 		// Only use a password if one was given.
       
  2055 		if(isset($content_struct["wp_password"])) {
       
  2056 			$post_password = $content_struct["wp_password"];
       
  2057 		}
       
  2058 
       
  2059 		// Only set a post parent if one was provided.
       
  2060 		if(isset($content_struct["wp_page_parent_id"])) {
       
  2061 			$post_parent = $content_struct["wp_page_parent_id"];
       
  2062 		}
       
  2063 
       
  2064 		// Only set the menu_order if it was provided.
       
  2065 		if(isset($content_struct["wp_page_order"])) {
       
  2066 			$menu_order = $content_struct["wp_page_order"];
       
  2067 		}
       
  2068 
       
  2069 		$post_author = $user->ID;
       
  2070 
       
  2071 		// If an author id was provided then use it instead.
       
  2072 		if(
       
  2073 			isset($content_struct["wp_author_id"])
       
  2074 			&& ($user->ID != $content_struct["wp_author_id"])
       
  2075 		) {
       
  2076 			switch($post_type) {
       
  2077 				case "post":
       
  2078 					if(!current_user_can("edit_others_posts")) {
       
  2079 						return(new IXR_Error(401, __("You are not allowed to post as this user")));
       
  2080 					}
       
  2081 					break;
       
  2082 				case "page":
       
  2083 					if(!current_user_can("edit_others_pages")) {
       
  2084 						return(new IXR_Error(401, __("You are not allowed to create pages as this user")));
       
  2085 					}
       
  2086 					break;
       
  2087 				default:
       
  2088 					return(new IXR_Error(401, __("Invalid post type.")));
       
  2089 					break;
       
  2090 			}
       
  2091 			$post_author = $content_struct["wp_author_id"];
       
  2092 		}
       
  2093 
       
  2094 		$post_title = $content_struct['title'];
       
  2095 		$post_content = apply_filters( 'content_save_pre', $content_struct['description'] );
       
  2096 
       
  2097 		$post_status = $publish ? 'publish' : 'draft';
       
  2098 
       
  2099 		if( isset( $content_struct["{$post_type}_status"] ) ) {
       
  2100 			switch( $content_struct["{$post_type}_status"] ) {
       
  2101 				case 'draft':
       
  2102 				case 'private':
       
  2103 				case 'publish':
       
  2104 					$post_status = $content_struct["{$post_type}_status"];
       
  2105 					break;
       
  2106 				case 'pending':
       
  2107 					// Pending is only valid for posts, not pages.
       
  2108 					if( $post_type === 'post' ) {
       
  2109 						$post_status = $content_struct["{$post_type}_status"];
       
  2110 					}
       
  2111 					break;
       
  2112 				default:
       
  2113 					$post_status = $publish ? 'publish' : 'draft';
       
  2114 					break;
       
  2115 			}
       
  2116 		}
       
  2117 
       
  2118 		$post_excerpt = $content_struct['mt_excerpt'];
       
  2119 		$post_more = $content_struct['mt_text_more'];
       
  2120 
       
  2121 		$tags_input = $content_struct['mt_keywords'];
       
  2122 
       
  2123 		if(isset($content_struct["mt_allow_comments"])) {
       
  2124 			if(!is_numeric($content_struct["mt_allow_comments"])) {
       
  2125 				switch($content_struct["mt_allow_comments"]) {
       
  2126 					case "closed":
       
  2127 						$comment_status = "closed";
       
  2128 						break;
       
  2129 					case "open":
       
  2130 						$comment_status = "open";
       
  2131 						break;
       
  2132 					default:
       
  2133 						$comment_status = get_option("default_comment_status");
       
  2134 						break;
       
  2135 				}
       
  2136 			}
       
  2137 			else {
       
  2138 				switch((int) $content_struct["mt_allow_comments"]) {
       
  2139 					case 0:
       
  2140 					case 2:
       
  2141 						$comment_status = "closed";
       
  2142 						break;
       
  2143 					case 1:
       
  2144 						$comment_status = "open";
       
  2145 						break;
       
  2146 					default:
       
  2147 						$comment_status = get_option("default_comment_status");
       
  2148 						break;
       
  2149 				}
       
  2150 			}
       
  2151 		}
       
  2152 		else {
       
  2153 			$comment_status = get_option("default_comment_status");
       
  2154 		}
       
  2155 
       
  2156 		if(isset($content_struct["mt_allow_pings"])) {
       
  2157 			if(!is_numeric($content_struct["mt_allow_pings"])) {
       
  2158 				switch($content_struct['mt_allow_pings']) {
       
  2159 					case "closed":
       
  2160 						$ping_status = "closed";
       
  2161 						break;
       
  2162 					case "open":
       
  2163 						$ping_status = "open";
       
  2164 						break;
       
  2165 					default:
       
  2166 						$ping_status = get_option("default_ping_status");
       
  2167 						break;
       
  2168 				}
       
  2169 			}
       
  2170 			else {
       
  2171 				switch((int) $content_struct["mt_allow_pings"]) {
       
  2172 					case 0:
       
  2173 						$ping_status = "closed";
       
  2174 						break;
       
  2175 					case 1:
       
  2176 						$ping_status = "open";
       
  2177 						break;
       
  2178 					default:
       
  2179 						$ping_status = get_option("default_ping_status");
       
  2180 						break;
       
  2181 				}
       
  2182 			}
       
  2183 		}
       
  2184 		else {
       
  2185 			$ping_status = get_option("default_ping_status");
       
  2186 		}
       
  2187 
       
  2188 		if ($post_more) {
       
  2189 			$post_content = $post_content . "<!--more-->" . $post_more;
       
  2190 		}
       
  2191 
       
  2192 		$to_ping = $content_struct['mt_tb_ping_urls'];
       
  2193 		if ( is_array($to_ping) )
       
  2194 			$to_ping = implode(' ', $to_ping);
       
  2195 
       
  2196 		// Do some timestamp voodoo
       
  2197 		if ( !empty( $content_struct['date_created_gmt'] ) )
       
  2198 			$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
       
  2199 		elseif ( !empty( $content_struct['dateCreated']) )
       
  2200 			$dateCreated = $content_struct['dateCreated']->getIso();
       
  2201 
       
  2202 		if ( !empty( $dateCreated ) ) {
       
  2203 			$post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated));
       
  2204 			$post_date_gmt = iso8601_to_datetime($dateCreated, GMT);
       
  2205 		} else {
       
  2206 			$post_date = current_time('mysql');
       
  2207 			$post_date_gmt = current_time('mysql', 1);
       
  2208 		}
       
  2209 
       
  2210 		$catnames = $content_struct['categories'];
       
  2211 		logIO('O', 'Post cats: ' . var_export($catnames,true));
       
  2212 		$post_category = array();
       
  2213 
       
  2214 		if (is_array($catnames)) {
       
  2215 			foreach ($catnames as $cat) {
       
  2216 				$post_category[] = get_cat_ID($cat);
       
  2217 			}
       
  2218 		}
       
  2219 
       
  2220 		// We've got all the data -- post it:
       
  2221 		$postdata = compact('post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'to_ping', 'post_type', 'post_name', 'post_password', 'post_parent', 'menu_order', 'tags_input', 'page_template');
       
  2222 
       
  2223 		$post_ID = wp_insert_post($postdata, true);
       
  2224 		if ( is_wp_error( $post_ID ) )
       
  2225 			return new IXR_Error(500, $post_ID->get_error_message());
       
  2226 
       
  2227 		if (!$post_ID) {
       
  2228 			return new IXR_Error(500, __('Sorry, your entry could not be posted. Something wrong happened.'));
       
  2229 		}
       
  2230 
       
  2231 		// Only posts can be sticky
       
  2232 		if ( $post_type == 'post' && isset( $content_struct['sticky'] ) )
       
  2233 			if ( $content_struct['sticky'] == true )
       
  2234 				stick_post( $post_ID );
       
  2235 			elseif ( $content_struct['sticky'] == false )
       
  2236 				unstick_post( $post_ID );
       
  2237 
       
  2238 		if ( isset($content_struct['custom_fields']) ) {
       
  2239 			$this->set_custom_fields($post_ID, $content_struct['custom_fields']);
       
  2240 		}
       
  2241 
       
  2242 		// Handle enclosures
       
  2243 		$this->add_enclosure_if_new($post_ID, $content_struct['enclosure']);
       
  2244 
       
  2245 		$this->attach_uploads( $post_ID, $post_content );
       
  2246 
       
  2247 		logIO('O', "Posted ! ID: $post_ID");
       
  2248 
       
  2249 		return strval($post_ID);
       
  2250 	}
       
  2251 
       
  2252 	function add_enclosure_if_new($post_ID, $enclosure) {
       
  2253 		if( is_array( $enclosure ) && isset( $enclosure['url'] ) && isset( $enclosure['length'] ) && isset( $enclosure['type'] ) ) {
       
  2254 
       
  2255 			$encstring = $enclosure['url'] . "\n" . $enclosure['length'] . "\n" . $enclosure['type'];
       
  2256 			$found = false;
       
  2257 			foreach ( (array) get_post_custom($post_ID) as $key => $val) {
       
  2258 				if ($key == 'enclosure') {
       
  2259 					foreach ( (array) $val as $enc ) {
       
  2260 						if ($enc == $encstring) {
       
  2261 							$found = true;
       
  2262 							break 2;
       
  2263 						}
       
  2264 					}
       
  2265 				}
       
  2266 			}
       
  2267 			if (!$found) {
       
  2268 				add_post_meta( $post_ID, 'enclosure', $encstring );
       
  2269 			}
       
  2270 		}
       
  2271 	}
       
  2272 
       
  2273 	/**
       
  2274 	 * Attach upload to a post.
       
  2275 	 *
       
  2276 	 * @since 2.1.0
       
  2277 	 *
       
  2278 	 * @param int $post_ID Post ID.
       
  2279 	 * @param string $post_content Post Content for attachment.
       
  2280 	 */
       
  2281 	function attach_uploads( $post_ID, $post_content ) {
       
  2282 		global $wpdb;
       
  2283 
       
  2284 		// find any unattached files
       
  2285 		$attachments = $wpdb->get_results( "SELECT ID, guid FROM {$wpdb->posts} WHERE post_parent = '-1' AND post_type = 'attachment'" );
       
  2286 		if( is_array( $attachments ) ) {
       
  2287 			foreach( $attachments as $file ) {
       
  2288 				if( strpos( $post_content, $file->guid ) !== false ) {
       
  2289 					$wpdb->update($wpdb->posts, array('post_parent' => $post_ID), array('ID' => $file->ID) );
       
  2290 				}
       
  2291 			}
       
  2292 		}
       
  2293 	}
       
  2294 
       
  2295 	/**
       
  2296 	 * Edit a post.
       
  2297 	 *
       
  2298 	 * @since 1.5.0
       
  2299 	 *
       
  2300 	 * @param array $args Method parameters.
       
  2301 	 * @return bool True on success.
       
  2302 	 */
       
  2303 	function mw_editPost($args) {
       
  2304 
       
  2305 		$this->escape($args);
       
  2306 
       
  2307 		$post_ID     = (int) $args[0];
       
  2308 		$username  = $args[1];
       
  2309 		$password   = $args[2];
       
  2310 		$content_struct = $args[3];
       
  2311 		$publish     = $args[4];
       
  2312 
       
  2313 		if ( !$user = $this->login($username, $password) ) {
       
  2314 			return $this->error;
       
  2315 		}
       
  2316 
       
  2317 		do_action('xmlrpc_call', 'metaWeblog.editPost');
       
  2318 
       
  2319 		$cap = ( $publish ) ? 'publish_posts' : 'edit_posts';
       
  2320 		$error_message = __( 'Sorry, you are not allowed to publish posts on this blog.' );
       
  2321 		$post_type = 'post';
       
  2322 		$page_template = '';
       
  2323 		if( !empty( $content_struct['post_type'] ) ) {
       
  2324 			if( $content_struct['post_type'] == 'page' ) {
       
  2325 				$cap = ( $publish ) ? 'publish_pages' : 'edit_pages';
       
  2326 				$error_message = __( 'Sorry, you are not allowed to publish pages on this blog.' );
       
  2327 				$post_type = 'page';
       
  2328 				if( !empty( $content_struct['wp_page_template'] ) )
       
  2329 					$page_template = $content_struct['wp_page_template'];
       
  2330 			}
       
  2331 			elseif( $content_struct['post_type'] == 'post' ) {
       
  2332 				// This is the default, no changes needed
       
  2333 			}
       
  2334 			else {
       
  2335 				// No other post_type values are allowed here
       
  2336 				return new IXR_Error( 401, __( 'Invalid post type.' ) );
       
  2337 			}
       
  2338 		}
       
  2339 
       
  2340 		if( !current_user_can( $cap ) ) {
       
  2341 			return new IXR_Error( 401, $error_message );
       
  2342 		}
       
  2343 
       
  2344 		$postdata = wp_get_single_post($post_ID, ARRAY_A);
       
  2345 
       
  2346 		// If there is no post data for the give post id, stop
       
  2347 		// now and return an error.  Other wise a new post will be
       
  2348 		// created (which was the old behavior).
       
  2349 		if(empty($postdata["ID"])) {
       
  2350 			return(new IXR_Error(404, __("Invalid post ID.")));
       
  2351 		}
       
  2352 
       
  2353 		$this->escape($postdata);
       
  2354 		extract($postdata, EXTR_SKIP);
       
  2355 
       
  2356 		// Let WordPress manage slug if none was provided.
       
  2357 		$post_name = "";
       
  2358 		if(isset($content_struct["wp_slug"])) {
       
  2359 			$post_name = $content_struct["wp_slug"];
       
  2360 		}
       
  2361 
       
  2362 		// Only use a password if one was given.
       
  2363 		if(isset($content_struct["wp_password"])) {
       
  2364 			$post_password = $content_struct["wp_password"];
       
  2365 		}
       
  2366 
       
  2367 		// Only set a post parent if one was given.
       
  2368 		if(isset($content_struct["wp_page_parent_id"])) {
       
  2369 			$post_parent = $content_struct["wp_page_parent_id"];
       
  2370 		}
       
  2371 
       
  2372 		// Only set the menu_order if it was given.
       
  2373 		if(isset($content_struct["wp_page_order"])) {
       
  2374 			$menu_order = $content_struct["wp_page_order"];
       
  2375 		}
       
  2376 
       
  2377 		$post_author = $postdata["post_author"];
       
  2378 
       
  2379 		// Only set the post_author if one is set.
       
  2380 		if(
       
  2381 			isset($content_struct["wp_author_id"])
       
  2382 			&& ($user->ID != $content_struct["wp_author_id"])
       
  2383 		) {
       
  2384 			switch($post_type) {
       
  2385 				case "post":
       
  2386 					if(!current_user_can("edit_others_posts")) {
       
  2387 						return(new IXR_Error(401, __("You are not allowed to change the post author as this user.")));
       
  2388 					}
       
  2389 					break;
       
  2390 				case "page":
       
  2391 					if(!current_user_can("edit_others_pages")) {
       
  2392 						return(new IXR_Error(401, __("You are not allowed to change the page author as this user.")));
       
  2393 					}
       
  2394 					break;
       
  2395 				default:
       
  2396 					return(new IXR_Error(401, __("Invalid post type.")));
       
  2397 					break;
       
  2398 			}
       
  2399 			$post_author = $content_struct["wp_author_id"];
       
  2400 		}
       
  2401 
       
  2402 		if(isset($content_struct["mt_allow_comments"])) {
       
  2403 			if(!is_numeric($content_struct["mt_allow_comments"])) {
       
  2404 				switch($content_struct["mt_allow_comments"]) {
       
  2405 					case "closed":
       
  2406 						$comment_status = "closed";
       
  2407 						break;
       
  2408 					case "open":
       
  2409 						$comment_status = "open";
       
  2410 						break;
       
  2411 					default:
       
  2412 						$comment_status = get_option("default_comment_status");
       
  2413 						break;
       
  2414 				}
       
  2415 			}
       
  2416 			else {
       
  2417 				switch((int) $content_struct["mt_allow_comments"]) {
       
  2418 					case 0:
       
  2419 					case 2:
       
  2420 						$comment_status = "closed";
       
  2421 						break;
       
  2422 					case 1:
       
  2423 						$comment_status = "open";
       
  2424 						break;
       
  2425 					default:
       
  2426 						$comment_status = get_option("default_comment_status");
       
  2427 						break;
       
  2428 				}
       
  2429 			}
       
  2430 		}
       
  2431 
       
  2432 		if(isset($content_struct["mt_allow_pings"])) {
       
  2433 			if(!is_numeric($content_struct["mt_allow_pings"])) {
       
  2434 				switch($content_struct["mt_allow_pings"]) {
       
  2435 					case "closed":
       
  2436 						$ping_status = "closed";
       
  2437 						break;
       
  2438 					case "open":
       
  2439 						$ping_status = "open";
       
  2440 						break;
       
  2441 					default:
       
  2442 						$ping_status = get_option("default_ping_status");
       
  2443 						break;
       
  2444 				}
       
  2445 			}
       
  2446 			else {
       
  2447 				switch((int) $content_struct["mt_allow_pings"]) {
       
  2448 					case 0:
       
  2449 						$ping_status = "closed";
       
  2450 						break;
       
  2451 					case 1:
       
  2452 						$ping_status = "open";
       
  2453 						break;
       
  2454 					default:
       
  2455 						$ping_status = get_option("default_ping_status");
       
  2456 						break;
       
  2457 				}
       
  2458 			}
       
  2459 		}
       
  2460 
       
  2461 		$post_title = $content_struct['title'];
       
  2462 		$post_content = apply_filters( 'content_save_pre', $content_struct['description'] );
       
  2463 		$catnames = $content_struct['categories'];
       
  2464 
       
  2465 		$post_category = array();
       
  2466 
       
  2467 		if (is_array($catnames)) {
       
  2468 			foreach ($catnames as $cat) {
       
  2469 		 		$post_category[] = get_cat_ID($cat);
       
  2470 			}
       
  2471 		}
       
  2472 
       
  2473 		$post_excerpt = $content_struct['mt_excerpt'];
       
  2474 		$post_more = $content_struct['mt_text_more'];
       
  2475 
       
  2476 		$post_status = $publish ? 'publish' : 'draft';
       
  2477 		if( isset( $content_struct["{$post_type}_status"] ) ) {
       
  2478 			switch( $content_struct["{$post_type}_status"] ) {
       
  2479 				case 'draft':
       
  2480 				case 'private':
       
  2481 				case 'publish':
       
  2482 					$post_status = $content_struct["{$post_type}_status"];
       
  2483 					break;
       
  2484 				case 'pending':
       
  2485 					// Pending is only valid for posts, not pages.
       
  2486 					if( $post_type === 'post' ) {
       
  2487 						$post_status = $content_struct["{$post_type}_status"];
       
  2488 					}
       
  2489 					break;
       
  2490 				default:
       
  2491 					$post_status = $publish ? 'publish' : 'draft';
       
  2492 					break;
       
  2493 			}
       
  2494 		}
       
  2495 
       
  2496 		$tags_input = $content_struct['mt_keywords'];
       
  2497 
       
  2498 		if ( ('publish' == $post_status) ) {
       
  2499 			if ( ( 'page' == $post_type ) && !current_user_can('publish_pages') )
       
  2500 				return new IXR_Error(401, __('Sorry, you do not have the right to publish this page.'));
       
  2501 			else if ( !current_user_can('publish_posts') )
       
  2502 				return new IXR_Error(401, __('Sorry, you do not have the right to publish this post.'));
       
  2503 		}
       
  2504 
       
  2505 		if ($post_more) {
       
  2506 			$post_content = $post_content . "<!--more-->" . $post_more;
       
  2507 		}
       
  2508 
       
  2509 		$to_ping = $content_struct['mt_tb_ping_urls'];
       
  2510 		if ( is_array($to_ping) )
       
  2511 			$to_ping = implode(' ', $to_ping);
       
  2512 
       
  2513 		// Do some timestamp voodoo
       
  2514 		if ( !empty( $content_struct['date_created_gmt'] ) )
       
  2515 			$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
       
  2516 		elseif ( !empty( $content_struct['dateCreated']) )
       
  2517 			$dateCreated = $content_struct['dateCreated']->getIso();
       
  2518 
       
  2519 		if ( !empty( $dateCreated ) ) {
       
  2520 			$post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated));
       
  2521 			$post_date_gmt = iso8601_to_datetime($dateCreated, GMT);
       
  2522 		} else {
       
  2523 			$post_date     = $postdata['post_date'];
       
  2524 			$post_date_gmt = $postdata['post_date_gmt'];
       
  2525 		}
       
  2526 
       
  2527 		// We've got all the data -- post it:
       
  2528 		$newpost = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'post_date', 'post_date_gmt', 'to_ping', 'post_name', 'post_password', 'post_parent', 'menu_order', 'post_author', 'tags_input', 'page_template');
       
  2529 
       
  2530 		$result = wp_update_post($newpost, true);
       
  2531 		if ( is_wp_error( $result ) )
       
  2532 			return new IXR_Error(500, $result->get_error_message());
       
  2533 
       
  2534 		if (!$result) {
       
  2535 			return new IXR_Error(500, __('Sorry, your entry could not be edited. Something wrong happened.'));
       
  2536 		}
       
  2537 
       
  2538 		// Only posts can be sticky
       
  2539 		if ( $post_type == 'post' && isset( $content_struct['sticky'] ) )
       
  2540 			if ( $content_struct['sticky'] == true )
       
  2541 				stick_post( $post_ID );
       
  2542 			elseif ( $content_struct['sticky'] == false )
       
  2543 				unstick_post( $post_ID );
       
  2544 
       
  2545 		if ( isset($content_struct['custom_fields']) ) {
       
  2546 			$this->set_custom_fields($post_ID, $content_struct['custom_fields']);
       
  2547 		}
       
  2548 
       
  2549 		// Handle enclosures
       
  2550 		$this->add_enclosure_if_new($post_ID, $content_struct['enclosure']);
       
  2551 
       
  2552 		$this->attach_uploads( $ID, $post_content );
       
  2553 
       
  2554 		logIO('O',"(MW) Edited ! ID: $post_ID");
       
  2555 
       
  2556 		return true;
       
  2557 	}
       
  2558 
       
  2559 	/**
       
  2560 	 * Retrieve post.
       
  2561 	 *
       
  2562 	 * @since 1.5.0
       
  2563 	 *
       
  2564 	 * @param array $args Method parameters.
       
  2565 	 * @return array
       
  2566 	 */
       
  2567 	function mw_getPost($args) {
       
  2568 
       
  2569 		$this->escape($args);
       
  2570 
       
  2571 		$post_ID     = (int) $args[0];
       
  2572 		$username  = $args[1];
       
  2573 		$password   = $args[2];
       
  2574 
       
  2575 		if ( !$user = $this->login($username, $password) ) {
       
  2576 			return $this->error;
       
  2577 		}
       
  2578 
       
  2579 		if( !current_user_can( 'edit_post', $post_ID ) )
       
  2580 			return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) );
       
  2581 
       
  2582 		do_action('xmlrpc_call', 'metaWeblog.getPost');
       
  2583 
       
  2584 		$postdata = wp_get_single_post($post_ID, ARRAY_A);
       
  2585 
       
  2586 		if ($postdata['post_date'] != '') {
       
  2587 			$post_date = mysql2date('Ymd\TH:i:s', $postdata['post_date'], false);
       
  2588 			$post_date_gmt = mysql2date('Ymd\TH:i:s', $postdata['post_date_gmt'], false);
       
  2589 
       
  2590 			// For drafts use the GMT version of the post date
       
  2591 			if ( $postdata['post_status'] == 'draft' ) {
       
  2592 				$post_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $postdata['post_date'] ), 'Ymd\TH:i:s' );
       
  2593 			}
       
  2594 
       
  2595 			$categories = array();
       
  2596 			$catids = wp_get_post_categories($post_ID);
       
  2597 			foreach($catids as $catid)
       
  2598 				$categories[] = get_cat_name($catid);
       
  2599 
       
  2600 			$tagnames = array();
       
  2601 			$tags = wp_get_post_tags( $post_ID );
       
  2602 			if ( !empty( $tags ) ) {
       
  2603 				foreach ( $tags as $tag )
       
  2604 					$tagnames[] = $tag->name;
       
  2605 				$tagnames = implode( ', ', $tagnames );
       
  2606 			} else {
       
  2607 				$tagnames = '';
       
  2608 			}
       
  2609 
       
  2610 			$post = get_extended($postdata['post_content']);
       
  2611 			$link = post_permalink($postdata['ID']);
       
  2612 
       
  2613 			// Get the author info.
       
  2614 			$author = get_userdata($postdata['post_author']);
       
  2615 
       
  2616 			$allow_comments = ('open' == $postdata['comment_status']) ? 1 : 0;
       
  2617 			$allow_pings = ('open' == $postdata['ping_status']) ? 1 : 0;
       
  2618 
       
  2619 			// Consider future posts as published
       
  2620 			if( $postdata['post_status'] === 'future' ) {
       
  2621 				$postdata['post_status'] = 'publish';
       
  2622 			}
       
  2623 
       
  2624 			$sticky = false;
       
  2625 			if ( is_sticky( $post_ID ) )
       
  2626 				$sticky = true;
       
  2627 
       
  2628 			$enclosure = array();
       
  2629 			foreach ( (array) get_post_custom($post_ID) as $key => $val) {
       
  2630 				if ($key == 'enclosure') {
       
  2631 					foreach ( (array) $val as $enc ) {
       
  2632 						$encdata = split("\n", $enc);
       
  2633 						$enclosure['url'] = trim(htmlspecialchars($encdata[0]));
       
  2634 						$enclosure['length'] = trim($encdata[1]);
       
  2635 						$enclosure['type'] = trim($encdata[2]);
       
  2636 						break 2;
       
  2637 					}
       
  2638 				}
       
  2639 			}
       
  2640 
       
  2641 			$resp = array(
       
  2642 				'dateCreated' => new IXR_Date($post_date),
       
  2643 				'userid' => $postdata['post_author'],
       
  2644 				'postid' => $postdata['ID'],
       
  2645 				'description' => $post['main'],
       
  2646 				'title' => $postdata['post_title'],
       
  2647 				'link' => $link,
       
  2648 				'permaLink' => $link,
       
  2649 				// commented out because no other tool seems to use this
       
  2650 				//	      'content' => $entry['post_content'],
       
  2651 				'categories' => $categories,
       
  2652 				'mt_excerpt' => $postdata['post_excerpt'],
       
  2653 				'mt_text_more' => $post['extended'],
       
  2654 				'mt_allow_comments' => $allow_comments,
       
  2655 				'mt_allow_pings' => $allow_pings,
       
  2656 				'mt_keywords' => $tagnames,
       
  2657 				'wp_slug' => $postdata['post_name'],
       
  2658 				'wp_password' => $postdata['post_password'],
       
  2659 				'wp_author_id' => $author->ID,
       
  2660 				'wp_author_display_name'	=> $author->display_name,
       
  2661 				'date_created_gmt' => new IXR_Date($post_date_gmt),
       
  2662 				'post_status' => $postdata['post_status'],
       
  2663 				'custom_fields' => $this->get_custom_fields($post_ID),
       
  2664 				'sticky' => $sticky
       
  2665 			);
       
  2666 
       
  2667 			if (!empty($enclosure)) $resp['enclosure'] = $enclosure;
       
  2668 
       
  2669 			return $resp;
       
  2670 		} else {
       
  2671 			return new IXR_Error(404, __('Sorry, no such post.'));
       
  2672 		}
       
  2673 	}
       
  2674 
       
  2675 	/**
       
  2676 	 * Retrieve list of recent posts.
       
  2677 	 *
       
  2678 	 * @since 1.5.0
       
  2679 	 *
       
  2680 	 * @param array $args Method parameters.
       
  2681 	 * @return array
       
  2682 	 */
       
  2683 	function mw_getRecentPosts($args) {
       
  2684 
       
  2685 		$this->escape($args);
       
  2686 
       
  2687 		$blog_ID     = (int) $args[0];
       
  2688 		$username  = $args[1];
       
  2689 		$password   = $args[2];
       
  2690 		$num_posts   = (int) $args[3];
       
  2691 
       
  2692 		if ( !$user = $this->login($username, $password) ) {
       
  2693 			return $this->error;
       
  2694 		}
       
  2695 
       
  2696 		do_action('xmlrpc_call', 'metaWeblog.getRecentPosts');
       
  2697 
       
  2698 		$posts_list = wp_get_recent_posts($num_posts);
       
  2699 
       
  2700 		if (!$posts_list) {
       
  2701 			return array( );
       
  2702 		}
       
  2703 
       
  2704 		foreach ($posts_list as $entry) {
       
  2705 			if( !current_user_can( 'edit_post', $entry['ID'] ) )
       
  2706 				continue;
       
  2707 
       
  2708 			$post_date = mysql2date('Ymd\TH:i:s', $entry['post_date'], false);
       
  2709 			$post_date_gmt = mysql2date('Ymd\TH:i:s', $entry['post_date_gmt'], false);
       
  2710 
       
  2711 			// For drafts use the GMT version of the date
       
  2712 			if ( $entry['post_status'] == 'draft' ) {
       
  2713 				$post_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $entry['post_date'] ), 'Ymd\TH:i:s' );
       
  2714 			}
       
  2715 
       
  2716 			$categories = array();
       
  2717 			$catids = wp_get_post_categories($entry['ID']);
       
  2718 			foreach($catids as $catid) {
       
  2719 				$categories[] = get_cat_name($catid);
       
  2720 			}
       
  2721 
       
  2722 			$tagnames = array();
       
  2723 			$tags = wp_get_post_tags( $entry['ID'] );
       
  2724 			if ( !empty( $tags ) ) {
       
  2725 				foreach ( $tags as $tag ) {
       
  2726 					$tagnames[] = $tag->name;
       
  2727 				}
       
  2728 				$tagnames = implode( ', ', $tagnames );
       
  2729 			} else {
       
  2730 				$tagnames = '';
       
  2731 			}
       
  2732 
       
  2733 			$post = get_extended($entry['post_content']);
       
  2734 			$link = post_permalink($entry['ID']);
       
  2735 
       
  2736 			// Get the post author info.
       
  2737 			$author = get_userdata($entry['post_author']);
       
  2738 
       
  2739 			$allow_comments = ('open' == $entry['comment_status']) ? 1 : 0;
       
  2740 			$allow_pings = ('open' == $entry['ping_status']) ? 1 : 0;
       
  2741 
       
  2742 			// Consider future posts as published
       
  2743 			if( $entry['post_status'] === 'future' ) {
       
  2744 				$entry['post_status'] = 'publish';
       
  2745 			}
       
  2746 
       
  2747 			$struct[] = array(
       
  2748 				'dateCreated' => new IXR_Date($post_date),
       
  2749 				'userid' => $entry['post_author'],
       
  2750 				'postid' => $entry['ID'],
       
  2751 				'description' => $post['main'],
       
  2752 				'title' => $entry['post_title'],
       
  2753 				'link' => $link,
       
  2754 				'permaLink' => $link,
       
  2755 				// commented out because no other tool seems to use this
       
  2756 				// 'content' => $entry['post_content'],
       
  2757 				'categories' => $categories,
       
  2758 				'mt_excerpt' => $entry['post_excerpt'],
       
  2759 				'mt_text_more' => $post['extended'],
       
  2760 				'mt_allow_comments' => $allow_comments,
       
  2761 				'mt_allow_pings' => $allow_pings,
       
  2762 				'mt_keywords' => $tagnames,
       
  2763 				'wp_slug' => $entry['post_name'],
       
  2764 				'wp_password' => $entry['post_password'],
       
  2765 				'wp_author_id' => $author->ID,
       
  2766 				'wp_author_display_name' => $author->display_name,
       
  2767 				'date_created_gmt' => new IXR_Date($post_date_gmt),
       
  2768 				'post_status' => $entry['post_status'],
       
  2769 				'custom_fields' => $this->get_custom_fields($entry['ID'])
       
  2770 			);
       
  2771 
       
  2772 		}
       
  2773 
       
  2774 		$recent_posts = array();
       
  2775 		for ($j=0; $j<count($struct); $j++) {
       
  2776 			array_push($recent_posts, $struct[$j]);
       
  2777 		}
       
  2778 
       
  2779 		return $recent_posts;
       
  2780 	}
       
  2781 
       
  2782 	/**
       
  2783 	 * Retrieve the list of categories on a given blog.
       
  2784 	 *
       
  2785 	 * @since 1.5.0
       
  2786 	 *
       
  2787 	 * @param array $args Method parameters.
       
  2788 	 * @return array
       
  2789 	 */
       
  2790 	function mw_getCategories($args) {
       
  2791 
       
  2792 		$this->escape($args);
       
  2793 
       
  2794 		$blog_ID     = (int) $args[0];
       
  2795 		$username  = $args[1];
       
  2796 		$password   = $args[2];
       
  2797 
       
  2798 		if ( !$user = $this->login($username, $password) ) {
       
  2799 			return $this->error;
       
  2800 		}
       
  2801 
       
  2802 		if( !current_user_can( 'edit_posts' ) )
       
  2803 			return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this blog in order to view categories.' ) );
       
  2804 
       
  2805 		do_action('xmlrpc_call', 'metaWeblog.getCategories');
       
  2806 
       
  2807 		$categories_struct = array();
       
  2808 
       
  2809 		if ( $cats = get_categories('get=all') ) {
       
  2810 			foreach ( $cats as $cat ) {
       
  2811 				$struct['categoryId'] = $cat->term_id;
       
  2812 				$struct['parentId'] = $cat->parent;
       
  2813 				$struct['description'] = $cat->name;
       
  2814 				$struct['categoryDescription'] = $cat->description;
       
  2815 				$struct['categoryName'] = $cat->name;
       
  2816 				$struct['htmlUrl'] = esc_html(get_category_link($cat->term_id));
       
  2817 				$struct['rssUrl'] = esc_html(get_category_feed_link($cat->term_id, 'rss2'));
       
  2818 
       
  2819 				$categories_struct[] = $struct;
       
  2820 			}
       
  2821 		}
       
  2822 
       
  2823 		return $categories_struct;
       
  2824 	}
       
  2825 
       
  2826 	/**
       
  2827 	 * Uploads a file, following your settings.
       
  2828 	 *
       
  2829 	 * Adapted from a patch by Johann Richard.
       
  2830 	 *
       
  2831 	 * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/
       
  2832 	 *
       
  2833 	 * @since 1.5.0
       
  2834 	 *
       
  2835 	 * @param array $args Method parameters.
       
  2836 	 * @return array
       
  2837 	 */
       
  2838 	function mw_newMediaObject($args) {
       
  2839 		global $wpdb;
       
  2840 
       
  2841 		$blog_ID     = (int) $args[0];
       
  2842 		$username  = $wpdb->escape($args[1]);
       
  2843 		$password   = $wpdb->escape($args[2]);
       
  2844 		$data        = $args[3];
       
  2845 
       
  2846 		$name = sanitize_file_name( $data['name'] );
       
  2847 		$type = $data['type'];
       
  2848 		$bits = $data['bits'];
       
  2849 
       
  2850 		logIO('O', '(MW) Received '.strlen($bits).' bytes');
       
  2851 
       
  2852 		if ( !$user = $this->login($username, $password) ) {
       
  2853 			return $this->error;
       
  2854 		}
       
  2855 
       
  2856 		do_action('xmlrpc_call', 'metaWeblog.newMediaObject');
       
  2857 
       
  2858 		if ( !current_user_can('upload_files') ) {
       
  2859 			logIO('O', '(MW) User does not have upload_files capability');
       
  2860 			$this->error = new IXR_Error(401, __('You are not allowed to upload files to this site.'));
       
  2861 			return $this->error;
       
  2862 		}
       
  2863 
       
  2864 		if ( $upload_err = apply_filters( "pre_upload_error", false ) )
       
  2865 			return new IXR_Error(500, $upload_err);
       
  2866 
       
  2867 		if(!empty($data["overwrite"]) && ($data["overwrite"] == true)) {
       
  2868 			// Get postmeta info on the object.
       
  2869 			$old_file = $wpdb->get_row("
       
  2870 				SELECT ID
       
  2871 				FROM {$wpdb->posts}
       
  2872 				WHERE post_title = '{$name}'
       
  2873 					AND post_type = 'attachment'
       
  2874 			");
       
  2875 
       
  2876 			// Delete previous file.
       
  2877 			wp_delete_attachment($old_file->ID);
       
  2878 
       
  2879 			// Make sure the new name is different by pre-pending the
       
  2880 			// previous post id.
       
  2881 			$filename = preg_replace("/^wpid\d+-/", "", $name);
       
  2882 			$name = "wpid{$old_file->ID}-{$filename}";
       
  2883 		}
       
  2884 
       
  2885 		$upload = wp_upload_bits($name, $type, $bits);
       
  2886 		if ( ! empty($upload['error']) ) {
       
  2887 			$errorString = sprintf(__('Could not write file %1$s (%2$s)'), $name, $upload['error']);
       
  2888 			logIO('O', '(MW) ' . $errorString);
       
  2889 			return new IXR_Error(500, $errorString);
       
  2890 		}
       
  2891 		// Construct the attachment array
       
  2892 		// attach to post_id -1
       
  2893 		$post_id = -1;
       
  2894 		$attachment = array(
       
  2895 			'post_title' => $name,
       
  2896 			'post_content' => '',
       
  2897 			'post_type' => 'attachment',
       
  2898 			'post_parent' => $post_id,
       
  2899 			'post_mime_type' => $type,
       
  2900 			'guid' => $upload[ 'url' ]
       
  2901 		);
       
  2902 
       
  2903 		// Save the data
       
  2904 		$id = wp_insert_attachment( $attachment, $upload[ 'file' ], $post_id );
       
  2905 		wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) );
       
  2906 
       
  2907 		return apply_filters( 'wp_handle_upload', array( 'file' => $name, 'url' => $upload[ 'url' ], 'type' => $type ) );
       
  2908 	}
       
  2909 
       
  2910 	/* MovableType API functions
       
  2911 	 * specs on http://www.movabletype.org/docs/mtmanual_programmatic.html
       
  2912 	 */
       
  2913 
       
  2914 	/**
       
  2915 	 * Retrieve the post titles of recent posts.
       
  2916 	 *
       
  2917 	 * @since 1.5.0
       
  2918 	 *
       
  2919 	 * @param array $args Method parameters.
       
  2920 	 * @return array
       
  2921 	 */
       
  2922 	function mt_getRecentPostTitles($args) {
       
  2923 
       
  2924 		$this->escape($args);
       
  2925 
       
  2926 		$blog_ID     = (int) $args[0];
       
  2927 		$username  = $args[1];
       
  2928 		$password   = $args[2];
       
  2929 		$num_posts   = (int) $args[3];
       
  2930 
       
  2931 		if ( !$user = $this->login($username, $password) ) {
       
  2932 			return $this->error;
       
  2933 		}
       
  2934 
       
  2935 		do_action('xmlrpc_call', 'mt.getRecentPostTitles');
       
  2936 
       
  2937 		$posts_list = wp_get_recent_posts($num_posts);
       
  2938 
       
  2939 		if (!$posts_list) {
       
  2940 			$this->error = new IXR_Error(500, __('Either there are no posts, or something went wrong.'));
       
  2941 			return $this->error;
       
  2942 		}
       
  2943 
       
  2944 		foreach ($posts_list as $entry) {
       
  2945 			if( !current_user_can( 'edit_post', $entry['ID'] ) )
       
  2946 				continue;
       
  2947 
       
  2948 			$post_date = mysql2date('Ymd\TH:i:s', $entry['post_date'], false);
       
  2949 			$post_date_gmt = mysql2date('Ymd\TH:i:s', $entry['post_date_gmt'], false);
       
  2950 
       
  2951 			// For drafts use the GMT version of the date
       
  2952 			if ( $entry['post_status'] == 'draft' ) {
       
  2953 				$post_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $entry['post_date'] ), 'Ymd\TH:i:s' );
       
  2954 			}
       
  2955 
       
  2956 			$struct[] = array(
       
  2957 				'dateCreated' => new IXR_Date($post_date),
       
  2958 				'userid' => $entry['post_author'],
       
  2959 				'postid' => $entry['ID'],
       
  2960 				'title' => $entry['post_title'],
       
  2961 				'date_created_gmt' => new IXR_Date($post_date_gmt)
       
  2962 			);
       
  2963 
       
  2964 		}
       
  2965 
       
  2966 		$recent_posts = array();
       
  2967 		for ($j=0; $j<count($struct); $j++) {
       
  2968 			array_push($recent_posts, $struct[$j]);
       
  2969 		}
       
  2970 
       
  2971 		return $recent_posts;
       
  2972 	}
       
  2973 
       
  2974 	/**
       
  2975 	 * Retrieve list of all categories on blog.
       
  2976 	 *
       
  2977 	 * @since 1.5.0
       
  2978 	 *
       
  2979 	 * @param array $args Method parameters.
       
  2980 	 * @return array
       
  2981 	 */
       
  2982 	function mt_getCategoryList($args) {
       
  2983 
       
  2984 		$this->escape($args);
       
  2985 
       
  2986 		$blog_ID     = (int) $args[0];
       
  2987 		$username  = $args[1];
       
  2988 		$password   = $args[2];
       
  2989 
       
  2990 		if ( !$user = $this->login($username, $password) ) {
       
  2991 			return $this->error;
       
  2992 		}
       
  2993 
       
  2994 		if( !current_user_can( 'edit_posts' ) )
       
  2995 			return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this blog in order to view categories.' ) );
       
  2996 
       
  2997 		do_action('xmlrpc_call', 'mt.getCategoryList');
       
  2998 
       
  2999 		$categories_struct = array();
       
  3000 
       
  3001 		if ( $cats = get_categories('hide_empty=0&hierarchical=0') ) {
       
  3002 			foreach ($cats as $cat) {
       
  3003 				$struct['categoryId'] = $cat->term_id;
       
  3004 				$struct['categoryName'] = $cat->name;
       
  3005 
       
  3006 				$categories_struct[] = $struct;
       
  3007 			}
       
  3008 		}
       
  3009 
       
  3010 		return $categories_struct;
       
  3011 	}
       
  3012 
       
  3013 	/**
       
  3014 	 * Retrieve post categories.
       
  3015 	 *
       
  3016 	 * @since 1.5.0
       
  3017 	 *
       
  3018 	 * @param array $args Method parameters.
       
  3019 	 * @return array
       
  3020 	 */
       
  3021 	function mt_getPostCategories($args) {
       
  3022 
       
  3023 		$this->escape($args);
       
  3024 
       
  3025 		$post_ID     = (int) $args[0];
       
  3026 		$username  = $args[1];
       
  3027 		$password   = $args[2];
       
  3028 
       
  3029 		if ( !$user = $this->login($username, $password) ) {
       
  3030 			return $this->error;
       
  3031 		}
       
  3032 
       
  3033 		if( !current_user_can( 'edit_post', $post_ID ) )
       
  3034 			return new IXR_Error( 401, __( 'Sorry, you can not edit this post.' ) );
       
  3035 
       
  3036 		do_action('xmlrpc_call', 'mt.getPostCategories');
       
  3037 
       
  3038 		$categories = array();
       
  3039 		$catids = wp_get_post_categories(intval($post_ID));
       
  3040 		// first listed category will be the primary category
       
  3041 		$isPrimary = true;
       
  3042 		foreach($catids as $catid) {
       
  3043 			$categories[] = array(
       
  3044 				'categoryName' => get_cat_name($catid),
       
  3045 				'categoryId' => (string) $catid,
       
  3046 				'isPrimary' => $isPrimary
       
  3047 			);
       
  3048 			$isPrimary = false;
       
  3049 		}
       
  3050 
       
  3051 		return $categories;
       
  3052 	}
       
  3053 
       
  3054 	/**
       
  3055 	 * Sets categories for a post.
       
  3056 	 *
       
  3057 	 * @since 1.5.0
       
  3058 	 *
       
  3059 	 * @param array $args Method parameters.
       
  3060 	 * @return bool True on success.
       
  3061 	 */
       
  3062 	function mt_setPostCategories($args) {
       
  3063 
       
  3064 		$this->escape($args);
       
  3065 
       
  3066 		$post_ID     = (int) $args[0];
       
  3067 		$username  = $args[1];
       
  3068 		$password   = $args[2];
       
  3069 		$categories  = $args[3];
       
  3070 
       
  3071 		if ( !$user = $this->login($username, $password) ) {
       
  3072 			return $this->error;
       
  3073 		}
       
  3074 
       
  3075 		do_action('xmlrpc_call', 'mt.setPostCategories');
       
  3076 
       
  3077 		if ( !current_user_can('edit_post', $post_ID) )
       
  3078 			return new IXR_Error(401, __('Sorry, you cannot edit this post.'));
       
  3079 
       
  3080 		foreach($categories as $cat) {
       
  3081 			$catids[] = $cat['categoryId'];
       
  3082 		}
       
  3083 
       
  3084 		wp_set_post_categories($post_ID, $catids);
       
  3085 
       
  3086 		return true;
       
  3087 	}
       
  3088 
       
  3089 	/**
       
  3090 	 * Retrieve an array of methods supported by this server.
       
  3091 	 *
       
  3092 	 * @since 1.5.0
       
  3093 	 *
       
  3094 	 * @param array $args Method parameters.
       
  3095 	 * @return array
       
  3096 	 */
       
  3097 	function mt_supportedMethods($args) {
       
  3098 
       
  3099 		do_action('xmlrpc_call', 'mt.supportedMethods');
       
  3100 
       
  3101 		$supported_methods = array();
       
  3102 		foreach($this->methods as $key=>$value) {
       
  3103 			$supported_methods[] = $key;
       
  3104 		}
       
  3105 
       
  3106 		return $supported_methods;
       
  3107 	}
       
  3108 
       
  3109 	/**
       
  3110 	 * Retrieve an empty array because we don't support per-post text filters.
       
  3111 	 *
       
  3112 	 * @since 1.5.0
       
  3113 	 *
       
  3114 	 * @param array $args Method parameters.
       
  3115 	 */
       
  3116 	function mt_supportedTextFilters($args) {
       
  3117 		do_action('xmlrpc_call', 'mt.supportedTextFilters');
       
  3118 		return apply_filters('xmlrpc_text_filters', array());
       
  3119 	}
       
  3120 
       
  3121 	/**
       
  3122 	 * Retrieve trackbacks sent to a given post.
       
  3123 	 *
       
  3124 	 * @since 1.5.0
       
  3125 	 *
       
  3126 	 * @param array $args Method parameters.
       
  3127 	 * @return mixed
       
  3128 	 */
       
  3129 	function mt_getTrackbackPings($args) {
       
  3130 
       
  3131 		global $wpdb;
       
  3132 
       
  3133 		$post_ID = intval($args);
       
  3134 
       
  3135 		do_action('xmlrpc_call', 'mt.getTrackbackPings');
       
  3136 
       
  3137 		$actual_post = wp_get_single_post($post_ID, ARRAY_A);
       
  3138 
       
  3139 		if (!$actual_post) {
       
  3140 			return new IXR_Error(404, __('Sorry, no such post.'));
       
  3141 		}
       
  3142 
       
  3143 		$comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID) );
       
  3144 
       
  3145 		if (!$comments) {
       
  3146 			return array();
       
  3147 		}
       
  3148 
       
  3149 		$trackback_pings = array();
       
  3150 		foreach($comments as $comment) {
       
  3151 			if ( 'trackback' == $comment->comment_type ) {
       
  3152 				$content = $comment->comment_content;
       
  3153 				$title = substr($content, 8, (strpos($content, '</strong>') - 8));
       
  3154 				$trackback_pings[] = array(
       
  3155 					'pingTitle' => $title,
       
  3156 					'pingURL'   => $comment->comment_author_url,
       
  3157 					'pingIP'    => $comment->comment_author_IP
       
  3158 				);
       
  3159 		}
       
  3160 		}
       
  3161 
       
  3162 		return $trackback_pings;
       
  3163 	}
       
  3164 
       
  3165 	/**
       
  3166 	 * Sets a post's publish status to 'publish'.
       
  3167 	 *
       
  3168 	 * @since 1.5.0
       
  3169 	 *
       
  3170 	 * @param array $args Method parameters.
       
  3171 	 * @return int
       
  3172 	 */
       
  3173 	function mt_publishPost($args) {
       
  3174 
       
  3175 		$this->escape($args);
       
  3176 
       
  3177 		$post_ID     = (int) $args[0];
       
  3178 		$username  = $args[1];
       
  3179 		$password   = $args[2];
       
  3180 
       
  3181 		if ( !$user = $this->login($username, $password) ) {
       
  3182 			return $this->error;
       
  3183 		}
       
  3184 
       
  3185 		do_action('xmlrpc_call', 'mt.publishPost');
       
  3186 
       
  3187 		if ( !current_user_can('edit_post', $post_ID) )
       
  3188 			return new IXR_Error(401, __('Sorry, you cannot edit this post.'));
       
  3189 
       
  3190 		$postdata = wp_get_single_post($post_ID,ARRAY_A);
       
  3191 
       
  3192 		$postdata['post_status'] = 'publish';
       
  3193 
       
  3194 		// retain old cats
       
  3195 		$cats = wp_get_post_categories($post_ID);
       
  3196 		$postdata['post_category'] = $cats;
       
  3197 		$this->escape($postdata);
       
  3198 
       
  3199 		$result = wp_update_post($postdata);
       
  3200 
       
  3201 		return $result;
       
  3202 	}
       
  3203 
       
  3204 	/* PingBack functions
       
  3205 	 * specs on www.hixie.ch/specs/pingback/pingback
       
  3206 	 */
       
  3207 
       
  3208 	/**
       
  3209 	 * Retrieves a pingback and registers it.
       
  3210 	 *
       
  3211 	 * @since 1.5.0
       
  3212 	 *
       
  3213 	 * @param array $args Method parameters.
       
  3214 	 * @return array
       
  3215 	 */
       
  3216 	function pingback_ping($args) {
       
  3217 		global $wpdb;
       
  3218 
       
  3219 		do_action('xmlrpc_call', 'pingback.ping');
       
  3220 
       
  3221 		$this->escape($args);
       
  3222 
       
  3223 		$pagelinkedfrom = $args[0];
       
  3224 		$pagelinkedto   = $args[1];
       
  3225 
       
  3226 		$title = '';
       
  3227 
       
  3228 		$pagelinkedfrom = str_replace('&amp;', '&', $pagelinkedfrom);
       
  3229 		$pagelinkedto = str_replace('&amp;', '&', $pagelinkedto);
       
  3230 		$pagelinkedto = str_replace('&', '&amp;', $pagelinkedto);
       
  3231 
       
  3232 		// Check if the page linked to is in our site
       
  3233 		$pos1 = strpos($pagelinkedto, str_replace(array('http://www.','http://','https://www.','https://'), '', get_option('home')));
       
  3234 		if( !$pos1 )
       
  3235 			return new IXR_Error(0, __('Is there no link to us?'));
       
  3236 
       
  3237 		// let's find which post is linked to
       
  3238 		// FIXME: does url_to_postid() cover all these cases already?
       
  3239 		//        if so, then let's use it and drop the old code.
       
  3240 		$urltest = parse_url($pagelinkedto);
       
  3241 		if ($post_ID = url_to_postid($pagelinkedto)) {
       
  3242 			$way = 'url_to_postid()';
       
  3243 		} elseif (preg_match('#p/[0-9]{1,}#', $urltest['path'], $match)) {
       
  3244 			// the path defines the post_ID (archives/p/XXXX)
       
  3245 			$blah = explode('/', $match[0]);
       
  3246 			$post_ID = (int) $blah[1];
       
  3247 			$way = 'from the path';
       
  3248 		} elseif (preg_match('#p=[0-9]{1,}#', $urltest['query'], $match)) {
       
  3249 			// the querystring defines the post_ID (?p=XXXX)
       
  3250 			$blah = explode('=', $match[0]);
       
  3251 			$post_ID = (int) $blah[1];
       
  3252 			$way = 'from the querystring';
       
  3253 		} elseif (isset($urltest['fragment'])) {
       
  3254 			// an #anchor is there, it's either...
       
  3255 			if (intval($urltest['fragment'])) {
       
  3256 				// ...an integer #XXXX (simpliest case)
       
  3257 				$post_ID = (int) $urltest['fragment'];
       
  3258 				$way = 'from the fragment (numeric)';
       
  3259 			} elseif (preg_match('/post-[0-9]+/',$urltest['fragment'])) {
       
  3260 				// ...a post id in the form 'post-###'
       
  3261 				$post_ID = preg_replace('/[^0-9]+/', '', $urltest['fragment']);
       
  3262 				$way = 'from the fragment (post-###)';
       
  3263 			} elseif (is_string($urltest['fragment'])) {
       
  3264 				// ...or a string #title, a little more complicated
       
  3265 				$title = preg_replace('/[^a-z0-9]/i', '.', $urltest['fragment']);
       
  3266 				$sql = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_title RLIKE %s", $title);
       
  3267 				if (! ($post_ID = $wpdb->get_var($sql)) ) {
       
  3268 					// returning unknown error '0' is better than die()ing
       
  3269 			  		return new IXR_Error(0, '');
       
  3270 				}
       
  3271 				$way = 'from the fragment (title)';
       
  3272 			}
       
  3273 		} else {
       
  3274 			// TODO: Attempt to extract a post ID from the given URL
       
  3275 	  		return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn&#8217;t exist, or it is not a pingback-enabled resource.'));
       
  3276 		}
       
  3277 		$post_ID = (int) $post_ID;
       
  3278 
       
  3279 
       
  3280 		logIO("O","(PB) URL='$pagelinkedto' ID='$post_ID' Found='$way'");
       
  3281 
       
  3282 		$post = get_post($post_ID);
       
  3283 
       
  3284 		if ( !$post ) // Post_ID not found
       
  3285 	  		return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn&#8217;t exist, or it is not a pingback-enabled resource.'));
       
  3286 
       
  3287 		if ( $post_ID == url_to_postid($pagelinkedfrom) )
       
  3288 			return new IXR_Error(0, __('The source URL and the target URL cannot both point to the same resource.'));
       
  3289 
       
  3290 		// Check if pings are on
       
  3291 		if ( !pings_open($post) )
       
  3292 	  		return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn&#8217;t exist, or it is not a pingback-enabled resource.'));
       
  3293 
       
  3294 		// Let's check that the remote site didn't already pingback this entry
       
  3295 		$wpdb->get_results( $wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_author_url = %s", $post_ID, $pagelinkedfrom) );
       
  3296 
       
  3297 		if ( $wpdb->num_rows ) // We already have a Pingback from this URL
       
  3298 	  		return new IXR_Error(48, __('The pingback has already been registered.'));
       
  3299 
       
  3300 		// very stupid, but gives time to the 'from' server to publish !
       
  3301 		sleep(1);
       
  3302 
       
  3303 		// Let's check the remote site
       
  3304 		$linea = wp_remote_fopen( $pagelinkedfrom );
       
  3305 		if ( !$linea )
       
  3306 	  		return new IXR_Error(16, __('The source URL does not exist.'));
       
  3307 
       
  3308 		$linea = apply_filters('pre_remote_source', $linea, $pagelinkedto);
       
  3309 
       
  3310 		// Work around bug in strip_tags():
       
  3311 		$linea = str_replace('<!DOC', '<DOC', $linea);
       
  3312 		$linea = preg_replace( '/[\s\r\n\t]+/', ' ', $linea ); // normalize spaces
       
  3313 		$linea = preg_replace( "/ <(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/", "\n\n", $linea );
       
  3314 
       
  3315 		preg_match('|<title>([^<]*?)</title>|is', $linea, $matchtitle);
       
  3316 		$title = $matchtitle[1];
       
  3317 		if ( empty( $title ) )
       
  3318 			return new IXR_Error(32, __('We cannot find a title on that page.'));
       
  3319 
       
  3320 		$linea = strip_tags( $linea, '<a>' ); // just keep the tag we need
       
  3321 
       
  3322 		$p = explode( "\n\n", $linea );
       
  3323 
       
  3324 		$preg_target = preg_quote($pagelinkedto, '|');
       
  3325 
       
  3326 		foreach ( $p as $para ) {
       
  3327 			if ( strpos($para, $pagelinkedto) !== false ) { // it exists, but is it a link?
       
  3328 				preg_match("|<a[^>]+?".$preg_target."[^>]*>([^>]+?)</a>|", $para, $context);
       
  3329 
       
  3330 				// If the URL isn't in a link context, keep looking
       
  3331 				if ( empty($context) )
       
  3332 					continue;
       
  3333 
       
  3334 				// We're going to use this fake tag to mark the context in a bit
       
  3335 				// the marker is needed in case the link text appears more than once in the paragraph
       
  3336 				$excerpt = preg_replace('|\</?wpcontext\>|', '', $para);
       
  3337 
       
  3338 				// prevent really long link text
       
  3339 				if ( strlen($context[1]) > 100 )
       
  3340 					$context[1] = substr($context[1], 0, 100) . '...';
       
  3341 
       
  3342 				$marker = '<wpcontext>'.$context[1].'</wpcontext>';    // set up our marker
       
  3343 				$excerpt= str_replace($context[0], $marker, $excerpt); // swap out the link for our marker
       
  3344 				$excerpt = strip_tags($excerpt, '<wpcontext>');        // strip all tags but our context marker
       
  3345 				$excerpt = trim($excerpt);
       
  3346 				$preg_marker = preg_quote($marker, '|');
       
  3347 				$excerpt = preg_replace("|.*?\s(.{0,100}$preg_marker.{0,100})\s.*|s", '$1', $excerpt);
       
  3348 				$excerpt = strip_tags($excerpt); // YES, again, to remove the marker wrapper
       
  3349 				break;
       
  3350 			}
       
  3351 		}
       
  3352 
       
  3353 		if ( empty($context) ) // Link to target not found
       
  3354 			return new IXR_Error(17, __('The source URL does not contain a link to the target URL, and so cannot be used as a source.'));
       
  3355 
       
  3356 		$pagelinkedfrom = str_replace('&', '&amp;', $pagelinkedfrom);
       
  3357 
       
  3358 		$context = '[...] ' . esc_html( $excerpt ) . ' [...]';
       
  3359 		$pagelinkedfrom = $wpdb->escape( $pagelinkedfrom );
       
  3360 
       
  3361 		$comment_post_ID = (int) $post_ID;
       
  3362 		$comment_author = $title;
       
  3363 		$this->escape($comment_author);
       
  3364 		$comment_author_url = $pagelinkedfrom;
       
  3365 		$comment_content = $context;
       
  3366 		$this->escape($comment_content);
       
  3367 		$comment_type = 'pingback';
       
  3368 
       
  3369 		$commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_url', 'comment_content', 'comment_type');
       
  3370 
       
  3371 		$comment_ID = wp_new_comment($commentdata);
       
  3372 		do_action('pingback_post', $comment_ID);
       
  3373 
       
  3374 		return sprintf(__('Pingback from %1$s to %2$s registered. Keep the web talking! :-)'), $pagelinkedfrom, $pagelinkedto);
       
  3375 	}
       
  3376 
       
  3377 	/**
       
  3378 	 * Retrieve array of URLs that pingbacked the given URL.
       
  3379 	 *
       
  3380 	 * Specs on http://www.aquarionics.com/misc/archives/blogite/0198.html
       
  3381 	 *
       
  3382 	 * @since 1.5.0
       
  3383 	 *
       
  3384 	 * @param array $args Method parameters.
       
  3385 	 * @return array
       
  3386 	 */
       
  3387 	function pingback_extensions_getPingbacks($args) {
       
  3388 
       
  3389 		global $wpdb;
       
  3390 
       
  3391 		do_action('xmlrpc_call', 'pingback.extensions.getPingbacks');
       
  3392 
       
  3393 		$this->escape($args);
       
  3394 
       
  3395 		$url = $args;
       
  3396 
       
  3397 		$post_ID = url_to_postid($url);
       
  3398 		if (!$post_ID) {
       
  3399 			// We aren't sure that the resource is available and/or pingback enabled
       
  3400 	  		return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn&#8217;t exist, or it is not a pingback-enabled resource.'));
       
  3401 		}
       
  3402 
       
  3403 		$actual_post = wp_get_single_post($post_ID, ARRAY_A);
       
  3404 
       
  3405 		if (!$actual_post) {
       
  3406 			// No such post = resource not found
       
  3407 	  		return new IXR_Error(32, __('The specified target URL does not exist.'));
       
  3408 		}
       
  3409 
       
  3410 		$comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID) );
       
  3411 
       
  3412 		if (!$comments) {
       
  3413 			return array();
       
  3414 		}
       
  3415 
       
  3416 		$pingbacks = array();
       
  3417 		foreach($comments as $comment) {
       
  3418 			if ( 'pingback' == $comment->comment_type )
       
  3419 				$pingbacks[] = $comment->comment_author_url;
       
  3420 		}
       
  3421 
       
  3422 		return $pingbacks;
       
  3423 	}
       
  3424 }
       
  3425 
       
  3426 $wp_xmlrpc_server = new wp_xmlrpc_server();
       
  3427 
       
  3428 ?>