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