~canonical-sysadmins/wordpress/3.9.x

« back to all changes in this revision

Viewing changes to xmlrpc.php

  • Committer: Andrew Glen-Young
  • Date: 2011-03-08 14:47:51 UTC
  • Revision ID: andrew.glen-young@canonical.com-20110308144751-1n6spqgayztf9h77
[AGY] import 3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/**
3
3
 * XML-RPC protocol support for WordPress
4
4
 *
5
 
 * @license GPL v2 <./license.txt>
6
5
 * @package WordPress
7
6
 */
8
7
 
53
52
 
54
53
include_once(ABSPATH . 'wp-admin/includes/admin.php');
55
54
include_once(ABSPATH . WPINC . '/class-IXR.php');
 
55
include_once(ABSPATH . WPINC . '/class-wp-xmlrpc-server.php');
56
56
 
57
57
// Turn off all warnings and errors.
58
58
// error_reporting(0);
98
98
if ( isset($HTTP_RAW_POST_DATA) )
99
99
        logIO("I", $HTTP_RAW_POST_DATA);
100
100
 
101
 
/**
102
 
 * WordPress XMLRPC server implementation.
103
 
 *
104
 
 * Implements compatability for Blogger API, MetaWeblog API, MovableType, and
105
 
 * pingback. Additional WordPress API for managing comments, pages, posts,
106
 
 * options, etc.
107
 
 *
108
 
 * Since WordPress 2.6.0, WordPress XMLRPC server can be disabled in the
109
 
 * administration panels.
110
 
 *
111
 
 * @package WordPress
112
 
 * @subpackage Publishing
113
 
 * @since 1.5.0
114
 
 */
115
 
class wp_xmlrpc_server extends IXR_Server {
116
 
 
117
 
        /**
118
 
         * Register all of the XMLRPC methods that XMLRPC server understands.
119
 
         *
120
 
         * PHP4 constructor and sets up server and method property. Passes XMLRPC
121
 
         * methods through the 'xmlrpc_methods' filter to allow plugins to extend
122
 
         * or replace XMLRPC methods.
123
 
         *
124
 
         * @since 1.5.0
125
 
         *
126
 
         * @return wp_xmlrpc_server
127
 
         */
128
 
        function wp_xmlrpc_server() {
129
 
                $this->methods = array(
130
 
                        // WordPress API
131
 
                        'wp.getUsersBlogs'              => 'this:wp_getUsersBlogs',
132
 
                        'wp.getPage'                    => 'this:wp_getPage',
133
 
                        'wp.getPages'                   => 'this:wp_getPages',
134
 
                        'wp.newPage'                    => 'this:wp_newPage',
135
 
                        'wp.deletePage'                 => 'this:wp_deletePage',
136
 
                        'wp.editPage'                   => 'this:wp_editPage',
137
 
                        'wp.getPageList'                => 'this:wp_getPageList',
138
 
                        'wp.getAuthors'                 => 'this:wp_getAuthors',
139
 
                        'wp.getCategories'              => 'this:mw_getCategories',             // Alias
140
 
                        'wp.getTags'                    => 'this:wp_getTags',
141
 
                        'wp.newCategory'                => 'this:wp_newCategory',
142
 
                        'wp.deleteCategory'             => 'this:wp_deleteCategory',
143
 
                        'wp.suggestCategories'  => 'this:wp_suggestCategories',
144
 
                        'wp.uploadFile'                 => 'this:mw_newMediaObject',    // Alias
145
 
                        'wp.getCommentCount'    => 'this:wp_getCommentCount',
146
 
                        'wp.getPostStatusList'  => 'this:wp_getPostStatusList',
147
 
                        'wp.getPageStatusList'  => 'this:wp_getPageStatusList',
148
 
                        'wp.getPageTemplates'   => 'this:wp_getPageTemplates',
149
 
                        'wp.getOptions'                 => 'this:wp_getOptions',
150
 
                        'wp.setOptions'                 => 'this:wp_setOptions',
151
 
                        'wp.getComment'                 => 'this:wp_getComment',
152
 
                        'wp.getComments'                => 'this:wp_getComments',
153
 
                        'wp.deleteComment'              => 'this:wp_deleteComment',
154
 
                        'wp.editComment'                => 'this:wp_editComment',
155
 
                        'wp.newComment'                 => 'this:wp_newComment',
156
 
                        'wp.getCommentStatusList' => 'this:wp_getCommentStatusList',
157
 
 
158
 
                        // Blogger API
159
 
                        'blogger.getUsersBlogs' => 'this:blogger_getUsersBlogs',
160
 
                        'blogger.getUserInfo' => 'this:blogger_getUserInfo',
161
 
                        'blogger.getPost' => 'this:blogger_getPost',
162
 
                        'blogger.getRecentPosts' => 'this:blogger_getRecentPosts',
163
 
                        'blogger.getTemplate' => 'this:blogger_getTemplate',
164
 
                        'blogger.setTemplate' => 'this:blogger_setTemplate',
165
 
                        'blogger.newPost' => 'this:blogger_newPost',
166
 
                        'blogger.editPost' => 'this:blogger_editPost',
167
 
                        'blogger.deletePost' => 'this:blogger_deletePost',
168
 
 
169
 
                        // MetaWeblog API (with MT extensions to structs)
170
 
                        'metaWeblog.newPost' => 'this:mw_newPost',
171
 
                        'metaWeblog.editPost' => 'this:mw_editPost',
172
 
                        'metaWeblog.getPost' => 'this:mw_getPost',
173
 
                        'metaWeblog.getRecentPosts' => 'this:mw_getRecentPosts',
174
 
                        'metaWeblog.getCategories' => 'this:mw_getCategories',
175
 
                        'metaWeblog.newMediaObject' => 'this:mw_newMediaObject',
176
 
 
177
 
                        // MetaWeblog API aliases for Blogger API
178
 
                        // see http://www.xmlrpc.com/stories/storyReader$2460
179
 
                        'metaWeblog.deletePost' => 'this:blogger_deletePost',
180
 
                        'metaWeblog.getTemplate' => 'this:blogger_getTemplate',
181
 
                        'metaWeblog.setTemplate' => 'this:blogger_setTemplate',
182
 
                        'metaWeblog.getUsersBlogs' => 'this:blogger_getUsersBlogs',
183
 
 
184
 
                        // MovableType API
185
 
                        'mt.getCategoryList' => 'this:mt_getCategoryList',
186
 
                        'mt.getRecentPostTitles' => 'this:mt_getRecentPostTitles',
187
 
                        'mt.getPostCategories' => 'this:mt_getPostCategories',
188
 
                        'mt.setPostCategories' => 'this:mt_setPostCategories',
189
 
                        'mt.supportedMethods' => 'this:mt_supportedMethods',
190
 
                        'mt.supportedTextFilters' => 'this:mt_supportedTextFilters',
191
 
                        'mt.getTrackbackPings' => 'this:mt_getTrackbackPings',
192
 
                        'mt.publishPost' => 'this:mt_publishPost',
193
 
 
194
 
                        // PingBack
195
 
                        'pingback.ping' => 'this:pingback_ping',
196
 
                        'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks',
197
 
 
198
 
                        'demo.sayHello' => 'this:sayHello',
199
 
                        'demo.addTwoNumbers' => 'this:addTwoNumbers'
200
 
                );
201
 
 
202
 
                $this->initialise_blog_option_info( );
203
 
                $this->methods = apply_filters('xmlrpc_methods', $this->methods);
204
 
        }
205
 
 
206
 
        function serve_request() {
207
 
                $this->IXR_Server($this->methods);
208
 
        }
209
 
 
210
 
        /**
211
 
         * Test XMLRPC API by saying, "Hello!" to client.
212
 
         *
213
 
         * @since 1.5.0
214
 
         *
215
 
         * @param array $args Method Parameters.
216
 
         * @return string
217
 
         */
218
 
        function sayHello($args) {
219
 
                return 'Hello!';
220
 
        }
221
 
 
222
 
        /**
223
 
         * Test XMLRPC API by adding two numbers for client.
224
 
         *
225
 
         * @since 1.5.0
226
 
         *
227
 
         * @param array $args Method Parameters.
228
 
         * @return int
229
 
         */
230
 
        function addTwoNumbers($args) {
231
 
                $number1 = $args[0];
232
 
                $number2 = $args[1];
233
 
                return $number1 + $number2;
234
 
        }
235
 
 
236
 
        /**
237
 
         * Check user's credentials.
238
 
         *
239
 
         * @since 1.5.0
240
 
         *
241
 
         * @param string $user_login User's username.
242
 
         * @param string $user_pass User's password.
243
 
         * @return bool Whether authentication passed.
244
 
         * @deprecated use wp_xmlrpc_server::login
245
 
         * @see wp_xmlrpc_server::login
246
 
         */
247
 
        function login_pass_ok($user_login, $user_pass) {
248
 
                if ( !get_option( 'enable_xmlrpc' ) ) {
249
 
                        $this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site.  An admin user can enable them at %s'),  admin_url('options-writing.php') ) );
250
 
                        return false;
251
 
                }
252
 
 
253
 
                if (!user_pass_ok($user_login, $user_pass)) {
254
 
                        $this->error = new IXR_Error(403, __('Bad login/pass combination.'));
255
 
                        return false;
256
 
                }
257
 
                return true;
258
 
        }
259
 
 
260
 
        /**
261
 
         * Log user in.
262
 
         *
263
 
         * @since 2.8
264
 
         *
265
 
         * @param string $username User's username.
266
 
         * @param string $password User's password.
267
 
         * @return mixed WP_User object if authentication passed, false otherwise
268
 
         */
269
 
        function login($username, $password) {
270
 
                if ( !get_option( 'enable_xmlrpc' ) ) {
271
 
                        $this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site.  An admin user can enable them at %s'),  admin_url('options-writing.php') ) );
272
 
                        return false;
273
 
                }
274
 
 
275
 
                $user = wp_authenticate($username, $password);
276
 
 
277
 
                if (is_wp_error($user)) {
278
 
                        $this->error = new IXR_Error(403, __('Bad login/pass combination.'));
279
 
                        return false;
280
 
                }
281
 
 
282
 
                wp_set_current_user( $user->ID );
283
 
                return $user;
284
 
        }
285
 
 
286
 
        /**
287
 
         * Sanitize string or array of strings for database.
288
 
         *
289
 
         * @since 1.5.2
290
 
         *
291
 
         * @param string|array $array Sanitize single string or array of strings.
292
 
         * @return string|array Type matches $array and sanitized for the database.
293
 
         */
294
 
        function escape(&$array) {
295
 
                global $wpdb;
296
 
 
297
 
                if (!is_array($array)) {
298
 
                        return($wpdb->escape($array));
299
 
                } else {
300
 
                        foreach ( (array) $array as $k => $v ) {
301
 
                                if ( is_array($v) ) {
302
 
                                        $this->escape($array[$k]);
303
 
                                } else if ( is_object($v) ) {
304
 
                                        //skip
305
 
                                } else {
306
 
                                        $array[$k] = $wpdb->escape($v);
307
 
                                }
308
 
                        }
309
 
                }
310
 
        }
311
 
 
312
 
        /**
313
 
         * Retrieve custom fields for post.
314
 
         *
315
 
         * @since 2.5.0
316
 
         *
317
 
         * @param int $post_id Post ID.
318
 
         * @return array Custom fields, if exist.
319
 
         */
320
 
        function get_custom_fields($post_id) {
321
 
                $post_id = (int) $post_id;
322
 
 
323
 
                $custom_fields = array();
324
 
 
325
 
                foreach ( (array) has_meta($post_id) as $meta ) {
326
 
                        // Don't expose protected fields.
327
 
                        if ( strpos($meta['meta_key'], '_wp_') === 0 ) {
328
 
                                continue;
329
 
                        }
330
 
 
331
 
                        $custom_fields[] = array(
332
 
                                "id"    => $meta['meta_id'],
333
 
                                "key"   => $meta['meta_key'],
334
 
                                "value" => $meta['meta_value']
335
 
                        );
336
 
                }
337
 
 
338
 
                return $custom_fields;
339
 
        }
340
 
 
341
 
        /**
342
 
         * Set custom fields for post.
343
 
         *
344
 
         * @since 2.5.0
345
 
         *
346
 
         * @param int $post_id Post ID.
347
 
         * @param array $fields Custom fields.
348
 
         */
349
 
        function set_custom_fields($post_id, $fields) {
350
 
                $post_id = (int) $post_id;
351
 
 
352
 
                foreach ( (array) $fields as $meta ) {
353
 
                        if ( isset($meta['id']) ) {
354
 
                                $meta['id'] = (int) $meta['id'];
355
 
 
356
 
                                if ( isset($meta['key']) ) {
357
 
                                        update_meta($meta['id'], $meta['key'], $meta['value']);
358
 
                                }
359
 
                                else {
360
 
                                        delete_meta($meta['id']);
361
 
                                }
362
 
                        }
363
 
                        else {
364
 
                                $_POST['metakeyinput'] = $meta['key'];
365
 
                                $_POST['metavalue'] = $meta['value'];
366
 
                                add_meta($post_id);
367
 
                        }
368
 
                }
369
 
        }
370
 
 
371
 
        /**
372
 
         * Set up blog options property.
373
 
         *
374
 
         * Passes property through 'xmlrpc_blog_options' filter.
375
 
         *
376
 
         * @since 2.6.0
377
 
         */
378
 
        function initialise_blog_option_info( ) {
379
 
                global $wp_version;
380
 
 
381
 
                $this->blog_options = array(
382
 
                        // Read only options
383
 
                        'software_name'         => array(
384
 
                                'desc'                  => __( 'Software Name' ),
385
 
                                'readonly'              => true,
386
 
                                'value'                 => 'WordPress'
387
 
                        ),
388
 
                        'software_version'      => array(
389
 
                                'desc'                  => __( 'Software Version' ),
390
 
                                'readonly'              => true,
391
 
                                'value'                 => $wp_version
392
 
                        ),
393
 
                        'blog_url'                      => array(
394
 
                                'desc'                  => __( 'Site URL' ),
395
 
                                'readonly'              => true,
396
 
                                'option'                => 'siteurl'
397
 
                        ),
398
 
 
399
 
                        // Updatable options
400
 
                        'time_zone'                     => array(
401
 
                                'desc'                  => __( 'Time Zone' ),
402
 
                                'readonly'              => false,
403
 
                                'option'                => 'gmt_offset'
404
 
                        ),
405
 
                        'blog_title'            => array(
406
 
                                'desc'                  => __( 'Site Title' ),
407
 
                                'readonly'              => false,
408
 
                                'option'                        => 'blogname'
409
 
                        ),
410
 
                        'blog_tagline'          => array(
411
 
                                'desc'                  => __( 'Site Tagline' ),
412
 
                                'readonly'              => false,
413
 
                                'option'                => 'blogdescription'
414
 
                        ),
415
 
                        'date_format'           => array(
416
 
                                'desc'                  => __( 'Date Format' ),
417
 
                                'readonly'              => false,
418
 
                                'option'                => 'date_format'
419
 
                        ),
420
 
                        'time_format'           => array(
421
 
                                'desc'                  => __( 'Time Format' ),
422
 
                                'readonly'              => false,
423
 
                                'option'                => 'time_format'
424
 
                        ),
425
 
                        'users_can_register'    => array(
426
 
                                'desc'                  => __( 'Allow new users to sign up' ),
427
 
                                'readonly'              => false,
428
 
                                'option'                => 'users_can_register'
429
 
                        )
430
 
                );
431
 
 
432
 
                $this->blog_options = apply_filters( 'xmlrpc_blog_options', $this->blog_options );
433
 
        }
434
 
 
435
 
        /**
436
 
         * Retrieve the blogs of the user.
437
 
         *
438
 
         * @since 2.6.0
439
 
         *
440
 
         * @param array $args Method parameters.
441
 
         * @return array
442
 
         */
443
 
        function wp_getUsersBlogs( $args ) {
444
 
                global $current_site;
445
 
                // If this isn't on WPMU then just use blogger_getUsersBlogs
446
 
                if ( !is_multisite() ) {
447
 
                        array_unshift( $args, 1 );
448
 
                        return $this->blogger_getUsersBlogs( $args );
449
 
                }
450
 
 
451
 
                $this->escape( $args );
452
 
 
453
 
                $username = $args[0];
454
 
                $password = $args[1];
455
 
 
456
 
                if ( !$user = $this->login($username, $password) )
457
 
                        return $this->error;
458
 
 
459
 
 
460
 
                do_action( 'xmlrpc_call', 'wp.getUsersBlogs' );
461
 
 
462
 
                $blogs = (array) get_blogs_of_user( $user->ID );
463
 
                $struct = array( );
464
 
 
465
 
                foreach ( $blogs as $blog ) {
466
 
                        // Don't include blogs that aren't hosted at this site
467
 
                        if ( $blog->site_id != $current_site->id )
468
 
                                continue;
469
 
 
470
 
                        $blog_id = $blog->userblog_id;
471
 
                        switch_to_blog($blog_id);
472
 
                        $is_admin = current_user_can('manage_options');
473
 
 
474
 
                        $struct[] = array(
475
 
                                'isAdmin'               => $is_admin,
476
 
                                'url'                   => get_option( 'home' ) . '/',
477
 
                                'blogid'                => $blog_id,
478
 
                                'blogName'              => get_option( 'blogname' ),
479
 
                                'xmlrpc'                => site_url( 'xmlrpc.php' )
480
 
                        );
481
 
 
482
 
                        restore_current_blog( );
483
 
                }
484
 
 
485
 
                return $struct;
486
 
        }
487
 
 
488
 
