| [ Root ] [ Search ] [ Index ] |
PHP Cross Reference of WordPress MU 2.9.2Provided by Yoast |
[Summary view] [Print] [Text view]
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 } 205 206 function serve_request() { 207 $this->IXR_Server($this->methods); 208 } 209 210 /** 211 * Test XMLRPC API by saying, "Hello!" to client. 212 * 213 * @since 1.5.0 214 * 215 * @param array $args Method Parameters. 216 * @return string 217 */ 218 function sayHello($args) { 219 return 'Hello!'; 220 } 221 222 /** 223 * Test XMLRPC API by adding two numbers for client. 224 * 225 * @since 1.5.0 226 * 227 * @param array $args Method Parameters. 228 * @return int 229 */ 230 function addTwoNumbers($args) { 231 $number1 = $args[0]; 232 $number2 = $args[1]; 233 return $number1 + $number2; 234 } 235 236 /** 237 * Check user's credentials. 238 * 239 * @since 1.5.0 240 * 241 * @param string $user_login User's username. 242 * @param string $user_pass User's password. 243 * @return bool Whether authentication passed. 244 * @deprecated use wp_xmlrpc_server::login 245 * @see wp_xmlrpc_server::login 246 */ 247 function login_pass_ok($user_login, $user_pass) { 248 if ( !get_option( 'enable_xmlrpc' ) ) { 249 $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') ) ); 250 return false; 251 } 252 253 if (!user_pass_ok($user_login, $user_pass)) { 254 $this->error = new IXR_Error(403, __('Bad login/pass combination.')); 255 return false; 256 } 257 return true; 258 } 259 260 /** 261 * Log user in. 262 * 263 * @since 2.8 264 * 265 * @param string $username User's username. 266 * @param string $password User's password. 267 * @return mixed WP_User object if authentication passed, false otherwise 268 */ 269 function login($username, $password) { 270 if ( !get_option( 'enable_xmlrpc' ) ) { 271 $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') ) ); 272 return false; 273 } 274 275 $user = wp_authenticate($username, $password); 276 277 if (is_wp_error($user)) { 278 $this->error = new IXR_Error(403, __('Bad login/pass combination.')); 279 return false; 280 } 281 282 set_current_user( $user->ID ); 283 return $user; 284 } 285 286 /** 287 * Sanitize string or array of strings for database. 288 * 289 * @since 1.5.2 290 * 291 * @param string|array $array Sanitize single string or array of strings. 292 * @return string|array Type matches $array and sanitized for the database. 293 */ 294 function escape(&$array) { 295 global $wpdb; 296 297 if(!is_array($array)) { 298 return($wpdb->escape($array)); 299 } 300 else { 301 foreach ( (array) $array as $k => $v ) { 302 if (is_array($v)) { 303 $this->escape($array[$k]); 304 } else if (is_object($v)) { 305 //skip 306 } else { 307 $array[$k] = $wpdb->escape($v); 308 } 309 } 310 } 311 } 312 313 /** 314 * Retrieve custom fields for post. 315 * 316 * @since 2.5.0 317 * 318 * @param int $post_id Post ID. 319 * @return array Custom fields, if exist. 320 */ 321 function get_custom_fields($post_id) { 322 $post_id = (int) $post_id; 323 324 $custom_fields = array(); 325 326 foreach ( (array) has_meta($post_id) as $meta ) { 327 // Don't expose protected fields. 328 if ( strpos($meta['meta_key'], '_wp_') === 0 ) { 329 continue; 330 } 331 332 $custom_fields[] = array( 333 "id" => $meta['meta_id'], 334 "key" => $meta['meta_key'], 335 "value" => $meta['meta_value'] 336 ); 337 } 338 339 return $custom_fields; 340 } 341 342 /** 343 * Set custom fields for post. 344 * 345 * @since 2.5.0 346 * 347 * @param int $post_id Post ID. 348 * @param array $fields Custom fields. 349 */ 350 function set_custom_fields($post_id, $fields) { 351 $post_id = (int) $post_id; 352 353 foreach ( (array) $fields as $meta ) { 354 if ( isset($meta['id']) ) { 355 $meta['id'] = (int) $meta['id']; 356 357 if ( isset($meta['key']) ) { 358 update_meta($meta['id'], $meta['key'], $meta['value']); 359 } 360 else { 361 delete_meta($meta['id']); 362 } 363 } 364 else { 365 $_POST['metakeyinput'] = $meta['key']; 366 $_POST['metavalue'] = $meta['value']; 367 add_meta($post_id); 368 } 369 } 370 } 371 372 /** 373 * Setup blog options property. 374 * 375 * Passes property through 'xmlrpc_blog_options' filter. 376 * 377 * @since 2.6.0 378 */ 379 function initialise_blog_option_info( ) { 380 global $wp_version; 381 382 $this->blog_options = array( 383 // Read only options 384 'software_name' => array( 385 'desc' => __( 'Software Name' ), 386 'readonly' => true, 387 'value' => 'WordPress' 388 ), 389 'software_version' => array( 390 'desc' => __( 'Software Version' ), 391 'readonly' => true, 392 'value' => $wp_version 393 ), 394 'blog_url' => array( 395 'desc' => __( 'Blog URL' ), 396 'readonly' => true, 397 'option' => 'siteurl' 398 ), 399 400 // Updatable options 401 'time_zone' => array( 402 'desc' => __( 'Time Zone' ), 403 'readonly' => false, 404 'option' => 'gmt_offset' 405 ), 406 'blog_title' => array( 407 'desc' => __( 'Blog Title' ), 408 'readonly' => false, 409 'option' => 'blogname' 410 ), 411 'blog_tagline' => array( 412 'desc' => __( 'Blog Tagline' ), 413 'readonly' => false, 414 'option' => 'blogdescription' 415 ), 416 'date_format' => array( 417 'desc' => __( 'Date Format' ), 418 'readonly' => false, 419 'option' => 'date_format' 420 ), 421 'time_format' => array( 422 'desc' => __( 'Time Format' ), 423 'readonly' => false, 424 'option' => 'time_format' 425 ), 426 'users_can_register' => array( 427 'desc' => __( 'Allow new users to sign up' ), 428 'readonly' => false, 429 'option' => 'users_can_register' 430 ) 431 ); 432 433 $this->blog_options = apply_filters( 'xmlrpc_blog_options', $this->blog_options ); 434 } 435 436 /** 437 * Retrieve the blogs of the user. 438 * 439 * @since 2.6.0 440 * 441 * @param array $args Method parameters. 442 * @return array 443 */ 444 function wp_getUsersBlogs( $args ) { 445 global $current_site; 446 // If this isn't on WPMU then just use blogger_getUsersBlogs 447 if( !function_exists( 'is_site_admin' ) ) { 448 array_unshift( $args, 1 ); 449 return $this->blogger_getUsersBlogs( $args ); 450 } 451 452 $this->escape( $args ); 453 454 $username = $args[0]; 455 $password = $args[1]; 456 457 if ( !$user = $this->login($username, $password) ) { 458 return $this->error; 459 } 460 461 do_action( 'xmlrpc_call', 'wp.getUsersBlogs' ); 462 463 $blogs = (array) get_blogs_of_user( $user->ID ); 464 $struct = array( ); 465 466 foreach( $blogs as $blog ) { 467 // Don't include blogs that aren't hosted at this site 468 if( $blog->site_id != $current_site->id ) 469 continue; 470 471 $blog_id = $blog->userblog_id; 472 switch_to_blog($blog_id); 473 $is_admin = current_user_can('level_8'); 474 475 $struct[] = array( 476 'isAdmin' => $is_admin, 477 'url' => get_option( 'home' ) . '/', 478 'blogid' => $blog_id, 479 'blogName' => get_option( 'blogname' ), 480 'xmlrpc' => site_url( 'xmlrpc.php' ) 481 ); 482 483 restore_current_blog( ); 484 } 485 486 return $struct; 487 } 488 489 /** 490 * Retrieve page. 491 * 492 * @since 2.2.0 493 * 494 * @param array $args Method parameters. 495 * @return array 496 */ 497 function wp_getPage($args) { 498 $this->escape($args); 499 500 $blog_id = (int) $args[0]; 501 $page_id = (int) $args[1]; 502 $username = $args[2]; 503 $password = $args[3]; 504 505 if ( !$user = $this->login($username, $password) ) { 506 return $this->error; 507 } 508 509 if( !current_user_can( 'edit_page', $page_id ) ) 510 return new IXR_Error( 401, __( 'Sorry, you cannot edit this page.' ) ); 511 512 do_action('xmlrpc_call', 'wp.getPage'); 513 514 // Lookup page info. 515 $page = get_page($page_id); 516 517 // If we found the page then format the data. 518 if($page->ID && ($page->post_type == "page")) { 519 // Get all of the page content and link. 520 $full_page = get_extended($page->post_content); 521 $link = post_permalink($page->ID); 522 523 // Get info the page parent if there is one. 524 $parent_title = ""; 525 if(!empty($page->post_parent)) { 526 $parent = get_page($page->post_parent); 527 $parent_title = $parent->post_title; 528 } 529 530 // Determine comment and ping settings. 531 $allow_comments = comments_open($page->ID) ? 1 : 0; 532 $allow_pings = pings_open($page->ID) ? 1 : 0; 533 534 // Format page date. 535 $page_date = mysql2date("Ymd\TH:i:s", $page->post_date, false); 536 $page_date_gmt = mysql2date("Ymd\TH:i:s", $page->post_date_gmt, false); 537 538 // For drafts use the GMT version of the date 539 if ( $page->post_status == 'draft' ) { 540 $page_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $page->post_date ), 'Ymd\TH:i:s' ); 541 } 542 543 // Pull the categories info together. 544 $categories = array(); 545 foreach(wp_get_post_categories($page->ID) as $cat_id) { 546 $categories[] = get_cat_name($cat_id); 547 } 548 549 // Get the author info. 550 $author = get_userdata($page->post_author); 551 552 $page_template = get_post_meta( $page->ID, '_wp_page_template', true ); 553 if( empty( $page_template ) ) 554 $page_template = 'default'; 555 556 $page_struct = array( 557 "dateCreated" => new IXR_Date($page_date), 558 "userid" => $page->post_author, 559 "page_id" => $page->ID, 560 "page_status" => $page->post_status, 561 "description" => $full_page["main"], 562 "title" => $page->post_title, 563 "link" => $link, 564 "permaLink" => $link, 565 "categories" => $categories, 566 "excerpt" => $page->post_excerpt, 567 "text_more" => $full_page["extended"], 568 "mt_allow_comments" => $allow_comments, 569 "mt_allow_pings" => $allow_pings, 570 "wp_slug" => $page->post_name, 571 "wp_password" => $page->post_password, 572 "wp_author" => $author->display_name, 573 "wp_page_parent_id" => $page->post_parent, 574 "wp_page_parent_title" => $parent_title, 575 "wp_page_order" => $page->menu_order, 576 "wp_author_id" => $author->ID, 577 "wp_author_display_name" => $author->display_name, 578 "date_created_gmt" => new IXR_Date($page_date_gmt), 579 "custom_fields" => $this->get_custom_fields($page_id), 580 "wp_page_template" => $page_template 581 ); 582 583 return($page_struct); 584 } 585 // If the page doesn't exist indicate that. 586 else { 587 return(new IXR_Error(404, __("Sorry, no such page."))); 588 } 589 } 590 591 /** 592 * Retrieve Pages. 593 * 594 * @since 2.2.0 595 * 596 * @param array $args Method parameters. 597 * @return array 598 */ 599 function wp_getPages($args) { 600 $this->escape($args); 601 602 $blog_id = (int) $args[0]; 603 $username = $args[1]; 604 $password = $args[2]; 605 $num_pages = isset($args[3]) ? (int) $args[3] : 10; 606 607 if ( !$user = $this->login($username, $password) ) { 608 return $this->error; 609 } 610 611 if( !current_user_can( 'edit_pages' ) ) 612 return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) ); 613 614 do_action('xmlrpc_call', 'wp.getPages'); 615 616 $pages = get_posts( array('post_type' => 'page', 'post_status' => 'any', 'numberposts' => $num_pages) ); 617 $num_pages = count($pages); 618 619 // If we have pages, put together their info. 620 if($num_pages >= 1) { 621 $pages_struct = array(); 622 623 for($i = 0; $i < $num_pages; $i++) { 624 $page = wp_xmlrpc_server::wp_getPage(array( 625 $blog_id, $pages[$i]->ID, $username, $password 626 )); 627 $pages_struct[] = $page; 628 } 629 630 return($pages_struct); 631 } 632 // If no pages were found return an error. 633 else { 634 return(array()); 635 } 636 } 637 638 /** 639 * Create new page. 640 * 641 * @since 2.2.0 642 * 643 * @param array $args Method parameters. 644 * @return unknown 645 */ 646 function wp_newPage($args) { 647 // Items not escaped here will be escaped in newPost. 648 $username = $this->escape($args[1]); 649 $password = $this->escape($args[2]); 650 $page = $args[3]; 651 $publish = $args[4]; 652 653 if ( !$user = $this->login($username, $password) ) { 654 return $this->error; 655 } 656 657 do_action('xmlrpc_call', 'wp.newPage'); 658 659 // Make sure the user is allowed to add new pages. 660 if(!current_user_can("publish_pages")) { 661 return(new IXR_Error(401, __("Sorry, you cannot add new pages."))); 662 } 663 664 // Mark this as content for a page. 665 $args[3]["post_type"] = "page"; 666 667 // Let mw_newPost do all of the heavy lifting. 668 return($this->mw_newPost($args)); 669 } 670 671 /** 672 * Delete page. 673 * 674 * @since 2.2.0 675 * 676 * @param array $args Method parameters. 677 * @return bool True, if success. 678 */ 679 function wp_deletePage($args) { 680 $this->escape($args); 681 682 $blog_id = (int) $args[0]; 683 $username = $args[1]; 684 $password = $args[2]; 685 $page_id = (int) $args[3]; 686 687 if ( !$user = $this->login($username, $password) ) { 688 return $this->error; 689 } 690 691 do_action('xmlrpc_call', 'wp.deletePage'); 692 693 // Get the current page based on the page_id and 694 // make sure it is a page and not a post. 695 $actual_page = wp_get_single_post($page_id, ARRAY_A); 696 if( 697 !$actual_page 698 || ($actual_page["post_type"] != "page") 699 ) { 700 return(new IXR_Error(404, __("Sorry, no such page."))); 701 } 702 703 // Make sure the user can delete pages. 704 if(!current_user_can("delete_page", $page_id)) { 705 return(new IXR_Error(401, __("Sorry, you do not have the right to delete this page."))); 706 } 707 708 // Attempt to delete the page. 709 $result = wp_delete_post($page_id); 710 if(!$result) { 711 return(new IXR_Error(500, __("Failed to delete the page."))); 712 } 713 714 return(true); 715 } 716 717 /** 718 * Edit page. 719 * 720 * @since 2.2.0 721 * 722 * @param array $args Method parameters. 723 * @return unknown 724 */ 725 function wp_editPage($args) { 726 // Items not escaped here will be escaped in editPost. 727 $blog_id = (int) $args[0]; 728 $page_id = (int) $this->escape($args[1]); 729 $username = $this->escape($args[2]); 730 $password = $this->escape($args[3]); 731 $content = $args[4]; 732 $publish = $args[5]; 733 734 if ( !$user = $this->login($username, $password) ) { 735 return $this->error; 736 } 737 738 do_action('xmlrpc_call', 'wp.editPage'); 739 740 // Get the page data and make sure it is a page. 741 $actual_page = wp_get_single_post($page_id, ARRAY_A); 742 if( 743 !$actual_page 744 || ($actual_page["post_type"] != "page") 745 ) { 746 return(new IXR_Error(404, __("Sorry, no such page."))); 747 } 748 749 // Make sure the user is allowed to edit pages. 750 if(!current_user_can("edit_page", $page_id)) { 751 return(new IXR_Error(401, __("Sorry, you do not have the right to edit this page."))); 752 } 753 754 // Mark this as content for a page. 755 $content["post_type"] = "page"; 756 757 // Arrange args in the way mw_editPost understands. 758 $args = array( 759 $page_id, 760 $username, 761 $password, 762 $content, 763 $publish 764 ); 765 766 // Let mw_editPost do all of the heavy lifting. 767 return($this->mw_editPost($args)); 768 } 769 770 /** 771 * Retrieve page list. 772 * 773 * @since 2.2.0 774 * 775 * @param array $args Method parameters. 776 * @return unknown 777 */ 778 function wp_getPageList($args) { 779 global $wpdb; 780 781 $this->escape($args); 782 783 $blog_id = (int) $args[0]; 784 $username = $args[1]; 785 $password = $args[2]; 786 787 if ( !$user = $this->login($username, $password) ) { 788 return $this->error; 789 } 790 791 if( !current_user_can( 'edit_pages' ) ) 792 return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) ); 793 794 do_action('xmlrpc_call', 'wp.getPageList'); 795 796 // Get list of pages ids and titles 797 $page_list = $wpdb->get_results(" 798 SELECT ID page_id, 799 post_title page_title, 800 post_parent page_parent_id, 801 post_date_gmt, 802 post_date, 803 post_status 804 FROM {$wpdb->posts} 805 WHERE post_type = 'page' 806 ORDER BY ID 807 "); 808 809 // The date needs to be formated properly. 810 $num_pages = count($page_list); 811 for($i = 0; $i < $num_pages; $i++) { 812 $post_date = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date, false); 813 $post_date_gmt = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date_gmt, false); 814 815 $page_list[$i]->dateCreated = new IXR_Date($post_date); 816 $page_list[$i]->date_created_gmt = new IXR_Date($post_date_gmt); 817 818 // For drafts use the GMT version of the date 819 if ( $page_list[$i]->post_status == 'draft' ) { 820 $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' ); 821 $page_list[$i]->date_created_gmt = new IXR_Date( $page_list[$i]->date_created_gmt ); 822 } 823 824 unset($page_list[$i]->post_date_gmt); 825 unset($page_list[$i]->post_date); 826 unset($page_list[$i]->post_status); 827 } 828 829 return($page_list); 830 } 831 832 /** 833 * Retrieve authors list. 834 * 835 * @since 2.2.0 836 * 837 * @param array $args Method parameters. 838 * @return array 839 */ 840 function wp_getAuthors($args) { 841 842 $this->escape($args); 843 844 $blog_id = (int) $args[0]; 845 $username = $args[1]; 846 $password = $args[2]; 847 848 if ( !$user = $this->login($username, $password) ) { 849 return $this->error; 850 } 851 852 if(!current_user_can("edit_posts")) { 853 return(new IXR_Error(401, __("Sorry, you cannot edit posts on this blog."))); 854 } 855 856 do_action('xmlrpc_call', 'wp.getAuthors'); 857 858 $authors = array(); 859 foreach( (array) get_users_of_blog() as $row ) { 860 $authors[] = array( 861 "user_id" => $row->user_id, 862 "user_login" => $row->user_login, 863 "display_name" => $row->display_name 864 ); 865 } 866 867 return($authors); 868 } 869 870 /** 871 * Get list of all tags 872 * 873 * @since 2.7 874 * 875 * @param array $args Method parameters. 876 * @return array 877 */ 878 function wp_getTags( $args ) { 879 $this->escape( $args ); 880 881 $blog_id = (int) $args[0]; 882 $username = $args[1]; 883 $password = $args[2]; 884 885 if ( !$user = $this->login($username, $password) ) { 886 return $this->error; 887 } 888 889 if( !current_user_can( 'edit_posts' ) ) { 890 return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this blog in order to view tags.' ) ); 891 } 892 893 do_action( 'xmlrpc_call', 'wp.getKeywords' ); 894 895 $tags = array( ); 896 897 if( $all_tags = get_tags( ) ) { 898 foreach( (array) $all_tags as $tag ) { 899 $struct['tag_id'] = $tag->term_id; 900 $struct['name'] = $tag->name; 901 $struct['count'] = $tag->count; 902 $struct['slug'] = $tag->slug; 903 $struct['html_url'] = esc_html( get_tag_link( $tag->term_id ) ); 904 $struct['rss_url'] = esc_html( get_tag_feed_link( $tag->term_id ) ); 905 906 $tags[] = $struct; 907 } 908 } 909 910 return $tags; 911 } 912 913 /** 914 * Create new category. 915 * 916 * @since 2.2.0 917 * 918 * @param array $args Method parameters. 919 * @return int Category ID. 920 */ 921 function wp_newCategory($args) { 922 $this->escape($args); 923 924 $blog_id = (int) $args[0]; 925 $username = $args[1]; 926 $password = $args[2]; 927 $category = $args[3]; 928 929 if ( !$user = $this->login($username, $password) ) { 930 return $this->error; 931 } 932 933 do_action('xmlrpc_call', 'wp.newCategory'); 934 935 // Make sure the user is allowed to add a category. 936 if(!current_user_can("manage_categories")) { 937 return(new IXR_Error(401, __("Sorry, you do not have the right to add a category."))); 938 } 939 940 // If no slug was provided make it empty so that 941 // WordPress will generate one. 942 if(empty($category["slug"])) { 943 $category["slug"] = ""; 944 } 945 946 // If no parent_id was provided make it empty 947 // so that it will be a top level page (no parent). 948 if ( !isset($category["parent_id"]) ) 949 $category["parent_id"] = ""; 950 951 // If no description was provided make it empty. 952 if(empty($category["description"])) { 953 $category["description"] = ""; 954 } 955 956 $new_category = array( 957 "cat_name" => $category["name"], 958 "category_nicename" => $category["slug"], 959 "category_parent" => $category["parent_id"], 960 "category_description" => $category["description"] 961 ); 962 963 $cat_id = wp_insert_category($new_category); 964 if(!$cat_id) { 965 return(new IXR_Error(500, __("Sorry, the new category failed."))); 966 } 967 968 return($cat_id); 969 } 970 971 /** 972 * Remove category. 973 * 974 * @since 2.5.0 975 * 976 * @param array $args Method parameters. 977 * @return mixed See {@link wp_delete_category()} for return info. 978 */ 979 function wp_deleteCategory($args) { 980 $this->escape($args); 981 982 $blog_id = (int) $args[0]; 983 $username = $args[1]; 984 $password = $args[2]; 985 $category_id = (int) $args[3]; 986 987 if ( !$user = $this->login($username, $password) ) { 988 return $this->error; 989 } 990 991 do_action('xmlrpc_call', 'wp.deleteCategory'); 992 993 if( !current_user_can("manage_categories") ) { 994 return new IXR_Error( 401, __( "Sorry, you do not have the right to delete a category." ) ); 995 } 996 997 return wp_delete_category( $category_id ); 998 } 999 1000 /** 1001 * Retrieve category list. 1002 * 1003 * @since 2.2.0 1004 * 1005 * @param array $args Method parameters. 1006 * @return array 1007 */ 1008 function wp_suggestCategories($args) { 1009 $this->escape($args); 1010 1011 $blog_id = (int) $args[0]; 1012 $username = $args[1]; 1013 $password = $args[2]; 1014 $category = $args[3]; 1015 $max_results = (int) $args[4]; 1016 1017 if ( !$user = $this->login($username, $password) ) { 1018 return $this->error; 1019 } 1020 1021 if( !current_user_can( 'edit_posts' ) ) 1022 return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts to this blog in order to view categories.' ) ); 1023 1024 do_action('xmlrpc_call', 'wp.suggestCategories'); 1025 1026 $category_suggestions = array(); 1027 $args = array('get' => 'all', 'number' => $max_results, 'name__like' => $category); 1028 foreach ( (array) get_categories($args) as $cat ) { 1029 $category_suggestions[] = array( 1030 "category_id" => $cat->cat_ID, 1031 "category_name" => $cat->cat_name 1032 ); 1033 } 1034 1035 return($category_suggestions); 1036 } 1037 1038 /** 1039 * Retrieve comment. 1040 * 1041 * @since 2.7.0 1042 * 1043 * @param array $args Method parameters. 1044 * @return array 1045 */ 1046 function wp_getComment($args) { 1047 $this->escape($args); 1048 1049 $blog_id = (int) $args[0]; 1050 $username = $args[1]; 1051 $password = $args[2]; 1052 $comment_id = (int) $args[3]; 1053 1054 if ( !$user = $this->login($username, $password) ) { 1055 return $this->error; 1056 } 1057 1058 if ( !current_user_can( 'moderate_comments' ) ) 1059 return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this blog.' ) ); 1060 1061 do_action('xmlrpc_call', 'wp.getComment'); 1062 1063 if ( ! $comment = get_comment($comment_id) ) 1064 return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); 1065 1066 // Format page date. 1067 $comment_date = mysql2date("Ymd\TH:i:s", $comment->comment_date, false); 1068 $comment_date_gmt = mysql2date("Ymd\TH:i:s", $comment->comment_date_gmt, false); 1069 1070 if ( '0' == $comment->comment_approved ) 1071 $comment_status = 'hold'; 1072 else if ( 'spam' == $comment->comment_approved ) 1073 $comment_status = 'spam'; 1074 else if ( '1' == $comment->comment_approved ) 1075 $comment_status = 'approve'; 1076 else 1077 $comment_status = $comment->comment_approved; 1078 1079 $link = get_comment_link($comment); 1080 1081 $comment_struct = array( 1082 "date_created_gmt" => new IXR_Date($comment_date_gmt), 1083 "user_id" => $comment->user_id, 1084 "comment_id" => $comment->comment_ID, 1085 "parent" => $comment->comment_parent, 1086 "status" => $comment_status, 1087 "content" => $comment->comment_content, 1088 "link" => $link, 1089 "post_id" => $comment->comment_post_ID, 1090 "post_title" => get_the_title($comment->comment_post_ID), 1091 "author" => $comment->comment_author, 1092 "author_url" => $comment->comment_author_url, 1093 "author_email" => $comment->comment_author_email, 1094 "author_ip" => $comment->comment_author_IP, 1095 "type" => $comment->comment_type, 1096 ); 1097 1098 return $comment_struct; 1099 } 1100 1101 /** 1102 * Retrieve comments. 1103 * 1104 * @since 2.7.0 1105 * 1106 * @param array $args Method parameters. 1107 * @return array 1108 */ 1109 function wp_getComments($args) { 1110 $this->escape($args); 1111 1112 $blog_id = (int) $args[0]; 1113 $username = $args[1]; 1114 $password = $args[2]; 1115 $struct = $args[3]; 1116 1117 if ( !$user = $this->login($username, $password) ) { 1118 return $this->error; 1119 } 1120 1121 if ( !current_user_can( 'moderate_comments' ) ) 1122 return new IXR_Error( 401, __( 'Sorry, you cannot edit comments.' ) ); 1123 1124 do_action('xmlrpc_call', 'wp.getComments'); 1125 1126 if ( isset($struct['status']) ) 1127 $status = $struct['status']; 1128 else 1129 $status = ''; 1130 1131 $post_id = ''; 1132 if ( isset($struct['post_id']) ) 1133 $post_id = absint($struct['post_id']); 1134 1135 $offset = 0; 1136 if ( isset($struct['offset']) ) 1137 $offset = absint($struct['offset']); 1138 1139 $number = 10; 1140 if ( isset($struct['number']) ) 1141 $number = absint($struct['number']); 1142 1143 $comments = get_comments( array('status' => $status, 'post_id' => $post_id, 'offset' => $offset, 'number' => $number ) ); 1144 $num_comments = count($comments); 1145 1146 if ( ! $num_comments ) 1147 return array(); 1148 1149 $comments_struct = array(); 1150 1151 for ( $i = 0; $i < $num_comments; $i++ ) { 1152 $comment = wp_xmlrpc_server::wp_getComment(array( 1153 $blog_id, $username, $password, $comments[$i]->comment_ID, 1154 )); 1155 $comments_struct[] = $comment; 1156 } 1157 1158 return $comments_struct; 1159 } 1160 1161 /** 1162 * Remove comment. 1163 * 1164 * @since 2.7.0 1165 * 1166 * @param array $args Method parameters. 1167 * @return mixed {@link wp_delete_comment()} 1168 */ 1169 function wp_deleteComment($args) { 1170 $this->escape($args); 1171 1172 $blog_id = (int) $args[0]; 1173 $username = $args[1]; 1174 $password = $args[2]; 1175 $comment_ID = (int) $args[3]; 1176 1177 if ( !$user = $this->login($username, $password) ) { 1178 return $this->error; 1179 } 1180 1181 if ( !current_user_can( 'moderate_comments' ) ) 1182 return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this blog.' ) ); 1183 1184 do_action('xmlrpc_call', 'wp.deleteComment'); 1185 1186 if ( ! get_comment($comment_ID) ) 1187 return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); 1188 1189 return wp_delete_comment($comment_ID); 1190 } 1191 1192 /** 1193 * Edit comment. 1194 * 1195 * @since 2.7.0 1196 * 1197 * @param array $args Method parameters. 1198 * @return bool True, on success. 1199 */ 1200 function wp_editComment($args) { 1201 $this->escape($args); 1202 1203 $blog_id = (int) $args[0]; 1204 $username = $args[1]; 1205 $password = $args[2]; 1206 $comment_ID = (int) $args[3]; 1207 $content_struct = $args[4]; 1208 1209 if ( !$user = $this->login($username, $password) ) { 1210 return $this->error; 1211 } 1212 1213 if ( !current_user_can( 'moderate_comments' ) ) 1214 return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this blog.' ) ); 1215 1216 do_action('xmlrpc_call', 'wp.editComment'); 1217 1218 if ( ! get_comment($comment_ID) ) 1219 return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); 1220 1221 if ( isset($content_struct['status']) ) { 1222 $statuses = get_comment_statuses(); 1223 $statuses = array_keys($statuses); 1224 1225 if ( ! in_array($content_struct['status'], $statuses) ) 1226 return new IXR_Error( 401, __( 'Invalid comment status.' ) ); 1227 $comment_approved = $content_struct['status']; 1228 } 1229 1230 // Do some timestamp voodoo 1231 if ( !empty( $content_struct['date_created_gmt'] ) ) { 1232 $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 1233 $comment_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); 1234 $comment_date_gmt = iso8601_to_datetime($dateCreated, GMT); 1235 } 1236 1237 if ( isset($content_struct['content']) ) 1238 $comment_content = $content_struct['content']; 1239 1240 if ( isset($content_struct['author']) ) 1241 $comment_author = $content_struct['author']; 1242 1243 if ( isset($content_struct['author_url']) ) 1244 $comment_author_url = $content_struct['author_url']; 1245 1246 if ( isset($content_struct['author_email']) ) 1247 $comment_author_email = $content_struct['author_email']; 1248 1249 // We've got all the data -- post it: 1250 $comment = compact('comment_ID', 'comment_content', 'comment_approved', 'comment_date', 'comment_date_gmt', 'comment_author', 'comment_author_email', 'comment_author_url'); 1251 1252 $result = wp_update_comment($comment); 1253 if ( is_wp_error( $result ) ) 1254 return new IXR_Error(500, $result->get_error_message()); 1255 1256 if ( !$result ) 1257 return new IXR_Error(500, __('Sorry, the comment could not be edited. Something wrong happened.')); 1258 1259 return true; 1260 } 1261 1262 /** 1263 * Create new comment. 1264 * 1265 * @since 2.7.0 1266 * 1267 * @param array $args Method parameters. 1268 * @return mixed {@link wp_new_comment()} 1269 */ 1270 function wp_newComment($args) { 1271 global $wpdb; 1272 1273 $this->escape($args); 1274 1275 $blog_id = (int) $args[0]; 1276 $username = $args[1]; 1277 $password = $args[2]; 1278 $post = $args[3]; 1279 $content_struct = $args[4]; 1280 1281 $allow_anon = apply_filters('xmlrpc_allow_anonymous_comments', false); 1282 1283 $user = $this->login($username, $password); 1284 1285 if ( !$user ) { 1286 $logged_in = false; 1287 if ( $allow_anon && get_option('comment_registration') ) 1288 return new IXR_Error( 403, __( 'You must be registered to comment' ) ); 1289 else if ( !$allow_anon ) 1290 return $this->error; 1291 } else { 1292 $logged_in = true; 1293 } 1294 1295 if ( is_numeric($post) ) 1296 $post_id = absint($post); 1297 else 1298 $post_id = url_to_postid($post); 1299 1300 if ( ! $post_id ) 1301 return new IXR_Error( 404, __( 'Invalid post ID.' ) ); 1302 1303 if ( ! get_post($post_id) ) 1304 return new IXR_Error( 404, __( 'Invalid post ID.' ) ); 1305 1306 $comment['comment_post_ID'] = $post_id; 1307 1308 if ( $logged_in ) { 1309 $comment['comment_author'] = $wpdb->escape( $user->display_name ); 1310 $comment['comment_author_email'] = $wpdb->escape( $user->user_email ); 1311 $comment['comment_author_url'] = $wpdb->escape( $user->user_url ); 1312 $comment['user_ID'] = $user->ID; 1313 } else { 1314 $comment['comment_author'] = ''; 1315 if ( isset($content_struct['author']) ) 1316 $comment['comment_author'] = $content_struct['author']; 1317 1318 $comment['comment_author_email'] = ''; 1319 if ( isset($content_struct['author_email']) ) 1320 $comment['comment_author_email'] = $content_struct['author_email']; 1321 1322 $comment['comment_author_url'] = ''; 1323 if ( isset($content_struct['author_url']) ) 1324 $comment['comment_author_url'] = $content_struct['author_url']; 1325 1326 $comment['user_ID'] = 0; 1327 1328 if ( get_option('require_name_email') ) { 1329 if ( 6 > strlen($comment['comment_author_email']) || '' == $comment['comment_author'] ) 1330 return new IXR_Error( 403, __( 'Comment author name and email are required' ) ); 1331 elseif ( !is_email($comment['comment_author_email']) ) 1332 return new IXR_Error( 403, __( 'A valid email address is required' ) ); 1333 } 1334 } 1335 1336 $comment['comment_parent'] = isset($content_struct['comment_parent']) ? absint($content_struct['comment_parent']) : 0; 1337 1338 $comment['comment_content'] = $content_struct['content']; 1339 1340 do_action('xmlrpc_call', 'wp.newComment'); 1341 1342 return wp_new_comment($comment); 1343 } 1344 1345 /** 1346 * Retrieve all of the comment status. 1347 * 1348 * @since 2.7.0 1349 * 1350 * @param array $args Method parameters. 1351 * @return array 1352 */ 1353 function wp_getCommentStatusList($args) { 1354 $this->escape( $args ); 1355 1356 $blog_id = (int) $args[0]; 1357 $username = $args[1]; 1358 $password = $args[2]; 1359 1360 if ( !$user = $this->login($username, $password) ) { 1361 return $this->error; 1362 } 1363 1364 if ( !current_user_can( 'moderate_comments' ) ) 1365 return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) ); 1366 1367 do_action('xmlrpc_call', 'wp.getCommentStatusList'); 1368 1369 return get_comment_statuses( ); 1370 } 1371 1372 /** 1373 * Retrieve comment count. 1374 * 1375 * @since 2.5.0 1376 * 1377 * @param array $args Method parameters. 1378 * @return array 1379 */ 1380 function wp_getCommentCount( $args ) { 1381 $this->escape($args); 1382 1383 $blog_id = (int) $args[0]; 1384 $username = $args[1]; 1385 $password = $args[2]; 1386 $post_id = (int) $args[3]; 1387 1388 if ( !$user = $this->login($username, $password) ) { 1389 return $this->error; 1390 } 1391 1392 if( !current_user_can( 'edit_posts' ) ) { 1393 return new IXR_Error( 403, __( 'You are not allowed access to details about comments.' ) ); 1394 } 1395 1396 do_action('xmlrpc_call', 'wp.getCommentCount'); 1397 1398 $count = wp_count_comments( $post_id ); 1399 return array( 1400 "approved" => $count->approved, 1401 "awaiting_moderation" => $count->moderated, 1402 "spam" => $count->spam, 1403 "total_comments" => $count->total_comments 1404 ); 1405 } 1406 1407 /** 1408 * Retrieve post statuses. 1409 * 1410 * @since 2.5.0 1411 * 1412 * @param array $args Method parameters. 1413 * @return array 1414 */ 1415 function wp_getPostStatusList( $args ) { 1416 $this->escape( $args ); 1417 1418 $blog_id = (int) $args[0]; 1419 $username = $args[1]; 1420 $password = $args[2]; 1421 1422 if ( !$user = $this->login($username, $password) ) { 1423 return $this->error; 1424 } 1425 1426 if( !current_user_can( 'edit_posts' ) ) { 1427 return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) ); 1428 } 1429 1430 do_action('xmlrpc_call', 'wp.getPostStatusList'); 1431 1432 return get_post_statuses( ); 1433 } 1434 1435 /** 1436 * Retrieve page statuses. 1437 * 1438 * @since 2.5.0 1439 * 1440 * @param array $args Method parameters. 1441 * @return array 1442 */ 1443 function wp_getPageStatusList( $args ) { 1444 $this->escape( $args ); 1445 1446 $blog_id = (int) $args[0]; 1447 $username = $args[1]; 1448 $password = $args[2]; 1449 1450 if ( !$user = $this->login($username, $password) ) { 1451 return $this->error; 1452 } 1453 1454 if( !current_user_can( 'edit_posts' ) ) { 1455 return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) ); 1456 } 1457 1458 do_action('xmlrpc_call', 'wp.getPageStatusList'); 1459 1460 return get_page_statuses( ); 1461 } 1462 1463 /** 1464 * Retrieve page templates. 1465 * 1466 * @since 2.6.0 1467 * 1468 * @param array $args Method parameters. 1469 * @return array 1470 */ 1471 function wp_getPageTemplates( $args ) { 1472 $this->escape( $args ); 1473 1474 $blog_id = (int) $args[0]; 1475 $username = $args[1]; 1476 $password = $args[2]; 1477 1478 if ( !$user = $this->login($username, $password) ) { 1479 return $this->error; 1480 } 1481 1482 if( !current_user_can( 'edit_pages' ) ) { 1483 return new IXR_Error( 403, __( 'You are not allowed access to details about this blog.' ) ); 1484 } 1485 1486 $templates = get_page_templates( ); 1487 $templates['Default'] = 'default'; 1488 1489 return $templates; 1490 } 1491 1492 /** 1493 * Retrieve blog options. 1494 * 1495 * @since 2.6.0 1496 * 1497 * @param array $args Method parameters. 1498 * @return array 1499 */ 1500 function wp_getOptions( $args ) { 1501 $this->escape( $args ); 1502 1503 $blog_id = (int) $args[0]; 1504 $username = $args[1]; 1505 $password = $args[2]; 1506 $options = (array) $args[3]; 1507 1508 if ( !$user = $this->login($username, $password) ) { 1509 return $this->error; 1510 } 1511 1512 // If no specific options where asked for, return all of them 1513 if (count( $options ) == 0 ) { 1514 $options = array_keys($this->blog_options); 1515 } 1516 1517 return $this->_getOptions($options); 1518 } 1519 1520 /** 1521 * Retrieve blog options value from list. 1522 * 1523 * @since 2.6.0 1524 * 1525 * @param array $options Options to retrieve. 1526 * @return array 1527 */ 1528 function _getOptions($options) 1529 { 1530 $data = array( ); 1531 foreach( $options as $option ) { 1532 if( array_key_exists( $option, $this->blog_options ) ) 1533 { 1534 $data[$option] = $this->blog_options[$option]; 1535 //Is the value static or dynamic? 1536 if( isset( $data[$option]['option'] ) ) { 1537 $data[$option]['value'] = get_option( $data[$option]['option'] ); 1538 unset($data[$option]['option']); 1539 } 1540 } 1541 } 1542 1543 return $data; 1544 } 1545 1546 /** 1547 * Update blog options. 1548 * 1549 * @since 2.6.0 1550 * 1551 * @param array $args Method parameters. 1552 * @return unknown 1553 */ 1554 function wp_setOptions( $args ) { 1555 $this->escape( $args ); 1556 1557 $blog_id = (int) $args[0]; 1558 $username = $args[1]; 1559 $password = $args[2]; 1560 $options = (array) $args[3]; 1561 1562 if ( !$user = $this->login($username, $password) ) { 1563 return $this->error; 1564 } 1565 1566 if( !current_user_can( 'manage_options' ) ) 1567 return new IXR_Error( 403, __( 'You are not allowed to update options.' ) ); 1568 1569 foreach( $options as $o_name => $o_value ) { 1570 $option_names[] = $o_name; 1571 if( !array_key_exists( $o_name, $this->blog_options ) ) 1572 continue; 1573 1574 if( $this->blog_options[$o_name]['readonly'] == true ) 1575 continue; 1576 1577 update_option( $this->blog_options[$o_name]['option'], $o_value ); 1578 } 1579 1580 //Now return the updated values 1581 return $this->_getOptions($option_names); 1582 } 1583 1584 /* Blogger API functions. 1585 * specs on http://plant.blogger.com/api and http://groups.yahoo.com/group/bloggerDev/ 1586 */ 1587 1588 /** 1589 * Retrieve blogs that user owns. 1590 * 1591 * Will make more sense once we support multiple blogs. 1592 * 1593 * @since 1.5.0 1594 * 1595 * @param array $args Method parameters. 1596 * @return array 1597 */ 1598 function blogger_getUsersBlogs($args) { 1599 1600 $this->escape($args); 1601 1602 $username = $args[1]; 1603 $password = $args[2]; 1604 1605 if ( !$user = $this->login($username, $password) ) { 1606 return $this->error; 1607 } 1608 1609 do_action('xmlrpc_call', 'blogger.getUsersBlogs'); 1610 1611 $is_admin = current_user_can('manage_options'); 1612 1613 $struct = array( 1614 'isAdmin' => $is_admin, 1615 'url' => get_option('home') . '/', 1616 'blogid' => '1', 1617 'blogName' => get_option('blogname'), 1618 'xmlrpc' => site_url( 'xmlrpc.php' ) 1619 ); 1620 1621 return array($struct); 1622 } 1623 1624 /** 1625 * Retrieve user's data. 1626 * 1627 * Gives your client some info about you, so you don't have to. 1628 * 1629 * @since 1.5.0 1630 * 1631 * @param array $args Method parameters. 1632 * @return array 1633 */ 1634 function blogger_getUserInfo($args) { 1635 1636 $this->escape($args); 1637 1638 $username = $args[1]; 1639 $password = $args[2]; 1640 1641 if ( !$user = $this->login($username, $password) ) { 1642 return $this->error; 1643 } 1644 1645 if( !current_user_can( 'edit_posts' ) ) 1646 return new IXR_Error( 401, __( 'Sorry, you do not have access to user data on this blog.' ) ); 1647 1648 do_action('xmlrpc_call', 'blogger.getUserInfo'); 1649 1650 $struct = array( 1651 'nickname' => $user->nickname, 1652 'userid' => $user->ID, 1653 'url' => $user->user_url, 1654 'lastname' => $user->last_name, 1655 'firstname' => $user->first_name 1656 ); 1657 1658 return $struct; 1659 } 1660 1661 /** 1662 * Retrieve post. 1663 * 1664 * @since 1.5.0 1665 * 1666 * @param array $args Method parameters. 1667 * @return array 1668 */ 1669 function blogger_getPost($args) { 1670 1671 $this->escape($args); 1672 1673 $post_ID = (int) $args[1]; 1674 $username = $args[2]; 1675 $password = $args[3]; 1676 1677 if ( !$user = $this->login($username, $password) ) { 1678 return $this->error; 1679 } 1680 1681 if( !current_user_can( 'edit_post', $post_ID ) ) 1682 return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) ); 1683 1684 do_action('xmlrpc_call', 'blogger.getPost'); 1685 1686 $post_data = wp_get_single_post($post_ID, ARRAY_A); 1687 1688 $categories = implode(',', wp_get_post_categories($post_ID)); 1689 1690 $content = '<title>'.stripslashes($post_data['post_title']).'</title>'; 1691 $content .= '<category>'.$categories.'</category>'; 1692 $content .= stripslashes($post_data['post_content']); 1693 1694 $struct = array( 1695 'userid' => $post_data['post_author'], 1696 'dateCreated' => new IXR_Date(mysql2date('Ymd\TH:i:s', $post_data['post_date'], false)), 1697 'content' => $content, 1698 'postid' => $post_data['ID'] 1699 ); 1700 1701 return $struct; 1702 } 1703 1704 /** 1705 * Retrieve list of recent posts. 1706 * 1707 * @since 1.5.0 1708 * 1709 * @param array $args Method parameters. 1710 * @return array 1711 */ 1712 function blogger_getRecentPosts($args) { 1713 1714 $this->escape($args); 1715 1716 $blog_ID = (int) $args[1]; /* though we don't use it yet */ 1717 $username = $args[2]; 1718 $password = $args[3]; 1719 $num_posts = $args[4]; 1720 1721 if ( !$user = $this->login($username, $password) ) { 1722 return $this->error; 1723 } 1724 1725 do_action('xmlrpc_call', 'blogger.getRecentPosts'); 1726 1727 $posts_list = wp_get_recent_posts($num_posts); 1728 1729 if (!$posts_list) { 1730 $this->error = new IXR_Error(500, __('Either there are no posts, or something went wrong.')); 1731 return $this->error; 1732 } 1733 1734 foreach ($posts_list as $entry) { 1735 if( !current_user_can( 'edit_post', $entry['ID'] ) ) 1736 continue; 1737 1738 $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date'], false); 1739 $categories = implode(',', wp_get_post_categories($entry['ID'])); 1740 1741 $content = '<title>'.stripslashes($entry['post_title']).'</title>'; 1742 $content .= '<category>'.$categories.'</category>'; 1743 $content .= stripslashes($entry['post_content']); 1744 1745 $struct[] = array( 1746 'userid' => $entry['post_author'], 1747 'dateCreated' => new IXR_Date($post_date), 1748 'content' => $content, 1749 'postid' => $entry['ID'], 1750 ); 1751 1752 } 1753 1754 $recent_posts = array(); 1755 for ($j=0; $j<count($struct); $j++) { 1756 array_push($recent_posts, $struct[$j]); 1757 } 1758 1759 return $recent_posts; 1760 } 1761 1762 /** 1763 * Retrieve blog_filename content. 1764 * 1765 * @since 1.5.0 1766 * 1767 * @param array $args Method parameters. 1768 * @return string 1769 */ 1770 function blogger_getTemplate($args) { 1771 1772 $this->escape($args); 1773 1774 $blog_ID = (int) $args[1]; 1775 $username = $args[2]; 1776 $password = $args[3]; 1777 $template = $args[4]; /* could be 'main' or 'archiveIndex', but we don't use it */ 1778 1779 if ( !$user = $this->login($username, $password) ) { 1780 return $this->error; 1781 } 1782 1783 do_action('xmlrpc_call', 'blogger.getTemplate'); 1784 1785 if ( !current_user_can('edit_themes') ) { 1786 return new IXR_Error(401, __('Sorry, this user can not edit the template.')); 1787 } 1788 1789 /* warning: here we make the assumption that the blog's URL is on the same server */ 1790 $filename = get_option('home') . '/'; 1791 $filename = preg_replace('#https?://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename); 1792 1793 $f = fopen($filename, 'r'); 1794 $content = fread($f, filesize($filename)); 1795 fclose($f); 1796 1797 /* so it is actually editable with a windows/mac client */ 1798 // 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); 1799 1800 return $content; 1801 } 1802 1803 /** 1804 * Updates the content of blog_filename. 1805 * 1806 * @since 1.5.0 1807 * 1808 * @param array $args Method parameters. 1809 * @return bool True when done. 1810 */ 1811 function blogger_setTemplate($args) { 1812 1813 $this->escape($args); 1814 1815 $blog_ID = (int) $args[1]; 1816 $username = $args[2]; 1817 $password = $args[3]; 1818 $content = $args[4]; 1819 $template = $args[5]; /* could be 'main' or 'archiveIndex', but we don't use it */ 1820 1821 if ( !$user = $this->login($username, $password) ) { 1822 return $this->error; 1823 } 1824 1825 do_action('xmlrpc_call', 'blogger.setTemplate'); 1826 1827 if ( !current_user_can('edit_themes') ) { 1828 return new IXR_Error(401, __('Sorry, this user cannot edit the template.')); 1829 } 1830 1831 /* warning: here we make the assumption that the blog's URL is on the same server */ 1832 $filename = get_option('home') . '/'; 1833 $filename = preg_replace('#https?://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename); 1834 1835 if ($f = fopen($filename, 'w+')) { 1836 fwrite($f, $content); 1837 fclose($f); 1838 } else { 1839 return new IXR_Error(500, __('Either the file is not writable, or something wrong happened. The file has not been updated.')); 1840 } 1841 1842 return true; 1843 } 1844 1845 /** 1846 * Create new post. 1847 * 1848 * @since 1.5.0 1849 * 1850 * @param array $args Method parameters. 1851 * @return int 1852 */ 1853 function blogger_newPost($args) { 1854 1855 $this->escape($args); 1856 1857 $blog_ID = (int) $args[1]; /* though we don't use it yet */ 1858 $username = $args[2]; 1859 $password = $args[3]; 1860 $content = $args[4]; 1861 $publish = $args[5]; 1862 1863 if ( !$user = $this->login($username, $password) ) { 1864 return $this->error; 1865 } 1866 1867 do_action('xmlrpc_call', 'blogger.newPost'); 1868 1869 $cap = ($publish) ? 'publish_posts' : 'edit_posts'; 1870 if ( !current_user_can($cap) ) 1871 return new IXR_Error(401, __('Sorry, you are not allowed to post on this blog.')); 1872 1873 $post_status = ($publish) ? 'publish' : 'draft'; 1874 1875 $post_author = $user->ID; 1876 1877 $post_title = xmlrpc_getposttitle($content); 1878 $post_category = xmlrpc_getpostcategory($content); 1879 $post_content = xmlrpc_removepostdata($content); 1880 1881 $post_date = current_time('mysql'); 1882 $post_date_gmt = current_time('mysql', 1); 1883 1884 $post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status'); 1885 1886 $post_ID = wp_insert_post($post_data); 1887 if ( is_wp_error( $post_ID ) ) 1888 return new IXR_Error(500, $post_ID->get_error_message()); 1889 1890 if (!$post_ID) 1891 return new IXR_Error(500, __('Sorry, your entry could not be posted. Something wrong happened.')); 1892 1893 $this->attach_uploads( $post_ID, $post_content ); 1894 1895 logIO('O', "Posted ! ID: $post_ID"); 1896 1897 return $post_ID; 1898 } 1899 1900 /** 1901 * Edit a post. 1902 * 1903 * @since 1.5.0 1904 * 1905 * @param array $args Method parameters. 1906 * @return bool true when done. 1907 */ 1908 function blogger_editPost($args) { 1909 1910 $this->escape($args); 1911 1912 $post_ID = (int) $args[1]; 1913 $username = $args[2]; 1914 $password = $args[3]; 1915 $content = $args[4]; 1916 $publish = $args[5]; 1917 1918 if ( !$user = $this->login($username, $password) ) { 1919 return $this->error; 1920 } 1921 1922 do_action('xmlrpc_call', 'blogger.editPost'); 1923 1924 $actual_post = wp_get_single_post($post_ID,ARRAY_A); 1925 1926 if (!$actual_post || $actual_post['post_type'] != 'post') { 1927 return new IXR_Error(404, __('Sorry, no such post.')); 1928 } 1929 1930 $this->escape($actual_post); 1931 1932 if ( !current_user_can('edit_post', $post_ID) ) 1933 return new IXR_Error(401, __('Sorry, you do not have the right to edit this post.')); 1934 1935 extract($actual_post, EXTR_SKIP); 1936 1937 if ( ('publish' == $post_status) && !current_user_can('publish_posts') ) 1938 return new IXR_Error(401, __('Sorry, you do not have the right to publish this post.')); 1939 1940 $post_title = xmlrpc_getposttitle($content); 1941 $post_category = xmlrpc_getpostcategory($content); 1942 $post_content = xmlrpc_removepostdata($content); 1943 1944 $postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt'); 1945 1946 $result = wp_update_post($postdata); 1947 1948 if (!$result) { 1949 return new IXR_Error(500, __('For some strange yet very annoying reason, this post could not be edited.')); 1950 } 1951 $this->attach_uploads( $ID, $post_content ); 1952 1953 return true; 1954 } 1955 1956 /** 1957 * Remove a post. 1958 * 1959 * @since 1.5.0 1960 * 1961 * @param array $args Method parameters. 1962 * @return bool True when post is deleted. 1963 */ 1964 function blogger_deletePost($args) { 1965 $this->escape($args); 1966 1967 $post_ID = (int) $args[1]; 1968 $username = $args[2]; 1969 $password = $args[3]; 1970 $publish = $args[4]; 1971 1972 if ( !$user = $this->login($username, $password) ) { 1973 return $this->error; 1974 } 1975 1976 do_action('xmlrpc_call', 'blogger.deletePost'); 1977 1978 $actual_post = wp_get_single_post($post_ID,ARRAY_A); 1979 1980 if (!$actual_post || $actual_post['post_type'] != 'post') { 1981 return new IXR_Error(404, __('Sorry, no such post.')); 1982 } 1983 1984 if ( !current_user_can('edit_post', $post_ID) ) 1985 return new IXR_Error(401, __('Sorry, you do not have the right to delete this post.')); 1986 1987 $result = wp_delete_post($post_ID); 1988 1989 if (!$result) { 1990 return new IXR_Error(500, __('For some strange yet very annoying reason, this post could not be deleted.')); 1991 } 1992 1993 return true; 1994 } 1995 1996 /* MetaWeblog API functions 1997 * specs on wherever Dave Winer wants them to be 1998 */ 1999 2000 /** 2001 * Create a new post. 2002 * 2003 * @since 1.5.0 2004 * 2005 * @param array $args Method parameters. 2006 * @return int 2007 */ 2008 function mw_newPost($args) { 2009 $this->escape($args); 2010 2011 $blog_ID = (int) $args[0]; // we will support this in the near future 2012 $username = $args[1]; 2013 $password = $args[2]; 2014 $content_struct = $args[3]; 2015 $publish = $args[4]; 2016 2017 if ( !$user = $this->login($username, $password) ) { 2018 return $this->error; 2019 } 2020 2021 do_action('xmlrpc_call', 'metaWeblog.newPost'); 2022 2023 $cap = ( $publish ) ? 'publish_posts' : 'edit_posts'; 2024 $error_message = __( 'Sorry, you are not allowed to publish posts on this blog.' ); 2025 $post_type = 'post'; 2026 $page_template = ''; 2027 if( !empty( $content_struct['post_type'] ) ) { 2028 if( $content_struct['post_type'] == 'page' ) { 2029 $cap = ( $publish ) ? 'publish_pages' : 'edit_pages'; 2030 $error_message = __( 'Sorry, you are not allowed to publish pages on this blog.' ); 2031 $post_type = 'page'; 2032 if( !empty( $content_struct['wp_page_template'] ) ) 2033 $page_template = $content_struct['wp_page_template']; 2034 } 2035 elseif( $content_struct['post_type'] == 'post' ) { 2036 // This is the default, no changes needed 2037 } 2038 else { 2039 // No other post_type values are allowed here 2040 return new IXR_Error( 401, __( 'Invalid post type.' ) ); 2041 } 2042 } 2043 2044 if( !current_user_can( $cap ) ) { 2045 return new IXR_Error( 401, $error_message ); 2046 } 2047 2048 // Let WordPress generate the post_name (slug) unless 2049 // one has been provided. 2050 $post_name = ""; 2051 if(isset($content_struct["wp_slug"])) { 2052 $post_name = $content_struct["wp_slug"]; 2053 } 2054 2055 // Only use a password if one was given. 2056 if(isset($content_struct["wp_password"])) { 2057 $post_password = $content_struct["wp_password"]; 2058 } 2059 2060 // Only set a post parent if one was provided. 2061 if(isset($content_struct["wp_page_parent_id"])) { 2062 $post_parent = $content_struct["wp_page_parent_id"]; 2063 } 2064 2065 // Only set the menu_order if it was provided. 2066 if(isset($content_struct["wp_page_order"])) { 2067 $menu_order = $content_struct["wp_page_order"]; 2068 } 2069 2070 $post_author = $user->ID; 2071 2072 // If an author id was provided then use it instead. 2073 if( 2074 isset($content_struct["wp_author_id"]) 2075 && ($user->ID != $content_struct["wp_author_id"]) 2076 ) { 2077 switch($post_type) { 2078 case "post": 2079 if(!current_user_can("edit_others_posts")) { 2080 return(new IXR_Error(401, __("You are not allowed to post as this user"))); 2081 } 2082 break; 2083 case "page": 2084 if(!current_user_can("edit_others_pages")) { 2085 return(new IXR_Error(401, __("You are not allowed to create pages as this user"))); 2086 } 2087 break; 2088 default: 2089 return(new IXR_Error(401, __("Invalid post type."))); 2090 break; 2091 } 2092 $post_author = $content_struct["wp_author_id"]; 2093 } 2094 2095 $post_title = $content_struct['title']; 2096 $post_content = $content_struct['description']; 2097 2098 $post_status = $publish ? 'publish' : 'draft'; 2099 2100 if( isset( $content_struct["{$post_type}_status"] ) ) { 2101 switch( $content_struct["{$post_type}_status"] ) { 2102 case 'draft': 2103 case 'private': 2104 case 'publish': 2105 $post_status = $content_struct["{$post_type}_status"]; 2106 break; 2107 case 'pending': 2108 // Pending is only valid for posts, not pages. 2109 if( $post_type === 'post' ) { 2110 $post_status = $content_struct["{$post_type}_status"]; 2111 } 2112 break; 2113 default: 2114 $post_status = $publish ? 'publish' : 'draft'; 2115 break; 2116 } 2117 } 2118 2119 $post_excerpt = $content_struct['mt_excerpt']; 2120 $post_more = $content_struct['mt_text_more']; 2121 2122 $tags_input = $content_struct['mt_keywords']; 2123 2124 if(isset($content_struct["mt_allow_comments"])) { 2125 if(!is_numeric($content_struct["mt_allow_comments"])) { 2126 switch($content_struct["mt_allow_comments"]) { 2127 case "closed": 2128 $comment_status = "closed"; 2129 break; 2130 case "open": 2131 $comment_status = "open"; 2132 break; 2133 default: 2134 $comment_status = get_option("default_comment_status"); 2135 break; 2136 } 2137 } 2138 else { 2139 switch((int) $content_struct["mt_allow_comments"]) { 2140 case 0: 2141 case 2: 2142 $comment_status = "closed"; 2143 break; 2144 case 1: 2145 $comment_status = "open"; 2146 break; 2147 default: 2148 $comment_status = get_option("default_comment_status"); 2149 break; 2150 } 2151 } 2152 } 2153 else { 2154 $comment_status = get_option("default_comment_status"); 2155 } 2156 2157 if(isset($content_struct["mt_allow_pings"])) { 2158 if(!is_numeric($content_struct["mt_allow_pings"])) { 2159 switch($content_struct['mt_allow_pings']) { 2160 case "closed": 2161 $ping_status = "closed"; 2162 break; 2163 case "open": 2164 $ping_status = "open"; 2165 break; 2166 default: 2167 $ping_status = get_option("default_ping_status"); 2168 break; 2169 } 2170 } 2171 else { 2172 switch((int) $content_struct["mt_allow_pings"]) { 2173 case 0: 2174 $ping_status = "closed"; 2175 break; 2176 case 1: 2177 $ping_status = "open"; 2178 break; 2179 default: 2180 $ping_status = get_option("default_ping_status"); 2181 break; 2182 } 2183 } 2184 } 2185 else { 2186 $ping_status = get_option("default_ping_status"); 2187 } 2188 2189 if ($post_more) { 2190 $post_content = $post_content . "<!--more-->" . $post_more; 2191 } 2192 2193 $to_ping = $content_struct['mt_tb_ping_urls']; 2194 if ( is_array($to_ping) ) 2195 $to_ping = implode(' ', $to_ping); 2196 2197 // Do some timestamp voodoo 2198 if ( !empty( $content_struct['date_created_gmt'] ) ) 2199 $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 2200 elseif ( !empty( $content_struct['dateCreated']) ) 2201 $dateCreated = $content_struct['dateCreated']->getIso(); 2202 2203 if ( !empty( $dateCreated ) ) { 2204 $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); 2205 $post_date_gmt = iso8601_to_datetime($dateCreated, GMT); 2206 } else { 2207 $post_date = current_time('mysql'); 2208 $post_date_gmt = current_time('mysql', 1); 2209 } 2210 2211 $catnames = $content_struct['categories']; 2212 logIO('O', 'Post cats: ' . var_export($catnames,true)); 2213 $post_category = array(); 2214 2215 if (is_array($catnames)) { 2216 foreach ($catnames as $cat) { 2217 $post_category[] = get_cat_ID($cat); 2218 } 2219 } 2220 2221 // We've got all the data -- post it: 2222 $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'); 2223 2224 $post_ID = wp_insert_post($postdata, true); 2225 if ( is_wp_error( $post_ID ) ) 2226 return new IXR_Error(500, $post_ID->get_error_message()); 2227 2228 if (!$post_ID) { 2229 return new IXR_Error(500, __('Sorry, your entry could not be posted. Something wrong happened.')); 2230 } 2231 2232 // Only posts can be sticky 2233 if ( $post_type == 'post' && isset( $content_struct['sticky'] ) ) 2234 if ( $content_struct['sticky'] == true ) 2235 stick_post( $post_ID ); 2236 elseif ( $content_struct['sticky'] == false ) 2237 unstick_post( $post_ID ); 2238 2239 if ( isset($content_struct['custom_fields']) ) { 2240 $this->set_custom_fields($post_ID, $content_struct['custom_fields']); 2241 } 2242 2243 // Handle enclosures 2244 $this->add_enclosure_if_new($post_ID, $content_struct['enclosure']); 2245 2246 $this->attach_uploads( $post_ID, $post_content ); 2247 2248 logIO('O', "Posted ! ID: $post_ID"); 2249 2250 return strval($post_ID); 2251 } 2252 2253 function add_enclosure_if_new($post_ID, $enclosure) { 2254 if( is_array( $enclosure ) && isset( $enclosure['url'] ) && isset( $enclosure['length'] ) && isset( $enclosure['type'] ) ) { 2255 2256 $encstring = $enclosure['url'] . "\n" . $enclosure['length'] . "\n" . $enclosure['type']; 2257 $found = false; 2258 foreach ( (array) get_post_custom($post_ID) as $key => $val) { 2259 if ($key == 'enclosure') { 2260 foreach ( (array) $val as $enc ) { 2261 if ($enc == $encstring) { 2262 $found = true; 2263 break 2; 2264 } 2265 } 2266 } 2267 } 2268 if (!$found) { 2269 add_post_meta( $post_ID, 'enclosure', $encstring ); 2270 } 2271 } 2272 } 2273 2274 /** 2275 * Attach upload to a post. 2276 * 2277 * @since 2.1.0 2278 * 2279 * @param int $post_ID Post ID. 2280 * @param string $post_content Post Content for attachment. 2281 */ 2282 function attach_uploads( $post_ID, $post_content ) { 2283 global $wpdb; 2284 2285 // find any unattached files 2286 $attachments = $wpdb->get_results( "SELECT ID, guid FROM {$wpdb->posts} WHERE post_parent = '0' AND post_type = 'attachment'" ); 2287 if( is_array( $attachments ) ) { 2288 foreach( $attachments as $file ) { 2289 if( strpos( $post_content, $file->guid ) !== false ) { 2290 $wpdb->update($wpdb->posts, array('post_parent' => $post_ID), array('ID' => $file->ID) ); 2291 } 2292 } 2293 } 2294 } 2295 2296 /** 2297 * Edit a post. 2298 * 2299 * @since 1.5.0 2300 * 2301 * @param array $args Method parameters. 2302 * @return bool True on success. 2303 */ 2304 function mw_editPost($args) { 2305 2306 $this->escape($args); 2307 2308 $post_ID = (int) $args[0]; 2309 $username = $args[1]; 2310 $password = $args[2]; 2311 $content_struct = $args[3]; 2312 $publish = $args[4]; 2313 2314 if ( !$user = $this->login($username, $password) ) { 2315 return $this->error; 2316 } 2317 2318 do_action('xmlrpc_call', 'metaWeblog.editPost'); 2319 2320 $cap = ( $publish ) ? 'publish_posts' : 'edit_posts'; 2321 $error_message = __( 'Sorry, you are not allowed to publish posts on this blog.' ); 2322 $post_type = 'post'; 2323 $page_template = ''; 2324 if( !empty( $content_struct['post_type'] ) ) { 2325 if( $content_struct['post_type'] == 'page' ) { 2326 $cap = ( $publish ) ? 'publish_pages' : 'edit_pages'; 2327 $error_message = __( 'Sorry, you are not allowed to publish pages on this blog.' ); 2328 $post_type = 'page'; 2329 if( !empty( $content_struct['wp_page_template'] ) ) 2330 $page_template = $content_struct['wp_page_template']; 2331 } 2332 elseif( $content_struct['post_type'] == 'post' ) { 2333 // This is the default, no changes needed 2334 } 2335 else { 2336 // No other post_type values are allowed here 2337 return new IXR_Error( 401, __( 'Invalid post type.' ) ); 2338 } 2339 } 2340 2341 if( !current_user_can( $cap ) ) { 2342 return new IXR_Error( 401, $error_message ); 2343 } 2344 2345 $postdata = wp_get_single_post($post_ID, ARRAY_A); 2346 2347 // If there is no post data for the give post id, stop 2348 // now and return an error. Other wise a new post will be 2349 // created (which was the old behavior). 2350 if(empty($postdata["ID"])) { 2351 return(new IXR_Error(404, __("Invalid post ID."))); 2352 } 2353 2354 $this->escape($postdata); 2355 extract($postdata, EXTR_SKIP); 2356 2357 // Let WordPress manage slug if none was provided. 2358 $post_name = ""; 2359 if(isset($content_struct["wp_slug"])) { 2360 $post_name = $content_struct["wp_slug"]; 2361 } 2362 2363 // Only use a password if one was given. 2364 if(isset($content_struct["wp_password"])) { 2365 $post_password = $content_struct["wp_password"]; 2366 } 2367 2368 // Only set a post parent if one was given. 2369 if(isset(