[ PHPXref.com ] [ Generated: Tue Apr 1 10:47:01 2008 ] [ WordPress 2.5 ]
[ Index ]     [ Classes ]     [ Functions ]     [ Variables ]     [ Constants ]     [ Statistics ]

title

Body

[close]

/ -> xmlrpc.php (source)

   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->