        /**
489
 
         * Retrieve page.
490
 
         *
491
 
         * @since 2.2.0
492
 
         *
493
 
         * @param array $args Method parameters.
494
 
         * @return array
495
 
         */
496
 
        function wp_getPage($args) {
497
 
                $this->escape($args);
498
 
 
499
 
                $blog_id        = (int) $args[0];
500
 
                $page_id        = (int) $args[1];
501
 
                $username       = $args[2];
502
 
                $password       = $args[3];
503
 
 
504
 
                if ( !$user = $this->login($username, $password) ) {
505
 
                        return $this->error;
506
 
                }
507
 
 
508
 
                if ( !current_user_can( 'edit_page', $page_id ) )
509
 
                        return new IXR_Error( 401, __( 'Sorry, you cannot edit this page.' ) );
510
 
 
511
 
                do_action('xmlrpc_call', 'wp.getPage');
512
 
 
513
 
                // Lookup page info.
514
 
                $page = get_page($page_id);
515
 
 
516
 
                // If we found the page then format the data.
517
 
                if ( $page->ID && ($page->post_type == "page") ) {
518
 
                        // Get all of the page content and link.
519
 
                        $full_page = get_extended($page->post_content);
520
 
                        $link = post_permalink($page->ID);
521
 
 
522
 
                        // Get info the page parent if there is one.
523
 
                        $parent_title = "";
524
 
                        if ( !empty($page->post_parent) ) {
525
 
                                $parent = get_page($page->post_parent);
526
 
                                $parent_title = $parent->post_title;
527
 
                        }
528
 
 
529
 
                        // Determine comment and ping settings.
530
 
                        $allow_comments = comments_open($page->ID) ? 1 : 0;
531
 
                        $allow_pings = pings_open($page->ID) ? 1 : 0;
532
 
 
533
 
                        // Format page date.
534
 
                        $page_date = mysql2date("Ymd\TH:i:s", $page->post_date, false);
535
 
                        $page_date_gmt = mysql2date("Ymd\TH:i:s", $page->post_date_gmt, false);
536
 
 
537
 
                        // For drafts use the GMT version of the date
538
 
                        if ( $page->post_status == 'draft' )
539
 
                                $page_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $page->post_date ), 'Ymd\TH:i:s' );
540
 
 
541
 
                        // Pull the categories info together.
542
 
                        $categories = array();
543
 
                        foreach ( wp_get_post_categories($page->ID) as $cat_id ) {
544
 
                                $categories[] = get_cat_name($cat_id);
545
 
                        }
546
 
 
547
 
                        // Get the author info.
548
 
                        $author = get_userdata($page->post_author);
549
 
 
550
 
                        $page_template = get_post_meta( $page->ID, '_wp_page_template', true );
551
 
                        if ( empty( $page_template ) )
552
 
                                $page_template = 'default';
553
 
 
554
 
                        $page_struct = array(
555
 
                                "dateCreated"                   => new IXR_Date($page_date),
556
 
                                "userid"                                => $page->post_author,
557
 
                                "page_id"                               => $page->ID,
558
 
                                "page_status"                   => $page->post_status,
559
 
                                "description"                   => $full_page["main"],
560
 
                                "title"                                 => $page->post_title,
561
 
                                "link"                                  => $link,
562
 
                                "permaLink"                             => $link,
563
 
                                "categories"                    => $categories,
564
 
                                "excerpt"                               => $page->post_excerpt,
565
 
                                "text_more"                             => $full_page["extended"],
566
 
                                "mt_allow_comments"             => $allow_comments,
567
 
                                "mt_allow_pings"                => $allow_pings,
568
 
                                "wp_slug"                               => $page->post_name,
569
 
                                "wp_password"                   => $page->post_password,
570
 
                                "wp_author"                             => $author->display_name,
571
 
                                "wp_page_parent_id"             => $page->post_parent,
572
 
                                "wp_page_parent_title"  => $parent_title,
573
 
                                "wp_page_order"                 => $page->menu_order,
574
 
                                "wp_author_id"                  => $author->ID,
575
 
                                "wp_author_display_name"        => $author->display_name,
576
 
                                "date_created_gmt"              => new IXR_Date($page_date_gmt),
577
 
                                "custom_fields"                 => $this->get_custom_fields($page_id),
578
 
                                "wp_page_template"              => $page_template
579
 
                        );
580
 
 
581
 
                        return($page_struct);
582
 
                }
583
 
                // If the page doesn't exist indicate that.
584
 
                else {
585
 
                        return(new IXR_Error(404, __("Sorry, no such page.")));
586
 
                }
587
 
        }
588
 
 
589
 
        /**
590
 
         * Retrieve Pages.
591
 
         *
592
 
         * @since 2.2.0
593
 
         *
594
 
         * @param array $args Method parameters.
595
 
         * @return array
596
 
         */
597
 
        function wp_getPages($args) {
598
 
                $this->escape($args);
599
 
 
600
 
                $blog_id        = (int) $args[0];
601
 
                $username       = $args[1];
602
 
                $password       = $args[2];
603
 
                $num_pages      = isset($args[3]) ? (int) $args[3] : 10;
604
 
 
605
 
                if ( !$user = $this->login($username, $password) )
606
 
                        return $this->error;
607
 
 
608
 
                if ( !current_user_can( 'edit_pages' ) )
609
 
                        return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) );
610
 
 
611
 
                do_action('xmlrpc_call', 'wp.getPages');
612
 
 
613
 
                $pages = get_posts( array('post_type' => 'page', 'post_status' => 'any', 'numberposts' => $num_pages) );
614
 
                $num_pages = count($pages);
615
 
 
616
 
                // If we have pages, put together their info.
617
 
                if ( $num_pages >= 1 ) {
618
 
                        $pages_struct = array();
619
 
 
620
 
                        for ( $i = 0; $i < $num_pages; $i++ ) {
621
 
                                $page = wp_xmlrpc_server::wp_getPage(array(
622
 
                                        $blog_id, $pages[$i]->ID, $username, $password
623
 
                                ));
624
 
                                $pages_struct[] = $page;
625
 
                        }
626
 
 
627
 
                        return($pages_struct);
628
 
                }
629
 
                // If no pages were found return an error.
630
 
                else {
631
 
                        return(array());
632
 
                }
633
 
        }
634
 
 
635
 
        /**
636
 
         * Create new page.
637
 
         *
638
 
         * @since 2.2.0
639
 
         *
640
 
         * @param array $args Method parameters.
641
 
         * @return unknown
642
 
         */
643
 
        function wp_newPage($args) {
644
 
                // Items not escaped here will be escaped in newPost.
645
 
                $username       = $this->escape($args[1]);
646
 
                $password       = $this->escape($args[2]);
647
 
                $page           = $args[3];
648
 
                $publish        = $args[4];
649
 
 
650
 
                if ( !$user = $this->login($username, $password) )
651
 
                        return $this->error;
652
 
 
653
 
                do_action('xmlrpc_call', 'wp.newPage');
654
 
 
655
 
                // Make sure the user is allowed to add new pages.
656
 
                if ( !current_user_can("publish_pages") )
657
 
                        return(new IXR_Error(401, __("Sorry, you cannot add new pages.")));
658
 
 
659
 
                // Mark this as content for a page.
660
 
                $args[3]["post_type"] = "page";
661
 
 
662
 
                // Let mw_newPost do all of the heavy lifting.
663
 
                return($this->mw_newPost($args));
664
 
        }
665
 
 
666
 
        /**
667
 
         * Delete page.
668
 
         *
669
 
         * @since 2.2.0
670
 
         *
671
 
         * @param array $args Method parameters.
672
 
         * @return bool True, if success.
673
 
         */
674
 
        function wp_deletePage($args) {
675
 
                $this->escape($args);
676
 
 
677
 
                $blog_id        = (int) $args[0];
678
 
                $username       = $args[1];
679
 
                $password       = $args[2];
680
 
                $page_id        = (int) $args[3];
681
 
 
682
 
                if ( !$user = $this->login($username, $password) )
683
 
                        return $this->error;
684
 
 
685
 
                do_action('xmlrpc_call', 'wp.deletePage');
686
 
 
687
 
                // Get the current page based on the page_id and
688
 
                // make sure it is a page and not a post.
689
 
                $actual_page = wp_get_single_post($page_id, ARRAY_A);
690
 
                if ( !$actual_page || ($actual_page["post_type"] != "page") )
691
 
                        return(new IXR_Error(404, __("Sorry, no such page.")));
692
 
 
693
 
                // Make sure the user can delete pages.
694
 
                if ( !current_user_can("delete_page", $page_id) )
695
 
                        return(new IXR_Error(401, __("Sorry, you do not have the right to delete this page.")));
696
 
 
697
 
                // Attempt to delete the page.
698
 
                $result = wp_delete_post($page_id);
699
 
                if ( !$result )
700
 
                        return(new IXR_Error(500, __("Failed to delete the page.")));
701
 
 
702
 
                return(true);
703
 
        }
704
 
 
705
 
        /**
706
 
         * Edit page.
707
 
         *
708
 
         * @since 2.2.0
709
 
         *
710
 
         * @param array $args Method parameters.
711
 
         * @return unknown
712
 
         */
713
 
        function wp_editPage($args) {
714
 
                // Items not escaped here will be escaped in editPost.
715
 
                $blog_id        = (int) $args[0];
716
 
                $page_id        = (int) $this->escape($args[1]);
717
 
                $username       = $this->escape($args[2]);
718
 
                $password       = $this->escape($args[3]);
719
 
                $content        = $args[4];
720
 
                $publish        = $args[5];
721
 
 
722
 
                if ( !$user = $this->login($username, $password) )
723
 
                        return $this->error;
724
 
 
725
 
                do_action('xmlrpc_call', 'wp.editPage');
726
 
 
727
 
                // Get the page data and make sure it is a page.
728
 
                $actual_page = wp_get_single_post($page_id, ARRAY_A);
729
 
                if ( !$actual_page || ($actual_page["post_type"] != "page") )
730
 
                        return(new IXR_Error(404, __("Sorry, no such page.")));
731
 
 
732
 
                // Make sure the user is allowed to edit pages.
733
 
                if ( !current_user_can("edit_page", $page_id) )
734
 
                        return(new IXR_Error(401, __("Sorry, you do not have the right to edit this page.")));
735
 
 
736
 
                // Mark this as content for a page.
737
 
                $content["post_type"] = "page";
738
 
 
739
 
                // Arrange args in the way mw_editPost understands.
740
 
                $args = array(
741
 
                        $page_id,
742
 
                        $username,
743
 
                        $password,
744
 
                        $content,
745
 
                        $publish
746
 
                );
747
 
 
748
 
                // Let mw_editPost do all of the heavy lifting.
749
 
                return($this->mw_editPost($args));
750
 
        }
751
 
 
752
 
        /**
753
 
         * Retrieve page list.
754
 
         *
755
 
         * @since 2.2.0
756
 
         *
757
 
         * @param array $args Method parameters.
758
 
         * @return unknown
759
 
         */
760
 
        function wp_getPageList($args) {
761
 
                global $wpdb;
762
 
 
763
 
                $this->escape($args);
764
 
 
765
 
                $blog_id                                = (int) $args[0];
766
 
                $username                               = $args[1];
767
 
                $password                               = $args[2];
768
 
 
769
 
                if ( !$user = $this->login($username, $password) )
770
 
                        return $this->error;
771
 
 
772
 
                if ( !current_user_can( 'edit_pages' ) )
773
 
                        return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) );
774
 
 
775
 
                do_action('xmlrpc_call', 'wp.getPageList');
776
 
 
777
 
                // Get list of pages ids and titles
778
 
                $page_list = $wpdb->get_results("
779
 
                        SELECT ID page_id,
780
 
                                post_title page_title,
781
 
                                post_parent page_parent_id,
782
 
                                post_date_gmt,
783
 
                                post_date,
784
 
                                post_status
785
 
                        FROM {$wpdb->posts}
786
 
                        WHERE post_type = 'page'
787
 
                        ORDER BY ID
788
 
                ");
789
 
 
790
 
                // The date needs to be formated properly.
791
 
                $num_pages = count($page_list);
792
 
                for ( $i = 0; $i < $num_pages; $i++ ) {
793
 
                        $post_date = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date, false);
794
 
                        $post_date_gmt = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date_gmt, false);
795
 
 
796
 
                        $page_list[$i]->dateCreated = new IXR_Date($post_date);
797
 
                        $page_list[$i]->date_created_gmt = new IXR_Date($post_date_gmt);
798
 
 
799
 
                        // For drafts use the GMT version of the date
800
 
                        if ( $page_list[$i]->post_status == 'draft' ) {
801
 
                                $page_list[$i]->date_created_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $page_list[$i]->post_date ), 'Ymd\TH:i:s' );
802
 
                                $page_list[$i]->date_created_gmt = new IXR_Date( $page_list[$i]->date_created_gmt );
803
 
                        }
804
 
 
805
 
                        unset($page_list[$i]->post_date_gmt);
806
 
                        unset($page_list[$i]->post_date);
807
 
                        unset($page_list[$i]->post_status);
808
 
                }
809
 
 
810
 
                return($page_list);
811
 
        }
812
 
 
813
 
        /**
814
 
         * Retrieve authors list.
815
 
         *
816
 
         * @since 2.2.0
817
 
         *
818
 
         * @param array $args Method parameters.
819
 
         * @return array
820
 
         */
821
 
        function wp_getAuthors($args) {
822
 
 
823
 
                $this->escape($args);
824
 
 
825
 
                $blog_id        = (int) $args[0];
826
 
                $username       = $args[1];
827
 
                $password       = $args[2];
828
 
 
829
 
                if ( !$user = $this->login($username, $password) )
830
 
                        return $this->error;
831
 
 
832
 
                if ( !current_user_can("edit_posts") )
833
 
                        return(new IXR_Error(401, __("Sorry, you cannot edit posts on this site.")));
834
 
 
835
 
                do_action('xmlrpc_call', 'wp.getAuthors');
836
 
 
837
 
                $authors = array();
838
 
                foreach ( (array) get_users_of_blog() as $row ) {
839
 
                        $authors[] = array(
840
 
                                "user_id"       => $row->user_id,
841
 
                                "user_login"    => $row->user_login,
842
 
                                "display_name"  => $row->display_name
843
 
                        );
844
 
                }
845
 
 
846
 
                return($authors);
847
 
        }
848
 
 
849
 
        /**
850
 
         * Get list of all tags
851
 
         *
852
 
         * @since 2.7
853
 
         *
854
 
         * @param array $args Method parameters.
855
 
         * @return array
856
 
         */
857
 
        function wp_getTags( $args ) {
858
 
                $this->escape( $args );
859
 
 
860
 
                $blog_id                = (int) $args[0];
861
 
                $username               = $args[1];
862
 
                $password               = $args[2];
863
 
 
864
 
                if ( !$user = $this->login($username, $password) )
865
 
                        return $this->error;
866
 
 
867
 
                if ( !current_user_can( 'edit_posts' ) )
868
 
                        return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this site in order to view tags.' ) );
869
 
 
870
 
                do_action( 'xmlrpc_call', 'wp.getKeywords' );
871
 
 
872
 
                $tags = array( );
873
 
 
874
 
                if ( $all_tags = get_tags() ) {
875
 
                        foreach( (array) $all_tags as $tag ) {
876
 
                                $struct['tag_id']                       = $tag->term_id;
877
 
                                $struct['name']                         = $tag->name;
878
 
                                $struct['count']                        = $tag->count;
879
 
                                $struct['slug']                         = $tag->slug;
880
 
                                $struct['html_url']                     = esc_html( get_tag_link( $tag->term_id ) );
881
 
                                $struct['rss_url']                      = esc_html( get_tag_feed_link( $tag->term_id ) );
882
 
 
883
 
                                $tags[] = $struct;
884
 
                        }
885
 
                }
886
 
 
887
 
                return $tags;
888
 
        }
889
 
 
890
 
        /**
891
 
         * Create new category.
892
 
         *
893
 
         * @since 2.2.0
894
 
         *
895
 
         * @param array $args Method parameters.
896
 
         * @return int Category ID.
897
 
         */
898
 
        function wp_newCategory($args) {
899
 
                $this->escape($args);
900
 
 
901
 
                $blog_id                                = (int) $args[0];
902
 
                $username                               = $args[1];
903
 
                $password                               = $args[2];
904
 
                $category                               = $args[3];
905
 
 
906
 
                if ( !$user = $this->login($username, $password) )
907
 
                        return $this->error;
908
 
 
909
 
                do_action('xmlrpc_call', 'wp.newCategory');
910
 
 
911
 
                // Make sure the user is allowed to add a category.
912
 
                if ( !current_user_can("manage_categories") )
913
 
                        return(new IXR_Error(401, __("Sorry, you do not have the right to add a category.")));
914
 
 
915
 
                // If no slug was provided make it empty so that
916
 
                // WordPress will generate one.
917
 
                if ( empty($category["slug"]) )
918
 
                        $category["slug"] = "";
919
 
 
920
 
                // If no parent_id was provided make it empty
921
 
                // so that it will be a top level page (no parent).
922
 
                if ( !isset($category["parent_id"]) )
923
 
                        $category["parent_id"] = "";
924
 
 
925
 
                // If no description was provided make it empty.
926
 
                if ( empty($category["description"]) )
927
 
                        $category["description"] = "";
928
 
 
929
 
                $new_category = array(
930
 
                        "cat_name"                              => $category["name"],
931
 
                        "category_nicename"             => $category["slug"],
932
 
                        "category_parent"               => $category["parent_id"],
933
 
                        "category_description"  => $category["description"]
934
 
                );
935
 
 
936
 
                $cat_id = wp_insert_category($new_category, true);
937
 
                if ( is_wp_error( $cat_id ) ) {
938
 
                        if ( 'term_exists' == $cat_id->get_error_code() )
939
 
                                return (int) $cat_id->get_error_data();
940
 
                        else
941
 
                                return(new IXR_Error(500, __("Sorry, the new category failed.")));
942
 
                } elseif ( ! $cat_id ) {
943
 
                        return(new IXR_Error(500, __("Sorry, the new category failed.")));
944
 
                }
945
 
 
946
 
                return($cat_id);
947
 
        }
