| [ PHPXref.com ] | [ Generated: Tue Apr 1 10:47:01 2008 ] | [ WordPress 2.5 ] |
| [ Index ] [ Classes ] [ Functions ] [ Variables ] [ Constants ] [ Statistics ] | ||
[Summary view] [Print] [Text view]
1 <?php 2 3 define('XMLRPC_REQUEST', true); 4 5 // Some browser-embedded clients send cookies. We don't want them. 6 $_COOKIE = array(); 7 8 // A bug in PHP < 5.2.2 makes $HTTP_RAW_POST_DATA not set by default, 9 // but we can do it ourself. 10 if ( !isset( $HTTP_RAW_POST_DATA ) ) { 11 $HTTP_RAW_POST_DATA = file_get_contents( 'php://input' ); 12 } 13 14 # fix for mozBlog and other cases where '<?xml' isn't on the very first line 15 if ( isset($HTTP_RAW_POST_DATA) ) 16 $HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA); 17 18 include('./wp-config.php'); 19 20 if ( isset( $_GET['rsd'] ) ) { // http://archipelago.phrasewise.com/rsd 21 header('Content-Type: text/xml; charset=' . get_option('blog_charset'), true); 22 ?> 23 <?php echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; ?> 24 <rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd"> 25 <service> 26 <engineName>WordPress</engineName> 27 <engineLink>http://wordpress.org/</engineLink> 28 <homePageLink><?php bloginfo_rss('url') ?></homePageLink> 29 <apis> 30 <api name="WordPress" blogID="1" preferred="true" apiLink="<?php bloginfo_rss('wpurl') ?>/xmlrpc.php" /> 31 <api name="Movable Type" blogID="1" preferred="false" apiLink="<?php bloginfo_rss('wpurl') ?>/xmlrpc.php" /> 32 <api name="MetaWeblog" blogID="1" preferred="false" apiLink="<?php bloginfo_rss('wpurl') ?>/xmlrpc.php" /> 33 <api name="Blogger" blogID="1" preferred="false" apiLink="<?php bloginfo_rss('wpurl') ?>/xmlrpc.php" /> 34 <api name="Atom" blogID="" preferred="false" apiLink="<?php echo apply_filters('atom_service_url', (get_bloginfo('url')."/wp-app.php/service"))?>" /> 35 </apis> 36 </service> 37 </rsd> 38 <?php 39 exit; 40 } 41 42 include_once (ABSPATH . 'wp-admin/includes/admin.php'); 43 include_once (ABSPATH . WPINC . '/class-IXR.php'); 44 45 // Turn off all warnings and errors. 46 // error_reporting(0); 47 48 $post_default_title = ""; // posts submitted via the xmlrpc interface get that title 49 50 $xmlrpc_logging = 0; 51 52 function logIO($io,$msg) { 53 global $xmlrpc_logging; 54 if ($xmlrpc_logging) { 55 $fp = fopen("../xmlrpc.log","a+"); 56 $date = gmdate("Y-m-d H:i:s "); 57 $iot = ($io == "I") ? " Input: " : " Output: "; 58 fwrite($fp, "\n\n".$date.$iot.$msg); 59 fclose($fp); 60 } 61 return true; 62 } 63 64 function starify($string) { 65 $i = strlen($string); 66 return str_repeat('*', $i); 67 } 68 69 if ( isset($HTTP_RAW_POST_DATA) ) 70 logIO("I", $HTTP_RAW_POST_DATA); 71 72 class wp_xmlrpc_server extends IXR_Server { 73 74 function wp_xmlrpc_server() { 75 $this->methods = array( 76 // WordPress API 77 'wp.getPage' => 'this:wp_getPage', 78 'wp.getPages' => 'this:wp_getPages', 79 'wp.newPage' => 'this:wp_newPage', 80 'wp.deletePage' => 'this:wp_deletePage', 81 'wp.editPage' => 'this:wp_editPage', 82 'wp.getPageList' => 'this:wp_getPageList', 83 'wp.getAuthors' => 'this:wp_getAuthors', 84 'wp.getCategories' => 'this:mw_getCategories', // Alias 85 'wp.newCategory' => 'this:wp_newCategory', 86 'wp.deleteCategory' => 'this:wp_deleteCategory', 87 'wp.suggestCategories' => 'this:wp_suggestCategories', 88 'wp.uploadFile' => 'this:mw_newMediaObject', // Alias 89 'wp.getCommentCount' => 'this:wp_getCommentCount', 90 'wp.getPostStatusList' => 'this:wp_getPostStatusList', 91 'wp.getPageStatusList' => 'this:wp_getPageStatusList', 92 93 // Blogger API 94 'blogger.getUsersBlogs' => 'this:blogger_getUsersBlogs', 95 'blogger.getUserInfo' => 'this:blogger_getUserInfo', 96 'blogger.getPost' => 'this:blogger_getPost', 97 'blogger.getRecentPosts' => 'this:blogger_getRecentPosts', 98 'blogger.getTemplate' => 'this:blogger_getTemplate', 99 'blogger.setTemplate' => 'this:blogger_setTemplate', 100 'blogger.newPost' => 'this:blogger_newPost', 101 'blogger.editPost' => 'this:blogger_editPost', 102 'blogger.deletePost' => 'this:blogger_deletePost', 103 104 // MetaWeblog API (with MT extensions to structs) 105 'metaWeblog.newPost' => 'this:mw_newPost', 106 'metaWeblog.editPost' => 'this:mw_editPost', 107 'metaWeblog.getPost' => 'this:mw_getPost', 108 'metaWeblog.getRecentPosts' => 'this:mw_getRecentPosts', 109 'metaWeblog.getCategories' => 'this:mw_getCategories', 110 'metaWeblog.newMediaObject' => 'this:mw_newMediaObject', 111 112 // MetaWeblog API aliases for Blogger API 113 // see http://www.xmlrpc.com/stories/storyReader$2460 114 'metaWeblog.deletePost' => 'this:blogger_deletePost', 115 'metaWeblog.getTemplate' => 'this:blogger_getTemplate', 116 'metaWeblog.setTemplate' => 'this:blogger_setTemplate', 117 'metaWeblog.getUsersBlogs' => 'this:blogger_getUsersBlogs', 118 119 // MovableType API 120 'mt.getCategoryList' => 'this:mt_getCategoryList', 121 'mt.getRecentPostTitles' => 'this:mt_getRecentPostTitles', 122 'mt.getPostCategories' => 'this:mt_getPostCategories', 123 'mt.setPostCategories' => 'this:mt_setPostCategories', 124 'mt.supportedMethods' => 'this:mt_supportedMethods', 125 'mt.supportedTextFilters' => 'this:mt_supportedTextFilters', 126 'mt.getTrackbackPings' => 'this:mt_getTrackbackPings', 127 'mt.publishPost' => 'this:mt_publishPost', 128 129 // PingBack 130 'pingback.ping' => 'this:pingback_ping', 131 'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks', 132 133 'demo.sayHello' => 'this:sayHello', 134 'demo.addTwoNumbers' => 'this:addTwoNumbers' 135 ); 136 $this->methods = apply_filters('xmlrpc_methods', $this->methods); 137 $this->IXR_Server($this->methods); 138 } 139 140 function sayHello($args) { 141 return 'Hello!'; 142 } 143 144 function addTwoNumbers($args) { 145 $number1 = $args[0]; 146 $number2 = $args[1]; 147 return $number1 + $number2; 148 } 149 150 function login_pass_ok($user_login, $user_pass) { 151 if (!user_pass_ok($user_login, $user_pass)) { 152 $this->error = new IXR_Error(403, __('Bad login/pass combination.')); 153 return false; 154 } 155 return true; 156 } 157 158 function escape(&$array) { 159 global $wpdb; 160 161 if(!is_array($array)) { 162 return($wpdb->escape($array)); 163 } 164 else { 165 foreach ( (array) $array as $k => $v ) { 166 if (is_array($v)) { 167 $this->escape($array[$k]); 168 } else if (is_object($v)) { 169 //skip 170 } else { 171 $array[$k] = $wpdb->escape($v); 172 } 173 } 174 } 175 } 176 177 function get_custom_fields($post_id) { 178 $post_id = (int) $post_id; 179 180 $custom_fields = array(); 181 182 foreach ( (array) has_meta($post_id) as $meta ) { 183 // Don't expose protected fields. 184 if ( strpos($meta['meta_key'], '_wp_') === 0 ) { 185 continue; 186 } 187 188 $custom_fields[] = array( 189 "id" => $meta['meta_id'], 190 "key" => $meta['meta_key'], 191 "value" => $meta['meta_value'] 192 ); 193 } 194 195 return $custom_fields; 196 } 197 198 function set_custom_fields($post_id, $fields) { 199 $post_id = (int) $post_id; 200 201 foreach ( (array) $fields as $meta ) { 202 if ( isset($meta['id']) ) { 203 $meta['id'] = (int) $meta['id']; 204 205 if ( isset($meta['key']) ) { 206 update_meta($meta['id'], $meta['key'], $meta['value']); 207 } 208 else { 209 delete_meta($meta['id']); 210 } 211 } 212 else { 213 $_POST['metakeyinput'] = $meta['key']; 214 $_POST['metavalue'] = $meta['value']; 215 add_meta($post_id); 216 } 217 } 218 } 219 220 /** 221 * WordPress XML-RPC API 222 * wp_getPage 223 */ 224 function wp_getPage($args) { 225 $this->escape($args); 226 227 $blog_id = (int) $args[0]; 228 $page_id = (int) $args[1]; 229 $username = $args[2]; 230 $password = $args[3]; 231 232 if(!$this->login_pass_ok($username, $password)) { 233 return($this->error); 234 } 235 236 set_current_user( 0, $username ); 237 if( !current_user_can( 'edit_page', $page_id ) ) 238 return new IXR_Error( 401, __( 'Sorry, you can not edit this page.' ) ); 239 240 do_action('xmlrpc_call', 'wp.getPage'); 241 242 // Lookup page info. 243 $page = get_page($page_id); 244 245 // If we found the page then format the data. 246 if($page->ID && ($page->post_type == "page")) { 247 // Get all of the page content and link. 248 $full_page = get_extended($page->post_content); 249 $link = post_permalink($page->ID); 250 251 // Get info the page parent if there is one. 252 $parent_title = ""; 253 if(!empty($page->post_parent)) { 254 $parent = get_page($page->post_parent); 255 $parent_title = $parent->post_title; 256 } 257 258 // Determine comment and ping settings. 259 $allow_comments = ("open" == $page->comment_status) ? 1 : 0; 260 $allow_pings = ("open" == $page->ping_status) ? 1 : 0; 261 262 // Format page date. 263 $page_date = mysql2date("Ymd\TH:i:s", $page->post_date); 264 $page_date_gmt = mysql2date("Ymd\TH:i:s", $page->post_date_gmt); 265 266 // Pull the categories info together. 267 $categories = array(); 268 foreach(wp_get_post_categories($page->ID) as $cat_id) { 269 $categories[] = get_cat_name($cat_id); 270 } 271 272 // Get the author info. 273 $author = get_userdata($page->post_author); 274 275 $page_struct = array( 276 "dateCreated" => new IXR_Date($page_date), 277 "userid" => $page->post_author, 278 "page_id" => $page->ID, 279 "page_status" => $page->post_status, 280 "description" => $full_page["main"], 281 "title" => $page->post_title, 282 "link" => $link, 283 "permaLink" => $link, 284 "categories" => $categories, 285 "excerpt" => $page->post_excerpt, 286 "text_more" => $full_page["extended"], 287 "mt_allow_comments" => $allow_comments, 288 "mt_allow_pings" => $allow_pings, 289 "wp_slug" => $page->post_name, 290 "wp_password" => $page->post_password, 291 "wp_author" => $author->display_name, 292 "wp_page_parent_id" => $page->post_parent, 293 "wp_page_parent_title" => $parent_title, 294 "wp_page_order" => $page->menu_order, 295 "wp_author_id" => $author->ID, 296 "wp_author_display_name" => $author->display_name, 297 "date_created_gmt" => new IXR_Date($page_date_gmt), 298 "custom_fields" => $this->get_custom_fields($page_id) 299 ); 300 301 return($page_struct); 302 } 303 // If the page doesn't exist indicate that. 304 else { 305 return(new IXR_Error(404, __("Sorry, no such page."))); 306 } 307 } 308 309 /** 310 * WordPress XML-RPC API 311 * wp_getPages 312 */ 313 function wp_getPages($args) { 314 $this->escape($args); 315 316 $blog_id = (int) $args[0]; 317 $username = $args[1]; 318 $password = $args[2]; 319 320 if(!$this->login_pass_ok($username, $password)) { 321 return($this->error); 322 } 323 324 set_current_user( 0, $username ); 325 if( !current_user_can( 'edit_pages' ) ) 326 return new IXR_Error( 401, __( 'Sorry, you can not edit pages.' ) ); 327 328 do_action('xmlrpc_call', 'wp.getPages'); 329 330 // Lookup info on pages. 331 $pages = get_pages(); 332 $num_pages = count($pages); 333 334 // If we have pages, put together their info. 335 if($num_pages >= 1) { 336 $pages_struct = array(); 337 338 for($i = 0; $i < $num_pages; $i++) { 339 $page = wp_xmlrpc_server::wp_getPage(array( 340 $blog_id, $pages[$i]->ID, $username, $password 341 )); 342 $pages_struct[] = $page; 343 } 344 345 return($pages_struct); 346 } 347 // If no pages were found return an error. 348 else { 349 return(array()); 350 } 351 } 352 353 /** 354 * WordPress XML-RPC API 355 * wp_newPage 356 */ 357 function wp_newPage($args) { 358 // Items not escaped here will be escaped in newPost. 359 $username = $this->escape($args[1]); 360 $password = $this->escape($args[2]); 361 $page = $args[3]; 362 $publish = $args[4]; 363 364 if(!$this->login_pass_ok($username, $password)) { 365 return($this->error); 366 } 367 368 do_action('xmlrpc_call', 'wp.newPage'); 369 370 // Set the user context and check if they are allowed 371 // to add new pages. 372 $user = set_current_user(0, $username); 373 if(!current_user_can("publish_pages")) { 374 return(new IXR_Error(401, __("Sorry, you can not add new pages."))); 375 } 376 377 // Mark this as content for a page. 378 $args[3]["post_type"] = "page"; 379 380 // Let mw_newPost do all of the heavy lifting. 381 return($this->mw_newPost($args)); 382 } 383 384 /** 385 * WordPress XML-RPC API 386 * wp_deletePage 387 */ 388 function wp_deletePage($args) { 389 $this->escape($args); 390 391 $blog_id = (int) $args[0]; 392 $username = $args[1]; 393 $password = $args[2]; 394 $page_id = (int) $args[3]; 395 396 if(!$this->login_pass_ok($username, $password)) { 397 return($this->error); 398 } 399 400 do_action('xmlrpc_call', 'wp.deletePage'); 401 402 // Get the current page based on the page_id and 403 // make sure it is a page and not a post. 404 $actual_page = wp_get_single_post($page_id, ARRAY_A); 405 if( 406 !$actual_page 407 || ($actual_page["post_type"] != "page") 408 ) { 409 return(new IXR_Error(404, __("Sorry, no such page."))); 410 } 411 412 // Set the user context and make sure they can delete pages. 413 set_current_user(0, $username); 414 if(!current_user_can("delete_page", $page_id)) { 415 return(new IXR_Error(401, __("Sorry, you do not have the right to delete this page."))); 416 } 417 418 // Attempt to delete the page. 419 $result = wp_delete_post($page_id); 420 if(!$result) { 421 return(new IXR_Error(500, __("Failed to delete the page."))); 422 } 423 424 return(true); 425 } 426 427 /** 428 * WordPress XML-RPC API 429 * wp_editPage 430 */ 431 function wp_editPage($args) { 432 // Items not escaped here will be escaped in editPost. 433 $blog_id = (int) $args[0]; 434 $page_id = (int) $this->escape($args[1]); 435 $username = $this->escape($args[2]); 436 $password = $this->escape($args[3]); 437 $content = $args[4]; 438 $publish = $args[5]; 439 440 if(!$this->login_pass_ok($username, $password)) { 441 return($this->error); 442 } 443 444 do_action('xmlrpc_call', 'wp.editPage'); 445 446 // Get the page data and make sure it is a page. 447 $actual_page = wp_get_single_post($page_id, ARRAY_A); 448 if( 449 !$actual_page 450 || ($actual_page["post_type"] != "page") 451 ) { 452 return(new IXR_Error(404, __("Sorry, no such page."))); 453 } 454 455 // Set the user context and make sure they are allowed to edit pages. 456 set_current_user(0, $username); 457 if(!current_user_can("edit_page", $page_id)) { 458 return(new IXR_Error(401, __("Sorry, you do not have the right to edit this page."))); 459 } 460 461 // Mark this as content for a page. 462 $content["post_type"] = "page"; 463 464 // Arrange args in the way mw_editPost understands. 465 $args = array( 466 $page_id, 467 $username, 468 $password, 469 $content, 470 $publish 471 ); 472 473 // Let mw_editPost do all of the heavy lifting. 474 return($this->mw_editPost($args)); 475 } 476 477 /** 478 * WordPress XML-RPC API 479 * wp_getPageList 480 */ 481 function wp_getPageList($args) { 482 global $wpdb; 483 484 $this->escape($args); 485 486 $blog_id = (int) $args[0]; 487 $username = $args[1]; 488 $password = $args[2]; 489 490 if(!$this->login_pass_ok($username, $password)) { 491 return($this->error); 492 } 493 494 set_current_user( 0, $username ); 495 if( !current_user_can( 'edit_pages' ) ) 496 return new IXR_Error( 401, __( 'Sorry, you can not edit pages.' ) ); 497 498 do_action('xmlrpc_call', 'wp.getPageList'); 499 500 // Get list of pages ids and titles 501 $page_list = $wpdb->get_results(" 502 SELECT ID page_id, 503 post_title page_title, 504 post_parent page_parent_id, 505 post_date_gmt, 506 post_date 507 FROM {$wpdb->posts} 508 WHERE post_type = 'page' 509 ORDER BY ID 510 "); 511 512 // The date needs to be formated properly. 513 $num_pages = count($page_list); 514 for($i = 0; $i < $num_pages; $i++) { 515 $post_date = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date); 516 $post_date_gmt = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date_gmt); 517 518 $page_list[$i]->dateCreated = new IXR_Date($post_date); 519 $page_list[$i]->date_created_gmt = new IXR_Date($post_date_gmt); 520 521 unset($page_list[$i]->post_date_gmt); 522 unset($page_list[$i]->post_date); 523 } 524 525 return($page_list); 526 } 527 528 /** 529 * WordPress XML-RPC API 530 * wp_getAuthors 531 */ 532 function wp_getAuthors($args) { 533 534 $this->escape($args); 535 536 $blog_id = (int) $args[0]; 537 $username = $args[1]; 538 $password = $args[2]; 539 540 if(!$this->login_pass_ok($username, $password)) { 541 return($this->error); 542 } 543 544 set_current_user(0, $username); 545 if(!current_user_can("edit_posts")) { 546 return(new IXR_Error(401, __("Sorry, you can not edit posts on this blog."))); 547 } 548 549 do_action('xmlrpc_call', 'wp.getAuthors'); 550 551 $authors = array(); 552 foreach( (array) get_users_of_blog() as $row ) { 553 $authors[] = array( 554 "user_id" => $row->user_id, 555 "user_login" => $row->user_login, 556 "display_name" => $row->display_name 557 ); 558 } 559 560 return($authors); 561 } 562 563 /** 564 * WordPress XML-RPC API 565 * wp_newCategory 566 */ 567 function wp_newCategory($args) { 568 $this->