Make WordPress Core

Changeset 1685 for trunk/xmlrpc.php


Ignore:
Timestamp:
09/17/2004 08:53:18 PM (22 years ago)
Author:
michelvaldrighi
Message:

big oopsie related to moving the xmlrpc.php file: somehow it got replaced by the old one. you can ignore version 1.21

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/xmlrpc.php

    r1684 r1685  
    44$HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA);
    55
    6 include('wp-config.php');
    7 
    8 include_once (ABSPATH . WPINC . '/class-xmlrpc.php');
    9 include_once (ABSPATH . WPINC . '/class-xmlrpcs.php');
    10 include_once (ABSPATH . WPINC . '/functions-post.php');
     6include('../wp-config.php');
     7include_once(ABSPATH . WPINC . '/class-IXR.php');
     8include_once(ABSPATH . WPINC . '/functions-post.php');
    119
    1210// Turn off all warnings and errors.
    13 error_reporting(0);
     11// error_reporting(0);
    1412
    1513$post_default_title = ""; // posts submitted via the xmlrpc interface get that title
     
    2119    global $xmlrpc_logging;
    2220    if ($xmlrpc_logging) {
    23         $fp = fopen("./xmlrpc.log","a+");
     21        $fp = fopen("../xmlrpc.log","a+");
    2422        $date = gmdate("Y-m-d H:i:s ");
    2523        $iot = ($io == "I") ? " Input: " : " Output: ";
     
    3836
    3937
    40 
    41 /**** B2 API ****/
    42 
    43 
    44 # note: the b2 API currently consists of the Blogger API,
    45 #       plus the following methods:
    46 #
    47 # b2.newPost , b2.getCategories
    48 
    49 # Note: the b2 API will be replaced by the standard Weblogs.API once the specs are defined.
    50 
    51 
    52 ### b2.newPost ###
    53 
    54 $wpnewpost_sig=array(array($xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString));
    55 
    56 $wpnewpost_doc='Adds a post, blogger-api like, +title +category +postdate';
    57 
    58 function b2newpost($m) {
    59     global $wpdb;
    60 
    61     global $xmlrpcerruser; // import user errcode value
    62     global $blog_ID,$cache_userdata,$use_rss;
    63     global $post_default_title,$post_default_category;
    64     global $cafelogID, $sleep_after_edit;
    65     $err="";
    66 
    67 
    68     $username=$m->getParam(2);
    69     $password=$m->getParam(3);
    70     $content=$m->getParam(4);
    71     $title=$m->getParam(6);
    72     $category=$m->getParam(7);
    73     $postdate=$m->getParam(8);
    74 
    75     $username = $username->scalarval();
    76     $password = $password->scalarval();
    77     $content = $content->scalarval();
    78     $title = $title->scalarval();
    79     $post_category = $category->scalarval();
    80     $postdate = $postdate->scalarval();
    81 
    82 
    83     if (user_pass_ok($username,$password)) {
    84 
    85         $userdata = get_userdatabylogin($username);
    86         $post_author = $userdata->ID;
    87         $user_level = $userdata->user_level;
    88         if ($user_level < 1) {
    89             return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
    90        "Sorry, level 0 users can not post");
    91         }
    92 
    93 
    94         $post_content = format_to_post($content);
    95         $post_title = addslashes($title);
    96 
    97 
    98         if ($postdate != "") {
    99             $post_date = $postdate;
    100             $post_date_gmt = get_gmt_from_date($postdate);
    101         } else {
    102             $post_date = current_time('mysql');
    103             $post_date_gmt = current_time('mysql', 1);
    104         }
    105 
    106         $post_data = compact('post_content','post_title','post_date','post_date_gmt','post_author','post_category');
     38function printr($var, $do_not_echo = false) {
     39    // from php.net/print_r user contributed notes
     40    ob_start();
     41    print_r($var);
     42    $code =  htmlentities(ob_get_contents());
     43    ob_clean();
     44    if (!$do_not_echo) {
     45      echo "<pre>$code</pre>";
     46    }
     47    return $code;
     48}
     49
     50function mkdir_p($target) {
     51    // from php.net/mkdir user contributed notes
     52    if (file_exists($target)) {
     53      if (!is_dir($target)) {
     54        return false;
     55      } else {
     56        return true;
     57      }
     58    }
     59
     60    // Attempting to create the directory may clutter up our display.
     61    if (@mkdir($target)) {
     62      return true;
     63    }
     64
     65    // If the above failed, attempt to create the parent node, then try again.
     66    if (mkdir_p(dirname($target))) {
     67      return mkdir_p($target);
     68    }
     69
     70    return false;
     71}
     72
     73
     74class wp_xmlrpc_server extends IXR_Server {
     75
     76    function wp_xmlrpc_server() {
     77        $this->methods = array(
     78          // Blogger API
     79          'blogger.getUsersBlogs' => 'this:blogger_getUsersBlogs',
     80          'blogger.getUserInfo' => 'this:blogger_getUserInfo',
     81          'blogger.getPost' => 'this:blogger_getPost',
     82          'blogger.getRecentPosts' => 'this:blogger_getRecentPosts',
     83          'blogger.getTemplate' => 'this:blogger_getTemplate',
     84          'blogger.setTemplate' => 'this:blogger_setTemplate',
     85          'blogger.newPost' => 'this:blogger_newPost',
     86          'blogger.editPost' => 'this:blogger_editPost',
     87          'blogger.deletePost' => 'this:blogger_deletePost',
     88
     89          // MetaWeblog API (with MT extensions to structs)
     90          'metaWeblog.newPost' => 'this:mw_newPost',
     91          'metaWeblog.editPost' => 'this:mw_editPost',
     92          'metaWeblog.getPost' => 'this:mw_getPost',
     93          'metaWeblog.getRecentPosts' => 'this:mw_getRecentPosts',
     94          'metaWeblog.getCategories' => 'this:mw_getCategories',
     95          'metaWeblog.newMediaObject' => 'this:mw_newMediaObject',
     96
     97          // MetaWeblog API aliases for Blogger API
     98          // see http://www.xmlrpc.com/stories/storyReader$2460
     99          'metaWeblog.deletePost' => 'this:blogger_deletePost',
     100          'metaWeblog.getTemplate' => 'this:blogger_getTemplate',
     101          'metaWeblog.setTemplate' => 'this:blogger_setTemplate',
     102          'metaWeblog.getUsersBlogs' => 'this:blogger_getUsersBlogs',
     103
     104          // MovableType API
     105          'mt.getCategoryList' => 'this:mt_getCategoryList',
     106          'mt.getRecentPostTitles' => 'this:mt_getRecentPostTitles',
     107          'mt.getPostCategories' => 'this:mt_getPostCategories',
     108          'mt.setPostCategories' => 'this:mt_setPostCategories',
     109          'mt.supportedMethods' => 'this:mt_supportedMethods',
     110          'mt.supportedTextFilters' => 'this:mt_supportedTextFilters',
     111          'mt.getTrackbackPings' => 'this:mt_getTrackbackPings',
     112          'mt.publishPost' => 'this:mt_publishPost',
     113
     114          // PingBack
     115          'pingback.ping' => 'this:pingback_ping',
     116          'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks',
     117
     118          'demo.sayHello' => 'this:sayHello',
     119          'demo.addTwoNumbers' => 'this:addTwoNumbers'
     120        );
     121        $this->IXR_Server($this->methods);
     122    }
     123
     124    function sayHello($args) {
     125        return 'Hello!';
     126    }
     127
     128    function addTwoNumbers($args) {
     129        $number1 = $args[0];
     130        $number2 = $args[1];
     131        return $number1 + $number2;
     132    }
     133
     134    function login_pass_ok($user_login, $user_pass) {
     135      if (!user_pass_ok($user_login, $user_pass)) {
     136        $this->error = new IXR_Error(403, 'Bad login/pass combination.');
     137        return false;
     138      }
     139      return true;
     140    }
     141
     142
     143
     144
     145    /* Blogger API functions
     146     * specs on http://plant.blogger.com/api and http://groups.yahoo.com/group/bloggerDev/
     147     */
     148
     149
     150    /* blogger.getUsersBlogs will make more sense once we support multiple blogs */
     151    function blogger_getUsersBlogs($args) {
     152
     153      $user_login = $args[1];
     154      $user_pass  = $args[2];
     155
     156      if (!$this->login_pass_ok($user_login, $user_pass)) {
     157        return $this->error;
     158      }
     159
     160      $user_data = get_userdatabylogin($user_login);
     161      $is_admin = $user_data->user_level > 3;
     162
     163      $struct = array(
     164        'isAdmin'  => $is_admin,
     165        'url'      => get_settings('home') .'/'.get_settings('blogfilename'),
     166        'blogid'   => '1',
     167        'blogName' => get_settings('blogname')
     168      );
     169
     170      return array($struct);
     171    }
     172
     173
     174    /* blogger.getUsersInfo gives your client some info about you, so you don't have to */
     175    function blogger_getUserInfo($args) {
     176
     177      $user_login = $args[1];
     178      $user_pass  = $args[2];
     179
     180      if (!$this->login_pass_ok($user_login, $user_pass)) {
     181        return $this->error;
     182      }
     183
     184      $user_data = get_userdatabylogin($user_login);
     185
     186      $struct = array(
     187        'nickname'  => $user_data->user_nickname,
     188        'userid'    => $user_data->ID,
     189        'url'       => $user_data->user_url,
     190        'email'     => $user_data->user_email,
     191        'lastname'  => $user_data->user_lastname,
     192        'firstname' => $user_data->user_firstname
     193      );
     194
     195      return $struct;
     196    }
     197
     198
     199    /* blogger.getPost ...gets a post */
     200    function blogger_getPost($args) {
     201
     202      $post_ID    = $args[1];
     203      $user_login = $args[2];
     204      $user_pass  = $args[3];
     205
     206      if (!$this->login_pass_ok($user_login, $user_pass)) {
     207        return $this->error;
     208      }
     209
     210      $user_data = get_userdatabylogin($user_login);
     211      $post_data = wp_get_single_post($post_ID, ARRAY_A);
     212
     213      $categories = implode(',', wp_get_post_cats(1, $post_ID));
     214
     215      $content  = '<title>'.stripslashes($post_data['post_title']).'</title>';
     216      $content .= '<category>'.$categories.'</category>';
     217      $content .= stripslashes($post_data['post_content']);
     218
     219      $struct = array(
     220        'userid'    => $post_data['post_author'],
     221        'dateCreated' => new IXR_Date(mysql2date('Ymd\TH:i:s', $post_data['post_date'])),
     222        'content'     => $content,
     223        'postid'  => $post_data['ID']
     224      );
     225
     226      return $struct;
     227    }
     228
     229
     230    /* blogger.getRecentPosts ...gets recent posts */
     231    function blogger_getRecentPosts($args) {
     232
     233      global $wpdb;
     234
     235      $blog_ID    = $args[1]; /* though we don't use it yet */
     236      $user_login = $args[2];
     237      $user_pass  = $args[3];
     238      $num_posts  = $args[4];
     239
     240      if (!$this->login_pass_ok($user_login, $user_pass)) {
     241        return $this->error;
     242      }
     243
     244      $posts_list = wp_get_recent_posts($num_posts);
     245
     246      if (!$posts_list) {
     247        $this->error = new IXR_Error(500, 'Either there are no posts, or something went wrong.');
     248        return $this->error;
     249      }
     250
     251      foreach ($posts_list as $entry) {
     252     
     253        $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']);
     254        $categories = implode(',', wp_get_post_cats(1, $entry['ID']));
     255
     256        $content  = '<title>'.stripslashes($entry['post_itle']).'</title>';
     257        $content .= '<category>'.$categories.'</category>';
     258        $content .= stripslashes($entry['post_content']);
     259
     260        $struct[] = array(
     261          'userid' => $entry['post_author'],
     262          'dateCreated' => new IXR_Date($post_date),
     263          'content' => $content,
     264          'postid' => $entry['ID'],
     265        );
     266
     267      }
     268
     269      $recent_posts = array();
     270      for ($j=0; $j<count($struct); $j++) {
     271        array_push($recent_posts, $struct[$j]);
     272      }
     273
     274      return $recent_posts;
     275    }
     276
     277
     278    /* blogger.getTemplate returns your blog_filename */
     279    function blogger_getTemplate($args) {
     280
     281      $blog_ID    = $args[1];
     282      $user_login = $args[2];
     283      $user_pass  = $args[3];
     284      $template   = $args[4]; /* could be 'main' or 'archiveIndex', but we don't use it */
     285
     286      if (!$this->login_pass_ok($user_login, $user_pass)) {
     287        return $this->error;
     288      }
     289
     290      $user_data = get_userdatabylogin($user_login);
     291
     292      if ($user_data->user_level < 3) {
     293        return new IXR_Error(401, 'Sorry, users whose level is less than 3, can not edit the template.');
     294      }
     295
     296      /* warning: here we make the assumption that the weblog's URI is on the same server */
     297      $filename = get_settings('home').'/'.get_settings('blogfilename');
     298      $filename = preg_replace('#http://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename);
     299
     300      $f = fopen($filename, 'r');
     301      $content = fread($f, filesize($filename));
     302      fclose($f);
     303
     304      /* so it is actually editable with a windows/mac client */
     305      // 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);
     306
     307      return $content;
     308    }
     309
     310
     311    /* blogger.setTemplate updates the content of blog_filename */
     312    function blogger_setTemplate($args) {
     313
     314      $blog_ID    = $args[1];
     315      $user_login = $args[2];
     316      $user_pass  = $args[3];
     317      $content    = $args[4];
     318      $template   = $args[5]; /* could be 'main' or 'archiveIndex', but we don't use it */
     319
     320      if (!$this->login_pass_ok($user_login, $user_pass)) {
     321        return $this->error;
     322      }
     323
     324      $user_data = get_userdatabylogin($user_login);
     325
     326      if ($user_data->user_level < 3) {
     327        return new IXR_Error(401, 'Sorry, users whose level is less than 3, can not edit the template.');
     328      }
     329
     330      /* warning: here we make the assumption that the weblog's URI is on the same server */
     331      $filename = get_settings('home').'/'.get_settings('blogfilename');
     332      $filename = preg_replace('#http://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename);
     333
     334      if ($f = fopen($filename, 'w+')) {
     335        fwrite($f, $content);
     336        fclose($f);
     337      } else {
     338        return new IXR_Error(500, 'Either the file is not writable, or something wrong happened. The file has not been updated.');
     339      }
     340
     341      return true;
     342    }
     343
     344
     345    /* blogger.newPost ...creates a new post */
     346    function blogger_newPost($args) {
     347
     348      global $wpdb;
     349
     350      $blog_ID    = $args[1]; /* though we don't use it yet */
     351      $user_login = $args[2];
     352      $user_pass  = $args[3];
     353      $content    = $args[4];
     354      $publish    = $args[5];
     355
     356      if (!$this->login_pass_ok($user_login, $user_pass)) {
     357        return $this->error;
     358      }
     359
     360      $user_data = get_userdatabylogin($user_login);
     361      if (!user_can_create_post($user_data->ID, $blog_ID)) {
     362        return new IXR_Error(401, 'Sorry, you can not post on this weblog or category.');
     363      }
     364
     365      $post_status = ($publish) ? 'publish' : 'draft';
     366
     367      $post_author = $user_data->ID;
     368
     369      $post_title = xmlrpc_getposttitle($content);
     370      $post_category = xmlrpc_getpostcategory($content);
     371
     372      $content = xmlrpc_removepostdata($content);
     373      $post_content = format_to_post($content);
     374
     375      $post_date = current_time('mysql');
     376      $post_date_gmt = current_time('mysql', 1);
     377
     378      $post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status');
     379
     380      $post_ID = wp_insert_post($post_data);
     381
     382      if (!$post_ID) {
     383        return new IXR_Error(500, 'Sorry, your entry could not be posted. Something wrong happened.');
     384      }
     385
     386      logIO('O', "Posted ! ID: $post_ID");
     387
     388      return $post_ID;
     389    }
     390
     391
     392    /* blogger.editPost ...edits a post */
     393    function blogger_editPost($args) {
     394
     395      global $wpdb;
     396
     397      $post_ID     = $args[1];
     398      $user_login  = $args[2];
     399      $user_pass   = $args[3];
     400      $new_content = $args[4];
     401      $publish     = $args[5];
     402
     403      if (!$this->login_pass_ok($user_login, $user_pass)) {
     404        return $this->error;
     405      }
     406
     407      $actual_post = wp_get_single_post($post_ID,ARRAY_A);
     408
     409      if (!$actual_post) {
     410        return new IXR_Error(404, 'Sorry, no such post.');
     411      }
     412
     413      $post_author_data = get_userdata($actual_post['post_author']);
     414      $user_data = get_userdatabylogin($user_login);
     415
     416      if (!user_can_edit_post($user_data->ID, $post_ID)) {
     417        return new IXR_Error(401, 'Sorry, you do not have the right to edit this post.');
     418      }
     419
     420      extract($actual_post);
     421      $content = $newcontent;
     422
     423      $post_title = xmlrpc_getposttitle($content);
     424      $post_category = xmlrpc_getpostcategory($content);
     425
     426      $content = xmlrpc_removepostdata($content);
     427      $post_content = format_to_post($content);
     428
     429      $postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt');
     430
     431      $result = wp_update_post($postdata);
     432
     433      if (!$result) {
     434        return new IXR_Error(500, 'For some strange yet very annoying reason, this post could not be edited.');
     435      }
     436
     437      return true;
     438    }
     439
     440
     441    /* blogger.deletePost ...deletes a post */
     442    function blogger_deletePost($args) {
     443
     444      global $wpdb;
     445
     446      $post_ID     = $args[1];
     447      $user_login  = $args[2];
     448      $user_pass   = $args[3];
     449      $publish     = $args[4];
     450
     451      if (!$this->login_pass_ok($user_login, $user_pass)) {
     452        return $this->error;
     453      }
     454
     455      $actual_post = wp_get_single_post($post_ID,ARRAY_A);
     456
     457      if (!$actual_post) {
     458        return new IXR_Error(404, 'Sorry, no such post.');
     459      }
     460
     461      $user_data = get_userdatabylogin($user_login);
     462
     463      if (!user_can_delete_post($user_data->ID, $post_ID)) {
     464        return new IXR_Error(401, 'Sorry, you do not have the right to delete this post.');
     465      }
     466
     467      $result = wp_delete_post($post_ID);
     468
     469      if (!$result) {
     470        return new IXR_Error(500, 'For some strange yet very annoying reason, this post could not be deleted.');
     471      }
     472
     473      return true;
     474    }
     475
     476
     477
     478    /* MetaWeblog API functions
     479     * specs on wherever Dave Winer wants them to be
     480     */
     481
     482    /* metaweblog.newPost creates a post */
     483    function mw_newPost($args) {
     484
     485      global $wpdb;
     486
     487      $blog_ID     = $args[0]; // we will support this in the near future
     488      $user_login  = $args[1];
     489      $user_pass   = $args[2];
     490      $content_struct = $args[3];
     491      $publish     = $args[4];
     492
     493      if (!$this->login_pass_ok($user_login, $user_pass)) {
     494        return $this->error;
     495      }
     496
     497      $user_data = get_userdatabylogin($user_login);
     498      if (!user_can_create_post($user_data->ID, $blog_ID)) {
     499        return new IXR_Error(401, 'Sorry, you can not post on this weblog or category.');
     500      }
     501
     502      $post_author = $user_data->ID;
     503
     504      $post_title = $content_struct['title'];
     505      $post_content = format_to_post($content_struct['description']);
     506      $post_status = $publish ? 'publish' : 'draft';
     507
     508      $post_excerpt = $content_struct['mt_excerpt'];
     509      $post_more = $content_struct['mt_text_more'];
     510
     511      $comment_status = (empty($content_struct['mt_allow_comments'])) ?
     512        get_settings('default_comment_status')
     513        : $content_struct['mt_allow_comments'];
     514
     515      $ping_status = (empty($content_struct['mt_allow_pings'])) ?
     516        get_settings('default_ping_status')
     517        : $content_struct['mt_allow_pings'];
     518
     519      if ($post_more) {
     520        $post_content = $post_content . "\n<!--more-->\n" . $post_more;
     521      }
    107522       
    108         $result = wp_insert_post($post_data);
    109 
    110         if (!$result)
    111             return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2
    112        "For some strange yet very annoying reason, your entry couldn't be posted.");
    113 
    114 
    115         $post_ID = $result;
    116 
    117         if (!isset($blog_ID)) { $blog_ID = 1; }
     523      // Do some timestamp voodoo
     524      $dateCreatedd = $content_struct['dateCreated'];
     525      $dateCreated = $dateCreatedd->getIso();
     526      if (!empty($dateCreated)) {
     527        $post_date     = get_date_from_gmt(iso8601_to_datetime($dateCreated));
     528        $post_date_gmt = iso8601_to_datetime($dateCreated, GMT);
     529      } else {
     530        $post_date     = current_time('mysql');
     531        $post_date_gmt = current_time('mysql', 1);
     532      }
     533
     534      $catnames = $content_struct['categories'];
     535      logio('O', 'Post cats: ' . printr($catnames,true));
     536      $post_category = array();
     537
     538      if ($catnames) {
     539        foreach ($catnames as $cat) {
     540          $post_category[] = get_cat_ID($cat);
     541        }
     542      } else {
     543        $post_category[] = 1;
     544      }
    118545       
    119         if (isset($sleep_after_edit) && $sleep_after_edit > 0) {
    120             sleep($sleep_after_edit);
    121         }
    122 
    123 
    124 
    125         pingback($content, $post_ID);
    126 
    127 
    128         return new xmlrpcresp(new xmlrpcval("$post_ID"));
    129 
    130     } else {
    131 
    132         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    133        'Wrong username/password combination '.$username.' / '.starify($password));
    134     }
    135 }
    136 
    137 
    138 
    139 ### b2.getCategories ###
    140 
    141 $wpgetcategories_sig=array(array($xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString));
    142 
    143 $wpgetcategories_doc='given a blogID, gives a struct that list categories in that blog, using categoryID and categoryName. categoryName is there so the user would choose a category name from the client, rather than just a number. however, when using b2.newPost, only the category ID number should be sent.';
    144 
    145 function b2getcategories($m) {
    146     global $wpdb;
    147     global $xmlrpcerruser;
    148 
    149 
    150     $blogid=$m->getParam(0);
    151     $blogid = $blogid->scalarval(); // we dot not use that yet, that will be used with multiple blogs
    152 
    153     $username=$m->getParam(1);
    154     $username = $username->scalarval();
    155 
    156     $password=$m->getParam(2);
    157     $password = $password->scalarval();
    158 
    159     $userdata = get_userdatabylogin($username);
    160 
    161 
    162     if (user_pass_ok($username,$password)) {
    163 
    164         $results = $wpdb->get_results("SELECT * FROM $wpdb->categories ORDER BY cat_ID ASC");
    165     if (!$results) die("Error getting data");
    166         $i = 0;
    167     foreach($results as $row) {
    168             $cat_name = $row->cat_name;
    169             $cat_ID = $row->cat_ID;
    170 
    171             $struct[$i] = new xmlrpcval(array("categoryID" => new xmlrpcval($cat_ID),
    172                                           "categoryName" => new xmlrpcval($cat_name)
    173                                           ),"struct");
    174             $i = $i + 1;
    175         }
    176 
    177         $data = array($struct[0]);
    178         for ($j=1; $j<$i; $j++) {
    179             array_push($data, $struct[$j]);
    180         }
    181 
    182         $resp = new xmlrpcval($data, "array");
    183 
    184         return new xmlrpcresp($resp);
    185 
    186     } else {
    187         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    188        'Wrong username/password combination '.$username.' / '.starify($password));
    189     }
    190 }
    191 
    192 
    193 
    194 ### b2.getPostURL ###
    195 
    196 $wp_getPostURL_sig = array(array($xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString));
    197 
    198 $wp_getPostURL_doc = 'Given a blog ID, username, password, and a post ID, returns the URL to that post.';
    199 
    200 function b2_getPostURL($m) {
    201     global $wpdb;
    202     global $xmlrpcerruser;
    203     global $querystring_start, $querystring_equal, $querystring_separator;
    204 
    205 
    206     // ideally, this would be used:
    207     // $blog_ID = $m->getParam(0);
    208     // $blog_ID = $blog_ID->scalarval();
    209     // but right now, b2 handles only one blog, so... :P
    210     $blog_ID = 1;
    211 
    212     $username=$m->getParam(2);
    213     $username = $username->scalarval();
    214 
    215     $password=$m->getParam(3);
    216     $password = $password->scalarval();
    217 
    218     $post_ID = $m->getParam(4);
    219     $post_ID = intval($post_ID->scalarval());
    220 
    221     $userdata = get_userdatabylogin($username);
    222 
    223     if ($userdata->user_level < 1) {
    224         return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
    225        "Sorry, users whose level is zero, can not use this method.");
    226     }
    227 
    228     if (user_pass_ok($username,$password)) {
    229         $blog_URL = get_settings('home') .'/' . get_settings('blogfilename');
    230         $post_URL = get_permalink($post_ID);
    231 
    232         if ($err) {
    233             return new xmlrpcresp(0, $xmlrpcerruser, $err);
    234         } else {
    235             return new xmlrpcresp(new xmlrpcval($post_URL));;
    236         }
    237 
    238     } else {
    239         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    240        'Wrong username/password combination '.$username.' / '.starify($password));
    241     }
    242 
    243 }
    244 
    245 /**** /B2 API ****/
    246 
    247 
    248 
    249 /**** Blogger API ****/
    250 
    251 # as described on http://plant.blogger.com/api and in various messages in http://groups.yahoo.com/group/bloggerDev/
    252 #
    253 # another list of these methods is there http://www.tswoam.co.uk/blogger_method_listing.html
    254 # so you won't have to browse the eGroup to find all the methods
    255 #
    256 # special note: Evan please keep _your_ API page up to date :p
    257 
    258 
    259 
    260 ### blogger.newPost ###
    261 
    262 $bloggernewpost_sig=array(array($xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcBoolean));
    263 
    264 $bloggernewpost_doc='Adds a post, blogger-api like';
    265 
    266 function bloggernewpost($m) {
    267     global $wpdb;
    268 
    269     global $xmlrpcerruser; // import user errcode value
    270     global $blog_ID,$cache_userdata,$use_rss;
    271     global $post_default_title,$post_default_category;
    272     global $cafelogID, $sleep_after_edit;
    273     $err="";
    274 
    275 
    276     $username=$m->getParam(2);
    277     $password=$m->getParam(3);
    278     $content=$m->getParam(4);
    279     $publish=$m->getParam(5);
    280 
    281     $username = $username->scalarval();
    282     $password = $password->scalarval();
    283     $content = $content->scalarval();
    284     // publish flag sets post status appropriately
    285     $post_status = $publish->scalarval()?'publish':'draft';
     546      // We've got all the data -- post it:
     547      $postdata = compact('post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status');
     548
     549      $post_ID = wp_insert_post($postdata);
     550
     551      if (!$post_ID) {
     552        return new IXR_Error(500, 'Sorry, your entry could not be posted. Something wrong happened.');
     553      }
     554
     555      logIO('O', "Posted ! ID: $post_ID");
     556
     557      // FIXME: do we pingback always? pingback($content, $post_ID);
     558      trackback_url_list($content_struct['mt_tb_ping_urls'],$post_ID);
     559
     560      return strval($post_ID);
     561    }
     562
     563
     564    /* metaweblog.editPost ...edits a post */
     565    function mw_editPost($args) {
     566
     567      global $wpdb;
     568
     569      $post_ID     = $args[0];
     570      $user_login  = $args[1];
     571      $user_pass   = $args[2];
     572      $content_struct = $args[3];
     573      $publish     = $args[4];
     574
     575      if (!$this->login_pass_ok($user_login, $user_pass)) {
     576        return $this->error;
     577      }
     578
     579      $user_data = get_userdatabylogin($user_login);
     580      if (!user_can_edit_post($user_data->ID, $post_ID)) {
     581        return new IXR_Error(401, 'Sorry, you can not edit this post.');
     582      }
     583
     584      $postdata = wp_get_single_post($post_ID, ARRAY_A);
     585      extract($postdata);
     586
     587      $post_title = $content_struct['title'];
     588      $post_content = format_to_post($content_struct['description']);
     589      $catnames = $content_struct['categories'];
     590       
     591      if ($catnames) {
     592        foreach ($catnames as $cat) {
     593          $post_category[] = get_cat_ID($cat);
     594        }
     595      }
     596
     597      $post_excerpt = $content_struct['mt_excerpt'];
     598      $post_more = $content_struct['mt_text_more'];
     599      $post_status = $publish ? 'publish' : 'draft';
     600
     601      if ($post_more) {
     602        $post_content = $post_content . "\n<!--more-->\n" . $post_more;
     603      }
     604
     605      $comment_status = (empty($content_struct['mt_allow_comments'])) ?
     606        get_settings('default_comment_status')
     607        : $content_struct['mt_allow_comments'];
     608
     609      $ping_status = (empty($content_struct['mt_allow_pings'])) ?
     610        get_settings('default_ping_status')
     611        : $content_struct['mt_allow_pings'];
     612
     613      // Do some timestamp voodoo
     614      $dateCreated = $content_struct['dateCreated'];
     615      $dateCreated = $dateCreated->getIso();
     616      if (!empty($dateCreated)) {
     617        $post_date     = get_date_from_gmt(iso8601_to_datetime($dateCreated));
     618        $post_date_gmt = iso8601_to_datetime($dateCreated, GMT);
     619      } else {
     620        $post_date     = $postdata['post_date'];
     621        $post_date_gmt = $postdata['post_date_gmt'];
     622      }
     623
     624      // We've got all the data -- post it:
     625      $newpost = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'post_date', 'post_date_gmt');
     626
     627      $post_ID = wp_update_post($newpost);
     628      if (!$post_ID) {
     629        return new IXR_Error(500, 'Sorry, your entry could not be edited. Something wrong happened.');
     630      }
     631
     632      logIO('O',"(MW) Edited ! ID: $post_ID");
     633
     634      // FIXME: do we pingback always? pingback($content, $post_ID);
     635      trackback_url_list($content_struct['mt_tb_ping_urls'], $post_ID);
     636
     637      return true;
     638    }
     639
     640
     641    /* metaweblog.getPost ...returns a post */
     642    function mw_getPost($args) {
     643
     644      global $wpdb;
     645
     646      $post_ID     = $args[0];
     647      $user_login  = $args[1];
     648      $user_pass   = $args[2];
     649
     650      if (!$this->login_pass_ok($user_login, $user_pass)) {
     651        return $this->error;
     652      }
     653
     654      $postdata = wp_get_single_post($post_ID, ARRAY_A);
     655
     656      if ($postdata['post_date'] != '') {
     657
     658        $post_date = mysql2date('Ymd\TH:i:s', $postdata['post_date']);
     659
     660        $categories = array();
     661        $catids = wp_get_post_cats('', $post_ID);
     662        foreach($catids as $catid) {
     663          $categories[] = get_cat_name($catid);
     664        }
     665
     666        $post = get_extended($postdata['post_content']);
     667        $link = post_permalink($postdata['ID']);
     668
     669        $allow_comments = ('open' == $postdata['comment_status']) ? 1 : 0;
     670        $allow_pings = ('open' == $postdata['ping_status']) ? 1 : 0;
     671
     672        $resp = array(
     673          'dateCreated' => new IXR_Date($post_date),
     674          'userid' => $postdata['post_author'],
     675          'postid' => $postdata['ID'],
     676          'description' => $post['main'],
     677          'title' => $postdata['post_title'],
     678          'link' => $link,
     679          'permaLink' => $link,
     680// commented out because no other tool seems to use this
     681//        'content' => $entry['post_content'],
     682          'categories' => $categories,
     683          'mt_excerpt' => $postdata['post_excerpt'],
     684          'mt_text_more' => $post['extended'],
     685          'mt_allow_comments' => $allow_comments,
     686          'mt_allow_pings' => $allow_pings
     687        );
     688
     689        return $resp;
     690      } else {
     691        return new IXR_Error(404, 'Sorry, no such post.');
     692      }
     693    }
     694
     695
     696    /* metaweblog.getRecentPosts ...returns recent posts */
     697    function mw_getRecentPosts($args) {
     698
     699      $blog_ID     = $args[0];
     700      $user_login  = $args[1];
     701      $user_pass   = $args[2];
     702      $num_posts   = $args[3];
     703
     704      if (!$this->login_pass_ok($user_login, $user_pass)) {
     705        return $this->error;
     706      }
     707
     708      $posts_list = wp_get_recent_posts($num_posts);
     709
     710      if (!$posts_list) {
     711        $this->error = new IXR_Error(500, 'Either there are no posts, or something went wrong.');
     712        return $this->error;
     713      }
     714
     715      foreach ($posts_list as $entry) {
     716     
     717        $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']);
     718        $categories = array();
     719        $catids = wp_get_post_cats('', $entry['ID']);
     720        foreach($catids as $catid) {
     721          $categories[] = get_cat_name($catid);
     722        }
     723
     724        $post = get_extended($entry['post_content']);
     725        $link = post_permalink($entry['ID']);
     726
     727        $allow_comments = ('open' == $entry['comment_status']) ? 1 : 0;
     728        $allow_pings = ('open' == $entry['ping_status']) ? 1 : 0;
     729
     730        $struct[] = array(
     731          'dateCreated' => new IXR_Date($post_date),
     732          'userid' => $entry['post_author'],
     733          'postid' => $entry['ID'],
     734          'description' => $post['main'],
     735          'title' => $entry['post_title'],
     736          'link' => $link,
     737          'permaLink' => $link,
     738// commented out because no other tool seems to use this
     739//        'content' => $entry['post_content'],
     740          'categories' => $categories,
     741          'mt_excerpt' => $entry['post_excerpt'],
     742          'mt_text_more' => $post['extended'],
     743          'mt_allow_comments' => $allow_comments,
     744          'mt_allow_pings' => $allow_pings
     745        );
     746
     747      }
     748
     749      $recent_posts = array();
     750      for ($j=0; $j<count($struct); $j++) {
     751        array_push($recent_posts, $struct[$j]);
     752      }
     753     
     754      return $recent_posts;
     755    }
     756
     757
     758    /* metaweblog.getCategories ...returns the list of categories on a given weblog */
     759    function mw_getCategories($args) {
     760
     761      global $wpdb;
     762
     763      $blog_ID     = $args[0];
     764      $user_login  = $args[1];
     765      $user_pass   = $args[2];
     766
     767      if (!$this->login_pass_ok($user_login, $user_pass)) {
     768        return $this->error;
     769      }
     770
     771      $categories_struct = array();
     772
     773      // FIXME: can we avoid using direct SQL there?
     774      if ($cats = $wpdb->get_results("SELECT cat_ID,cat_name FROM $wpdb->categories", ARRAY_A)) {
     775        foreach ($cats as $cat) {
     776          $struct['categoryId'] = $cat['cat_ID'];
     777          $struct['description'] = $cat['cat_name'];
     778          $struct['categoryName'] = $cat['cat_name'];
     779          $struct['htmlUrl'] = htmlspecialchars(get_category_link(false, $cat['cat_ID'], $cat['cat_name']));
     780          $struct['rssUrl'] = htmlspecialchars(get_category_rss_link(false, $cat['cat_ID'], $cat['cat_name']));
     781
     782          $categories_struct[] = $struct;
     783        }
     784      }
     785
     786      return $categories_struct;
     787    }
     788
     789
     790    /* metaweblog.newMediaObject uploads a file, following your settings */
     791    function mw_newMediaObject($args) {
     792      // adapted from a patch by Johann Richard
     793      // http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/
     794
     795      $blog_ID     = $args[0];
     796      $user_login  = $args[1];
     797      $user_pass   = $args[2];
     798      $data        = $args[3];
     799
     800      $name = $data['name'];
     801      $type = $data['type'];
     802      $bits = $data['bits'];
     803
     804      $file_realpath = get_settings('fileupload_realpath');
     805      $file_url = get_settings('fileupload_url');
     806
     807      logIO('O', '(MW) Received '.strlen($bits).' bytes');
     808
     809      if (!$this->login_pass_ok($user_login, $user_pass)) {
     810        return $this->error;
     811      }
     812
     813      $user_data = get_userdatabylogin($user_login);
     814
     815      if(!get_settings('use_fileupload')) {
     816        // Uploads not allowed
     817        logIO('O', '(MW) Uploads not allowed');
     818        $this->error = new IXR_Error(405, 'No uploads allowed for this site.');
     819        return $this->error;
     820      }
     821
     822      if(get_settings('fileupload_minlevel') > $user_data->user_level) {
     823        // User has not enough privileges
     824        logIO('O', '(MW) Not enough privilege: user level too low');
     825        $this->error = new IXR_Error(401, 'You are not allowed to upload files to this site.');
     826        return $this->error;
     827      }
     828
     829      if(trim($file_realpath) == '' || trim($file_url) == '' ) {
     830        // WordPress is not correctly configured
     831        logIO('O', '(MW) Bad configuration. Real/URL path not defined');
     832        $this->error = new IXR_Error(500, 'Please configure WordPress with valid paths for file upload.');
     833        return $this->error;
     834      }
     835
     836      $prefix = '/';
     837
     838      if(!empty($name)) {
     839        // Create the path
     840        $localpath = $file_realpath.$prefix.$name;
     841        $url = $file_url.$prefix.$name;
     842
     843        if (mkdir_p(dirname($localpath))) {
     844
     845          /* encode & write data (binary) */
     846          $ifp = fopen($localpath, 'wb');
     847          $success = fwrite($ifp, $bits);
     848          fclose($ifp);
     849          @chmod($localpath, 0666);
     850
     851          if($success) {
     852            $resp = array('url' => $url);
     853            return $resp;
     854          } else {
     855            logIO('O', '(MW) Could not write file '.$name.' to '.$localpath);
     856            return new IXR_Error(500, 'Could not write file '.$name);
     857          }
     858
     859        } else {
     860          return new IXR_Error(500, 'Could not create directories for '.$name);
     861        }
     862      }
     863    }
     864
     865
     866
     867    /* MovableType API functions
     868     * specs on http://www.movabletype.org/docs/mtmanual_programmatic.html
     869     */
     870
     871    /* mt.getRecentPostTitles ...returns recent posts' titles */
     872    function mt_getRecentPostTitles($args) {
     873
     874      $blog_ID     = $args[0];
     875      $user_login  = $args[1];
     876      $user_pass   = $args[2];
     877      $num_posts   = $args[3];
     878
     879      if (!$this->login_pass_ok($user_login, $user_pass)) {
     880        return $this->error;
     881      }
     882
     883      $posts_list = wp_get_recent_posts($num_posts);
     884
     885      if (!$posts_list) {
     886        $this->error = new IXR_Error(500, 'Either there are no posts, or something went wrong.');
     887        return $this->error;
     888      }
     889
     890      foreach ($posts_list as $entry) {
     891     
     892        $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']);
     893
     894        $struct[] = array(
     895          'dateCreated' => new IXR_Date($post_date),
     896          'userid' => $entry['post_author'],
     897          'postid' => $entry['ID'],
     898          'title' => $entry['post_title'],
     899        );
     900
     901      }
     902
     903      $recent_posts = array();
     904      for ($j=0; $j<count($struct); $j++) {
     905        array_push($recent_posts, $struct[$j]);
     906      }
     907     
     908      return $recent_posts;
     909    }
     910
     911
     912    /* mt.getCategoryList ...returns the list of categories on a given weblog */
     913    function mt_getCategoryList($args) {
     914
     915      global $wpdb;
     916
     917      $blog_ID     = $args[0];
     918      $user_login  = $args[1];
     919      $user_pass   = $args[2];
     920
     921      if (!$this->login_pass_ok($user_login, $user_pass)) {
     922        return $this->error;
     923      }
     924
     925      $categories_struct = array();
     926
     927      // FIXME: can we avoid using direct SQL there?
     928      if ($cats = $wpdb->get_results("SELECT cat_ID, cat_name FROM $wpdb->categories", ARRAY_A)) {
     929        foreach ($cats as $cat) {
     930          $struct['categoryId'] = $cat['cat_ID'];
     931          $struct['categoryName'] = $cat['cat_name'];
     932
     933          $categories_struct[] = $struct;
     934        }
     935      }
     936
     937      return $categories_struct;
     938    }
     939
     940
     941    /* mt.getPostCategories ...returns a post's categories */
     942    function mt_getPostCategories($args) {
     943
     944      $post_ID     = $args[0];
     945      $user_login  = $args[1];
     946      $user_pass   = $args[2];
     947
     948      if (!$this->login_pass_ok($user_login, $user_pass)) {
     949        return $this->error;
     950      }
     951
     952      $categories = array();
     953      $catids = wp_get_post_cats('', intval($post_ID));
     954      // first listed category will be the primary category
     955      $isPrimary = true;
     956      foreach($catids as $catid) {
     957        $categories[] = array(
     958          'categoryName' => get_cat_name($catid),
     959          'categoryId' => $catid,
     960          'isPrimary' => $isPrimary
     961        );
     962        $isPrimary = false;
     963      }
     964 
     965      return $categories;
     966    }
     967
     968
     969    /* mt.setPostCategories ...sets a post's categories */
     970    function mt_setPostCategories($args) {
     971
     972      $post_ID     = $args[0];
     973      $user_login  = $args[1];
     974      $user_pass   = $args[2];
     975      $categories  = $args[3];
     976
     977      if (!$this->login_pass_ok($user_login, $user_pass)) {
     978        return $this->error;
     979      }
     980
     981      $user_data = get_userdatabylogin($user_login);
     982      if (!user_can_edit_post($user_data->ID, $post_ID)) {
     983        return new IXR_Error(401, 'Sorry, you can not edit this post.');
     984      }
     985
     986      foreach($categories as $cat) {
     987        $catids[] = $cat['categoryId'];
     988      }
    286989   
    287     if (user_pass_ok($username,$password)) {
    288 
    289         $userdata = get_userdatabylogin($username);
    290         $post_author = $userdata->ID;
    291         $user_level = $userdata->user_level;
    292         if ($user_level < 1) {
    293             return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
    294        "Sorry, level 0 users can not post");
    295         }
    296 
    297         $post_title = addslashes(xmlrpc_getposttitle($content));
    298         $post_category = xmlrpc_getpostcategory($content);
    299 
    300         $content = xmlrpc_removepostdata($content);
    301         $post_content = format_to_post($content);
    302 
    303         $post_date = current_time('mysql');
    304         $post_date_gmt = current_time('mysql', 1);
    305        
    306         $postdata = compact('post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status');
    307 
    308         $post_ID = wp_insert_post($postdata);
    309 
    310         if (!$post_ID)
    311             return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2
    312        "For some strange yet very annoying reason, your entry couldn't be posted.");
    313 
    314         if (!isset($blog_ID)) { $blog_ID = 1; }
    315        
    316         if (isset($sleep_after_edit) && $sleep_after_edit > 0) {
    317             sleep($sleep_after_edit);
    318         }
    319 
    320 
    321         pingback($content, $post_ID);
    322 
    323         logIO("O","Posted ! ID: $post_ID");
    324         return new xmlrpcresp(new xmlrpcval("$post_ID"));
    325 
    326     } else {
    327         logIO("O","Wrong username/password combination <b>$username / $password</b>");
    328         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    329        'Wrong username/password combination '.$username.' / '.starify($password));
    330     }
    331 }
    332 
    333 
    334 
    335 ### blogger.editPost ###
    336 
    337 $bloggereditpost_sig=array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcBoolean));
    338 
    339 $bloggereditpost_doc='Edits a post, blogger-api like';
    340 
    341 function bloggereditpost($m) {
    342     global $wpdb;
    343 
    344     global $xmlrpcerruser; // import user errcode value
    345     global $blog_ID,$cache_userdata,$use_rss;
    346     global $post_default_title,$post_default_category, $sleep_after_edit;
    347     $err="";
    348 
    349 
    350     $post_ID=$m->getParam(1);
    351     $username=$m->getParam(2);
    352     $password=$m->getParam(3);
    353     $newcontent=$m->getParam(4);
    354     $publish=$m->getParam(5);
    355 
    356     $ID = $post_ID->scalarval();
    357     $username = $username->scalarval();
    358     $password = $password->scalarval();
    359     $newcontent = $newcontent->scalarval();
    360     $post_status = $publish->scalarval()?'publish':'draft';
    361 
    362     $result = wp_get_single_post($ID,ARRAY_A);
    363 
    364     if (!$result)
    365         return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2
    366       "No such post '$ID'.");
    367 
    368     $userdata = get_userdatabylogin($username);
    369     $user_ID = $userdata->ID;
    370     $user_level = $userdata->user_level;
    371 
    372     $postdata=get_postdata($ID);
    373     $post_authordata=get_userdata($postdata["Author_ID"]);
    374     $post_author_ID=$postdata["Author_ID"];
    375 
    376     if (($user_ID != $post_author_ID) && ($user_level <= $post_authordata->user_level)) {
    377             return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
    378        "Sorry, you do not have the right to edit this post");
    379     }
    380 
    381     if (user_pass_ok($username,$password)) {
    382 
    383         if ($user_level < 1) {
    384             return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
    385        "Sorry, level 0 users can not edit posts");
    386         }
    387        
    388         extract($result);
    389 
    390         $content = $newcontent;
    391 
    392         $post_title = xmlrpc_getposttitle($content);
    393         $post_category = xmlrpc_getpostcategory($content);
    394 
    395         $content = xmlrpc_removepostdata($content);
    396         $post_content = format_to_post($content);
    397        
    398         $postdata = compact('ID','post_content','post_title','post_category','post_status','post_excerpt');
    399 
    400         $result = wp_update_post($postdata);
    401 
    402         if (!$result)
    403             return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2
    404        "For some strange yet very annoying reason, the entry couldn't be edited.");
    405 
    406         if (!isset($blog_ID)) { $blog_ID = 1; }
    407        
    408         if (isset($sleep_after_edit) && $sleep_after_edit > 0) {
    409             sleep($sleep_after_edit);
    410         }
    411 
    412 
    413 
    414         return new xmlrpcresp(new xmlrpcval(true, "boolean"));
    415 
    416     } else {
    417         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    418        'Wrong username/password combination '.$username.' / '.starify($password));
    419     }
    420 }
    421 
    422 
    423 
    424 ### blogger.deletePost ###
    425 
    426 $bloggerdeletepost_sig=array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcBoolean));
    427 
    428 $bloggerdeletepost_doc='Deletes a post, blogger-api like';
    429 
    430 function bloggerdeletepost($m) {
    431     global $wpdb;
    432 
    433     global $xmlrpcerruser; // import user errcode value
    434     global $blog_ID,$cache_userdata,$use_rss;
    435     global $post_default_title,$post_default_category, $sleep_after_edit;
    436     $err="";
    437 
    438 
    439     $post_ID=$m->getParam(1);
    440     $username=$m->getParam(2);
    441     $password=$m->getParam(3);
    442     $newcontent=$m->getParam(4);
    443 
    444     $post_ID = $post_ID->scalarval();
    445     $username = $username->scalarval();
    446     $password = $password->scalarval();
    447     $newcontent = $newcontent->scalarval();
    448 
    449     $sql = "SELECT * FROM $wpdb->posts WHERE ID = '$post_ID'";
    450     $result = $wpdb->get_results($sql);
    451     if (!$result)
    452         return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2
    453       "No such post '$post_ID'.");
    454 
    455     $userdata = get_userdatabylogin($username);
    456     $user_ID = $userdata->ID;
    457     $user_level = $userdata->user_level;
    458 
    459     $postdata=get_postdata($post_ID);
    460     $post_authordata=get_userdata($postdata["Author_ID"]);
    461     $post_author_ID=$postdata["Author_ID"];
    462 
    463     if (($user_ID != $post_author_ID) && ($user_level <= $post_authordata->user_level)) {
    464             return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
    465        "Sorry, you do not have the right to delete this post");
    466     }
    467 
    468     if (user_pass_ok($username,$password)) {
    469 
    470         if ($user_level < 1) {
    471             return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
    472        "Sorry, level 0 users can not delete posts");
    473         }
    474 
    475         $result = wp_delete_post($post_ID);
    476 
    477         if (!$result)
    478             return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2
    479        "For some strange yet very annoying reason, the entry couldn't be deleted.");
    480 
    481         if (!isset($blog_ID)) { $blog_ID = 1; }
    482        
    483         if (isset($sleep_after_edit) && $sleep_after_edit > 0) {
    484             sleep($sleep_after_edit);
    485         }
    486 
    487 
    488 
    489         return new xmlrpcresp(new xmlrpcval(true,'boolean'));
    490 
    491     } else {
    492         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    493        'Wrong username/password combination '.$username.' / '.starify($password));
    494     }
    495 }
    496 
    497 
    498 
    499 ### blogger.getUsersBlogs ###
    500 
    501 $bloggergetusersblogs_sig=array(array($xmlrpcArray, $xmlrpcString, $xmlrpcString, $xmlrpcString));
    502 
    503 $bloggergetusersblogs_doc='returns the user\'s blogs - this is a dummy function, just so that BlogBuddy and other blogs-retrieving apps work';
    504 
    505 function bloggergetusersblogs($m) {
    506     global $wpdb;
    507     // this function will have a real purpose with CafeLog's multiple blogs capability
    508 
    509     global $xmlrpcerruser;
    510 
    511     $user_login = $m->getParam(1);
    512     $user_login = $user_login->scalarval();
    513 
    514 
    515     $sql = "SELECT user_level FROM $wpdb->users WHERE user_login = '$user_login' AND user_level > 3";
    516     $result = $wpdb->get_results($sql);
    517 
    518 
    519     $is_admin = $wpdb->num_rows;
    520 
    521     $struct = new xmlrpcval(array("isAdmin" => new xmlrpcval($is_admin,"boolean"),
    522                                     "url" => new xmlrpcval(get_settings('home') .'/'.get_settings('blogfilename')),
    523                                     "blogid" => new xmlrpcval("1"),
    524                                     "blogName" => new xmlrpcval(get_settings('blogname'))
    525                                     ),"struct");
    526     $resp = new xmlrpcval(array($struct), "array");
    527 
    528     return new xmlrpcresp($resp);
    529 }
    530 
    531 
    532 
    533 ### blogger.getUserInfo ###
    534 
    535 $bloggergetuserinfo_sig=array(array($xmlrpcStruct, $xmlrpcString, $xmlrpcString, $xmlrpcString));
    536 
    537 $bloggergetuserinfo_doc='gives the info about a user';
    538 
    539 function bloggergetuserinfo($m) {
    540     global $xmlrpcerruser;
    541 
    542 
    543     $username=$m->getParam(1);
    544     $username = $username->scalarval();
    545 
    546     $password=$m->getParam(2);
    547     $password = $password->scalarval();
    548 
    549     $userdata = get_userdatabylogin($username);
    550 
    551     if (user_pass_ok($username,$password)) {
    552         $struct = new xmlrpcval(array("nickname" => new xmlrpcval($userdata->user_nickname),
    553                                       "userid" => new xmlrpcval($userdata->ID),
    554                                       "url" => new xmlrpcval($userdata->user_url),
    555                                       "email" => new xmlrpcval($userdata->user_email),
    556                                       "lastname" => new xmlrpcval($userdata->user_lastname),
    557                                       "firstname" => new xmlrpcval($userdata->user_firstname)
    558                                       ),"struct");
    559         $resp = $struct;
    560         return new xmlrpcresp($resp);
    561 
    562     } else {
    563         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    564        'Wrong username/password combination '.$username.' / '.starify($password));
    565     }
    566 }
    567 
    568 
    569 
    570 ### blogger.getPost ###
    571 
    572 $bloggergetpost_sig=array(array($xmlrpcStruct, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString));
    573 
    574 $bloggergetpost_doc='fetches a post, blogger-api like';
    575 
    576 function bloggergetpost($m) {
    577     global $xmlrpcerruser;
    578 
    579 
    580     $post_ID=$m->getParam(1);
    581     $post_ID = $post_ID->scalarval();
    582 
    583     $username=$m->getParam(2);
    584     $username = $username->scalarval();
    585 
    586     $password=$m->getParam(3);
    587     $password = $password->scalarval();
    588 
    589     if (user_pass_ok($username,$password)) {
    590         $postdata = wp_get_single_post($post_ID);
    591 
    592         if ($postdata['post_date'] != '') {
    593             $post_date = mysql2date('Ymd\TH:i:s\Z', $postdata['post_date_gmt']);
    594 
    595             $categories = implode(',', $postdata['post_category']);
    596 
    597             $content  = '<title>'.stripslashes($postdata['post_title']).'</title>';
    598             $content .= '<category>'.$categories.'</category>';
    599             $content .= stripslashes($postdata['post_content']);
    600 
    601             $struct = new xmlrpcval(array('userid' => new xmlrpcval($postdata['post_author']),
    602                                           "dateCreated" => new xmlrpcval($post_date,"dateTime.iso8601"),
    603                                           "content" => new xmlrpcval($content),
    604                                           "postid" => new xmlrpcval($postdata["ID"])
    605                                           ),"struct");
    606 
    607             $resp = $struct;
    608             return new xmlrpcresp($resp);
    609         } else {
    610         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 4
    611        "No such post #$post_ID");
    612         }
    613     } else {
    614         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    615        'Wrong username/password combination '.$username.' / '.starify($password));
    616     }
    617 }
    618 
    619 
    620 
    621 ### blogger.getRecentPosts ###
    622 
    623 $bloggergetrecentposts_sig=array(array($xmlrpcArray, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcInt));
    624 
    625 $bloggergetrecentposts_doc='fetches X most recent posts, blogger-api like';
    626 
    627 function bloggergetrecentposts($m) {
    628     global $wpdb;
    629     global $xmlrpcerruser;
    630 
    631     error_reporting(0); // there is a bug in phpxmlrpc that makes it say there are errors while the output is actually valid, so let's disable errors for that function
    632 
    633 
    634     $blogid = 1;    // we don't need that yet
    635 
    636     $numposts=$m->getParam(4);
    637     $numposts = $numposts->scalarval();
    638 
    639     if ($numposts > 0) {
    640         $limit = " LIMIT $numposts";
    641     } else {
    642         $limit = "";
    643     }
    644 
    645     $username=$m->getParam(2);
    646     $username = $username->scalarval();
    647 
    648     $password=$m->getParam(3);
    649     $password = $password->scalarval();
    650 
    651     if (user_pass_ok($username,$password)) {
    652 
    653         $sql = "SELECT * FROM $wpdb->posts ORDER BY post_date_gmt DESC".$limit;
    654         $result = $wpdb->get_results($sql);
    655         if (!$result)
    656             return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2
    657        "For some strange yet very annoying reason, the entries couldn't be fetched.");
    658 
    659         $data = new xmlrpcval("","array");
    660 
    661         $i = 0;
    662         foreach ($result as $row) {
    663             $postdata = array(
    664                 "ID" => $row->ID,
    665                 "Author_ID" => $row->post_author,
    666                 "Date" => $row->post_date_gmt,
    667                 "Content" => $row->post_content,
    668                 "Title" => $row->post_title,
    669                 "Category" => $row->post_category
    670             );
    671 
    672             $post_date = mysql2date('Ymd\TH:i:s\Z', $postdata['Date']);
    673 
    674             $categories = implode(',', wp_get_post_cats(1, $postdata['ID']));
    675 
    676             $content  = "<title>".stripslashes($postdata["Title"])."</title>";
    677             $content .= "<category>".$categories."</category>";
    678             $content .= stripslashes($postdata["Content"]);
    679 
    680 //          $content = convert_chars($content,"html");
    681 //          $content = $postdata["Title"];
    682 
    683             $category = new xmlrpcval($postdata['Category']);
    684 
    685             $authordata = get_userdata($postdata["Author_ID"]);
    686             switch($authordata["user_idmode"]) {
    687                 case "nickname":
    688                     $authorname = $authordata["user_nickname"];
    689 
    690             case "login":
    691                     $authorname = $authordata["user_login"];
    692                     break;
    693             case "firstname":
    694                     $authorname = $authordata["user_firstname"];
    695                     break;
    696             case "lastname":
    697                     $authorname = $authordata["user_lastname"];
    698                     break;
    699             case "namefl":
    700                     $authorname = $authordata["user_firstname"]." ".$authordata["user_lastname"];
    701                     break;
    702             case "namelf":
    703                     $authorname = $authordata["user_lastname"]." ".$authordata["user_firstname"];
    704                     break;
    705             default:
    706                     $authorname = $authordata["user_nickname"];
    707                     break;
    708             }
    709 
    710             $struct[$i] = new xmlrpcval(array("authorName" => new xmlrpcval($authorname),
    711                                         "userid" => new xmlrpcval($postdata["Author_ID"]),
    712                                         "dateCreated" => new xmlrpcval($post_date,"dateTime.iso8601"),
    713                                         "content" => new xmlrpcval($content),
    714                                         "postid" => new xmlrpcval($postdata["ID"]),
    715                                         'category' => $category
    716                                         ),"struct");
    717             $i = $i + 1;
    718         }
    719 
    720         $data = array($struct[0]);
    721         for ($j=1; $j<$i; $j++) {
    722             array_push($data, $struct[$j]);
    723         }
    724 
    725         $resp = new xmlrpcval($data, "array");
    726 
    727         return new xmlrpcresp($resp);
    728 
    729     } else {
    730         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    731        'Wrong username/password combination '.$username.' / '.starify($password));
    732     }
    733 }
    734 
    735 
    736 
    737 ### blogger.getTemplate ###
    738 
    739 # note: on b2, it fetches your $blogfilename, or b2.php if you didn't specify the variable
    740 
    741 $bloggergettemplate_sig=array(array($xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString));
    742 
    743 $bloggergettemplate_doc='returns the default template file\'s code';
    744 
    745 function bloggergettemplate($m) {
    746     global $xmlrpcerruser;
    747 
    748     error_reporting(0); // there is a bug in phpxmlrpc that makes it say there are errors while the output is actually valid, so let's disable errors for that function
    749 
    750 
    751     $blogid = 1;    // we do not need this yet
    752 
    753     $templateType=$m->getParam(4);
    754     $templateType = $templateType->scalarval();
    755 
    756     $username=$m->getParam(2);
    757     $username = $username->scalarval();
    758 
    759     $password=$m->getParam(3);
    760     $password = $password->scalarval();
    761 
    762     $userdata = get_userdatabylogin($username);
    763 
    764     if ($userdata->user_level < 3) {
    765         return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
    766        "Sorry, users whose level is less than 3, can not edit the template.");
    767     }
    768 
    769     if (user_pass_ok($username,$password)) {
    770 
    771     if ($templateType == "main") {
    772         if (get_settings('blogfilename') != '') {
    773             $file = get_settings('blogfilename');
    774         } else {
    775             $file = "wp.php";
    776         }
    777     } elseif ($templateType == "archiveIndex") {
    778         $file = "wp.php";
    779     }
    780 
    781     $doc_root = preg_replace('#http://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', get_settings('home'));
    782     $file = $doc_root.'/'.$file;
    783 
    784     $f = fopen($file,"r");
    785     $content = fread($f,filesize($file));
    786     fclose($f);
    787 
    788     $content = str_replace("\n","\r\n",$content);   // so it is actually editable with a windows/mac client, instead of being returned as a looooooooooong line of code
    789 
    790     return new xmlrpcresp(new xmlrpcval("$content"));
    791 
    792     } else {
    793         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    794        'Wrong username/password combination '.$username.' / '.starify($password));
    795     }
    796 }
    797 
    798 
    799 
    800 ### blogger.setTemplate ###
    801 
    802 # note: on b2, it saves that in your $blogfilename, or b2.php if you didn't specify the variable
    803 
    804 $bloggersettemplate_sig=array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcString));
    805 
    806 $bloggersettemplate_doc='saves the default template file\'s code';
    807 
    808 function bloggersettemplate($m) {
    809     global $xmlrpcerruser;
    810 
    811     error_reporting(0); // there is a bug in phpxmlrpc that makes it say there are errors while the output is actually valid, so let's disable errors for that function
    812 
    813 
    814     $blogid = 1;    // we do not need this yet
    815 
    816     $template=$m->getParam(4);
    817     $template = $template->scalarval();
    818 
    819     $templateType=$m->getParam(5);
    820     $templateType = $templateType->scalarval();
    821 
    822     $username=$m->getParam(2);
    823     $username = $username->scalarval();
    824 
    825     $password=$m->getParam(3);
    826     $password = $password->scalarval();
    827 
    828     $userdata = get_userdatabylogin($username);
    829 
    830     if ($userdata->user_level < 3) {
    831         return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
    832        "Sorry, users whose level is less than 3, can not edit the template.");
    833     }
    834 
    835     if (user_pass_ok($username,$password)) {
    836 
    837     if ($templateType == 'main') {
    838         if (get_settings('blogfilename') != '') {
    839             $file = get_settings('blogfilename');
    840         } else {
    841             $file = "wp.php";
    842         }
    843     } elseif ($templateType == "archiveIndex") {
    844         $file = "wp.php";
    845     }
    846 
    847     $doc_root = preg_replace('#http://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', get_settings('home'));
    848     $file = $doc_root.'/'.$file;
    849 
    850     $f = fopen($file,"w+");
    851     fwrite($f, $template);
    852     fclose($f);
    853 
    854     return new xmlrpcresp(new xmlrpcval(true, "boolean"));
    855 
    856     } else {
    857         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    858        'Wrong username/password combination '.$username.' / '.starify($password));
    859     }
    860 }
    861 
    862 /**** /Blogger API ****/
    863 
    864 
    865 
    866 /**** metaWeblog API ****/
    867 
    868 /**********************
    869  *
    870  * metaWeblog API extensions
    871  * added by
    872  *  Dougal Campbell <dougal@gunters.org>
    873  *  http://dougal.gunters.org/
    874  *
    875  **********************/
    876 
    877 $mwnewpost_sig =  array(array($xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcStruct,$xmlrpcBoolean));
    878 $mwnewpost_doc = 'Add a post, MetaWeblog API-style';
    879 
    880 function mwnewpost($params) {
    881     global $xmlrpcerruser;
    882     global $blog_ID, $cache_userdata;
    883     global $use_rss, $post_default_title;
    884     global $post_default_category,$cafelogID,$sleep_after_edit;
    885 
    886     $xblogid = $params->getParam(0);
    887     $xuser = $params->getParam(1);
    888     $xpass = $params->getParam(2);
    889     $xcontent = $params->getParam(3);
    890     $xpublish = $params->getParam(4);
    891    
    892     $blogid = $xblogid->scalarval();
    893     $username = $xuser->scalarval();
    894     $password = $xpass->scalarval();
    895     $contentstruct = phpxmlrpc_decode($xcontent);
    896     $post_status = $xpublish->scalarval()?'publish':'draft';
    897 
    898     // Check login
    899     if (user_pass_ok($username,$password)) {
    900         $userdata = get_userdatabylogin($username);
    901         $post_author = $userdata->ID;
    902         $user_level = $userdata->user_level;
    903         if ($user_level < 1) {
    904             return new xmlrpcresp(0, $xmlrpcerruser+1,
    905               "Sorry, level 0 users cannot post");
    906         }
    907 
    908 
    909         $post_title = $contentstruct['title'];
    910         $post_content = format_to_post($contentstruct['description']);
    911 
    912         $post_excerpt = $contentstruct['mt_excerpt'];
    913         $post_more = $contentstruct['mt_text_more'];
    914 
    915         $comment_status = $contentstruct['mt_allow_comments']?'open':'closed';
    916         $ping_status = $contentstruct['mt_allow_pings']?'open':'closed';
    917 
    918         if ($post_more) {
    919             $post_content = $post_content . "\n<!--more-->\n" . $post_more;
    920         }
    921        
    922         // Do some timestamp voodoo
    923         $dateCreated = $contentstruct['dateCreated'];
    924         if (!empty($dateCreated)) {
    925           $post_date     = get_date_from_gmt(iso8601_to_datetime($dateCreated));
    926           $post_date_gmt = iso8601_to_datetime($dateCreated, GMT);
    927         } else {
    928           $post_date     = current_time('mysql');
    929           $post_date_gmt = current_time('mysql', 1);
    930         }
    931 
    932         $catnames = $contentstruct['categories'];
    933         // FIXME: commented until proper fix // logio("O","Post cats: " . print_r($catnames,true));
    934         $post_category = array();
    935         if ($catnames) {
    936             foreach ($catnames as $cat) {
    937                 $post_category[] = get_cat_ID($cat);
    938             }
    939         } else {
    940             $post_category[] = 1;
    941         }
    942        
    943         // We've got all the data -- post it:
    944         $postarr = compact('post_author','post_date','post_date_gmt','post_content','post_title','post_category','post_status','post_excerpt','comment_status','ping_status');
    945 
    946         $post_ID = wp_insert_post($postarr);
    947        
    948         if (!$post_ID) {
    949             return new xmlrpcresp(0, $xmlrpcerruser+2, "For some strange yet very annoying reason, your entry could not be posted.");
    950         }
    951 
    952         if (!isset($blog_ID)) { $blog_ID = 1; }
    953 
    954         if (isset($sleep_after_edit) && $sleep_after_edit > 0) {
    955             sleep($sleep_after_edit);
    956         }
    957 
    958         pingback($content, $post_ID);
    959         trackback_url_list($contentstruct['mt_tb_ping_urls'],$post_ID);
    960 
    961         logIO("O","(MW) Posted ! ID: $post_ID");
    962         $myResp = new xmlrpcval($post_ID,"string");
    963 
    964         return new xmlrpcresp($myResp);
    965 
    966     } else {
    967         logIO("O","(MW) Wrong username/password combination <b>$username / $password</b>");
    968         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    969        'Wrong username/password combination '.$username.' / '.starify($password));
    970     }
    971 }
    972 
    973 $mweditpost_sig =  array(array($xmlrpcBoolean,$xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcStruct,$xmlrpcBoolean));
    974 $mweditpost_doc = 'Edit a post, MetaWeblog API-style';
    975 
    976 function mweditpost ($params) { // ($postid, $user, $pass, $content, $publish)
    977     global $xmlrpcerruser;
    978 
    979     $xpostid = $params->getParam(0);
    980     $xuser = $params->getParam(1);
    981     $xpass = $params->getParam(2);
    982     $xcontent = $params->getParam(3);
    983     $xpublish = $params->getParam(4);
    984    
    985     $ID = $xpostid->scalarval();
    986     $username = $xuser->scalarval();
    987     $password = $xpass->scalarval();
    988     $contentstruct = phpxmlrpc_decode($xcontent);
    989     $postdata = wp_get_single_post($ID,ARRAY_A);
    990 
    991     if (!$postdata)
    992         return new xmlrpcresp(0, $xmlrpcerruser+2, // user error 2
    993             "No such post $ID.");
    994            
    995     $userdata = get_userdatabylogin($username);
    996     $user_ID = $userdata->ID;
    997     $user_level = $userdata->user_level;
    998     $time_difference = get_settings('gmt_offset');
    999    
    1000     $post_author_ID = $postdata['post_author'];
    1001     $post_authordata = get_userdata($post_author_ID);
    1002 
    1003     if (($user_ID != $post_author_ID) && ($user_level <= $post_authordata->user_level)) {
    1004         return new xmlrpcresp(0, $xmlrpcerruser+1, // user error 1
    1005             "Sorry, you do not have the right to edit this post.");
    1006     }
    1007        
    1008     // Check login
    1009     if (user_pass_ok($username,$password)) {
    1010         if ($user_level < 1) {
    1011             return new xmlrpcresp(0, $xmlrpcerruser+1,
    1012 
    1013               "Sorry, level 0 users cannot edit posts");
    1014         }
    1015 
    1016         extract($postdata);
    1017 
    1018         $post_title = $contentstruct['title'];
    1019         $post_content = format_to_post($contentstruct['description']);
    1020         $catnames = $contentstruct['categories'];
    1021        
    1022         if ($catnames) {
    1023             foreach ($catnames as $cat) {
    1024                 $post_category[] = get_cat_ID($cat);
    1025             }
    1026         }
    1027 
    1028         $post_excerpt = $contentstruct['mt_excerpt'];
    1029         $post_more = $contentstruct['mt_text_more'];
    1030         $post_status = $xpublish->scalarval()?'publish':'draft';
    1031         if ($post_more) {
    1032             $post_content = $post_content . "\n<!--more-->\n" . $post_more;
    1033         }
    1034         $comment_status = (1 == $contentstruct['mt_allow_comments'])?'open':'closed';
    1035         $ping_status = $contentstruct['mt_allow_pings']?'open':'closed';
    1036 
    1037         // Do some timestamp voodoo
    1038         $dateCreated = $contentstruct['dateCreated'];
    1039         if (!empty($dateCreated)) {
    1040           $post_date     = get_date_from_gmt(iso8601_to_datetime($dateCreated));
    1041           $post_date_gmt = iso8601_to_datetime($dateCreated, GMT);
    1042         } else {
    1043           $post_date     = $postdata['post_date'];
    1044           $post_date_gmt = $postdata['post_date_gmt'];
    1045         }
    1046 
    1047         // We've got all the data -- post it:
    1048         $newpost = compact('ID','post_content','post_title','post_category','post_status','post_excerpt','comment_status','ping_status','post_date','post_date_gmt');
    1049 
    1050         $post_ID = wp_update_post($newpost);
    1051        
    1052         if (!$post_ID) {
    1053             return new xmlrpcresp(0, $xmlrpcerruser+2, "For some strange yet very annoying reason, your entry could not be posted.");
    1054         }
    1055 
    1056         if (!isset($blog_ID)) { $blog_ID = 1; }
    1057 
    1058         if (isset($sleep_after_edit) && $sleep_after_edit > 0) {
    1059             sleep($sleep_after_edit);
    1060         }
    1061 
    1062         pingback($content, $post_ID);
    1063         trackback_url_list($contentstruct['mt_tb_ping_urls'],$post_ID);
    1064 
    1065         logIO("O","(MW) Edited ! ID: $post_ID");
    1066         $myResp = new xmlrpcval(true,"boolean");
    1067 
    1068         return new xmlrpcresp($myResp);
    1069 
    1070     } else {
    1071         logIO("O","(MW) Wrong username/password combination <b>$username / $password</b>");
    1072         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    1073        'Wrong username/password combination '.$username.' / '.starify($password));
    1074     }
    1075 }
    1076 
    1077 $mwgetpost_sig =  array(array($xmlrpcStruct,$xmlrpcString,$xmlrpcString,$xmlrpcString));
    1078 $mwegetpost_doc = 'Get a post, MetaWeblog API-style';
    1079 
    1080 function mwgetpost ($params) {  // ($postid, $user, $pass)
    1081     global $xmlrpcerruser;
    1082    
    1083     $xpostid = $params->getParam(0);
    1084     $xuser = $params->getParam(1);
    1085     $xpass = $params->getParam(2);
    1086    
    1087     $post_ID = $xpostid->scalarval();
    1088     $username = $xuser->scalarval();
    1089     $password = $xpass->scalarval();
    1090 
    1091     // Check login
    1092     if (user_pass_ok($username,$password)) {
    1093         $postdata = wp_get_single_post($post_ID, ARRAY_A);
    1094 
    1095         if ($postdata['post_date'] != '') {
    1096 
    1097             $post_date = mysql2date('Ymd\TH:i:s\Z', $postdata['post_date_gmt']);
    1098            
    1099             $catids = wp_get_post_cats('', $post_ID);
    1100             foreach($catids as $catid) {
    1101                 $catname = get_cat_name($catid);
    1102                 $catnameenc = new xmlrpcval($catname);
    1103                 $catlist[] = $catnameenc;
    1104             }           
    1105             $post = get_extended($postdata['post_content']);
    1106             $allow_comments = ('open' == $postdata['comment_status'])?1:0;
    1107             $allow_pings = ('open' == $postdata['ping_status'])?1:0;
    1108 
    1109             $resp = array(
    1110                 'link' => new xmlrpcval(post_permalink($post_ID)),
    1111                 'title' => new xmlrpcval($postdata['post_title']),
    1112                 'description' => new xmlrpcval($post['main']),
    1113                 'dateCreated' => new xmlrpcval($post_date,'dateTime.iso8601'),
    1114                 'userid' => new xmlrpcval($postdata['post_author']),
    1115                 'postid' => new xmlrpcval($postdata['ID']),
    1116                 'content' => new xmlrpcval($postdata['post_content']),
    1117                 'permalink' => new xmlrpcval(post_permalink($post_ID)),
    1118                 'categories' => new xmlrpcval($catlist,'array'),
    1119                 'mt_excerpt' => new xmlrpcval($postdata['post_excerpt']),
    1120                 'mt_allow_comments' => new xmlrpcval($allow_comments,'int'),
    1121                 'mt_allow_pings' => new xmlrpcval($allow_pings,'int'),
    1122                 'mt_text_more' => new xmlrpcval($post['extended'])
    1123             );
    1124            
    1125             $resp = new xmlrpcval($resp,'struct');
    1126            
    1127             return new xmlrpcresp($resp);
    1128         } else {
    1129         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 4
    1130             "No such post #$post_ID");
    1131         }
    1132     } else {
    1133         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    1134        'Wrong username/password combination '.$username.' / '.starify($password));
    1135     }
    1136 
    1137 }
    1138 
    1139 $mwrecentposts_sig =  array(array($xmlrpcArray,$xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcInt));
    1140 $mwerecentposts_doc = 'Get recent posts, MetaWeblog API-style';
    1141 
    1142 function mwrecentposts ($params) {  // ($blogid, $user, $pass, $num)
    1143     global $xmlrpcerruser;
    1144 
    1145     $xblogid = $params->getParam(0);
    1146     $xuser = $params->getParam(1);
    1147     $xpass = $params->getParam(2);
    1148     $xnum = $params->getParam(3);
    1149    
    1150     $blogid = $xblogid->scalarval();
    1151     $username = $xuser->scalarval();
    1152     $password = $xpass->scalarval();
    1153     $num = $xnum->scalarval();
    1154 
    1155     // Check login
    1156     if (user_pass_ok($username,$password)) {
    1157 
    1158         $postlist = wp_get_recent_posts($num);
    1159        
    1160         // Build response packet. We can't just use xmlrpc_encode,
    1161         // because of the dateCreated field, which must be a date type.
    1162        
    1163         // Encode each entry of the array.
    1164         foreach($postlist as $entry) {
    1165 
    1166             $isoString = mysql2date('Ymd\TH:i:s\Z', $entry['post_date_gmt']);
    1167             $date = new xmlrpcval($isoString,"dateTime.iso8601");
    1168             $userid = new xmlrpcval($entry['post_author']);
    1169             $content = new xmlrpcval($entry['post_content']);
    1170             $excerpt = new xmlrpcval($entry['post_excerpt']);
    1171            
    1172             // $pcat = stripslashes(get_cat_name($entry['post_category']));
    1173 
    1174             $catlist = array();
    1175             $catids = wp_get_post_cats('', $entry['ID']);
    1176             foreach($catids as $catid) {
    1177                 $catname = get_cat_name($catid);
    1178                 $catnameenc = new xmlrpcval($catname);
    1179                 $catlist[] = $catnameenc;
    1180             }
    1181 
    1182             // For multiple cats, we might do something like
    1183             // this in the future:
    1184             //$catstruct['description'] = $pcat;
    1185             //$catstruct['categoryId'] = $entry['post_category'];
    1186             //$catstruct['categoryName'] = $pcat;
    1187             //$catstruct['isPrimary'] = TRUE;
    1188            
    1189             //$catstruct2 = phpxmlrpc_encode($catstruct);
    1190            
    1191             // $categories = new xmlrpcval(array(new xmlrpcval($pcat)),'array');
    1192             $categories = new xmlrpcval($catlist, 'array');
    1193 
    1194             $post = get_extended($entry['post_content']);
    1195 
    1196             $postid = new xmlrpcval($entry['ID']);
    1197             $title = new xmlrpcval(stripslashes($entry['post_title']));
    1198             $description = new xmlrpcval(stripslashes($post['main']));
    1199             $link = new xmlrpcval(post_permalink($entry['ID']));
    1200             $permalink = $link;
    1201 
    1202             $extended = new xmlrpcval(stripslashes($post['extended']));
    1203 
    1204             $allow_comments = new xmlrpcval((('open' == $entry['comment_status'])?1:0),'int');
    1205             $allow_pings = new xmlrpcval((('open' == $entry['ping_status'])?1:0),'int');
    1206 
    1207             $encode_arr = array(
    1208                 'dateCreated' => $date,
    1209                 'userid' => $userid,
    1210                 'postid' => $postid,
    1211                 'categories' => $categories,
    1212                 'title' => $title,
    1213                 'description' => $description,
    1214                 'link' => $link,
    1215                 'permalink' => $permalink,
    1216                 'mt_excerpt' => $excerpt,
    1217                 'mt_allow_comments' => $allow_comments,
    1218                 'mt_allow_pings' => $allow_pings,
    1219                 'mt_text_more' => $extended
    1220             );
    1221            
    1222             $xmlrpcpostarr[] = new xmlrpcval($encode_arr,"struct");
    1223         }   
    1224 
    1225         // Now convert that to an xmlrpc array type
    1226         $myResp = new xmlrpcval($xmlrpcpostarr,"array");
    1227 
    1228         return new xmlrpcresp($myResp);
    1229     } else {
    1230         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    1231        'Wrong username/password combination '.$username.' / '.starify($password));
    1232     }
    1233 }
    1234 
    1235 
    1236 $mwgetcats_sig =  array(array($xmlrpcArray,$xmlrpcString,$xmlrpcString,$xmlrpcString));
    1237 $mwgetcats_doc = 'Get a post, MetaWeblog API-style';
    1238 
    1239 function mwgetcats ($params) {  // ($blogid, $user, $pass)
    1240     global $xmlrpcerruser,$wpdb;
    1241     global $querystring_start, $querystring_equal, $querystring_separator;
    1242    
    1243     $blog_URL = get_settings('home') . '/' . get_settings('blogfilename');
    1244    
    1245     $arr = array();
    1246 
    1247     if ($cats = $wpdb->get_results("SELECT cat_ID,cat_name FROM $wpdb->categories",ARRAY_A)) {
    1248         foreach ($cats as $cat) {
    1249             $struct['categoryId'] = $cat['cat_ID'];
    1250             $struct['description'] = $cat['cat_name'];
    1251             $struct['categoryName'] = $cat['cat_name'];
    1252             $struct['htmlUrl'] = htmlspecialchars($blog_URL . $querystring_start . 'cat' . $querystring_equal . $cat['cat_ID']);
    1253             $struct['rssUrl'] = ''; // will probably hack alexking's stuff in here
    1254            
    1255             $arr[] = phpxmlrpc_encode($struct);
    1256         }
    1257     }
    1258    
    1259     $resp = new xmlrpcval($arr,'array');
    1260 
    1261     return new xmlrpcresp($resp);
    1262 }
    1263 
    1264 
    1265 $mwnewmedia_sig =  array(array($xmlrpcStruct,$xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcStruct));
    1266 $mwnewmedia_doc = 'Upload image or other binary data, MetaWeblog API-style (unimplemented)';
    1267 
    1268 function mwnewmedia($params) {  // ($blogid, $user, $pass, $struct)
    1269     global $xmlrpcerruser;
    1270    
    1271     return new xmlrpcresp(0, $xmlrpcerruser+10, // user error 10
    1272       'metaWeblog.newMediaObject not implemented (yet)');
    1273 }
    1274 
    1275 
    1276 /**** /MetaWeblog API ****/
    1277 
    1278 
    1279 /**** MovableType API ****/
    1280 
    1281 /**********************
    1282  *
    1283  * MovableType API extensions
    1284  * added by
    1285  *  Dougal Campbell <dougal@gunters.org>
    1286  *  http://dougal.gunters.org/
    1287  *
    1288  * DONE:
    1289  *  mt.getCategoryList
    1290  *  mt.setPostCategories
    1291  *  mt.supportedMethods
    1292  *  mt.getPostCategories
    1293  *  mt.publishPost
    1294  *  mt.getRecentPostTitles
    1295  *  extend metaWeblog.newPost
    1296  *  extend metaWeblog.editPost
    1297  *  extend metaWeblog.getPost
    1298  *  extend metaWeblog.getRecentPosts
    1299  *
    1300  * PARTIALLY DONE:
    1301  *  mt.supportedTextFilters     // empty stub, because WP doesn't support per-post text filters at this time
    1302  *  mt.getTrackbackPings        // another stub.
    1303  *  metaWeblog.newMediaObject   // ditto. For now.
    1304  *
    1305  **********************/
    1306  
    1307 $mt_supportedMethods_sig = array(array($xmlrpcArray));
    1308 $mt_supportedMethods_doc = 'Retrieve information about the XML-RPC methods supported by the server.';
    1309 
    1310 // ripped out of system.listMethods
    1311 function mt_supportedMethods($params) {
    1312     global $dispatch_map, $xmlrpcerr, $xmlrpcstr, $_xmlrpcs_dmap;
    1313     $v=new xmlrpcval();
    1314     $dmap=$dispatch_map;
    1315     $outAr=array();
    1316     for(reset($dmap); list($key, $val)=each($dmap); ) {
    1317     $outAr[]=new xmlrpcval($key, "string");
    1318     }
    1319     $dmap=$_xmlrpcs_dmap;
    1320     for(reset($dmap); list($key, $val)=each($dmap); ) {
    1321     $outAr[]=new xmlrpcval($key, "string");
    1322     }
    1323     $v->addArray($outAr);
    1324     return new xmlrpcresp($v);
    1325 
    1326 }
    1327 
    1328 $mt_getPostCategories_sig = array(array($xmlrpcArray, $xmlrpcString, $xmlrpcString, $xmlrpcString));
    1329 $mt_getPostCategories_doc = "Returns a list of all categories to which the post is assigned.";
    1330 
    1331 function mt_getPostCategories($params) {
    1332     global $xmlrpcusererr;
    1333 
    1334     $xpostid = $params->getParam(0);
    1335     $xuser = $params->getParam(1);
    1336     $xpass = $params->getParam(2);
    1337    
    1338     $post_ID = $xpostid->scalarval();
    1339     $username = $xuser->scalarval();
    1340     $password = $xpass->scalarval();
    1341 
    1342     if (user_pass_ok($username,$password)) {
    1343         $catids = wp_get_post_cats('1', $post_ID);
    1344 
    1345         // The first category listed will be set as primary
    1346         $struct['isPrimary'] = true;
    1347         foreach($catids as $catid) {   
    1348             $struct['categoryId'] = $catid;
    1349             $struct['categoryName'] = get_cat_name($catid);
    1350 
    1351             $resp_struct[] = phpxmlrpc_encode($struct);
    1352             $struct['isPrimary'] = false;
    1353         }
    1354        
    1355         // Return an array of structs   
    1356         $resp_array = new xmlrpcval($resp_struct,'array');
    1357        
    1358         return new xmlrpcresp($resp_array);
    1359 
    1360     } else {
    1361         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    1362        'Wrong username/password combination '.$username.' / '.starify($password));
    1363     }
    1364 }
    1365 
    1366 $mt_setPostCategories_sig = array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString, $xmlrpcArray));
    1367 $mt_setPostCategories_doc = "Sets the categories for a post";
    1368 
    1369 function mt_setPostCategories($params) {
    1370     global $xmlrpcusererr;
    1371    
    1372     $xpostid = $params->getParam(0);
    1373     $xuser = $params->getParam(1);
    1374     $xpass = $params->getParam(2);
    1375     $xcats = $params->getParam(3);
    1376    
    1377     $post_ID = $xpostid->scalarval();
    1378     $username = $xuser->scalarval();
    1379     $password = $xpass->scalarval();
    1380     $cats = phpxmlrpc_decode($xcats);
    1381    
    1382     foreach($cats as $cat) {
    1383         $catids[] = $cat['categoryId'];
    1384     }
    1385    
    1386     if (user_pass_ok($username,$password)) {
    1387         wp_set_post_cats('', $post_ID, $catids);
    1388        
    1389         return new xmlrpcresp(new xmlrpcval(true,'boolean'));
    1390     } else {
    1391         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    1392        'Wrong username/password combination '.$username.' / '.starify($password));
    1393     }
    1394 }
    1395 
    1396 $mt_publishPost_sig = array(array($xmlrpcBoolean, $xmlrpcString, $xmlrpcString, $xmlrpcString));
    1397 $mt_publishPost_doc = "Publish (rebuild) all of the static files related to an entry. Equivalent to saving an entry in the system (but without the ping).";
    1398 
    1399 function mt_publishPost($params) {
    1400     global $xmlrpcusererr;
    1401    
    1402     $xpostid = $params->getParam(0);
    1403     $xuser = $params->getParam(1);
    1404     $xpass = $params->getParam(2);
    1405    
    1406     $post_ID = $xpostid->scalarval();
    1407     $username = $xuser->scalarval();
    1408     $password = $xpass->scalarval();
    1409 
    1410     if (user_pass_ok($username,$password)) {
    1411         $postdata = wp_get_single_post($post_ID,ARRAY_A);
    1412        
    1413         $postdata['post_status'] = 'publish';
    1414        
    1415         // retain old cats
    1416         $cats = wp_get_post_cats('',$post_ID);
    1417         $postdata['post_category'] = $cats;
    1418    
    1419         $result = wp_update_post($postdata);
    1420 
    1421         return new xmlrpcresp(new xmlrpcval($result,'boolean'));
    1422     } else {
    1423         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    1424        'Wrong username/password combination '.$username.' / '.starify($password));
    1425     }
    1426 }
    1427 
    1428 $mt_getRecentPostTitles_sig = array(array($xmlrpcArray,$xmlrpcString,$xmlrpcString,$xmlrpcString,$xmlrpcInt));
    1429 $mt_getRecentPostTitles_doc = "Returns a bandwidth-friendly list of the most recent posts in the system.";
    1430 
    1431 function mt_getRecentPostTitles($params) {
    1432     global $xmlrpcusererr, $wpdb;
    1433 
    1434     $xblogid = $params->getParam(0);
    1435     $xuser = $params->getParam(1);
    1436     $xpass = $params->getParam(2);
    1437     $xnumposts = $params->getParam(3);
    1438 
    1439     $blogid = $xblogid->scalarval();
    1440     $username = $xuser->scalarval();
    1441     $password = $xpass->scalarval();
    1442     $numposts = intval($xnumposts->scalarval());
    1443 
    1444     if (user_pass_ok($username,$password)) {
    1445         $sql = "SELECT post_date, post_date_gmt, post_author, ID, post_title FROM $wpdb->posts ORDER BY post_date_gmt DESC LIMIT $numposts";
    1446         $posts = $wpdb->get_results($sql,ARRAY_A);
    1447        
    1448         foreach($posts as $post) {
    1449 
    1450             $post_date = mysql2date('Ymd\TH:i:s\Z', $post['post_date_gmt']);
    1451 
    1452             $struct['dateCreated'] = new xmlrpcval($post_date, 'dateTime.iso8601');
    1453             $struct['userid'] = new xmlrpcval($post['post_author'], 'string');
    1454             $struct['postid'] = new xmlrpcval($post['ID'], 'string');
    1455             $struct['title'] = new xmlrpcval($post['post_title'], 'string');
    1456            
    1457             $result[] = $struct;
    1458         }
    1459        
    1460         return new xmlrpcresp(new xmlrpcval($results,'array'));
    1461 
    1462     } else {
    1463         return new xmlrpcresp(0, $xmlrpcerruser+3, // user error 3
    1464        'Wrong username/password combination '.$username.' / '.starify($password));
    1465     }
    1466 }
    1467 
    1468 
    1469 $mt_supportedTextFilters_sig = array(array($xmlrpcArray));
    1470 $mt_supportedTextFilters_doc = "Retrieve information about the text formatting plugins supported by the server. (not implemented)";
    1471 
    1472 function mt_supportedTextFilters($params) {
    1473     // This should probably check the status of the 'use_bbcode'
    1474     // and 'use_gmcode' config options.
    1475    
    1476     return new xmlrpcresp(new xmlrpcval(array(),'array'));
    1477 }
    1478 
    1479 
    1480 
    1481 $mt_getTrackbackPings_sig = array(array($xmlrpcArray,$xmlrpcString));
    1482 $mt_getTrackbackPings_doc = "Retrieve the list of Trackback pings posted to a particular entry. (not implemented)";
    1483 
    1484 function mt_getTrackbackPings($params) {
    1485     $struct['pingTitle'] = '';
    1486     $struct['pingURL'] = '';
    1487     $struct['pingIP'] = '';
    1488    
    1489     $xmlstruct = phpxmlrpc_encode($struct);
    1490    
    1491     return new xmlrpcresp(new xmlrpcval(array($xmlstruct),'array'));
    1492 }
    1493 
    1494 
    1495 
    1496 /**** /MovableType API ****/
    1497 
    1498 
    1499 /**** PingBack functions ****/
    1500 
    1501 $pingback_ping_sig = array(array($xmlrpcString, $xmlrpcString, $xmlrpcString));
    1502 
    1503 $pingback_ping_doc = 'Gets a pingback and registers it as a comment prefixed by &lt;pingback /&gt;';
    1504 
    1505 function pingback_ping($m) { // original code by Mort
    1506     // (http://mort.mine.nu:8080)
    1507     global $wpdb, $wp_version;
    1508 
    1509     //$log = debug_fopen('./xmlrpc.log', 'w');
    1510 
    1511     $title='';
    1512 
    1513     $pagelinkedfrom = $m->getParam(0);
    1514     $pagelinkedfrom = $pagelinkedfrom->scalarval();
    1515 
    1516     $pagelinkedto = $m->getParam(1);
    1517     $pagelinkedto = $pagelinkedto->scalarval();
    1518 
    1519     $pagelinkedfrom = str_replace('&amp;', '&', $pagelinkedfrom);
    1520     $pagelinkedto = preg_replace('#&([^amp\;])#is', '&amp;$1', $pagelinkedto);
    1521 
    1522     //debug_fwrite($log, 'BEGIN '.time().' - '.date('Y-m-d H:i:s')."\n\n");
    1523     //debug_fwrite($log, 'Page linked from: '.$pagelinkedfrom."\n");
    1524     //debug_fwrite($log, 'Page linked to: '.$pagelinkedto."\n");
    1525 
    1526     $messages = array(
    1527         htmlentities("Pingback from ".$pagelinkedfrom." to "
    1528             . $pagelinkedto . " registered. Keep the web talking! :-)"),
    1529         htmlentities("We can't find the URL to the post you are trying to "
    1530             . "link to in your entry. Please check how you wrote the post's permalink in your entry."),
    1531         htmlentities("We can't find the post you are trying to link to."
    1532             . " Please check the post's permalink.")
    1533     );
    1534 
    1535     $message = $messages[0];
    1536 
    1537     // Check if the page linked to is in our site
    1538     $pos1 = strpos($pagelinkedto, str_replace('http://', '', str_replace('www.', '', get_settings('home'))));
    1539     if($pos1) {
     990      wp_set_post_cats('', $post_ID, $catids);
     991
     992      return true;
     993    }
     994
     995
     996    /* mt.supportedMethods ...returns an array of methods supported by this server */
     997    function mt_supportedMethods($args) {
     998
     999      $supported_methods = array();
     1000      foreach($this->methods as $key=>$value) {
     1001        $supported_methods[] = $key;
     1002      }
     1003
     1004      return $supported_methods;
     1005    }
     1006
     1007
     1008    /* mt.supportedTextFilters ...returns an empty array because we don't
     1009       support per-post text filters yet */
     1010    function mt_supportedTextFilters($args) {
     1011      return array();
     1012    }
     1013
     1014
     1015    /* mt.getTrackbackPings ...returns trackbacks sent to a given post */
     1016    function mt_getTrackbackPings($args) {
     1017
     1018      global $wpdb;
     1019
     1020      $post_ID = intval($args);
     1021
     1022      $actual_post = wp_get_single_post($post_ID, ARRAY_A);
     1023
     1024      if (!$actual_post) {
     1025        return new IXR_Error(404, 'Sorry, no such post.');
     1026      }
     1027
     1028      $comments = $wpdb->get_results("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = $post_ID");
     1029
     1030      if (!$comments) {
     1031        return array();
     1032      }
     1033
     1034      $trackback_pings = array();
     1035      foreach($comments as $comment) {
     1036        if ((strpos($comment->comment_content, '<trackback />') === 0)
     1037            || ('trackback' == $comment->comment_type)) {
     1038          // FIXME: would be nicer to have a comment_title field?
     1039          // FIXME: assumption: here we make the assumption that trackback
     1040          //        titles are stored as <strong>title</strong>
     1041          $content = str_replace('<trackback />', '', $comment->comment_content);
     1042          $title = substr($content, 8, (strpos($content, '</strong>') - 8));
     1043          $trackback_pings[] = array(
     1044            'pingTitle' => $title,
     1045            'pingURL'   => $comment->comment_author_url,
     1046            'pingIP'    => $comment->comment_author_IP
     1047          );
     1048        }
     1049      }
     1050
     1051      return $trackback_pings;
     1052    }
     1053
     1054
     1055    /* mt.publishPost ...sets a post's publish status to 'publish' */
     1056    function mt_publishPost($args) {
     1057
     1058      $post_ID     = $args[0];
     1059      $user_login  = $args[1];
     1060      $user_pass   = $args[2];
     1061
     1062      if (!$this->login_pass_ok($user_login, $user_pass)) {
     1063        return $this->error;
     1064      }
     1065
     1066      $user_data = get_userdatabylogin($user_login);
     1067      if (!user_can_edit_post($user_data->ID, $post_ID)) {
     1068        return new IXR_Error(401, 'Sorry, you can not edit this post.');
     1069      }
     1070
     1071      $postdata = wp_get_single_post($post_ID,ARRAY_A);
     1072
     1073      $postdata['post_status'] = 'publish';
     1074
     1075      // retain old cats
     1076      $cats = wp_get_post_cats('',$post_ID);
     1077      $postdata['post_category'] = $cats;
     1078
     1079      $result = wp_update_post($postdata);
     1080
     1081      return $result;
     1082    }
     1083
     1084
     1085
     1086    /* PingBack functions
     1087     * specs on www.hixie.ch/specs/pingback/pingback
     1088     */
     1089
     1090    /* pingback.ping gets a pingback and registers it */
     1091    function pingback_ping($args) {
     1092        // original code by Mort (http://mort.mine.nu:8080 -- site seems dead)
     1093        // refactored to return error codes and avoid deep ifififif headaches
     1094        global $wpdb, $wp_version;
     1095
     1096        $pagelinkedfrom = $args[0];
     1097        $pagelinkedto   = $args[1];
     1098
     1099        $title = '';
     1100
     1101        $pagelinkedfrom = str_replace('&amp;', '&', $pagelinkedfrom);
     1102        $pagelinkedto   = preg_replace('#&([^amp\;])#is', '&amp;$1', $pagelinkedto);
     1103
     1104        $error_code = -1;
     1105
     1106        // Check if the page linked to is in our site
     1107        $pos1 = strpos($pagelinkedto, str_replace('http://', '', str_replace('www.', '', get_settings('home'))));
     1108        if(!$pos1) {
     1109            return new IXR_Error(0, '');
     1110        }
     1111
    15401112
    15411113        // let's find which post is linked to
     1114        // FIXME: does url_to_postid() cover all these cases already?
     1115        //        if so, then let's use it and drop the old code.
    15421116        $urltest = parse_url($pagelinkedto);
    15431117        if ($post_ID = url_to_postid($pagelinkedto)) {
    15441118            $way = 'url_to_postid()';
    1545         }
    1546         elseif (preg_match('#p/[0-9]{1,}#', $urltest['path'], $match)) {
     1119        } elseif (preg_match('#p/[0-9]{1,}#', $urltest['path'], $match)) {
    15471120            // the path defines the post_ID (archives/p/XXXX)
    15481121            $blah = explode('/', $match[0]);
     
    15681141                $title = preg_replace('/[^a-zA-Z0-9]/', '.', $urltest['fragment']);
    15691142                $sql = "SELECT ID FROM $wpdb->posts WHERE post_title RLIKE '$title'";
    1570                 $post_ID = $wpdb->get_var($sql) or die("Query: $sql\n\nError: ");
     1143                if (! ($post_ID = $wpdb->get_var($sql)) ) {
     1144                    // returning unknown error '0' is better than die()ing
     1145                    return new IXR_Error(0, '');
     1146                }
    15711147                $way = 'from the fragment (title)';
    15721148            }
    15731149        } else {
    15741150            // TODO: Attempt to extract a post ID from the given URL
    1575             $post_ID = -1;
    1576             $way = 'no match';
    1577         }
     1151            return new IXR_Error(33, 'The specified target URI cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.');
     1152        }
     1153
    15781154
    15791155        logIO("O","(PB) URI='$pagelinkedto' ID='$post_ID' Found='$way'");
    1580 
    1581         //debug_fwrite($log, "Found post ID $way: $post_ID\n");
    15821156
    15831157        $sql = 'SELECT post_author FROM '.$wpdb->posts.' WHERE ID = '.$post_ID;
    15841158        $result = $wpdb->get_results($sql);
    15851159
     1160        if (!$wpdb->num_rows) {
     1161            // Post_ID not found
     1162            return new IXR_Error(33, 'The specified target URI cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.');
     1163        }
     1164
     1165
     1166        // Let's check that the remote site didn't already pingback this entry
     1167        $sql = 'SELECT * FROM '.$wpdb->comments.'
     1168            WHERE comment_post_ID = '.$post_ID.'
     1169                AND comment_author_url = \''.$pagelinkedfrom.'\'
     1170                AND comment_type = \'pingback\'';
     1171        $result = $wpdb->get_results($sql);
     1172//return($sql);
     1173
    15861174        if ($wpdb->num_rows) {
    1587 
    1588             //debug_fwrite($log, 'Post exists'."\n");
    1589 
    1590             // Let's check that the remote site didn't already pingback this entry
    1591             $sql = 'SELECT * FROM '.$wpdb->comments.'
    1592                 WHERE comment_post_ID = '.$post_ID.'
    1593                     AND comment_author_url = \''.$pagelinkedfrom.'\'
    1594                     AND comment_content LIKE \'%<pingback />%\'';
    1595             $result = $wpdb->get_results($sql);
    1596        
    1597             if ($wpdb->num_rows || (1==1)) {
    1598 
    1599                 // very stupid, but gives time to the 'from' server to publish !
    1600                 sleep(1);
    1601 
    1602                 // Let's check the remote site
    1603                 $fp = @fopen($pagelinkedfrom, 'r');
    1604 
    1605                 $puntero = 4096;
    1606                 while($remote_read = fread($fp, $puntero)) {
    1607                     $linea .= $remote_read;
    1608                 }
    1609                     // Work around bug in strip_tags():
    1610                     $linea = str_replace('<!DOCTYPE','<DOCTYPE',$linea);
    1611                     $linea = strip_tags($linea, '<title><a>');
    1612                     $linea = strip_all_but_one_link($linea, $pagelinkedto);
    1613                     // I don't think we need this? -- emc3
    1614                     //$linea = preg_replace('#&([^amp\;])#is', '&amp;$1', $linea);
    1615                     if (empty($matchtitle)) {
    1616                         preg_match('|<title>([^<]*?)</title>|is', $linea, $matchtitle);
    1617                     }
    1618                     $pos2 = strpos($linea, $pagelinkedto);
    1619                     $pos3 = strpos($linea, str_replace('http://www.', 'http://', $pagelinkedto));
    1620                     if (is_integer($pos2) || is_integer($pos3)) {
    1621                         //debug_fwrite($log, 'The page really links to us :)'."\n");
    1622                         $pos4 = (is_integer($pos2)) ? $pos2 : $pos3;
    1623                         $start = $pos4-100;
    1624                         $context = substr($linea, $start, 250);
    1625                         $context = str_replace("\n", ' ', $context);
    1626                         $context = str_replace('&amp;', '&', $context);
    1627                     } else {
    1628                         //debug_fwrite($log, 'The page doesn\'t link to us, here\'s an excerpt :'."\n\n".$linea."\n\n");
    1629                     }
    1630                 //}
    1631                 //debug_fwrite($log, '*****'."\n\n");
    1632                 fclose($fp);
    1633 
    1634                 if (!empty($context)) {
    1635                     // Check if pings are on, inelegant exit
    1636                     $pingstatus = $wpdb->get_var("SELECT ping_status FROM $wpdb->posts WHERE ID = $post_ID");
    1637                     if ('closed' == $pingstatus) die('Sorry, pings are turned off for this post.');
    1638 
    1639                     $pagelinkedfrom = preg_replace('#&([^amp\;])#is', '&amp;$1', $pagelinkedfrom);
    1640                     $title = (!strlen($matchtitle[1])) ? $pagelinkedfrom : $matchtitle[1];
    1641                     $original_context = strip_tags($context);
    1642                     $context = '<pingback />[...] ';
    1643                     $context = htmlspecialchars($original_context);
    1644                     $context .= ' [...]';
    1645                     $original_pagelinkedfrom = $pagelinkedfrom;
    1646                     $pagelinkedfrom = addslashes($pagelinkedfrom);
    1647                     $original_title = $title;
    1648                     $title = addslashes(strip_tags(trim($title)));
    1649                     $user_ip = $_SERVER['REMOTE_ADDR'];
    1650                     $user_agent = addslashes($_SERVER['HTTP_USER_AGENT']);
    1651                     $now = current_time('mysql');
    1652                     $now_gmt = current_time('mysql', 1);
    1653                     if( check_comment($title, '', $pagelinkedfrom, $context, $user_ip, $user_agent) ) {
    1654                         $approved = 1;
    1655                     } else {
    1656                         $approved = 0;
    1657                     }
    1658                     $consulta = $wpdb->query("INSERT INTO $wpdb->comments
    1659                         (comment_post_ID, comment_author, comment_author_url, comment_author_IP, comment_date, comment_date_gmt, comment_content, comment_approved, comment_agent)
    1660                         VALUES
    1661                         ($post_ID, '$title', '$pagelinkedfrom', '$user_ip', $now', '$now_gmt', '$context', '$approved', '$user_agent')
    1662                         ");
    1663 
    1664                     $comment_ID = $wpdb->get_var('SELECT last_insert_id()');
    1665                     if (get_settings('comments_notify'))
    1666                         wp_notify_postauthor($comment_ID, 'pingback');
    1667                     do_action('pingback_post', $comment_ID);
    1668                 } else {
    1669                     // URL pattern not found
    1670                     $message = "Page linked to: $pagelinkedto\nPage linked from:"
    1671                         . " $pagelinkedfrom\nTitle: $title\nContext: $context\n\n".$messages[1];
    1672                 }
    1673             } else {
    1674                 // We already have a Pingback from this URL
    1675                 $message = "Sorry, you already did a pingback to $pagelinkedto"
    1676                 . " from $pagelinkedfrom.";
     1175            // We already have a Pingback from this URL
     1176            return new IXR_Error(48, 'The pingback has already been registered.');
     1177        }
     1178
     1179
     1180        // very stupid, but gives time to the 'from' server to publish !
     1181        sleep(1);
     1182
     1183        // Let's check the remote site
     1184        $fp = @fopen($pagelinkedfrom, 'r');
     1185        if (!$fp) {
     1186            // The source URI does not exist
     1187            return new IXR_Error(16, 'The source URI does not exist.');
     1188        }
     1189
     1190        $puntero = 4096;
     1191        while($remote_read = fread($fp, $puntero)) {
     1192            $linea .= $remote_read;
     1193        }
     1194
     1195        // Work around bug in strip_tags():
     1196        $linea = str_replace('<!DOCTYPE','<DOCTYPE',$linea);
     1197        $linea = strip_tags($linea, '<title><a>');
     1198        $linea = strip_all_but_one_link($linea, $pagelinkedto);
     1199        // I don't think we need this? -- emc3
     1200        //$linea = preg_replace('#&([^amp\;])#is', '&amp;$1', $linea);
     1201        if (empty($matchtitle)) {
     1202            preg_match('|<title>([^<]*?)</title>|is', $linea, $matchtitle);
     1203        }
     1204        $pos2 = strpos($linea, $pagelinkedto);
     1205        $pos3 = strpos($linea, str_replace('http://www.', 'http://', $pagelinkedto));
     1206        if (is_integer($pos2) || is_integer($pos3)) {
     1207            // The page really links to us :)
     1208            $pos4 = (is_integer($pos2)) ? $pos2 : $pos3;
     1209            $start = $pos4-100;
     1210            $context = substr($linea, $start, 250);
     1211            $context = str_replace("\n", ' ', $context);
     1212            $context = str_replace('&amp;', '&', $context);
     1213        }
     1214                   
     1215        fclose($fp);
     1216
     1217        if (empty($context)) {
     1218            // URL pattern not found
     1219            return new IXR_Error(17, 'The source URI does not contain a link to the target URI, and so cannot be used as a source.');
     1220        }
     1221
     1222
     1223        // Check if pings are on, inelegant exit
     1224        $pingstatus = $wpdb->get_var("SELECT ping_status FROM $wpdb->posts WHERE ID = $post_ID");
     1225        if ('closed' == $pingstatus) {
     1226            return new IXR_Error(33, 'The specified target URI cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.');
     1227        }
     1228
     1229
     1230        $pagelinkedfrom = preg_replace('#&([^amp\;])#is', '&amp;$1', $pagelinkedfrom);
     1231        $title = (!strlen($matchtitle[1])) ? $pagelinkedfrom : $matchtitle[1];
     1232        $original_context = strip_tags($context);
     1233        $context = '[...] ';
     1234        $context = htmlspecialchars($original_context);
     1235        $context .= ' [...]';
     1236        $original_pagelinkedfrom = $pagelinkedfrom;
     1237        $pagelinkedfrom = addslashes($pagelinkedfrom);
     1238        $original_title = $title;
     1239        $title = addslashes(strip_tags(trim($title)));
     1240        $user_ip = $_SERVER['REMOTE_ADDR'];
     1241        $user_agent = addslashes($_SERVER['HTTP_USER_AGENT']);
     1242        $now = current_time('mysql');
     1243        $now_gmt = current_time('mysql', 1);
     1244
     1245        // Check if the entry allows pings
     1246        if( !check_comment($title, '', $pagelinkedfrom, $context, $user_ip, $user_agent) ) {
     1247            return new IXR_Error(49, 'Pingbacks not allowed on this entry.');
     1248        }
     1249
     1250
     1251        $consulta = $wpdb->query("INSERT INTO $wpdb->comments
     1252            (comment_post_ID, comment_author, comment_author_url, comment_author_IP, comment_date, comment_date_gmt, comment_content, comment_approved, comment_agent, comment_type)
     1253            VALUES
     1254            ($post_ID, '$title', '$pagelinkedfrom', '$user_ip', '$now', '$now_gmt', '$context', '1', '$user_agent', 'pingback')
     1255        ");
     1256
     1257        $comment_ID = $wpdb->get_var('SELECT last_insert_id()');
     1258
     1259        if (get_settings('comments_notify')) {
     1260            wp_notify_postauthor($comment_ID, 'pingback');
     1261        }
     1262
     1263        do_action('pingback_post', $comment_ID);
     1264       
     1265        return "Pingback from $pagelinkedfrom to $pagelinkedto registered. Keep the web talking! :-)";
     1266    }
     1267
     1268
     1269    /* pingback.extensions.getPingbacks returns an array of URLs
     1270       that pingbacked the given URL
     1271       specs on http://www.aquarionics.com/misc/archives/blogite/0198.html */
     1272    function pingback_extensions_getPingbacks($args) {
     1273
     1274        global $wpdb;
     1275
     1276        $url = $args;
     1277
     1278        $post_ID = url_to_postid($url);
     1279        if (!$post_ID) {
     1280            // We aren't sure that the resource is available and/or pingback enabled
     1281            return new IXR_Error(33, 'The specified target URI cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.');
     1282        }
     1283
     1284        $actual_post = wp_get_single_post($post_ID, ARRAY_A);
     1285
     1286        if (!$actual_post) {
     1287            // No such post = resource not found
     1288            return new IXR_Error(32, 'The specified target URI does not exist.');
     1289        }
     1290
     1291        $comments = $wpdb->get_results("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = $post_ID");
     1292
     1293        if (!$comments) {
     1294            return array();
     1295        }
     1296
     1297        $pingbacks = array();
     1298        foreach($comments as $comment) {
     1299            if ((strpos($comment->comment_content, '<pingback />') === 0)
     1300                || ('pingback' == $comment->comment_type)) {
     1301                $pingbacks[] = $comment->comment_author_url;
    16771302            }
    1678         } else {
    1679             // Post_ID not found
    1680             $message = $messages[2];
    1681             //debug_fwrite($log, 'Post doesn\'t exist'."\n");
    1682         }
    1683     }
    1684     return new xmlrpcresp(new xmlrpcval($message));
     1303        }
     1304
     1305        return $pingbacks;
     1306    }
    16851307}
    16861308
    1687 /**** /PingBack functions ****/
    1688 
    1689 /**** SERVER FUNCTIONS ARRAY ****/
    1690 
    1691 $dispatch_map = 
    1692 array( "blogger.newPost" =>
    1693 array("function" => "bloggernewpost",
    1694      "signature" => $bloggernewpost_sig,
    1695      "docstring" => $bloggernewpost_doc),
    1696 
    1697 
    1698 "blogger.editPost" =>
    1699 array("function" => "bloggereditpost",
    1700      "signature" => $bloggereditpost_sig,
    1701      "docstring" => $bloggereditpost_doc),
    1702 
    1703 
    1704 "blogger.deletePost" =>
    1705 array("function" => "bloggerdeletepost",
    1706      "signature" => $bloggerdeletepost_sig,
    1707      "docstring" => $bloggerdeletepost_doc),
    1708 
    1709 
    1710 "blogger.getUsersBlogs" =>
    1711 array("function" => "bloggergetusersblogs",
    1712      "signature" => $bloggergetusersblogs_sig,
    1713      "docstring" => $bloggergetusersblogs_doc),
    1714 
    1715 "blogger.getUserInfo" =>
    1716 array("function" => "bloggergetuserinfo",
    1717      "signature" => $bloggergetuserinfo_sig,
    1718      "docstring" => $bloggergetuserinfo_doc),
    1719 
    1720 "blogger.getPost" =>
    1721 array("function" => "bloggergetpost",
    1722      "signature" => $bloggergetpost_sig,
    1723      "docstring" => $bloggergetpost_doc),
    1724 
    1725 "blogger.getRecentPosts" =>
    1726 array("function" => "bloggergetrecentposts",
    1727      "signature" => $bloggergetrecentposts_sig,
    1728      "docstring" => $bloggergetrecentposts_doc),
    1729 
    1730 "blogger.getTemplate" =>
    1731 array("function" => "bloggergettemplate",
    1732      "signature" => $bloggergettemplate_sig,
    1733      "docstring" => $bloggergettemplate_doc),
    1734 
    1735 "blogger.setTemplate" =>
    1736 array("function" => "bloggersettemplate",
    1737      "signature" => $bloggersettemplate_sig,
    1738      "docstring" => $bloggersettemplate_doc),
    1739 
    1740 "metaWeblog.newPost" =>
    1741 array("function" => "mwnewpost",
    1742      "signature" => $mwnewpost_sig,
    1743      "docstring" => $mwnewpost_doc),
    1744 
    1745 "metaWeblog.editPost" =>
    1746 array("function" => "mweditpost",
    1747      "signature" => $mweditpost_sig,
    1748      "docstring" => $mweditpost_doc),
    1749 
    1750 "metaWeblog.getPost" =>
    1751 array("function" => "mwgetpost",
    1752      "signature" => $mwgetpost_sig,
    1753      "docstring" => $mwgetpost_doc),
    1754 
    1755 "metaWeblog.getRecentPosts" =>
    1756 array("function" => "mwrecentposts",
    1757      "signature" => $mwrecentposts_sig,
    1758      "docstring" => $mwrecentposts_doc),
    1759 
    1760 "metaWeblog.getCategories" =>
    1761 array("function" => "mwgetcats",
    1762      "signature" => $mwgetcats_sig,
    1763      "docstring" => $mwgetcats_doc),
    1764 
    1765 "metaWeblog.newMediaObject" =>
    1766 array("function" => "mwnewmedia",
    1767      "signature" => $mwnewmedia_sig,
    1768      "docstring" => $mwnewmedia_doc),
    1769 
    1770 "mt.getCategoryList" =>
    1771 array("function" => "mwgetcats",
    1772      "signature" => $mwgetcats_sig,
    1773      "docstring" => $mwgetcats_doc),
    1774 
    1775 "mt.getPostCategories" =>
    1776 array("function" => "mt_getPostCategories",
    1777      "signature" => $mt_getPostCategories_sig,
    1778      "docstring" => $mt_getPostCategories_doc),
    1779 
    1780 "mt.setPostCategories" =>
    1781 array("function" => "mt_setPostCategories",
    1782      "signature" => $mt_setPostCategories_sig,
    1783      "docstring" => $mt_setPostCategories_doc),
    1784 
    1785 "mt.publishPost" =>
    1786 array("function" => "mt_publishPost",
    1787      "signature" => $mt_publishPost_sig,
    1788      "docstring" => $mt_publishPost_doc),
    1789 
    1790 "mt.supportedMethods" =>
    1791 array("function" => "mt_supportedMethods",
    1792      "signature" => $mt_supportedMethods_sig,
    1793      "docstring" => $mt_supportedMethods_doc),
    1794 
    1795 "mt.supportedTextFilters" =>
    1796 array("function" => "mt_supportedTextFilters",
    1797      "signature" => $mt_supportedTextFilters_sig,
    1798      "docstring" => $mt_supportedTextFilters_doc),
    1799 
    1800 "mt.getRecentPostTitles" =>
    1801 array("function" => "mt_getRecentPostTitles",
    1802      "signature" => $mt_getRecentPostTitles_sig,
    1803      "docstring" => $mt_getRecentPostTitles_doc),
    1804 
    1805 "mt.getTrackbackPings" =>
    1806 array("function" => "mt_getTrackbackPings",
    1807      "signature" => $mt_getTrackbackPings_sig,
    1808      "docstring" => $mt_getTrackbackPings_doc),
    1809 
    1810 "b2.newPost" =>
    1811 array("function" => "b2newpost",
    1812      "signature" => $wpnewpost_sig,
    1813      "docstring" => $wpnewpost_doc),
    1814 "b2.getCategories" =>
    1815 array("function" => "b2getcategories",
    1816      "signature" => $wpgetcategories_sig,
    1817      "docstring" => $wpgetcategories_doc),
    1818 
    1819 "b2.ping" =>
    1820 array("function" => "b2ping",
    1821      "signature" => $wpping_sig,
    1822      "docstring" => $wpping_doc),
    1823 
    1824 "pingback.ping" =>
    1825 array("function" => "pingback_ping",
    1826      "signature" => $pingback_ping_sig,
    1827      "docstring" => $pingback_ping_doc),
    1828 
    1829 "b2.getPostURL" =>
    1830 array("function" => "pingback_getPostURL",
    1831      "signature" => $wp_getPostURL_sig,
    1832      "docstring" => $wp_getPostURL_doc),
    1833 );
    1834 
    1835 $s = new xmlrpc_server($dispatch_map);
     1309
     1310$wp_xmlrpc_server = new wp_xmlrpc_server();
    18361311
    18371312?>
Note: See TracChangeset for help on using the changeset viewer.