948
 
 
949
 
        /**
950
 
         * Remove category.
951
 
         *
952
 
         * @since 2.5.0
953
 
         *
954
 
         * @param array $args Method parameters.
955
 
         * @return mixed See {@link wp_delete_category()} for return info.
956
 
         */
957
 
        function wp_deleteCategory($args) {
958
 
                $this->escape($args);
959
 
 
960
 
                $blog_id                = (int) $args[0];
961
 
                $username               = $args[1];
962
 
                $password               = $args[2];
963
 
                $category_id    = (int) $args[3];
964
 
 
965
 
                if ( !$user = $this->login($username, $password) )
966
 
                        return $this->error;
967
 
 
968
 
                do_action('xmlrpc_call', 'wp.deleteCategory');
969
 
 
970
 
                if ( !current_user_can("manage_categories") )
971
 
                        return new IXR_Error( 401, __( "Sorry, you do not have the right to delete a category." ) );
972
 
 
973
 
                return wp_delete_category( $category_id );
974
 
        }
975
 
 
976
 
        /**
977
 
         * Retrieve category list.
978
 
         *
979
 
         * @since 2.2.0
980
 
         *
981
 
         * @param array $args Method parameters.
982
 
         * @return array
983
 
         */
984
 
        function wp_suggestCategories($args) {
985
 
                $this->escape($args);
986
 
 
987
 
                $blog_id                                = (int) $args[0];
988
 
                $username                               = $args[1];
989
 
                $password                               = $args[2];
990
 
                $category                               = $args[3];
991
 
                $max_results                    = (int) $args[4];
992
 
 
993
 
                if ( !$user = $this->login($username, $password) )
994
 
                        return $this->error;
995
 
 
996
 
                if ( !current_user_can( 'edit_posts' ) )
997
 
                        return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts to this site in order to view categories.' ) );
998
 
 
999
 
                do_action('xmlrpc_call', 'wp.suggestCategories');
1000
 
 
1001
 
                $category_suggestions = array();
1002
 
                $args = array('get' => 'all', 'number' => $max_results, 'name__like' => $category);
1003
 
                foreach ( (array) get_categories($args) as $cat ) {
1004
 
                        $category_suggestions[] = array(
1005
 
                                "category_id"   => $cat->cat_ID,
1006
 
                                "category_name" => $cat->cat_name
1007
 
                        );
1008
 
                }
1009
 
 
1010
 
                return($category_suggestions);
1011
 
        }
1012
 
 
1013
 
        /**
1014
 
         * Retrieve comment.
1015
 
         *
1016
 
         * @since 2.7.0
1017
 
         *
1018
 
         * @param array $args Method parameters.
1019
 
         * @return array
1020
 
         */
1021
 
        function wp_getComment($args) {
1022
 
                $this->escape($args);
1023
 
 
1024
 
                $blog_id        = (int) $args[0];
1025
 
                $username       = $args[1];
1026
 
                $password       = $args[2];
1027
 
                $comment_id     = (int) $args[3];
1028
 
 
1029
 
                if ( !$user = $this->login($username, $password) )
1030
 
                        return $this->error;
1031
 
 
1032
 
                if ( !current_user_can( 'moderate_comments' ) )
1033
 
                        return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) );
1034
 
 
1035
 
                do_action('xmlrpc_call', 'wp.getComment');
1036
 
 
1037
 
                if ( ! $comment = get_comment($comment_id) )
1038
 
                        return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
1039
 
 
1040
 
                // Format page date.
1041
 
                $comment_date = mysql2date("Ymd\TH:i:s", $comment->comment_date, false);
1042
 
                $comment_date_gmt = mysql2date("Ymd\TH:i:s", $comment->comment_date_gmt, false);
1043
 
 
1044
 
                if ( '0' == $comment->comment_approved )
1045
 
                        $comment_status = 'hold';
1046
 
                else if ( 'spam' == $comment->comment_approved )
1047
 
                        $comment_status = 'spam';
1048
 
                else if ( '1' == $comment->comment_approved )
1049
 
                        $comment_status = 'approve';
1050
 
                else
1051
 
                        $comment_status = $comment->comment_approved;
1052
 
 
1053
 
                $link = get_comment_link($comment);
1054
 
 
1055
 
                $comment_struct = array(
1056
 
                        "date_created_gmt"              => new IXR_Date($comment_date_gmt),
1057
 
                        "user_id"                               => $comment->user_id,
1058
 
                        "comment_id"                    => $comment->comment_ID,
1059
 
                        "parent"                                => $comment->comment_parent,
1060
 
                        "status"                                => $comment_status,
1061
 
                        "content"                               => $comment->comment_content,
1062
 
                        "link"                                  => $link,
1063
 
                        "post_id"                               => $comment->comment_post_ID,
1064
 
                        "post_title"                    => get_the_title($comment->comment_post_ID),
1065
 
                        "author"                                => $comment->comment_author,
1066
 
                        "author_url"                    => $comment->comment_author_url,
1067
 
                        "author_email"                  => $comment->comment_author_email,
1068
 
                        "author_ip"                             => $comment->comment_author_IP,
1069
 
                        "type"                                  => $comment->comment_type,
1070
 
                );
1071
 
 
1072
 
                return $comment_struct;
1073
 
        }
1074
 
 
1075
 
        /**
1076
 
         * Retrieve comments.
1077
 
         *
1078
 
         * @since 2.7.0
1079
 
         *
1080
 
         * @param array $args Method parameters.
1081
 
         * @return array
1082
 
         */
1083
 
        function wp_getComments($args) {
1084
 
                $raw_args = $args;
1085
 
                $this->escape($args);
1086
 
 
1087
 
                $blog_id        = (int) $args[0];
1088
 
                $username       = $args[1];
1089
 
                $password       = $args[2];
1090
 
                $struct         = $args[3];
1091
 
 
1092
 
                if ( !$user = $this->login($username, $password) )
1093
 
                        return $this->error;
1094
 
 
1095
 
                if ( !current_user_can( 'moderate_comments' ) )
1096
 
                        return new IXR_Error( 401, __( 'Sorry, you cannot edit comments.' ) );
1097
 
 
1098
 
                do_action('xmlrpc_call', 'wp.getComments');
1099
 
 
1100
 
                if ( isset($struct['status']) )
1101
 
                        $status = $struct['status'];
1102
 
                else
1103
 
                        $status = '';
1104
 
 
1105
 
                $post_id = '';
1106
 
                if ( isset($struct['post_id']) )
1107
 
                        $post_id = absint($struct['post_id']);
1108
 
 
1109
 
                $offset = 0;
1110
 
                if ( isset($struct['offset']) )
1111
 
                        $offset = absint($struct['offset']);
1112
 
 
1113
 
                $number = 10;
1114
 
                if ( isset($struct['number']) )
1115
 
                        $number = absint($struct['number']);
1116
 
 
1117
 
                $comments = get_comments( array('status' => $status, 'post_id' => $post_id, 'offset' => $offset, 'number' => $number ) );
1118
 
                $num_comments = count($comments);
1119
 
 
1120
 
                if ( ! $num_comments )
1121
 
                        return array();
1122
 
 
1123
 
                $comments_struct = array();
1124
 
 
1125
 
                for ( $i = 0; $i < $num_comments; $i++ ) {
1126
 
                        $comment = wp_xmlrpc_server::wp_getComment(array(
1127
 
                                $raw_args[0], $raw_args[1], $raw_args[2], $comments[$i]->comment_ID,
1128
 
                        ));
1129
 
                        $comments_struct[] = $comment;
1130
 
                }
1131
 
 
1132
 
                return $comments_struct;
1133
 
        }
1134
 
 
1135
 
        /**
1136
 
         * Remove comment.
1137
 
         *
1138
 
         * @since 2.7.0
1139
 
         *
1140
 
         * @param array $args Method parameters.
1141
 
         * @return mixed {@link wp_delete_comment()}
1142
 
         */
1143
 
        function wp_deleteComment($args) {
1144
 
                $this->escape($args);
1145
 
 
1146
 
                $blog_id        = (int) $args[0];
1147
 
                $username       = $args[1];
1148
 
                $password       = $args[2];
1149
 
                $comment_ID     = (int) $args[3];
1150
 
 
1151
 
                if ( !$user = $this->login($username, $password) )
1152
 
                        return $this->error;
1153
 
 
1154
 
                if ( !current_user_can( 'moderate_comments' ) )
1155
 
                        return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) );
1156
 
 
1157
 
                do_action('xmlrpc_call', 'wp.deleteComment');
1158
 
 
1159
 
                if ( ! get_comment($comment_ID) )
1160
 
                        return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
1161
 
 
1162
 
                return wp_delete_comment($comment_ID);
1163
 
        }
1164
 
 
1165
 
        /**
1166
 
         * Edit comment.
1167
 
         *
1168
 
         * @since 2.7.0
1169
 
         *
1170
 
         * @param array $args Method parameters.
1171
 
         * @return bool True, on success.
1172
 
         */
1173
 
        function wp_editComment($args) {
1174
 
                $this->escape($args);
1175
 
 
1176
 
                $blog_id        = (int) $args[0];
1177
 
                $username       = $args[1];
1178
 
                $password       = $args[2];
1179
 
                $comment_ID     = (int) $args[3];
1180
 
                $content_struct = $args[4];
1181
 
 
1182
 
                if ( !$user = $this->login($username, $password) )
1183
 
                        return $this->error;
1184
 
 
1185
 
                if ( !current_user_can( 'moderate_comments' ) )
1186
 
                        return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) );
1187
 
 
1188
 
                do_action('xmlrpc_call', 'wp.editComment');
1189
 
 
1190
 
                if ( ! get_comment($comment_ID) )
1191
 
                        return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
1192
 
 
1193
 
                if ( isset($content_struct['status']) ) {
1194
 
                        $statuses = get_comment_statuses();
1195
 
                        $statuses = array_keys($statuses);
1196
 
 
1197
 
                        if ( ! in_array($content_struct['status'], $statuses) )
1198
 
                                return new IXR_Error( 401, __( 'Invalid comment status.' ) );
1199
 
                        $comment_approved = $content_struct['status'];
1200
 
                }
1201
 
 
1202
 
                // Do some timestamp voodoo
1203
 
                if ( !empty( $content_struct['date_created_gmt'] ) ) {
1204
 
                        $dateCreated = str_replace( 'Z', '', $content_struct['date_created_gmt']->getIso() ) . 'Z'; // We know this is supposed to be GMT, so we're going to slap that Z on there by force
1205
 
                        $comment_date = get_date_from_gmt(iso8601_to_datetime($dateCreated));
1206
 
                        $comment_date_gmt = iso8601_to_datetime($dateCreated, GMT);
1207
 
                }
1208
 
 
1209
 
                if ( isset($content_struct['content']) )
1210
 
                        $comment_content = $content_struct['content'];
1211
 
 
1212
 
                if ( isset($content_struct['author']) )
1213
 
                        $comment_author = $content_struct['author'];
1214
 
 
1215
 
                if ( isset($content_struct['author_url']) )
1216
 
                        $comment_author_url = $content_struct['author_url'];
1217
 
 
1218
 
                if ( isset($content_struct['author_email']) )
1219
 
                        $comment_author_email = $content_struct['author_email'];
1220
 
 
1221
 
                // We've got all the data -- post it:
1222
 
                $comment = compact('comment_ID', 'comment_content', 'comment_approved', 'comment_date', 'comment_date_gmt', 'comment_author', 'comment_author_email', 'comment_author_url');
1223
 
 
1224
 
                $result = wp_update_comment($comment);
1225
 
                if ( is_wp_error( $result ) )
1226
 
                        return new IXR_Error(500, $result->get_error_message());
1227
 
 
1228
 
                if ( !$result )
1229
 
                        return new IXR_Error(500, __('Sorry, the comment could not be edited. Something wrong happened.'));
1230
 
 
1231
 
                return true;
1232
 
        }
1233
 
 
1234
 
        /**
1235
 
         * Create new comment.
1236
 
         *
1237
 
         * @since 2.7.0
1238
 
         *
1239
 
         * @param array $args Method parameters.
1240
 
         * @return mixed {@link wp_new_comment()}
1241
 
         */
1242
 
        function wp_newComment($args) {
1243
 
                global $wpdb;
1244
 
 
1245
 
                $this->escape($args);
1246
 
 
1247
 
                $blog_id        = (int) $args[0];
1248
 
                $username       = $args[1];
1249
 
                $password       = $args[2];
1250
 
                $post           = $args[3];
1251
 
                $content_struct = $args[4];
1252
 
 
1253
 
                $allow_anon = apply_filters('xmlrpc_allow_anonymous_comments', false);
1254
 
 
1255
 
                $user = $this->login($username, $password);
1256
 
 
1257
 
                if ( !$user ) {
1258
 
                        $logged_in = false;
1259
 
                        if ( $allow_anon && get_option('comment_registration') )
1260
 
                                return new IXR_Error( 403, __( 'You must be registered to comment' ) );
1261
 
                        else if ( !$allow_anon )
1262
 
                                return $this->error;
1263
 
                } else {
1264
 
                        $logged_in = true;
1265
 
                }
1266
 
 
1267
 
                if ( is_numeric($post) )
1268
 
                        $post_id = absint($post);
1269
 
                else
1270
 
                        $post_id = url_to_postid($post);
1271
 
 
1272
 
                if ( ! $post_id )
1273
 
                        return new IXR_Error( 404, __( 'Invalid post ID.' ) );
1274
 
 
1275
 
                if ( ! get_post($post_id) )
1276
 
                        return new IXR_Error( 404, __( 'Invalid post ID.' ) );
1277
 
 
1278
 
                $comment['comment_post_ID'] = $post_id;
1279
 
 
1280
 
                if ( $logged_in ) {
1281
 
                        $comment['comment_author'] = $wpdb->escape( $user->display_name );
1282
 
                        $comment['comment_author_email'] = $wpdb->escape( $user->user_email );
1283
 
                        $comment['comment_author_url'] = $wpdb->escape( $user->user_url );
1284
 
                        $comment['user_ID'] = $user->ID;
1285
 
                } else {
1286
 
                        $comment['comment_author'] = '';
1287
 
                        if ( isset($content_struct['author']) )
1288
 
                                $comment['comment_author'] = $content_struct['author'];
1289
 
 
1290
 
                        $comment['comment_author_email'] = '';
1291
 
                        if ( isset($content_struct['author_email']) )
1292
 
                                $comment['comment_author_email'] = $content_struct['author_email'];
1293
 
 
1294
 
                        $comment['comment_author_url'] = '';
1295
 
                        if ( isset($content_struct['author_url']) )
1296
 
                                $comment['comment_author_url'] = $content_struct['author_url'];
1297
 
 
1298
 
                        $comment['user_ID'] = 0;
1299
 
 
1300
 
                        if ( get_option('require_name_email') ) {
1301
 
                                if ( 6 > strlen($comment['comment_author_email']) || '' == $comment['comment_author'] )
1302
 
                                        return new IXR_Error( 403, __( 'Comment author name and email are required' ) );
1303
 
                                elseif ( !is_email($comment['comment_author_email']) )
1304
 
                                        return new IXR_Error( 403, __( 'A valid email address is required' ) );
1305
 
                        }
1306
 
                }
1307
 
 
1308
 
                $comment['comment_parent'] = isset($content_struct['comment_parent']) ? absint($content_struct['comment_parent']) : 0;
1309
 
 
1310
 
                $comment['comment_content'] = $content_struct['content'];
1311
 
 
1312
 
                do_action('xmlrpc_call', 'wp.newComment');
1313
 
 
1314
 
                return wp_new_comment($comment);
1315
 
        }
1316
 
 
1317
 
        /**
1318
 
         * Retrieve all of the comment status.
1319
 
         *
1320
 
         * @since 2.7.0
1321
 
         *
1322
 
         * @param array $args Method parameters.
1323
 
         * @return array
1324
 
         */
1325
 
        function wp_getCommentStatusList($args) {
1326
 
                $this->escape( $args );
1327
 
 
1328
 
                $blog_id        = (int) $args[0];
1329
 
                $username       = $args[1];
1330
 
                $password       = $args[2];
1331
 
 
1332
 
                if ( !$user = $this->login($username, $password) )
1333
 
                        return $this->error;
1334
 
 
1335
 
                if ( !current_user_can( 'moderate_comments' ) )
1336
 
                        return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
1337
 
 
1338
 
                do_action('xmlrpc_call', 'wp.getCommentStatusList');
1339
 
 
1340
 
                return get_comment_statuses( );
1341
 
        }
