Make WordPress Core

Changeset 1685 for trunk/xmlrpc.php


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

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/xmlrpc.php

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