Make WordPress Core

Changeset 1684


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

moved wp-admin/xmlrpc.php to the root dir

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/xmlrpc.php

    r1679 r1684  
    44$HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA);
    55
    6 include('../wp-config.php');
    7 include_once(ABSPATH . WPINC . '/class-IXR.php');
    8 include_once(ABSPATH . WPINC . '/functions-post.php');
     6include('wp-config.php');
     7
     8include_once (ABSPATH . WPINC . '/class-xmlrpc.php');
     9include_once (ABSPATH . WPINC . '/class-xmlrpcs.php');
     10include_once (ABSPATH . WPINC . '/functions-post.php');
    911
    1012// Turn off all warnings and errors.
    11 // error_reporting(0);
     13error_reporting(0);
    1214
    1315$post_default_title = ""; // posts submitted via the xmlrpc interface get that title
     
    1921    global $xmlrpc_logging;
    2022    if ($xmlrpc_logging) {
    21         $fp = fopen("../xmlrpc.log","a+");
     23        $fp = fopen("./xmlrpc.log","a+");
    2224        $date = gmdate("Y-m-d H:i:s ");
    2325        $iot = ($io == "I") ? " Input: " : " Output: ";
     
    3638
    3739
    38 function 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 
    50 function 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 
    74 class 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       }
    522        
    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       }
    545        
    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       }
     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
     58function 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');
     107       
     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; }
     118       
     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
     145function 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
     200function 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
     266function 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';
     286   
     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
     341function 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
     430function 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
     505function 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
     539function 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
     576function 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
     627function 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
     745function 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
     808function 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
     880function 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
     976function 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
     1080function 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
     1142function 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
     1239function 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
     1268function 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 **********************/
    9641306 
    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       }
    989    
    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 
     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
     1311function 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
     1331function 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
     1369function 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
     1399function 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
     1431function 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
     1472function 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
     1484function 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
     1505function 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) {
    11121540
    11131541        // 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.
    11161542        $urltest = parse_url($pagelinkedto);
    11171543        if ($post_ID = url_to_postid($pagelinkedto)) {
    11181544            $way = 'url_to_postid()';
    1119         } elseif (preg_match('#p/[0-9]{1,}#', $urltest['path'], $match)) {
     1545        }
     1546        elseif (preg_match('#p/[0-9]{1,}#', $urltest['path'], $match)) {
    11201547            // the path defines the post_ID (archives/p/XXXX)
    11211548            $blah = explode('/', $match[0]);
     
    11411568                $title = preg_replace('/[^a-zA-Z0-9]/', '.', $urltest['fragment']);
    11421569                $sql = "SELECT ID FROM $wpdb->posts WHERE post_title RLIKE '$title'";
    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                 }
     1570                $post_ID = $wpdb->get_var($sql) or die("Query: $sql\n\nError: ");
    11471571                $way = 'from the fragment (title)';
    11481572            }
    11491573        } else {
    11501574            // TODO: Attempt to extract a post ID from the given URL
    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 
     1575            $post_ID = -1;
     1576            $way = 'no match';
     1577        }
    11541578
    11551579        logIO("O","(PB) URI='$pagelinkedto' ID='$post_ID' Found='$way'");
     1580
     1581        //debug_fwrite($log, "Found post ID $way: $post_ID\n");
    11561582
    11571583        $sql = 'SELECT post_author FROM '.$wpdb->posts.' WHERE ID = '.$post_ID;
    11581584        $result = $wpdb->get_results($sql);
    11591585
    1160         if (!$wpdb->num_rows) {
     1586        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.";
     1677            }
     1678        } else {
    11611679            // 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 
    1174         if ($wpdb->num_rows) {
    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;
    1302             }
    1303         }
    1304 
    1305         return $pingbacks;
    1306     }
    1307 }
    1308 
    1309 
    1310 $wp_xmlrpc_server = new wp_xmlrpc_server();
     1680            $message = $messages[2];
     1681            //debug_fwrite($log, 'Post doesn\'t exist'."\n");
     1682        }
     1683    }
     1684    return new xmlrpcresp(new xmlrpcval($message));
     1685}
     1686
     1687/**** /PingBack functions ****/
     1688
     1689/**** SERVER FUNCTIONS ARRAY ****/
     1690
     1691$dispatch_map = 
     1692array( "blogger.newPost" =>
     1693array("function" => "bloggernewpost",
     1694     "signature" => $bloggernewpost_sig,
     1695     "docstring" => $bloggernewpost_doc),
     1696
     1697
     1698"blogger.editPost" =>
     1699array("function" => "bloggereditpost",
     1700     "signature" => $bloggereditpost_sig,
     1701     "docstring" => $bloggereditpost_doc),
     1702
     1703
     1704"blogger.deletePost" =>
     1705array("function" => "bloggerdeletepost",
     1706     "signature" => $bloggerdeletepost_sig,
     1707     "docstring" => $bloggerdeletepost_doc),
     1708
     1709
     1710"blogger.getUsersBlogs" =>
     1711array("function" => "bloggergetusersblogs",
     1712     "signature" => $bloggergetusersblogs_sig,
     1713     "docstring" => $bloggergetusersblogs_doc),
     1714
     1715"blogger.getUserInfo" =>
     1716array("function" => "bloggergetuserinfo",
     1717     "signature" => $bloggergetuserinfo_sig,
     1718     "docstring" => $bloggergetuserinfo_doc),
     1719
     1720"blogger.getPost" =>
     1721array("function" => "bloggergetpost",
     1722     "signature" => $bloggergetpost_sig,
     1723     "docstring" => $bloggergetpost_doc),
     1724
     1725"blogger.getRecentPosts" =>
     1726array("function" => "bloggergetrecentposts",
     1727     "signature" => $bloggergetrecentposts_sig,
     1728     "docstring" => $bloggergetrecentposts_doc),
     1729
     1730"blogger.getTemplate" =>
     1731array("function" => "bloggergettemplate",
     1732     "signature" => $bloggergettemplate_sig,
     1733     "docstring" => $bloggergettemplate_doc),
     1734
     1735"blogger.setTemplate" =>
     1736array("function" => "bloggersettemplate",
     1737     "signature" => $bloggersettemplate_sig,
     1738     "docstring" => $bloggersettemplate_doc),
     1739
     1740"metaWeblog.newPost" =>
     1741array("function" => "mwnewpost",
     1742     "signature" => $mwnewpost_sig,
     1743     "docstring" => $mwnewpost_doc),
     1744
     1745"metaWeblog.editPost" =>
     1746array("function" => "mweditpost",
     1747     "signature" => $mweditpost_sig,
     1748     "docstring" => $mweditpost_doc),
     1749
     1750"metaWeblog.getPost" =>
     1751array("function" => "mwgetpost",
     1752     "signature" => $mwgetpost_sig,
     1753     "docstring" => $mwgetpost_doc),
     1754
     1755"metaWeblog.getRecentPosts" =>
     1756array("function" => "mwrecentposts",
     1757     "signature" => $mwrecentposts_sig,
     1758     "docstring" => $mwrecentposts_doc),
     1759
     1760"metaWeblog.getCategories" =>
     1761array("function" => "mwgetcats",
     1762     "signature" => $mwgetcats_sig,
     1763     "docstring" => $mwgetcats_doc),
     1764
     1765"metaWeblog.newMediaObject" =>
     1766array("function" => "mwnewmedia",
     1767     "signature" => $mwnewmedia_sig,
     1768     "docstring" => $mwnewmedia_doc),
     1769
     1770"mt.getCategoryList" =>
     1771array("function" => "mwgetcats",
     1772     "signature" => $mwgetcats_sig,
     1773     "docstring" => $mwgetcats_doc),
     1774
     1775"mt.getPostCategories" =>
     1776array("function" => "mt_getPostCategories",
     1777     "signature" => $mt_getPostCategories_sig,
     1778     "docstring" => $mt_getPostCategories_doc),
     1779
     1780"mt.setPostCategories" =>
     1781array("function" => "mt_setPostCategories",
     1782     "signature" => $mt_setPostCategories_sig,
     1783     "docstring" => $mt_setPostCategories_doc),
     1784
     1785"mt.publishPost" =>
     1786array("function" => "mt_publishPost",
     1787     "signature" => $mt_publishPost_sig,
     1788     "docstring" => $mt_publishPost_doc),
     1789
     1790"mt.supportedMethods" =>
     1791array("function" => "mt_supportedMethods",
     1792     "signature" => $mt_supportedMethods_sig,
     1793     "docstring" => $mt_supportedMethods_doc),
     1794
     1795"mt.supportedTextFilters" =>
     1796array("function" => "mt_supportedTextFilters",
     1797     "signature" => $mt_supportedTextFilters_sig,
     1798     "docstring" => $mt_supportedTextFilters_doc),
     1799
     1800"mt.getRecentPostTitles" =>
     1801array("function" => "mt_getRecentPostTitles",
     1802     "signature" => $mt_getRecentPostTitles_sig,
     1803     "docstring" => $mt_getRecentPostTitles_doc),
     1804
     1805"mt.getTrackbackPings" =>
     1806array("function" => "mt_getTrackbackPings",
     1807     "signature" => $mt_getTrackbackPings_sig,
     1808     "docstring" => $mt_getTrackbackPings_doc),
     1809
     1810"b2.newPost" =>
     1811array("function" => "b2newpost",
     1812     "signature" => $wpnewpost_sig,
     1813     "docstring" => $wpnewpost_doc),
     1814"b2.getCategories" =>
     1815array("function" => "b2getcategories",
     1816     "signature" => $wpgetcategories_sig,
     1817     "docstring" => $wpgetcategories_doc),
     1818
     1819"b2.ping" =>
     1820array("function" => "b2ping",
     1821     "signature" => $wpping_sig,
     1822     "docstring" => $wpping_doc),
     1823
     1824"pingback.ping" =>
     1825array("function" => "pingback_ping",
     1826     "signature" => $pingback_ping_sig,
     1827     "docstring" => $pingback_ping_doc),
     1828
     1829"b2.getPostURL" =>
     1830array("function" => "pingback_getPostURL",
     1831     "signature" => $wp_getPostURL_sig,
     1832     "docstring" => $wp_getPostURL_doc),
     1833);
     1834
     1835$s = new xmlrpc_server($dispatch_map);
    13111836
    13121837?>
Note: See TracChangeset for help on using the changeset viewer.