1342
 
 
1343
 
        /**
1344
 
         * Retrieve comment count.
1345
 
         *
1346
 
         * @since 2.5.0
1347
 
         *
1348
 
         * @param array $args Method parameters.
1349
 
         * @return array
1350
 
         */
1351
 
        function wp_getCommentCount( $args ) {
1352
 
                $this->escape($args);
1353
 
 
1354
 
                $blog_id        = (int) $args[0];
1355
 
                $username       = $args[1];
1356
 
                $password       = $args[2];
1357
 
                $post_id        = (int) $args[3];
1358
 
 
1359
 
                if ( !$user = $this->login($username, $password) )
1360
 
                        return $this->error;
1361
 
 
1362
 
                if ( !current_user_can( 'edit_posts' ) )
1363
 
                        return new IXR_Error( 403, __( 'You are not allowed access to details about comments.' ) );
1364
 
 
1365
 
                do_action('xmlrpc_call', 'wp.getCommentCount');
1366
 
 
1367
 
                $count = wp_count_comments( $post_id );
1368
 
                return array(
1369
 
                        "approved" => $count->approved,
1370
 
                        "awaiting_moderation" => $count->moderated,
1371
 
                        "spam" => $count->spam,
1372
 
                        "total_comments" => $count->total_comments
1373
 
                );
1374
 
        }
1375
 
 
1376
 
        /**
1377
 
         * Retrieve post statuses.
1378
 
         *
1379
 
         * @since 2.5.0
1380
 
         *
1381
 
         * @param array $args Method parameters.
1382
 
         * @return array
1383
 
         */
1384
 
        function wp_getPostStatusList( $args ) {
1385
 
                $this->escape( $args );
1386
 
 
1387
 
                $blog_id        = (int) $args[0];
1388
 
                $username       = $args[1];
1389
 
                $password       = $args[2];
1390
 
 
1391
 
                if ( !$user = $this->login($username, $password) )
1392
 
                        return $this->error;
1393
 
 
1394
 
                if ( !current_user_can( 'edit_posts' ) )
1395
 
                        return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
1396
 
 
1397
 
                do_action('xmlrpc_call', 'wp.getPostStatusList');
1398
 
 
1399
 
                return get_post_statuses( );
1400
 
        }
1401
 
 
1402
 
        /**
1403
 
         * Retrieve page statuses.
1404
 
         *
1405
 
         * @since 2.5.0
1406
 
         *
1407
 
         * @param array $args Method parameters.
1408
 
         * @return array
1409
 
         */
1410
 
        function wp_getPageStatusList( $args ) {
1411
 
                $this->escape( $args );
1412
 
 
1413
 
                $blog_id        = (int) $args[0];
1414
 
                $username       = $args[1];
1415
 
                $password       = $args[2];
1416
 
 
1417
 
                if ( !$user = $this->login($username, $password) )
1418
 
                        return $this->error;
1419
 
 
1420
 
                if ( !current_user_can( 'edit_posts' ) )
1421
 
                        return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
1422
 
 
1423
 
                do_action('xmlrpc_call', 'wp.getPageStatusList');
1424
 
 
1425
 
                return get_page_statuses( );
1426
 
        }
1427
 
 
1428
 
        /**
1429
 
         * Retrieve page templates.
1430
 
         *
1431
 
         * @since 2.6.0
1432
 
         *
1433
 
         * @param array $args Method parameters.
1434
 
         * @return array
1435
 
         */
1436
 
        function wp_getPageTemplates( $args ) {
1437
 
                $this->escape( $args );
1438
 
 
1439
 
                $blog_id        = (int) $args[0];
1440
 
                $username       = $args[1];
1441
 
                $password       = $args[2];
1442
 
 
1443
 
                if ( !$user = $this->login($username, $password) )
1444
 
                        return $this->error;
1445
 
 
1446
 
                if ( !current_user_can( 'edit_pages' ) )
1447
 
                        return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
1448
 
 
1449
 
                $templates = get_page_templates( );
1450
 
                $templates['Default'] = 'default';
1451
 
 
1452
 
                return $templates;
1453
 
        }
1454
 
 
1455
 
        /**
1456
 
         * Retrieve blog options.
1457
 
         *
1458
 
         * @since 2.6.0
1459
 
         *
1460
 
         * @param array $args Method parameters.
1461
 
         * @return array
1462
 
         */
1463
 
        function wp_getOptions( $args ) {
1464
 
                $this->escape( $args );
1465
 
 
1466
 
                $blog_id        = (int) $args[0];
1467
 
                $username       = $args[1];
1468
 
                $password       = $args[2];
1469
 
                $options        = (array) $args[3];
1470
 
 
1471
 
                if ( !$user = $this->login($username, $password) )
1472
 
                        return $this->error;
1473
 
 
1474
 
                // If no specific options where asked for, return all of them
1475
 
                if ( count( $options ) == 0 )
1476
 
                        $options = array_keys($this->blog_options);
1477
 
 
1478
 
                return $this->_getOptions($options);
1479
 
        }
1480
 
 
1481
 
        /**
1482
 
         * Retrieve blog options value from list.
1483
 
         *
1484
 
         * @since 2.6.0
1485
 
         *
1486
 
         * @param array $options Options to retrieve.
1487
 
         * @return array
1488
 
         */
1489
 
        function _getOptions($options) {
1490
 
                $data = array( );
1491
 
                foreach ( $options as $option ) {
1492
 
                        if ( array_key_exists( $option, $this->blog_options ) ) {
1493
 
                                $data[$option] = $this->blog_options[$option];
1494
 
                                //Is the value static or dynamic?
1495
 
                                if ( isset( $data[$option]['option'] ) ) {
1496
 
                                        $data[$option]['value'] = get_option( $data[$option]['option'] );
1497
 
                                        unset($data[$option]['option']);
1498
 
                                }
1499
 
                        }
1500
 
                }
1501
 
 
1502
 
                return $data;
1503
 
        }
1504
 
 
1505
 
        /**
1506
 
         * Update blog options.
1507
 
         *
1508
 
         * @since 2.6.0
1509
 
         *
1510
 
         * @param array $args Method parameters.
1511
 
         * @return unknown
1512
 
         */
1513
 
        function wp_setOptions( $args ) {
1514
 
                $this->escape( $args );
1515
 
 
1516
 
                $blog_id        = (int) $args[0];
1517
 
                $username       = $args[1];
1518
 
                $password       = $args[2];
1519
 
                $options        = (array) $args[3];
1520
 
 
1521
 
                if ( !$user = $this->login($username, $password) )
1522
 
                        return $this->error;
1523
 
 
1524
 
                if ( !current_user_can( 'manage_options' ) )
1525
 
                        return new IXR_Error( 403, __( 'You are not allowed to update options.' ) );
1526
 
 
1527
 
                foreach ( $options as $o_name => $o_value ) {
1528
 
                        $option_names[] = $o_name;
1529
 
                        if ( !array_key_exists( $o_name, $this->blog_options ) )
1530
 
                                continue;
1531
 
 
1532
 
                        if ( $this->blog_options[$o_name]['readonly'] == true )
1533
 
                                continue;
1534
 
 
1535
 
                        update_option( $this->blog_options[$o_name]['option'], $o_value );
1536
 
                }
1537
 
 
1538
 
                //Now return the updated values
1539
 
                return $this->_getOptions($option_names);
1540
 
        }
1541
 
 
1542
 
        /* Blogger API functions.
1543
 
         * specs on http://plant.blogger.com/api and http://groups.yahoo.com/group/bloggerDev/
1544
 
         */
1545
 
 
1546
 
        /**
1547
 
         * Retrieve blogs that user owns.
1548
 
         *
1549
 
         * Will make more sense once we support multiple blogs.
1550
 
         *
1551
 
         * @since 1.5.0
1552
 
         *
1553
 
         * @param array $args Method parameters.
1554
 
         * @return array
1555
 
         */
1556
 
        function blogger_getUsersBlogs($args) {
1557
 
                if ( is_multisite() )
1558
 
                        return $this->_multisite_getUsersBlogs($args);
1559
 
 
1560
 
                $this->escape($args);
1561
 
 
1562
 
                $username = $args[1];
1563
 
                $password  = $args[2];
1564
 
 
1565
 
                if ( !$user = $this->login($username, $password) )
1566
 
                        return $this->error;
1567
 
 
1568
 
                do_action('xmlrpc_call', 'blogger.getUsersBlogs');
1569
 
 
1570
 
                $is_admin = current_user_can('manage_options');
1571
 
 
1572
 
                $struct = array(
1573
 
                        'isAdmin'  => $is_admin,
1574
 
                        'url'      => get_option('home') . '/',
1575
 
                        'blogid'   => '1',
1576
 
                        'blogName' => get_option('blogname'),
1577
 
                        'xmlrpc'   => site_url( 'xmlrpc.php' )
1578
 
                );
1579
 
 
1580
 
                return array($struct);
1581
 
        }
1582
 
 
1583
 
        /**
1584
 
         * Private function for retrieving a users blogs for multisite setups
1585
 
         *
1586
 
         * @access protected
1587
 
         */
1588
 
        function _multisite_getUsersBlogs($args) {
1589
 
                global $current_blog;
1590
 
                $domain = $current_blog->domain;
1591
 
                $path = $current_blog->path . 'xmlrpc.php';
1592
 
                $protocol = is_ssl() ? 'https' : 'http';
1593
 
 
1594
 
                $rpc = new IXR_Client("$protocol://{$domain}{$path}");
1595
 
                $rpc->query('wp.getUsersBlogs', $args[1], $args[2]);
1596
 
                $blogs = $rpc->getResponse();
1597
 
 
1598
 
                if ( isset($blogs['faultCode']) )
1599
 
                        return new IXR_Error($blogs['faultCode'], $blogs['faultString']);
1600
 
 
1601
 
                if ( $_SERVER['HTTP_HOST'] == $domain && $_SERVER['REQUEST_URI'] == $path ) {
1602
 
                        return $blogs;
1603
 
                } else {
1604
 
                        foreach ( (array) $blogs as $blog ) {
1605
 
                                if ( strpos($blog['url'], $_SERVER['HTTP_HOST']) )
1606
 
                                        return array($blog);
1607
 
                        }
1608
 
                        return array();
1609
 
                }
1610
 
        }
1611
 
 
1612
 
        /**
1613
 
         * Retrieve user's data.
1614
 
         *
1615
 
         * Gives your client some info about you, so you don't have to.
1616
 
         *
1617
 
         * @since 1.5.0
1618
 
         *
1619
 
         * @param array $args Method parameters.
1620
 
         * @return array
1621
 
         */
1622
 
        function blogger_getUserInfo($args) {
1623
 
 
1624
 
                $this->escape($args);
1625
 
 
1626
 
                $username = $args[1];
1627
 
                $password  = $args[2];
1628
 
 
1629
 
                if ( !$user = $this->login($username, $password) )
1630
 
                        return $this->error;
1631
 
 
1632
 
                if ( !current_user_can( 'edit_posts' ) )
1633
 
                        return new IXR_Error( 401, __( 'Sorry, you do not have access to user data on this site.' ) );
1634
 
 
1635
 
                do_action('xmlrpc_call', 'blogger.getUserInfo');
1636
 
 
1637
 
                $struct = array(
1638
 
                        'nickname'  => $user->nickname,
1639
 
                        'userid'    => $user->ID,
1640
 
                        'url'       => $user->user_url,
1641
 
                        'lastname'  => $user->last_name,
1642
 
                        'firstname' => $user->first_name
1643
 
                );
1644
 
 
1645
 
                return $struct;
1646
 
        }
1647
 
 
1648
 
        /**
1649
 
         * Retrieve post.
1650
 
         *
1651
 
         * @since 1.5.0
1652
 
         *
1653
 
         * @param array $args Method parameters.
1654
 
         * @return array
1655
 
         */
1656
 
        function blogger_getPost($args) {
1657
 
 
1658
 
                $this->escape($args);
1659
 
 
1660
 
                $post_ID    = (int) $args[1];
1661
 
                $username = $args[2];
1662
 
                $password  = $args[3];
1663
 
 
1664
 
                if ( !$user = $this->login($username, $password) )
1665
 
                        return $this->error;
1666
 
 
1667
 
                if ( !current_user_can( 'edit_post', $post_ID ) )
1668
 
                        return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) );
1669
 
 
1670
 
                do_action('xmlrpc_call', 'blogger.getPost');
1671
 
 
1672
 
                $post_data = wp_get_single_post($post_ID, ARRAY_A);
1673
 
 
1674
 
                $categories = implode(',', wp_get_post_categories($post_ID));
1675
 
 
1676
 
                $content  = '<title>'.stripslashes($post_data['post_title']).'</title>';
1677
 
                $content .= '<category>'.$categories.'</category>';
1678
 
                $content .= stripslashes($post_data['post_content']);
1679
 
 
1680
 
                $struct = array(
1681
 
                        'userid'    => $post_data['post_author'],
1682
 
                        'dateCreated' => new IXR_Date(mysql2date('Ymd\TH:i:s', $post_data['post_date'], false)),
1683
 
                        'content'     => $content,
1684
 
                        'postid'  => $post_data['ID']
1685
 
                );
1686
 
 
1687
 
                return $struct;
1688
 
        }
1689
 
 
1690
 
        /**
1691
 
         * Retrieve list of recent posts.
1692
 
         *
1693
 
         * @since 1.5.0
1694
 
         *
1695
 
         * @param array $args Method parameters.
1696
 
         * @return array
1697
 
         */
1698
 
        function blogger_getRecentPosts($args) {
1699
 
 
1700
 
                $this->escape($args);
1701
 
 
1702
 
                $blog_ID    = (int) $args[1]; /* though we don't use it yet */
1703
 
                $username = $args[2];
1704
 
                $password  = $args[3];
1705
 
                $num_posts  = $args[4];
1706
 
 
1707
 
                if ( !$user = $this->login($username, $password) )
1708
 
                        return $this->error;
1709
 
 
1710
 
                do_action('xmlrpc_call', 'blogger.getRecentPosts');
1711
 
 
1712
 
                $posts_list = wp_get_recent_posts($num_posts);
1713
 
 
1714
 
                if ( !$posts_list ) {
1715
 
                        $this->error = new IXR_Error(500, __('Either there are no posts, or something went wrong.'));
1716
 
                        return $this->error;
1717
 
                }
1718
 
 
1719
 
                foreach ($posts_list as $entry) {
1720
 
                        if ( !current_user_can( 'edit_post', $entry['ID'] ) )
1721
 
                                continue;
1722
 
 
1723
 
                        $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date'], false);
1724
 
                        $categories = implode(',', wp_get_post_categories($entry['ID']));
1725
 
 
1726
 
                        $content  = '<title>'.stripslashes($entry['post_title']).'</title>';
1727
 
                        $content .= '<category>'.$categories.'</category>';
1728
 
                        $content .= stripslashes($entry['post_content']);
1729
 
 
1730
 
                        $struct[] = array(
1731
 
                                'userid' => $entry['post_author'],
1732
 
                                'dateCreated' => new IXR_Date($post_date),
1733
 
                                'content' => $content,
1734
 
                                'postid' => $entry['ID'],
1735
 
                        );
1736
 
 
1737
 
                }
1738
 
 
1739
 
                $recent_posts = array();
1740
 
                for ( $j=0; $j<count($struct); $j++ ) {
1741
 
                        array_push($recent_posts, $struct[$j]);
1742
 
                }
1743
 
 
1744
 
                return $recent_posts;
1745
 
        }
1746
 
 
1747
 
        /**
1748
 
         * Retrieve blog_filename content.
1749
 
         *
1750
 
         * @since 1.5.0
1751
 
         *
1752
 
         * @param array $args Method parameters.
1753
 
         * @return string
1754
 
         */
1755
 
        function blogger_getTemplate($args) {
1756
 
 
1757
 
                $this->escape($args);
1758
 
 
1759
 
                $blog_ID    = (int) $args[1];
1760
 
                $username = $args[2];
1761
 
                $password  = $args[3];
1762
 
                $template   = $args[4]; /* could be 'main' or 'archiveIndex', but we don't use it */
1763
 
 
1764
 
                if ( !$user = $this->login($username, $password) )
1765
 
                        return $this->error;
1766
 
 
1767
 
                do_action('xmlrpc_call', 'blogger.getTemplate');
1768
 
 
1769
 
                if ( !current_user_can('edit_themes') )
1770
 
                        return new IXR_Error(401, __('Sorry, this user can not edit the template.'));
1771
 
 
1772
 
                /* warning: here we make the assumption that the blog's URL is on the same server */
1773
 
                $filename = get_option('home') . '/';
1774
 
                $filename = preg_replace('#https?://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename);
1775
 
 
1776
 
                $f = fopen($filename, 'r');
1777
 
                $content = fread($f, filesize($filename));
1778
 
                fclose($f);
1779
 
 
1780
 
                /* so it is actually editable with a windows/mac client */
1781
 
                // 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);
1782
 
 
1783
 
                return $content;
1784
 
        }
1785
 
 
1786
 
        /**
1787
 
         * Updates the content of blog_filename.
1788
 
         *
1789
 
         * @since 1.5.0
1790
 
         *
1791
 
         * @param array $args Method parameters.
1792
 
         * @return bool True when done.
1793
 
         */
1794
 
        function blogger_setTemplate($args) {
1795
 
 
1796
 
                $this->escape($args);
1797
 
 
1798
 
                $blog_ID    = (int) $args[1];
1799
 
                $username = $args[2];
1800
 
                $password  = $args[3];
1801
 
                $content    = $args[4];
1802
 
                $template   = $args[5]; /* could be 'main' or 'archiveIndex', but we don't use it */
1803
 
 
1804
 
                if ( !$user = $this->login($username, $password) )
1805
 
                        return $this->error;
1806
 
 
1807
 
                do_action('xmlrpc_call', 'blogger.setTemplate');
1808
 
 
1809
 
                if ( !current_user_can('edit_themes') )
1810
 
                        return new IXR_Error(401, __('Sorry, this user cannot edit the template.'));
1811
 
 
1812
 
                /* warning: here we make the assumption that the blog's URL is on the same server */
1813
 
                $filename = get_option('home') . '/';
1814
 
                $filename = preg_replace('#https?://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename);
1815
 
 
1816
 
                if ($f = fopen($filename, 'w+')) {
1817
 
                        fwrite($f, $content);
1818
 
                        fclose($f);
1819
 
                } else {
1820
 
                        return new IXR_Error(500, __('Either the file is not writable, or something wrong happened. The file has not been updated.'));
1821
 
                }
1822
 
 
1823
 
                return true;
1824
 
        }
1825
 
 
1826
 
        /**
1827
 
         * Create new post.
1828
 
         *
1829
 
         * @since 1.5.0
1830
 
         *
1831
 
         * @param array $args Method parameters.
1832
 
         * @return int
1833
 
         */
1834
 
        function blogger_newPost($args) {
1835
 
 
1836
 
                $this->escape($args);
1837
 
 
1838
 
                $blog_ID    = (int) $args[1]; /* though we don't use it yet */
1839
 
                $username = $args[2];
1840
 
                $password  = $args[3];
1841
 
                $content    = $args[4];
1842
 
                $publish    = $args[5];
1843
 
 
1844
 
                if ( !$user = $this->login($username, $password) )
1845
 
                        return $this->error;
1846
 
 
1847
 
                do_action('xmlrpc_call', 'blogger.newPost');
1848
 
 
1849
 
                $cap = ($publish) ? 'publish_posts' : 'edit_posts';
1850
 
                if ( !current_user_can($cap) )
1851
 
                        return new IXR_Error(401, __('Sorry, you are not allowed to post on this site.'));
1852
 
 
1853
 
                $post_status = ($publish) ? 'publish' : 'draft';
1854
 
 
1855
 
                $post_author = $user->ID;
1856
 
 
1857
 
                $post_title = xmlrpc_getposttitle($content);
1858
 
                $post_category = xmlrpc_getpostcategory($content);
1859
 
                $post_content = xmlrpc_removepostdata($content);
1860
 
 
1861
 
                $post_date = current_time('mysql');
1862
 
                $post_date_gmt = current_time('mysql', 1);
1863
 
 
1864
 
                $post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status');
1865
 
 
1866
 
                $post_ID = wp_insert_post($post_data);
1867
 
                if ( is_wp_error( $post_ID ) )
1868
 
                        return new IXR_Error(500, $post_ID->get_error_message());
1869
 
 
1870
 
                if ( !$post_ID )
1871
 
                        return new IXR_Error(500, __('Sorry, your entry could not be posted. Something wrong happened.'));
1872
 
 
1873
 
                $this->attach_uploads( $post_ID, $post_content );
1874
 
 
1875
 
                logIO('O', "Posted ! ID: $post_ID");
1876
 
 
1877
 
                return $post_ID;
1878
 
        }
1879
 
 
1880
 
        /**
1881
 
         * Edit a post.
1882
 
         *
1883
 
         * @since 1.5.0
1884
 
         *
1885
 
         * @param array $args Method parameters.
1886
 
         * @return bool true when done.
1887
 
         */
1888
 
        function blogger_editPost($args) {
1889
 
 
1890
 
                $this->escape($args);
1891
 
 
1892
 
                $post_ID     = (int) $args[1];
1893
 
                $username  = $args[2];
1894
 
                $password   = $args[3];
1895
 
                $content     = $args[4];
1896
 
                $publish     = $args[5];
1897
 
 
1898
 
                if ( !$user = $this->login($username, $password) )
1899
 
                        return $this->error;
1900
 
 
1901
 
                do_action('xmlrpc_call', 'blogger.editPost');
1902
 
 
1903
 
                $actual_post = wp_get_single_post($post_ID,ARRAY_A);
1904
 
 
1905
 
                if ( !$actual_post || $actual_post['post_type'] != 'post' )
1906
 
                        return new IXR_Error(404, __('Sorry, no such post.'));
1907
 
 
1908
 
                $this->escape($actual_post);
1909
 
 
1910
 
                if ( !current_user_can('edit_post', $post_ID) )
1911
 
                        return new IXR_Error(401, __('Sorry, you do not have the right to edit this post.'));
1912
 
 
1913
 
                extract($actual_post, EXTR_SKIP);
1914
 
 
1915
 
                if ( ('publish' == $post_status) && !current_user_can('publish_posts') )
1916
 
                        return new IXR_Error(401, __('Sorry, you do not have the right to publish this post.'));
1917
 
 
1918
 
                $post_title = xmlrpc_getposttitle($content);
1919
 
                $post_category = xmlrpc_getpostcategory($content);
1920
 
                $post_content = xmlrpc_removepostdata($content);
1921
 
 
1922
 
                $postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt');
1923
 
 
1924
 
                $result = wp_update_post($postdata);
1925
 
 
1926
 
                if ( !$result )
1927
 
                        return new IXR_Error(500, __('For some strange yet very annoying reason, this post could not be edited.'));
1928
 
 
1929
 
                $this->attach_uploads( $ID, $post_content );
1930
 
 
1931
 
                return true;
1932
 
        }
1933
 
 
1934
 
        /**
1935
 
         * Remove a post.
1936
 
         *
1937
 
         * @since 1.5.0
1938
 
         *
1939
 
         * @param array $args Method parameters.
1940
 
         * @return bool True when post is deleted.
1941
 
         */
1942
 
        function blogger_deletePost($args) {
1943
 
                $this->escape($args);
1944
 
 
1945
 
                $post_ID     = (int) $args[1];
1946
 
                $username  = $args[2];
1947
 
                $password   = $args[3];
1948
 
                $publish     = $args[4];
1949
 
 
1950
 
                if ( !$user = $this->login($username, $password) )
1951
 
                        return $this->error;
1952
 
 
1953
 
                do_action('xmlrpc_call', 'blogger.deletePost');
1954
 
 
1955
 
                $actual_post = wp_get_single_post($post_ID,ARRAY_A);
1956
 
 
1957
 
                if ( !$actual_post || $actual_post['post_type'] != 'post' )
1958
 
                        return new IXR_Error(404, __('Sorry, no such post.'));
1959
 
 
1960
 
                if ( !current_user_can('edit_post', $post_ID) )
1961
 
                        return new IXR_Error(401, __('Sorry, you do not have the right to delete this post.'));
1962
 
 
1963
 
                $result = wp_delete_post($post_ID);
1964
 
 
1965
 
                if ( !$result )
1966
 
                        return new IXR_Error(500, __('For some strange yet very annoying reason, this post could not be deleted.'));
1967
 
 
1968
 
                return true;
1969
 
        }
1970
 
 
1971
 
        /* MetaWeblog API functions
1972
 
         * specs on wherever Dave Winer wants them to be
1973
 
         */
1974
 
 
1975
 
        /**
1976
 
         * Create a new post.
1977
 
         *
1978
 
         * @since 1.5.0
1979
 
         *
1980
 
         * @param array $args Method parameters.
1981
 
         * @return int
1982
 
         */
1983
 
        function mw_newPost($args) {
1984
 
                $this->escape($args);
1985
 
 
1986
 
                $blog_ID     = (int) $args[0]; // we will support this in the near future
1987
 
                $username  = $args[1];
1988
 
                $password   = $args[2];
1989
 
                $content_struct = $args[3];
1990
 
                $publish     = $args[4];
1991
 
 
1992
 
                if ( !$user = $this->login($username, $password) )
1993
 
                        return $this->error;
1994
 
 
1995
 
                do_action('xmlrpc_call', 'metaWeblog.newPost');
1996
 
 
1997
 
                $cap = ( $publish ) ? 'publish_posts' : 'edit_posts';
1998
 
                $error_message = __( 'Sorry, you are not allowed to publish posts on this site.' );
1999
 
                $post_type = 'post';
2000
 
                $page_template = '';
2001
 
                if ( !empty( $content_struct['post_type'] ) ) {
2002
 
                        if ( $content_struct['post_type'] == 'page' ) {
2003
 
                                $cap = ( $publish ) ? 'publish_pages' : 'edit_pages';
2004
 
                                $error_message = __( 'Sorry, you are not allowed to publish pages on this site.' );
2005
 
                                $post_type = 'page';
2006
 
                                if ( !empty( $content_struct['wp_page_template'] ) )
2007
 
                                        $page_template = $content_struct['wp_page_template'];
2008
 
                        } elseif ( $content_struct['post_type'] == 'post' ) {
2009
 
                                // This is the default, no changes needed
2010
 
                        } else {
2011
 
                                // No other post_type values are allowed here
2012
 
                                return new IXR_Error( 401, __( 'Invalid post type.' ) );
2013
 
                        }
2014
 
                }
2015
 
 
2016
 
                if ( !current_user_can( $cap ) )
2017
 
                        return new IXR_Error( 401, $error_message );
2018
 
 
2019
 
                // Let WordPress generate the post_name (slug) unless
2020
 
                // one has been provided.
2021
 
                $post_name = "";
2022
 
                if ( isset($content_struct["wp_slug"]) )
2023
 
                        $post_name = $content_struct["wp_slug"];
2024
 
 
2025
 
                // Only use a password if one was given.
2026
 
                if ( isset($content_struct["wp_password"]) )
2027
 
                        $post_password = $content_struct["wp_password"];
2028
 
 
2029
 
                // Only set a post parent if one was provided.
2030
 
                if ( isset($content_struct["wp_page_parent_id"]) )
2031
 
                        $post_parent = $content_struct["wp_page_parent_id"];
2032
 
 
2033
 
                // Only set the menu_order if it was provided.
2034
 
                if ( isset($content_struct["wp_page_order"]) )
2035
 
                        $menu_order = $content_struct["wp_page_order"];
2036
 
 
2037
 
                $post_author = $user->ID;
2038
 
 
2039
 
                // If an author id was provided then use it instead.
2040
 
                if ( isset($content_struct["wp_author_id"]) && ($user->ID != $content_struct["wp_author_id"]) ) {
2041
 
                        switch ( $post_type ) {
2042
 
                                case "post":
2043
 
                                        if ( !current_user_can("edit_others_posts") )
2044
 
                                                return(new IXR_Error(401, __("You are not allowed to post as this user")));
2045
 
                                        break;
2046
 
                                case "page":
2047
 
                                        if ( !current_user_can("edit_others_pages") )
2048
 
                                                return(new IXR_Error(401, __("You are not allowed to create pages as this user")));
2049
 
                                        break;
2050
 
                                default:
2051
 
                                        return(new IXR_Error(401, __("Invalid post type.")));
2052
 
                                        break;
2053
 
                        }
2054
 
                        $post_author = $content_struct["wp_author_id"];
2055
 
                }
2056
 
 
2057
 
                $post_title = $content_struct['title'];
2058
 
                $post_content = $content_struct['description'];
2059
 
 
2060
 
                $post_status = $publish ? 'publish' : 'draft';
2061
 
 
2062
 
                if ( isset( $content_struct["{$post_type}_status"] ) ) {
2063
 
                        switch ( $content_struct["{$post_type}_status"] ) {
2064
 
                                case 'draft':
2065
 
                                case 'private':
2066
 
                                case 'publish':
2067
 
                                        $post_status = $content_struct["{$post_type}_status"];
2068
 
                                        break;
2069
 
                                case 'pending':
2070
 
                                        // Pending is only valid for posts, not pages.
2071
 
                                        if ( $post_type === 'post' )
2072
 
                                                $post_status = $content_struct["{$post_type}_status"];
2073
 
                                        break;
2074
 
                                default:
2075
 
                                        $post_status = $publish ? 'publish' : 'draft';
2076
 
                                        break;
2077
 
                        }
2078
 
                }
2079
 
 
2080
 
                $post_excerpt = $content_struct['mt_excerpt'];
2081
 
                $post_more = $content_struct['mt_text_more'];
2082
 
 
2083
 
                $tags_input = $content_struct['mt_keywords'];
2084
 
 
2085
 
                if ( isset($content_struct["mt_allow_comments"]) ) {
2086
 
                        if ( !is_numeric($content_struct["mt_allow_comments"]) ) {
2087
 
                                switch ( $content_struct["mt_allow_comments"] ) {
2088
 
                                        case "closed":
2089
 
                                                $comment_status = "closed";
2090
 
                                                break;
2091
 
                                        case "open":
2092
 
                                                $comment_status = "open";
2093
 
                                                break;
2094
 
                                        default:
2095
 
                                                $comment_status = get_option("default_comment_status");
2096
 
                                                break;
2097
 
                                }
2098
 
                        } else {
2099
 
                                switch ( (int) $content_struct["mt_allow_comments"] ) {
2100
 
                                        case 0:
2101
 
                                        case 2:
2102
 
                                                $comment_status = "closed";
2103
 
                                                break;
2104
 
                                        case 1:
2105
 
                                                $comment_status = "open";
2106
 
                                                break;
2107
 
                                        default:
2108
 
                                                $comment_status = get_option("default_comment_status");
2109
 
                                                break;
2110
 
                                }
2111
 
                        }
2112
 
                } else {
2113
 
                        $comment_status = get_option("default_comment_status");
2114
 
                }
2115
 
 
2116
 
                if ( isset($content_struct["mt_allow_pings"]) ) {
2117
 
                        if ( !is_numeric($content_struct["mt_allow_pings"]) ) {
2118
 
                                switch ( $content_struct['mt_allow_pings'] ) {
2119
 
                                        case "closed":
2120
 
                                                $ping_status = "closed";
2121
 
                                                break;
2122
 
                                        case "open":
2123
 
                                                $ping_status = "open";
2124
 
                                                break;
2125
 
                                        default:
2126
 
                                                $ping_status = get_option("default_ping_status");
2127
 
                                                break;
2128
 
                                }
2129
 
                        } else {
2130
 
                                switch ( (int) $content_struct["mt_allow_pings"] ) {
2131
 
                                        case 0:
2132
 
                                                $ping_status = "closed";
2133
 
                                                break;
2134
 
                                        case 1:
2135
 
                                                $ping_status = "open";
2136
 
                                                break;
2137
 
                                        default:
2138
 
                                                $ping_status = get_option("default_ping_status");
2139
 
                                                break;
2140
 
                                }
2141
 
                        }
2142
 
                } else {
2143
 
                        $ping_status = get_option("default_ping_status");
2144
 
                }
2145
 
 
2146
 
                if ( $post_more )
2147
 
                        $post_content = $post_content . "<!--more-->" . $post_more;
2148
 
 
2149
 
                $to_ping = $content_struct['mt_tb_ping_urls'];
2150
 
                if ( is_array($to_ping) )
2151
 
                        $to_ping = implode(' ', $to_ping);
2152
 
 
2153
 
                // Do some timestamp voodoo
2154
 
                if ( !empty( $content_struct['date_created_gmt'] ) )
2155
 
                        $dateCreated = str_replace( 'Z', '', $content_struct['date_created_gmt']->getIso() ) . 'Z'; // We know this is supposed to be GMT, so we're going to slap that Z on there by force
2156
 
                elseif ( !empty( $content_struct['dateCreated']) )
2157
 
                        $dateCreated = $content_struct['dateCreated']->getIso();
2158
 
 
2159
 
                if ( !empty( $dateCreated ) ) {
2160
 
                        $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated));
2161
 
                        $post_date_gmt = iso8601_to_datetime($dateCreated, GMT);
2162
 
                } else {
2163
 
                        $post_date = current_time('mysql');
2164
 
                        $post_date_gmt = current_time('mysql', 1);
2165
 
                }
2166
 
 
2167
 
                $catnames = $content_struct['categories'];
2168
 
                logIO('O', 'Post cats: ' . var_export($catnames,true));
2169
 
                $post_category = array();
2170
 
 
2171
 
                if ( is_array($catnames) ) {
2172
 
                        foreach ($catnames as $cat) {
2173
 
                                $post_category[] = get_cat_ID($cat);
2174
 
                        }
2175
 
                }
2176
 
 
2177
 
                // We've got all the data -- post it:
2178
 
                $postdata = compact('post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'to_ping', 'post_type', 'post_name', 'post_password', 'post_parent', 'menu_order', 'tags_input', 'page_template');
2179
 
 
2180
 
                $post_ID = wp_insert_post($postdata, true);
2181
 
                if ( is_wp_error( $post_ID ) )
2182
 
                        return new IXR_Error(500, $post_ID->get_error_message());
2183
 
 
2184
 
                if ( !$post_ID )
2185
 
                        return new IXR_Error(500, __('Sorry, your entry could not be posted. Something wrong happened.'));
2186
 
 
2187
 
                // Only posts can be sticky
2188
 
                if ( $post_type == 'post' && isset( $content_struct['sticky'] ) ) {
2189
 
                        if ( $content_struct['sticky'] == true )
2190
 
                                stick_post( $post_ID );
2191
 
                        elseif ( $content_struct['sticky'] == false )
2192
 
                                unstick_post( $post_ID );
2193
 
                }
2194
 
 
2195
 
                if ( isset($content_struct['custom_fields']) )
2196
 
                        $this->set_custom_fields($post_ID, $content_struct['custom_fields']);
2197
 
 
2198
 
                // Handle enclosures
2199
 
                $this->add_enclosure_if_new($post_ID, $content_struct['enclosure']);
2200
 
 
2201
 
                $this->attach_uploads( $post_ID, $post_content );
2202
 
 
2203
 
                logIO('O', "Posted ! ID: $post_ID");
2204
 
 
2205
 
                return strval($post_ID);
2206
 
        }
2207
 
 
2208
 
        function add_enclosure_if_new($post_ID, $enclosure) {
2209
 
                if ( is_array( $enclosure ) && isset( $enclosure['url'] ) && isset( $enclosure['length'] ) && isset( $enclosure['type'] ) ) {
2210
 
 
2211
 
                        $encstring = $enclosure['url'] . "\n" . $enclosure['length'] . "\n" . $enclosure['type'];
2212
 
                        $found = false;
2213
 
                        foreach ( (array) get_post_custom($post_ID) as $key => $val) {
2214
 
                                if ($key == 'enclosure') {
2215
 
                                        foreach ( (array) $val as $enc ) {
2216
 
                                                if ($enc == $encstring) {
2217
 
                                                        $found = true;
2218
 
                                                        break 2;
2219
 
                                                }
2220
 
                                        }
2221
 
                                }
2222
 
                        }
2223
 
                        if (!$found)
2224
 
                                add_post_meta( $post_ID, 'enclosure', $encstring );
2225
 
                }
2226
 
        }
2227
 
 
2228
 
        /**
2229
 
         * Attach upload to a post.
2230
 
         *
2231
 
         * @since 2.1.0
2232
 
         *
2233
 
         * @param int $post_ID Post ID.
2234
 
         * @param string $post_content Post Content for attachment.
2235
 
         */
2236
 
        function attach_uploads( $post_ID, $post_content ) {
2237
 
                global $wpdb;
2238
 
 
2239
 
                // find any unattached files
2240
 
                $attachments = $wpdb->get_results( "SELECT ID, guid FROM {$wpdb->posts} WHERE post_parent = '0' AND post_type = 'attachment'" );
2241
 
                if ( is_array( $attachments ) ) {
2242
 
                        foreach ( $attachments as $file ) {
2243
 
                                if ( strpos( $post_content, $file->guid ) !== false )
2244
 
                                        $wpdb->update($wpdb->posts, array('post_parent' => $post_ID), array('ID' => $file->ID) );
2245
 
                        }
2246
 
                }
2247
 
        }
2248
 
 
2249
 
        /**
2250
 
         * Edit a post.
2251
 
         *
2252
 
         * @since 1.5.0
2253
 
         *
2254
 
         * @param array $args Method parameters.
2255
 
         * @return bool True on success.
2256
 
         */
2257
 
        function mw_editPost($args) {
2258
 
 
2259
 
                $this->escape($args);
2260
 
 
2261
 
                $post_ID     = (int) $args[0];
2262
 
                $username  = $args[1];
2263
 
                $password   = $args[2];
2264
 
                $content_struct = $args[3];
2265
 
                $publish     = $args[4];
2266
 
 
2267
 
                if ( !$user = $this->login($username, $password) )
2268
 
                        return $this->error;
2269
 
 
2270
 
                do_action('xmlrpc_call', 'metaWeblog.editPost');
2271
 
 
2272
 
                $cap = ( $publish ) ? 'publish_posts' : 'edit_posts';
2273
 
                $error_message = __( 'Sorry, you are not allowed to publish posts on this site.' );
2274
 
                $post_type = 'post';
2275
 
                $page_template = '';
2276
 
                if ( !empty( $content_struct['post_type'] ) ) {
2277
 
                        if ( $content_struct['post_type'] == 'page' ) {
2278
 
                                $cap = ( $publish ) ? 'publish_pages' : 'edit_pages';
2279
 
                                $error_message = __( 'Sorry, you are not allowed to publish pages on this site.' );
2280
 
                                $post_type = 'page';
2281
 
                                if ( !empty( $content_struct['wp_page_template'] ) )
2282
 
                                        $page_template = $content_struct['wp_page_template'];
2283
 
                        } elseif ( $content_struct['post_type'] == 'post' ) {
2284
 
                                // This is the default, no changes needed
2285
 
                        } else {
2286
 
                                // No other post_type values are allowed here
2287
 
                                return new IXR_Error( 401, __( 'Invalid post type.' ) );
2288
 
                        }
2289
 
                }
2290
 
 
2291
 
                if ( !current_user_can( $cap ) )
2292
 
                        return new IXR_Error( 401, $error_message );
2293
 
 
2294
 
                $postdata = wp_get_single_post($post_ID, ARRAY_A);
2295
 
 
2296
 
                // If there is no post data for the give post id, stop
2297
 
                // now and return an error.  Other wise a new post will be
2298
 
                // created (which was the old behavior).
2299
 
                if ( empty($postdata["ID"]) )
2300
 
                        return(new IXR_Error(404, __("Invalid post ID.")));
2301
 
 
2302
 
                $this->escape($postdata);
2303
 
                extract($postdata, EXTR_SKIP);
2304
 
 
2305
 
                // Let WordPress manage slug if none was provided.
2306
 
                $post_name = "";
2307
 
                if ( isset($content_struct["wp_slug"]) )
2308
 
                        $post_name = $content_struct["wp_slug"];
2309
 
 
2310
 
                // Only use a password if one was given.
2311
 
                if ( isset($content_struct["wp_password"]) )
2312
 
                        $post_password = $content_struct["wp_password"];
2313
 
 
2314
 
                // Only set a post parent if one was given.
2315
 
                if ( isset($content_struct["wp_page_parent_id"]) )
2316
 
                        $post_parent = $content_struct["wp_page_parent_id"];
2317
 
 
2318
 
                // Only set the menu_order if it was given.
2319
 
                if ( isset($content_struct["wp_page_order"]) )
2320
 
                        $menu_order = $content_struct["wp_page_order"];
2321
 
 
2322
 
                $post_author = $postdata["post_author"];
2323
 
 
2324
 
                // Only set the post_author if one is set.
2325
 
                if ( isset($content_struct["wp_author_id"]) && ($user->ID != $content_struct["wp_author_id"]) ) {
2326
 
                        switch ( $post_type ) {
2327
 
                                case "post":
2328
 
                                        if ( !current_user_can("edit_others_posts") )
2329
 
                                                return(new IXR_Error(401, __("You are not allowed to change the post author as this user.")));
2330
 
                                        break;
2331
 
                                case "page":
2332
 
                                        if ( !current_user_can("edit_others_pages") )
2333
 
                                                return(new IXR_Error(401, __("You are not allowed to change the page author as this user.")));
2334
 
                                        break;
2335
 
                                default:
2336
 
                                        return(new IXR_Error(401, __("Invalid post type.")));
2337
 
                                        break;
2338
 
                        }
2339
 
                        $post_author = $content_struct["wp_author_id"];
2340
 
                }
2341
 
 
2342
 
                if ( isset($content_struct["mt_allow_comments"]) ) {
2343
 
                        if ( !is_numeric($content_struct["mt_allow_comments"]) ) {
2344
 
                                switch ( $content_struct["mt_allow_comments"] ) {
2345
 
                                        case "closed":
2346
 
                                                $comment_status = "closed";
2347
 
                                                break;
2348
 
                                        case "open":
2349
 
                                                $comment_status = "open";
2350
 
                                                break;
2351
 
                                        default:
2352
 
                                                $comment_status = get_option("default_comment_status");
2353
 
                                                break;
2354
 
                                }
2355
 
                        } else {
2356
 
                                switch ( (int) $content_struct["mt_allow_comments"] ) {
2357
 
                                        case 0:
2358
 
                                        case 2:
2359
 
                                                $comment_status = "closed";
2360
 
                                                break;
2361
 
                                        case 1:
2362
 
                                                $comment_status = "open";
2363
 
                                                break;
2364
 
                                        default:
2365
 
                                                $comment_status = get_option("default_comment_status");
2366
 
                                                break;
2367
 
                                }
2368
 
                        }
2369
 
                }
2370
 
 
2371
 
                if ( isset($content_struct["mt_allow_pings"]) ) {
2372
 
                        if ( !is_numeric($content_struct["mt_allow_pings"]) ) {
2373
 
                                switch ( $content_struct["mt_allow_pings"] ) {
2374
 
                                        case "closed":
2375
 
                                                $ping_status = "closed";
2376
 
                                                break;
2377
 
                                        case "open":
2378
 
                                                $ping_status = "open";
2379
 
                                                break;
2380
 
                                        default:
2381
 
                                                $ping_status = get_option("default_ping_status");
2382
 
                                                break;
2383
 
                                }
2384
 
                        } else {
2385
 
                                switch ( (int) $content_struct["mt_allow_pings"] ) {
2386
 
                                        case 0:
2387
 
                                                $ping_status = "closed";
2388
 
                                                break;
2389
 
                                        case 1:
2390
 
                                                $ping_status = "open";
2391
 
                                                break;
2392
 
                                        default:
2393
 
                                                $ping_status = get_option("default_ping_status");
2394
 
                                                break;
2395
 
                                }
2396
 
                        }
2397
 
                }
2398
 
 
2399
 
                $post_title = $content_struct['title'];
2400
 
                $post_content = $content_struct['description'];
2401
 
                $catnames = $content_struct['categories'];
2402
 
 
2403
 
                $post_category = array();
2404
 
 
2405
 
                if ( is_array($catnames) ) {
2406
 
                        foreach ($catnames as $cat) {
2407
 
                                $post_category[] = get_cat_ID($cat);
2408
 
                        }
2409
 
                }
2410
 
 
2411
 
                $post_excerpt = $content_struct['mt_excerpt'];
2412
 
                $post_more = $content_struct['mt_text_more'];
2413
 
 
2414
 
                $post_status = $publish ? 'publish' : 'draft';
2415
 
                if ( isset( $content_struct["{$post_type}_status"] ) ) {
2416
 
                        switch( $content_struct["{$post_type}_status"] ) {
2417
 
                                case 'draft':
2418
 
                                case 'private':
2419
 
                                case 'publish':
2420
 
                                        $post_status = $content_struct["{$post_type}_status"];
2421
 
                                        break;
2422
 
                                case 'pending':
2423
 
                                        // Pending is only valid for posts, not pages.
2424
 
                                        if ( $post_type === 'post' )
2425
 
                                                $post_status = $content_struct["{$post_type}_status"];
2426
 
                                        break;
2427
 
                                default:
2428
 
                                        $post_status = $publish ? 'publish' : 'draft';
2429
 
                                        break;
2430
 
                        }
2431
 
                }
2432
 
 
2433
 
                $tags_input = $content_struct['mt_keywords'];
2434
 
 
2435
 
                if ( ('publish' == $post_status) ) {
2436
 
                        if ( ( 'page' == $post_type ) && !current_user_can('publish_pages') )
2437
 
                                return new IXR_Error(401, __('Sorry, you do not have the right to publish this page.'));
2438
 
                        else if ( !current_user_can('publish_posts') )
2439
 
                                return new IXR_Error(401, __('Sorry, you do not have the right to publish this post.'));
2440
 
                }
2441
 
 
2442
 
                if ( $post_more )
2443
 
                        $post_content = $post_content . "<!--more-->" . $post_more;
2444
 
 
2445
 
                $to_ping = $content_struct['mt_tb_ping_urls'];
2446
 
                if ( is_array($to_ping) )
2447
 
                        $to_ping = implode(' ', $to_ping);
2448
 
 
2449
 
                // Do some timestamp voodoo
2450
 
                if ( !empty( $content_struct['date_created_gmt'] ) )
2451
 
                        $dateCreated = str_replace( 'Z', '', $content_struct['date_created_gmt']->getIso() ) . 'Z'; // We know this is supposed to be GMT, so we're going to slap that Z on there by force
2452
 
                elseif ( !empty( $content_struct['dateCreated']) )
2453
 
                        $dateCreated = $content_struct['dateCreated']->getIso();
2454
 
 
2455
 
                if ( !empty( $dateCreated ) ) {
2456
 
                        $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated));
2457
 
                        $post_date_gmt = iso8601_to_datetime($dateCreated, GMT);
2458
 
                } else {
2459
 
                        $post_date     = $postdata['post_date'];
2460
 
                        $post_date_gmt = $postdata['post_date_gmt'];
2461
 
                }
2462
 
 
2463
 
                // We've got all the data -- post it:
2464
 
                $newpost = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'post_date', 'post_date_gmt', 'to_ping', 'post_name', 'post_password', 'post_parent', 'menu_order', 'post_author', 'tags_input', 'page_template');
2465
 
 
2466
 
                $result = wp_update_post($newpost, true);
2467
 
                if ( is_wp_error( $result ) )
2468
 
                        return new IXR_Error(500, $result->get_error_message());
2469
 
 
2470
 
                if ( !$result )
2471
 
                        return new IXR_Error(500, __('Sorry, your entry could not be edited. Something wrong happened.'));
2472
 
 
2473
 
                // Only posts can be sticky
2474
 
                if ( $post_type == 'post' && isset( $content_struct['sticky'] ) ) {
2475
 
                        if ( $content_struct['sticky'] == true )
2476
 
                                stick_post( $post_ID );
2477
 
                        elseif ( $content_struct['sticky'] == false )
2478
 
                                unstick_post( $post_ID );
2479
 
                }
2480
 
 
2481
 
                if ( isset($content_struct['custom_fields']) )
2482
 
                        $this->set_custom_fields($post_ID, $content_struct['custom_fields']);
2483
 
 
2484
 
                // Handle enclosures
2485
 
                $this->add_enclosure_if_new($post_ID, $content_struct['enclosure']);
2486
 
 
2487
 
                $this->attach_uploads( $ID, $post_content );
2488
 
 
2489
 
                logIO('O',"(MW) Edited ! ID: $post_ID");
2490
 
 
2491
 
                return true;
2492
 
        }
2493
 
 
2494
 
        /**
2495
 
         * Retrieve post.
2496
 
         *
2497
 
         * @since 1.5.0
2498
 
         *
2499
 
         * @param array $args Method parameters.
2500
 
         * @return array
2501
 
         */
2502
 
        function mw_getPost($args) {
2503
 
 
2504
 
                $this->escape($args);
2505
 
 
2506
 
                $post_ID     = (int) $args[0];
2507
 
                $username  = $args[1];
2508
 
                $password   = $args[2];
2509
 
 
2510
 
                if ( !$user = $this->login($username, $password) )
2511
 
                        return $this->error;
2512
 
 
2513
 
                if ( !current_user_can( 'edit_post', $post_ID ) )
2514
 
                        return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) );
2515
 
 
2516
 
                do_action('xmlrpc_call', 'metaWeblog.getPost');
2517
 
 
2518
 
                $postdata = wp_get_single_post($post_ID, ARRAY_A);
2519
 
 
2520
 
                if ($postdata['post_date'] != '') {
2521
 
                        $post_date = mysql2date('Ymd\TH:i:s', $postdata['post_date'], false);
2522
 
                        $post_date_gmt = mysql2date('Ymd\TH:i:s', $postdata['post_date_gmt'], false);
2523
 
 
2524
 
                        // For drafts use the GMT version of the post date
2525
 
                        if ( $postdata['post_status'] == 'draft' )
2526
 
                                $post_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $postdata['post_date'] ), 'Ymd\TH:i:s' );
2527
 
 
2528
 
                        $categories = array();
2529
 
                        $catids = wp_get_post_categories($post_ID);
2530
 
                        foreach($catids as $catid)
2531
 
                                $categories[] = get_cat_name($catid);
2532
 
 
2533
 
                        $tagnames = array();
2534
 
                        $tags = wp_get_post_tags( $post_ID );
2535
 
                        if ( !empty( $tags ) ) {
2536
 
                                foreach ( $tags as $tag )
2537
 
                                        $tagnames[] = $tag->name;
2538
 
                                $tagnames = implode( ', ', $tagnames );
2539
 
                        } else {
2540
 
                                $tagnames = '';
2541
 
                        }
2542
 
 
2543
 
                        $post = get_extended($postdata['post_content']);
2544
 
                        $link = post_permalink($postdata['ID']);
2545
 
 
2546
 
                        // Get the author info.
2547
 
                        $author = get_userdata($postdata['post_author']);
2548
 
 
2549
 
                        $allow_comments = ('open' == $postdata['comment_status']) ? 1 : 0;
2550
 
                        $allow_pings = ('open' == $postdata['ping_status']) ? 1 : 0;
2551
 
 
2552
 
                        // Consider future posts as published
2553
 
                        if ( $postdata['post_status'] === 'future' )
2554
 
                                $postdata['post_status'] = 'publish';
2555
 
 
2556
 
                        $sticky = false;
2557
 
                        if ( is_sticky( $post_ID ) )
2558
 
                                $sticky = true;
2559
 
 
2560
 
                        $enclosure = array();
2561
 
                        foreach ( (array) get_post_custom($post_ID) as $key => $val) {
2562
 
                                if ($key == 'enclosure') {
2563
 
                                        foreach ( (array) $val as $enc ) {
2564
 
                                                $encdata = split("\n", $enc);
2565
 
                                                $enclosure['url'] = trim(htmlspecialchars($encdata[0]));
2566
 
                                                $enclosure['length'] = (int) trim($encdata[1]);
2567
 
                                                $enclosure['type'] = trim($encdata[2]);
2568
 
                                                break 2;
2569
 
                                        }
2570
 
                                }
2571
 
                        }
2572
 
 
2573
 
                        $resp = array(
2574
 
                                'dateCreated' => new IXR_Date($post_date),
2575
 
                                'userid' => $postdata['post_author'],
2576
 
                                'postid' => $postdata['ID'],
2577
 
                                'description' => $post['main'],
2578
 
                                'title' => $postdata['post_title'],
2579
 
                                'link' => $link,
2580
 
                                'permaLink' => $link,
2581
 
                                // commented out because no other tool seems to use this
2582
 
                                //            'content' => $entry['post_content'],
2583
 
                                'categories' => $categories,
2584
 
                                'mt_excerpt' => $postdata['post_excerpt'],
2585
 
                                'mt_text_more' => $post['extended'],
2586
 
                                'mt_allow_comments' => $allow_comments,
2587
 
                                'mt_allow_pings' => $allow_pings,
2588
 
                                'mt_keywords' => $tagnames,
2589
 
                                'wp_slug' => $postdata['post_name'],
2590
 
                                'wp_password' => $postdata['post_password'],
2591
 
                                'wp_author_id' => $author->ID,
2592
 
                                'wp_author_display_name'        => $author->display_name,
2593
 
                                'date_created_gmt' => new IXR_Date($post_date_gmt),
2594
 
                                'post_status' => $postdata['post_status'],
2595
 
                                'custom_fields' => $this->get_custom_fields($post_ID),
2596
 
                                'sticky' => $sticky
2597
 
                        );
2598
 
 
2599
 
                        if ( !empty($enclosure) ) $resp['enclosure'] = $enclosure;
2600
 
 
2601
 
                        return $resp;
2602
 
                } else {
2603
 
                        return new IXR_Error(404, __('Sorry, no such post.'));
2604
 
                }
2605
 
        }
2606
 
 
2607
 
        /**
2608
 
         * Retrieve list of recent posts.
2609
 
         *
2610
 
         * @since 1.5.0
2611
 
         *
2612
 
         * @param array $args Method parameters.
2613
 
         * @return array
2614
 
         */
2615
 
        function mw_getRecentPosts($args) {
2616
 
 
2617
 
                $this->escape($args);
2618
 
 
2619
 
                $blog_ID     = (int) $args[0];
2620
 
                $username  = $args[1];
2621
 
                $password   = $args[2];
2622
 
                $num_posts   = (int) $args[3];
2623
 
 
2624
 
                if ( !$user = $this->login($username, $password) )
2625
 
                        return $this->error;
2626
 
 
2627
 
                do_action('xmlrpc_call', 'metaWeblog.getRecentPosts');
2628
 
 
2629
 
                $posts_list = wp_get_recent_posts($num_posts);
2630
 
 
2631
 
                if ( !$posts_list )
2632
 
                        return array( );
2633
 
 
2634
 
                foreach ($posts_list as $entry) {
2635
 
                        if ( !current_user_can( 'edit_post', $entry['ID'] ) )
2636
 
                                continue;
2637
 
 
2638
 
                        $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date'], false);
2639
 
                        $post_date_gmt = mysql2date('Ymd\TH:i:s', $entry['post_date_gmt'], false);
2640
 
 
2641
 
                        // For drafts use the GMT version of the date
2642
 
                        if ( $entry['post_status'] == 'draft' )
2643
 
                                $post_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $entry['post_date'] ), 'Ymd\TH:i:s' );
2644
 
 
2645
 
                        $categories = array();
2646
 
                        $catids = wp_get_post_categories($entry['ID']);
2647
 
                        foreach( $catids as $catid )
2648
 
                                $categories[] = get_cat_name($catid);
2649
 
 
2650
 
                        $tagnames = array();
2651
 
                        $tags = wp_get_post_tags( $entry['ID'] );
2652
 
                        if ( !empty( $tags ) ) {
2653
 
                                foreach ( $tags as $tag ) {
2654
 
                                        $tagnames[] = $tag->name;
2655
 
                                }
2656
 
                                $tagnames = implode( ', ', $tagnames );
2657
 
                        } else {
2658
 
                                $tagnames = '';
2659
 
                        }
2660
 
 
2661
 
                        $post = get_extended($entry['post_content']);
2662
 
                        $link = post_permalink($entry['ID']);
2663
 
 
2664
 
                        // Get the post author info.
2665
 
                        $author = get_userdata($entry['post_author']);
2666
 
 
2667
 
                        $allow_comments = ('open' == $entry['comment_status']) ? 1 : 0;
2668
 
                        $allow_pings = ('open' == $entry['ping_status']) ? 1 : 0;
2669
 
 
2670
 
                        // Consider future posts as published
2671
 
                        if ( $entry['post_status'] === 'future' )
2672
 
                                $entry['post_status'] = 'publish';
2673
 
 
2674
 
                        $struct[] = array(
2675
 
                                'dateCreated' => new IXR_Date($post_date),
2676
 
                                'userid' => $entry['post_author'],
2677
 
                                'postid' => $entry['ID'],
2678
 
                                'description' => $post['main'],
2679
 
                                'title' => $entry['post_title'],
2680
 
                                'link' => $link,
2681
 
                                'permaLink' => $link,
2682
 
                                // commented out because no other tool seems to use this
2683
 
                                // 'content' => $entry['post_content'],
2684
 
                                'categories' => $categories,
2685
 
                                'mt_excerpt' => $entry['post_excerpt'],
2686
 
                                'mt_text_more' => $post['extended'],
2687
 
                                'mt_allow_comments' => $allow_comments,
2688
 
                                'mt_allow_pings' => $allow_pings,
2689
 
                                'mt_keywords' => $tagnames,
2690
 
                                'wp_slug' => $entry['post_name'],
2691
 
                                'wp_password' => $entry['post_password'],
2692
 
                                'wp_author_id' => $author->ID,
2693
 
                                'wp_author_display_name' => $author->display_name,
2694
 
                                'date_created_gmt' => new IXR_Date($post_date_gmt),
2695
 
                                'post_status' => $entry['post_status'],
2696
 
                                'custom_fields' => $this->get_custom_fields($entry['ID'])
2697
 
                        );
2698
 
 
2699
 
                }
2700
 
 
2701
 
                $recent_posts = array();
2702
 
                for ( $j=0; $j<count($struct); $j++ ) {
2703
 
                        array_push($recent_posts, $struct[$j]);
2704
 
                }
2705
 
 
2706
 
                return $recent_posts;
2707
 
        }
2708
 
 
2709
 
        /**
2710
 
         * Retrieve the list of categories on a given blog.
2711
 
         *
2712
 
         * @since 1.5.0
2713
 
         *
2714
 
         * @param array $args Method parameters.
2715
 
         * @return array
2716
 
         */
2717
 
        function mw_getCategories($args) {
2718
 
 
2719
 
                $this->escape($args);
2720
 
 
2721
 
                $blog_ID     = (int) $args[0];
2722
 
                $username  = $args[1];
2723
 
                $password   = $args[2];
2724
 
 
2725
 
                if ( !$user = $this->login($username, $password) )
2726
 
                        return $this->error;
2727
 
 
2728
 
                if ( !current_user_can( 'edit_posts' ) )
2729
 
                        return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this site in order to view categories.' ) );
2730
 
 
2731
 
                do_action('xmlrpc_call', 'metaWeblog.getCategories');
2732
 
 
2733
 
                $categories_struct = array();
2734
 
 
2735
 
                if ( $cats = get_categories(array('get' => 'all')) ) {
2736
 
                        foreach ( $cats as $cat ) {
2737
 
                                $struct['categoryId'] = $cat->term_id;
2738
 
                                $struct['parentId'] = $cat->parent;
2739
 
                                $struct['description'] = $cat->name;
2740
 
                                $struct['categoryDescription'] = $cat->description;
2741
 
                                $struct['categoryName'] = $cat->name;
2742
 
                                $struct['htmlUrl'] = esc_html(get_category_link($cat->term_id));
2743
 
                                $struct['rssUrl'] = esc_html(get_category_feed_link($cat->term_id, 'rss2'));
2744
 
 
2745
 
                                $categories_struct[] = $struct;
2746
 
                        }
2747
 
                }
2748
 
 
2749
 
                return $categories_struct;
2750
 
        }
2751
 
 
2752
 
        /**
2753
 
         * Uploads a file, following your settings.
2754
 
         *
2755
 
         * Adapted from a patch by Johann Richard.
2756
 
         *
2757
 
         * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/
2758
 
         *
2759
 
         * @since 1.5.0
2760
 
         *
2761
 
         * @param array $args Method parameters.
2762
 
         * @return array
2763
 
         */
2764
 
        function mw_newMediaObject($args) {
2765
 
                global $wpdb;
2766
 
 
2767
 
                $blog_ID     = (int) $args[0];
2768
 
                $username  = $wpdb->escape($args[1]);
2769
 
                $password   = $wpdb->escape($args[2]);
2770
 
                $data        = $args[3];
2771
 
 
2772
 
                $name = sanitize_file_name( $data['name'] );
2773
 
                $type = $data['type'];
2774
 
                $bits = $data['bits'];
2775
 
 
2776
 
                logIO('O', '(MW) Received '.strlen($bits).' bytes');
2777
 
 
2778
 
                if ( !$user = $this->login($username, $password) )
2779
 
                        return $this->error;
2780
 
 
2781
 
                do_action('xmlrpc_call', 'metaWeblog.newMediaObject');
2782
 
 
2783
 
                if ( !current_user_can('upload_files') ) {
2784
 
                        logIO('O', '(MW) User does not have upload_files capability');
2785
 
                        $this->error = new IXR_Error(401, __('You are not allowed to upload files to this site.'));
2786
 
                        return $this->error;
2787
 
                }
2788
 
 
2789
 
                if ( $upload_err = apply_filters( "pre_upload_error", false ) )
2790
 
                        return new IXR_Error(500, $upload_err);
2791
 
 
2792
 
                if ( !empty($data["overwrite"]) && ($data["overwrite"] == true) ) {
2793
 
                        // Get postmeta info on the object.
2794
 
                        $old_file = $wpdb->get_row("
2795
 
                                SELECT ID
2796
 
                                FROM {$wpdb->posts}
2797
 
                                WHERE post_title = '{$name}'
2798
 
                                        AND post_type = 'attachment'
2799
 
                        ");
2800
 
 
2801
 
                        // Delete previous file.
2802
 
                        wp_delete_attachment($old_file->ID);
2803
 
 
2804
 
                        // Make sure the new name is different by pre-pending the
2805
 
                        // previous post id.
2806
 
                        $filename = preg_replace("/^wpid\d+-/", "", $name);
2807
 
                        $name = "wpid{$old_file->ID}-{$filename}";
2808
 
                }
2809
 
 
2810
 
                $upload = wp_upload_bits($name, $type, $bits);
2811
 
                if ( ! empty($upload['error']) ) {
2812
 
                        $errorString = sprintf(__('Could not write file %1$s (%2$s)'), $name, $upload['error']);
2813
 
                        logIO('O', '(MW) ' . $errorString);
2814
 
                        return new IXR_Error(500, $errorString);
2815
 
                }
2816
 
                // Construct the attachment array
2817
 
                // attach to post_id 0
2818
 
                $post_id = 0;
2819
 
                $attachment = array(
2820
 
                        'post_title' => $name,
2821
 
                        'post_content' => '',
2822
 
                        'post_type' => 'attachment',
2823
 
                        'post_parent' => $post_id,
2824
 
                        'post_mime_type' => $type,
2825
 
                        'guid' => $upload[ 'url' ]
2826
 
                );
2827
 
 
2828
 
                // Save the data
2829
 
                $id = wp_insert_attachment( $attachment, $upload[ 'file' ], $post_id );
2830
 
                wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) );
2831
 
 
2832
 
                return apply_filters( 'wp_handle_upload', array( 'file' => $name, 'url' => $upload[ 'url' ], 'type' => $type ), 'upload' );
2833
 
        }
2834
 
 
2835
 
        /* MovableType API functions
2836
 
         * specs on http://www.movabletype.org/docs/mtmanual_programmatic.html
2837
 
         */
2838
 
 
2839
 
        /**
2840
 
         * Retrieve the post titles of recent posts.
2841
 
         *
2842
 
         * @since 1.5.0
2843
 
         *
2844
 
         * @param array $args Method parameters.
2845
 
         * @return array
2846
 
         */
2847
 
        function mt_getRecentPostTitles($args) {
2848
 
 
2849
 
                $this->escape($args);
2850
 
 
2851
 
                $blog_ID     = (int) $args[0];
2852
 
                $username  = $args[1];
2853
 
                $password   = $args[2];
2854
 
                $num_posts   = (int) $args[3];
2855
 
 
2856
 
                if ( !$user = $this->login($username, $password) )
2857
 
                        return $this->error;
2858
 
 
2859
 
                do_action('xmlrpc_call', 'mt.getRecentPostTitles');
2860
 
 
2861
 
                $posts_list = wp_get_recent_posts($num_posts);
2862
 
 
2863
 
                if ( !$posts_list ) {
2864
 
                        $this->error = new IXR_Error(500, __('Either there are no posts, or something went wrong.'));
2865
 
                        return $this->error;
2866
 
                }
2867
 
 
2868
 
                foreach ($posts_list as $entry) {
2869
 
                        if ( !current_user_can( 'edit_post', $entry['ID'] ) )
2870
 
                                continue;
2871
 
 
2872
 
                        $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date'], false);
2873
 
                        $post_date_gmt = mysql2date('Ymd\TH:i:s', $entry['post_date_gmt'], false);
2874
 
 
2875
 
                        // For drafts use the GMT version of the date
2876
 
                        if ( $entry['post_status'] == 'draft' )
2877
 
                                $post_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $entry['post_date'] ), 'Ymd\TH:i:s' );
2878
 
 
2879
 
                        $struct[] = array(
2880
 
                                'dateCreated' => new IXR_Date($post_date),
2881
 
                                'userid' => $entry['post_author'],
2882
 
                                'postid' => $entry['ID'],
2883
 
                                'title' => $entry['post_title'],
2884
 
                                'date_created_gmt' => new IXR_Date($post_date_gmt)
2885
 
                        );
2886
 
 
2887
 
                }
2888
 
 
2889
 
                $recent_posts = array();
2890
 
                for ( $j=0; $j<count($struct); $j++ ) {
2891
 
                        array_push($recent_posts, $struct[$j]);
2892
 
                }
2893
 
 
2894
 
                return $recent_posts;
2895
 
        }
2896
 
 
2897
 
        /**
2898
 
         * Retrieve list of all categories on blog.
2899
 
         *
2900
 
         * @since 1.5.0
2901
 
         *
2902
 
         * @param array $args Method parameters.
2903
 
         * @return array
2904
 
         */
2905
 
        function mt_getCategoryList($args) {
2906
 
 
2907
 
                $this->escape($args);
2908
 
 
2909
 
                $blog_ID     = (int) $args[0];
2910
 
                $username  = $args[1];
2911
 
                $password   = $args[2];
2912
 
 
2913
 
                if ( !$user = $this->login($username, $password) )
2914
 
                        return $this->error;
2915
 
 
2916
 
                if ( !current_user_can( 'edit_posts' ) )
2917
 
                        return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this site in order to view categories.' ) );
2918
 
 
2919
 
                do_action('xmlrpc_call', 'mt.getCategoryList');
2920
 
 
2921
 
                $categories_struct = array();
2922
 
 
2923
 
                if ( $cats = get_categories(array('hide_empty' => 0, 'hierarchical' => 0)) ) {
2924
 
                        foreach ( $cats as $cat ) {
2925
 
                                $struct['categoryId'] = $cat->term_id;
2926
 
                                $struct['categoryName'] = $cat->name;
2927
 
 
2928
 
                                $categories_struct[] = $struct;
2929
 
                        }
2930
 
                }
2931
 
 
2932
 
                return $categories_struct;
2933
 
        }
2934
 
 
2935
 
        /**
2936
 
         * Retrieve post categories.
2937
 
         *
2938
 
         * @since 1.5.0
2939
 
         *
2940
 
         * @param array $args Method parameters.
2941
 
         * @return array
2942
 
         */
2943
 
        function mt_getPostCategories($args) {
2944
 
 
2945
 
                $this->escape($args);
2946
 
 
2947
 
                $post_ID     = (int) $args[0];
2948
 
                $username  = $args[1];
2949
 
                $password   = $args[2];
2950
 
 
2951
 
                if ( !$user = $this->login($username, $password) )
2952
 
                        return $this->error;
2953
 
 
2954
 
                if ( !current_user_can( 'edit_post', $post_ID ) )
2955
 
                        return new IXR_Error( 401, __( 'Sorry, you can not edit this post.' ) );
2956
 
 
2957
 
                do_action('xmlrpc_call', 'mt.getPostCategories');
2958
 
 
2959
 
                $categories = array();
2960
 
                $catids = wp_get_post_categories(intval($post_ID));
2961
 
                // first listed category will be the primary category
2962
 
                $isPrimary = true;
2963
 
                foreach ( $catids as $catid ) {
2964
 
                        $categories[] = array(
2965
 
                                'categoryName' => get_cat_name($catid),
2966
 
                                'categoryId' => (string) $catid,
2967
 
                                'isPrimary' => $isPrimary
2968
 
                        );
2969
 
                        $isPrimary = false;
2970
 
                }
2971
 
 
2972
 
                return $categories;
2973
 
        }
2974
 
 
2975
 
        /**
2976
 
         * Sets categories for a post.
2977
 
         *
2978
 
         * @since 1.5.0
2979
 
         *
2980
 
         * @param array $args Method parameters.
2981
 
         * @return bool True on success.
2982
 
         */
2983
 
        function mt_setPostCategories($args) {
2984
 
 
2985
 
                $this->escape($args);
2986
 
 
2987
 
                $post_ID     = (int) $args[0];
2988
 
                $username  = $args[1];
2989
 
                $password   = $args[2];
2990
 
                $categories  = $args[3];
2991
 
 
2992
 
                if ( !$user = $this->login($username, $password) )
2993
 
                        return $this->error;
2994
 
 
2995
 
                do_action('xmlrpc_call', 'mt.setPostCategories');
2996
 
 
2997
 
                if ( !current_user_can('edit_post', $post_ID) )
2998
 
                        return new IXR_Error(401, __('Sorry, you cannot edit this post.'));
2999
 
 
3000
 
                foreach ( $categories as $cat ) {
3001
 
                        $catids[] = $cat['categoryId'];
3002
 
                }
3003
 
 
3004
 
                wp_set_post_categories($post_ID, $catids);
3005
 
 
3006
 
                return true;
3007
 
        }
3008
 
 
3009
 
        /**
3010
 
         * Retrieve an array of methods supported by this server.
3011
 
         *
3012
 
         * @since 1.5.0
3013
 
         *
3014
 
         * @param array $args Method parameters.
3015
 
         * @return array
3016
 
         */
3017
 
        function mt_supportedMethods($args) {
3018
 
 
3019
 
                do_action('xmlrpc_call', 'mt.supportedMethods');
3020
 
 
3021
 
                $supported_methods = array();
3022
 
                foreach ( $this->methods as $key => $value ) {
3023
 
                        $supported_methods[] = $key;
3024
 
                }
3025
 
 
3026
 
                return $supported_methods;
3027
 
        }
3028
 
 
3029
 
        /**
3030
 
         * Retrieve an empty array because we don't support per-post text filters.
3031
 
         *
3032
 
         * @since 1.5.0
3033
 
         *
3034
 
         * @param array $args Method parameters.
3035
 
         */
3036
 
        function mt_supportedTextFilters($args) {
3037
 
                do_action('xmlrpc_call', 'mt.supportedTextFilters');
3038
 
                return apply_filters('xmlrpc_text_filters', array());
3039
 
        }
3040
 
 
3041
 
        /**
3042
 
         * Retrieve trackbacks sent to a given post.
3043
 
         *
3044
 
         * @since 1.5.0
3045
 
         *
3046
 
         * @param array $args Method parameters.
3047
 
         * @return mixed
3048
 
         */
3049
 
        function mt_getTrackbackPings($args) {
3050
 
 
3051
 
                global $wpdb;
3052
 
 
3053
 
                $post_ID = intval($args);
3054
 
 
3055
 
                do_action('xmlrpc_call', 'mt.getTrackbackPings');
3056
 
 
3057
 
                $actual_post = wp_get_single_post($post_ID, ARRAY_A);
3058
 
 
3059
 
                if ( !$actual_post )
3060
 
                        return new IXR_Error(404, __('Sorry, no such post.'));
3061
 
 
3062
 
                $comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID) );
3063
 
 
3064
 
                if ( !$comments )
3065
 
                        return array();
3066
 
 
3067
 
                $trackback_pings = array();
3068
 
                foreach ( $comments as $comment ) {
3069
 
                        if ( 'trackback' == $comment->comment_type ) {
3070
 
                                $content = $comment->comment_content;
3071
 
                                $title = substr($content, 8, (strpos($content, '</strong>') - 8));
3072
 
                                $trackback_pings[] = array(
3073
 
                                        'pingTitle' => $title,
3074
 
                                        'pingURL'   => $comment->comment_author_url,
3075
 
                                        'pingIP'    => $comment->comment_author_IP
3076
 
                                );
3077
 
                        }
3078
 
                }
3079
 
 
3080
 
                return $trackback_pings;
3081
 
        }
3082
 
 
3083
 
        /**
3084
 
         * Sets a post's publish status to 'publish'.
3085
 
         *
3086
 
         * @since 1.5.0
3087
 
         *
3088
 
         * @param array $args Method parameters.
3089
 
         * @return int
3090
 
         */
3091
 
        function mt_publishPost($args) {
3092
 
 
3093
 
                $this->escape($args);
3094
 
 
3095
 
                $post_ID     = (int) $args[0];
3096
 
                $username  = $args[1];
3097
 
                $password   = $args[2];
3098
 
 
3099
 
                if ( !$user = $this->login($username, $password) )
3100
 
                        return $this->error;
3101
 
 
3102
 
                do_action('xmlrpc_call', 'mt.publishPost');
3103
 
 
3104
 
                if ( !current_user_can('edit_post', $post_ID) )
3105
 
                        return new IXR_Error(401, __('Sorry, you cannot edit this post.'));
3106
 
 
3107
 
                $postdata = wp_get_single_post($post_ID,ARRAY_A);
3108
 
 
3109
 
                $postdata['post_status'] = 'publish';
3110
 
 
3111
 
                // retain old cats
3112
 
                $cats = wp_get_post_categories($post_ID);
3113
 
                $postdata['post_category'] = $cats;
3114
 
                $this->escape($postdata);
3115
 
 
3116
 
                $result = wp_update_post($postdata);
3117
 
 
3118
 
                return $result;
3119
 
        }
3120
 
 
3121
 
        /* PingBack functions
3122
 
         * specs on www.hixie.ch/specs/pingback/pingback
3123
 
         */
3124
 
 
3125
 
        /**
3126
 
         * Retrieves a pingback and registers it.
3127
 
         *
3128
 
         * @since 1.5.0
3129
 
         *
3130
 
         * @param array $args Method parameters.
3131
 
         * @return array
3132
 
         */
3133
 
        function pingback_ping($args) {
3134
 
                global $wpdb;
3135
 
 
3136
 
                do_action('xmlrpc_call', 'pingback.ping');
3137
 
 
3138
 
                $this->escape($args);
3139
 
 
3140
 
                $pagelinkedfrom = $args[0];
3141
 
                $pagelinkedto   = $args[1];
3142
 
 
3143
 
                $title = '';
3144
 
 
3145
 
                $pagelinkedfrom = str_replace('&amp;', '&', $pagelinkedfrom);
3146
 
                $pagelinkedto = str_replace('&amp;', '&', $pagelinkedto);
3147
 
                $pagelinkedto = str_replace('&', '&amp;', $pagelinkedto);
3148
 
 
3149
 
                // Check if the page linked to is in our site
3150
 
                $pos1 = strpos($pagelinkedto, str_replace(array('http://www.','http://','https://www.','https://'), '', get_option('home')));
3151
 
                if ( !$pos1 )
3152
 
                        return new IXR_Error(0, __('Is there no link to us?'));
3153
 
 
3154
 
                // let's find which post is linked to
3155
 
                // FIXME: does url_to_postid() cover all these cases already?
3156
 
                //        if so, then let's use it and drop the old code.
3157
 
                $urltest = parse_url($pagelinkedto);
3158
 
                if ( $post_ID = url_to_postid($pagelinkedto) ) {
3159
 
                        $way = 'url_to_postid()';
3160
 
                } elseif ( preg_match('#p/[0-9]{1,}#', $urltest['path'], $match) ) {
3161
 
                        // the path defines the post_ID (archives/p/XXXX)
3162
 
                        $blah = explode('/', $match[0]);
3163
 
                        $post_ID = (int) $blah[1];
3164
 
                        $way = 'from the path';
3165
 
                } elseif ( preg_match('#p=[0-9]{1,}#', $urltest['query'], $match) ) {
3166
 
                        // the querystring defines the post_ID (?p=XXXX)
3167
 
                        $blah = explode('=', $match[0]);
3168
 
                        $post_ID = (int) $blah[1];
3169
 
                        $way = 'from the querystring';
3170
 
                } elseif ( isset($urltest['fragment']) ) {
3171
 
                        // an #anchor is there, it's either...
3172
 
                        if ( intval($urltest['fragment']) ) {
3173
 
                                // ...an integer #XXXX (simpliest case)
3174
 
                                $post_ID = (int) $urltest['fragment'];
3175
 
                                $way = 'from the fragment (numeric)';
3176
 
                        } elseif ( preg_match('/post-[0-9]+/',$urltest['fragment']) ) {
3177
 
                                // ...a post id in the form 'post-###'
3178
 
                                $post_ID = preg_replace('/[^0-9]+/', '', $urltest['fragment']);
3179
 
                                $way = 'from the fragment (post-###)';
3180
 
                        } elseif ( is_string($urltest['fragment']) ) {
3181
 
                                // ...or a string #title, a little more complicated
3182
 
                                $title = preg_replace('/[^a-z0-9]/i', '.', $urltest['fragment']);
3183
 
                                $sql = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_title RLIKE %s", $title);
3184
 
                                if (! ($post_ID = $wpdb->get_var($sql)) ) {
3185
 
                                        // returning unknown error '0' is better than die()ing
3186
 
                                        return new IXR_Error(0, '');
3187
 
                                }
3188
 
                                $way = 'from the fragment (title)';
3189
 
                        }
3190
 
                } else {
3191
 
                        // TODO: Attempt to extract a post ID from the given URL
3192
 
                        return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn&#8217;t exist, or it is not a pingback-enabled resource.'));
3193
 
                }
3194
 
                $post_ID = (int) $post_ID;
3195
 
 
3196
 
 
3197
 
                logIO("O","(PB) URL='$pagelinkedto' ID='$post_ID' Found='$way'");
3198
 
 
3199
 
                $post = get_post($post_ID);
3200
 
 
3201
 
                if ( !$post ) // Post_ID not found
3202
 
                        return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn&#8217;t exist, or it is not a pingback-enabled resource.'));
3203
 
 
3204
 
                if ( $post_ID == url_to_postid($pagelinkedfrom) )
3205
 
                        return new IXR_Error(0, __('The source URL and the target URL cannot both point to the same resource.'));
3206
 
 
3207
 
                // Check if pings are on
3208
 
                if ( !pings_open($post) )
3209
 
                        return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn&#8217;t exist, or it is not a pingback-enabled resource.'));
3210
 
 
3211
 
                // Let's check that the remote site didn't already pingback this entry
3212
 
                if ( $wpdb->get_results( $wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_author_url = %s", $post_ID, $pagelinkedfrom) ) )
3213
 
                        return new IXR_Error( 48, __( 'The pingback has already been registered.' ) );
3214
 
 
3215
 
                // very stupid, but gives time to the 'from' server to publish !
3216
 
                sleep(1);
3217
 
 
3218
 
                // Let's check the remote site
3219
 
                $linea = wp_remote_fopen( $pagelinkedfrom );
3220
 
                if ( !$linea )
3221
 
                        return new IXR_Error(16, __('The source URL does not exist.'));
3222
 
 
3223
 
                $linea = apply_filters('pre_remote_source', $linea, $pagelinkedto);
3224
 
 
3225
 
                // Work around bug in strip_tags():
3226
 
                $linea = str_replace('<!DOC', '<DOC', $linea);
3227
 
                $linea = preg_replace( '/[\s\r\n\t]+/', ' ', $linea ); // normalize spaces
3228
 
                $linea = preg_replace( "/ <(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/", "\n\n", $linea );
3229
 
 
3230
 
                preg_match('|<title>([^<]*?)</title>|is', $linea, $matchtitle);
3231
 
                $title = $matchtitle[1];
3232
 
                if ( empty( $title ) )
3233
 
                        return new IXR_Error(32, __('We cannot find a title on that page.'));
3234
 
 
3235
 
                $linea = strip_tags( $linea, '<a>' ); // just keep the tag we need
3236
 
 
3237
 
                $p = explode( "\n\n", $linea );
3238
 
 
3239
 
                $preg_target = preg_quote($pagelinkedto, '|');
3240
 
 
3241
 
                foreach ( $p as $para ) {
3242
 
                        if ( strpos($para, $pagelinkedto) !== false ) { // it exists, but is it a link?
3243
 
                                preg_match("|<a[^>]+?".$preg_target."[^>]*>([^>]+?)</a>|", $para, $context);
3244
 
 
3245
 
                                // If the URL isn't in a link context, keep looking
3246
 
                                if ( empty($context) )
3247
 
                                        continue;
3248
 
 
3249
 
                                // We're going to use this fake tag to mark the context in a bit
3250
 
                                // the marker is needed in case the link text appears more than once in the paragraph
3251
 
                                $excerpt = preg_replace('|\</?wpcontext\>|', '', $para);
3252
 
 
3253
 
                                // prevent really long link text
3254
 
                                if ( strlen($context[1]) > 100 )
3255
 
                                        $context[1] = substr($context[1], 0, 100) . '...';
3256
 
 
3257
 
                                $marker = '<wpcontext>'.$context[1].'</wpcontext>';    // set up our marker
3258
 
                                $excerpt= str_replace($context[0], $marker, $excerpt); // swap out the link for our marker
3259
 
                                $excerpt = strip_tags($excerpt, '<wpcontext>');        // strip all tags but our context marker
3260
 
                                $excerpt = trim($excerpt);
3261
 
                                $preg_marker = preg_quote($marker, '|');
3262
 
                                $excerpt = preg_replace("|.*?\s(.{0,100}$preg_marker.{0,100})\s.*|s", '$1', $excerpt);
3263
 
                                $excerpt = strip_tags($excerpt); // YES, again, to remove the marker wrapper
3264
 
                                break;
3265
 
                        }
3266
 
                }
3267
 
 
3268
 
                if ( empty($context) ) // Link to target not found
3269
 
                        return new IXR_Error(17, __('The source URL does not contain a link to the target URL, and so cannot be used as a source.'));
3270
 
 
3271
 
                $pagelinkedfrom = str_replace('&', '&amp;', $pagelinkedfrom);
3272
 
 
3273
 
                $context = '[...] ' . esc_html( $excerpt ) . ' [...]';
3274
 
                $pagelinkedfrom = $wpdb->escape( $pagelinkedfrom );
3275
 
 
3276
 
                $comment_post_ID = (int) $post_ID;
3277
 
                $comment_author = $title;
3278
 
                $this->escape($comment_author);
3279
 
                $comment_author_url = $pagelinkedfrom;
3280
 
                $comment_content = $context;
3281
 
                $this->escape($comment_content);
3282
 
                $comment_type = 'pingback';
3283
 
 
3284
 
                $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_url', 'comment_content', 'comment_type');
3285
 
 
3286
 
                $comment_ID = wp_new_comment($commentdata);
3287
 
                do_action('pingback_post', $comment_ID);
3288
 
 
3289
 
                return sprintf(__('Pingback from %1$s to %2$s registered. Keep the web talking! :-)'), $pagelinkedfrom, $pagelinkedto);
3290
 
        }
3291
 
 
3292
 
        /**
3293
 
         * Retrieve array of URLs that pingbacked the given URL.
3294
 
         *
3295
 
         * Specs on http://www.aquarionics.com/misc/archives/blogite/0198.html
3296
 
         *
3297
 
         * @since 1.5.0
3298
 
         *
3299
 
         * @param array $args Method parameters.
3300
 
         * @return array
3301
 
         */
3302
 
        function pingback_extensions_getPingbacks($args) {
3303
 
 
3304
 
                global $wpdb;
3305
 
 
3306
 
                do_action('xmlrpc_call', 'pingback.extensions.getPingbacks');
3307
 
 
3308
 
                $this->escape($args);
3309
 
 
3310
 
                $url = $args;
3311
 
 
3312
 
                $post_ID = url_to_postid($url);
3313
 
                if ( !$post_ID ) {
3314
 
                        // We aren't sure that the resource is available and/or pingback enabled
3315
 
                        return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn&#8217;t exist, or it is not a pingback-enabled resource.'));
3316
 
                }
3317
 
 
3318
 
                $actual_post = wp_get_single_post($post_ID, ARRAY_A);
3319
 
 
3320
 
                if ( !$actual_post ) {
3321
 
                        // No such post = resource not found
3322
 
                        return new IXR_Error(32, __('The specified target URL does not exist.'));
3323
 
                }
3324
 
 
3325
 
                $comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID) );
3326
 
 
3327
 
                if ( !$comments )
3328
 
                        return array();
3329
 
 
3330
 
                $pingbacks = array();
3331
 
                foreach ( $comments as $comment ) {
3332
 
                        if ( 'pingback' == $comment->comment_type )
3333
 
                                $pingbacks[] = $comment->comment_author_url;
3334
 
                }
3335
 
 
3336
 
                return $pingbacks;
3337
 
        }
3338
 
}
3339
 
 
3340
 
$wp_xmlrpc_server = new wp_xmlrpc_server();
 
101
// Allow for a plugin to insert a different class to handle requests.
 
102
$wp_xmlrpc_server_class = apply_filters('wp_xmlrpc_server_class', 'wp_xmlrpc_server');
 
103
$wp_xmlrpc_server = new $wp_xmlrpc_server_class;
 
104
 
 
105
// Fire off the request
3341
106
$wp_xmlrpc_server->serve_request();
3342
 
?>
 
107
?>
 
 
b'\\ No newline at end of file'