| [ Index ] |
|
Code source de WordPress 2.1.2 |
1 <?php 2 3 define('XMLRPC_REQUEST', true); 4 5 // Some browser-embedded clients send cookies. We don't want them. 6 $_COOKIE = array(); 7 8 # fix for mozBlog and other cases where '<?xml' isn't on the very first line 9 if ( isset($HTTP_RAW_POST_DATA) ) 10 $HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA); 11 12 include('./wp-config.php'); 13 14 if ( isset( $_GET['rsd'] ) ) { // http://archipelago.phrasewise.com/rsd 15 header('Content-type: text/xml; charset=' . get_option('blog_charset'), true); 16 17 ?> 18 <?php echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; ?> 19 <rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd"> 20 <service> 21 <engineName>WordPress</engineName> 22 <engineLink>http://wordpress.org/</engineLink> 23 <homePageLink><?php bloginfo_rss('url') ?></homePageLink> 24 <apis> 25 <api name="Movable Type" blogID="1" preferred="true" apiLink="<?php bloginfo_rss('url') ?>/xmlrpc.php" /> 26 <api name="MetaWeblog" blogID="1" preferred="false" apiLink="<?php bloginfo_rss('url') ?>/xmlrpc.php" /> 27 <api name="Blogger" blogID="1" preferred="false" apiLink="<?php bloginfo_rss('url') ?>/xmlrpc.php" /> 28 </apis> 29 </service> 30 </rsd> 31 <?php 32 exit; 33 } 34 35 include_once (ABSPATH . 'wp-admin/admin-functions.php'); 36 include_once (ABSPATH . WPINC . '/class-IXR.php'); 37 38 // Turn off all warnings and errors. 39 // error_reporting(0); 40 41 $post_default_title = ""; // posts submitted via the xmlrpc interface get that title 42 43 $xmlrpc_logging = 0; 44 45 function logIO($io,$msg) { 46 global $xmlrpc_logging; 47 if ($xmlrpc_logging) { 48 $fp = fopen("../xmlrpc.log","a+"); 49 $date = gmdate("Y-m-d H:i:s "); 50 $iot = ($io == "I") ? " Input: " : " Output: "; 51 fwrite($fp, "\n\n".$date.$iot.$msg); 52 fclose($fp); 53 } 54 return true; 55 } 56 57 function starify($string) { 58 $i = strlen($string); 59 return str_repeat('*', $i); 60 } 61 62 if ( isset($HTTP_RAW_POST_DATA) ) 63 logIO("I", $HTTP_RAW_POST_DATA); 64 65 66 class wp_xmlrpc_server extends IXR_Server { 67 68 function wp_xmlrpc_server() { 69 $this->methods = array( 70 // Blogger API 71 'blogger.getUsersBlogs' => 'this:blogger_getUsersBlogs', 72 'blogger.getUserInfo' => 'this:blogger_getUserInfo', 73 'blogger.getPost' => 'this:blogger_getPost', 74 'blogger.getRecentPosts' => 'this:blogger_getRecentPosts', 75 'blogger.getTemplate' => 'this:blogger_getTemplate', 76 'blogger.setTemplate' => 'this:blogger_setTemplate', 77 'blogger.newPost' => 'this:blogger_newPost', 78 'blogger.editPost' => 'this:blogger_editPost', 79 'blogger.deletePost' => 'this:blogger_deletePost', 80 81 // MetaWeblog API (with MT extensions to structs) 82 'metaWeblog.newPost' => 'this:mw_newPost', 83 'metaWeblog.editPost' => 'this:mw_editPost', 84 'metaWeblog.getPost' => 'this:mw_getPost', 85 'metaWeblog.getRecentPosts' => 'this:mw_getRecentPosts', 86 'metaWeblog.getCategories' => 'this:mw_getCategories', 87 'metaWeblog.newMediaObject' => 'this:mw_newMediaObject', 88 89 // MetaWeblog API aliases for Blogger API 90 // see http://www.xmlrpc.com/stories/storyReader$2460 91 'metaWeblog.deletePost' => 'this:blogger_deletePost', 92 'metaWeblog.getTemplate' => 'this:blogger_getTemplate', 93 'metaWeblog.setTemplate' => 'this:blogger_setTemplate', 94 'metaWeblog.getUsersBlogs' => 'this:blogger_getUsersBlogs', 95 96 // MovableType API 97 'mt.getCategoryList' => 'this:mt_getCategoryList', 98 'mt.getRecentPostTitles' => 'this:mt_getRecentPostTitles', 99 'mt.getPostCategories' => 'this:mt_getPostCategories', 100 'mt.setPostCategories' => 'this:mt_setPostCategories', 101 'mt.supportedMethods' => 'this:mt_supportedMethods', 102 'mt.supportedTextFilters' => 'this:mt_supportedTextFilters', 103 'mt.getTrackbackPings' => 'this:mt_getTrackbackPings', 104 'mt.publishPost' => 'this:mt_publishPost', 105 106 // PingBack 107 'pingback.ping' => 'this:pingback_ping', 108 'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks', 109 110 'demo.sayHello' => 'this:sayHello', 111 'demo.addTwoNumbers' => 'this:addTwoNumbers' 112 ); 113 $this->methods = apply_filters('xmlrpc_methods', $this->methods); 114 $this->IXR_Server($this->methods); 115 } 116 117 function sayHello($args) { 118 return 'Hello!'; 119 } 120 121 function addTwoNumbers($args) { 122 $number1 = $args[0]; 123 $number2 = $args[1]; 124 return $number1 + $number2; 125 } 126 127 function login_pass_ok($user_login, $user_pass) { 128 if (!user_pass_ok($user_login, $user_pass)) { 129 $this->error = new IXR_Error(403, 'Bad login/pass combination.'); 130 return false; 131 } 132 return true; 133 } 134 135 function escape(&$array) { 136 global $wpdb; 137 138 foreach ( (array) $array as $k => $v ) { 139 if (is_array($v)) { 140 $this->escape($array[$k]); 141 } else if (is_object($v)) { 142 //skip 143 } else { 144 $array[$k] = $wpdb->escape($v); 145 } 146 } 147 } 148 149 /* Blogger API functions 150 * specs on http://plant.blogger.com/api and http://groups.yahoo.com/group/bloggerDev/ 151 */ 152 153 154 /* blogger.getUsersBlogs will make more sense once we support multiple blogs */ 155 function blogger_getUsersBlogs($args) { 156 157 $this->escape($args); 158 159 $user_login = $args[1]; 160 $user_pass = $args[2]; 161 162 if (!$this->login_pass_ok($user_login, $user_pass)) { 163 return $this->error; 164 } 165 166 set_current_user(0, $user_login); 167 $is_admin = current_user_can('level_8'); 168 169 $struct = array( 170 'isAdmin' => $is_admin, 171 'url' => get_option('home') . '/', 172 'blogid' => '1', 173 'blogName' => get_option('blogname') 174 ); 175 176 return array($struct); 177 } 178 179 180 /* blogger.getUsersInfo gives your client some info about you, so you don't have to */ 181 function blogger_getUserInfo($args) { 182 183 $this->escape($args); 184 185 $user_login = $args[1]; 186 $user_pass = $args[2]; 187 188 if (!$this->login_pass_ok($user_login, $user_pass)) { 189 return $this->error; 190 } 191 192 $user_data = get_userdatabylogin($user_login); 193 194 $struct = array( 195 'nickname' => $user_data->nickname, 196 'userid' => $user_data->ID, 197 'url' => $user_data->user_url, 198 'email' => $user_data->user_email, 199 'lastname' => $user_data->last_name, 200 'firstname' => $user_data->first_name 201 ); 202 203 return $struct; 204 } 205 206 207 /* blogger.getPost ...gets a post */ 208 function blogger_getPost($args) { 209 210 $this->escape($args); 211 212 $post_ID = $args[1]; 213 $user_login = $args[2]; 214 $user_pass = $args[3]; 215 216 if (!$this->login_pass_ok($user_login, $user_pass)) { 217 return $this->error; 218 } 219 220 $user_data = get_userdatabylogin($user_login); 221 $post_data = wp_get_single_post($post_ID, ARRAY_A); 222 223 $categories = implode(',', wp_get_post_categories($post_ID)); 224 225 $content = '<title>'.stripslashes($post_data['post_title']).'</title>'; 226 $content .= '<category>'.$categories.'</category>'; 227 $content .= stripslashes($post_data['post_content']); 228 229 $struct = array( 230 'userid' => $post_data['post_author'], 231 'dateCreated' => new IXR_Date(mysql2date('Ymd\TH:i:s', $post_data['post_date'])), 232 'content' => $content, 233 'postid' => $post_data['ID'] 234 ); 235 236 return $struct; 237 } 238 239 240 /* blogger.getRecentPosts ...gets recent posts */ 241 function blogger_getRecentPosts($args) { 242 243 global $wpdb; 244 245 $this->escape($args); 246 247 $blog_ID = $args[1]; /* though we don't use it yet */ 248 $user_login = $args[2]; 249 $user_pass = $args[3]; 250 $num_posts = $args[4]; 251 252 if (!$this->login_pass_ok($user_login, $user_pass)) { 253 return $this->error; 254 } 255 256 $posts_list = wp_get_recent_posts($num_posts); 257 258 if (!$posts_list) { 259 $this->error = new IXR_Error(500, 'Either there are no posts, or something went wrong.'); 260 return $this->error; 261 } 262 263 foreach ($posts_list as $entry) { 264 265 $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']); 266 $categories = implode(',', wp_get_post_categories($entry['ID'])); 267 268 $content = '<title>'.stripslashes($entry['post_title']).'</title>'; 269 $content .= '<category>'.$categories.'</category>'; 270 $content .= stripslashes($entry['post_content']); 271 272 $struct[] = array( 273 'userid' => $entry['post_author'], 274 'dateCreated' => new IXR_Date($post_date), 275 'content' => $content, 276 'postid' => $entry['ID'], 277 ); 278 279 } 280 281 $recent_posts = array(); 282 for ($j=0; $j<count($struct); $j++) { 283 array_push($recent_posts, $struct[$j]); 284 } 285 286 return $recent_posts; 287 } 288 289 290 /* blogger.getTemplate returns your blog_filename */ 291 function blogger_getTemplate($args) { 292 293 $this->escape($args); 294 295 $blog_ID = $args[1]; 296 $user_login = $args[2]; 297 $user_pass = $args[3]; 298 $template = $args[4]; /* could be 'main' or 'archiveIndex', but we don't use it */ 299 300 if (!$this->login_pass_ok($user_login, $user_pass)) { 301 return $this->error; 302 } 303 304 set_current_user(0, $user_login); 305 if ( !current_user_can('edit_themes') ) { 306 return new IXR_Error(401, 'Sorry, this user can not edit the template.'); 307 } 308 309 /* warning: here we make the assumption that the weblog's URL is on the same server */ 310 $filename = get_option('home') . '/'; 311 $filename = preg_replace('#https?://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename); 312 313 $f = fopen($filename, 'r'); 314 $content = fread($f, filesize($filename)); 315 fclose($f); 316 317 /* so it is actually editable with a windows/mac client */ 318 // 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); 319 320 return $content; 321 } 322 323 324 /* blogger.setTemplate updates the content of blog_filename */ 325 function blogger_setTemplate($args) { 326 327 $this->escape($args); 328 329 $blog_ID = $args[1]; 330 $user_login = $args[2]; 331 $user_pass = $args[3]; 332 $content = $args[4]; 333 $template = $args[5]; /* could be 'main' or 'archiveIndex', but we don't use it */ 334 335 if (!$this->login_pass_ok($user_login, $user_pass)) { 336 return $this->error; 337 } 338 339 set_current_user(0, $user_login); 340 if ( !current_user_can('edit_themes') ) { 341 return new IXR_Error(401, 'Sorry, this user can not edit the template.'); 342 } 343 344 /* warning: here we make the assumption that the weblog's URL is on the same server */ 345 $filename = get_option('home') . '/'; 346 $filename = preg_replace('#https?://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename); 347 348 if ($f = fopen($filename, 'w+')) { 349 fwrite($f, $content); 350 fclose($f); 351 } else { 352 return new IXR_Error(500, 'Either the file is not writable, or something wrong happened. The file has not been updated.'); 353 } 354 355 return true; 356 } 357 358 359 /* blogger.newPost ...creates a new post */ 360 function blogger_newPost($args) { 361 362 global $wpdb; 363 364 $this->escape($args); 365 366 $blog_ID = $args[1]; /* though we don't use it yet */ 367 $user_login = $args[2]; 368 $user_pass = $args[3]; 369 $content = $args[4]; 370 $publish = $args[5]; 371 372 if (!$this->login_pass_ok($user_login, $user_pass)) { 373 return $this->error; 374 } 375 376 $cap = ($publish) ? 'publish_posts' : 'edit_posts'; 377 $user = set_current_user(0, $user_login); 378 if ( !current_user_can($cap) ) 379 return new IXR_Error(401, 'Sorry, you can not post on this weblog or category.'); 380 381 $post_status = ($publish) ? 'publish' : 'draft'; 382 383 $post_author = $user->ID; 384 385 $post_title = xmlrpc_getposttitle($content); 386 $post_category = xmlrpc_getpostcategory($content); 387 $post_content = xmlrpc_removepostdata($content); 388 389 $post_date = current_time('mysql'); 390 $post_date_gmt = current_time('mysql', 1); 391 392 $post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status'); 393 394 $post_ID = wp_insert_post($post_data); 395 396 if (!$post_ID) { 397 return new IXR_Error(500, 'Sorry, your entry could not be posted. Something wrong happened.'); 398 } 399 $this->attach_uploads( $post_ID, $post_content ); 400 401 logIO('O', "Posted ! ID: $post_ID"); 402 403 return $post_ID; 404 } 405 406 407 /* blogger.editPost ...edits a post */ 408 function blogger_editPost($args) { 409 410 global $wpdb; 411 412 $this->escape($args); 413 414 $post_ID = $args[1]; 415 $user_login = $args[2]; 416 $user_pass = $args[3]; 417 $content = $args[4]; 418 $publish = $args[5]; 419 420 if (!$this->login_pass_ok($user_login, $user_pass)) { 421 return $this->error; 422 } 423 424 $actual_post = wp_get_single_post($post_ID,ARRAY_A); 425 426 if (!$actual_post) { 427 return new IXR_Error(404, 'Sorry, no such post.'); 428 } 429 430 $this->escape($actual_post); 431 432 set_current_user(0, $user_login); 433 if ( !current_user_can('edit_post', $post_ID) ) 434 return new IXR_Error(401, 'Sorry, you do not have the right to edit this post.'); 435 436 extract($actual_post); 437 438 $post_title = xmlrpc_getposttitle($content); 439 $post_category = xmlrpc_getpostcategory($content); 440 $post_content = xmlrpc_removepostdata($content); 441 442 $postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt'); 443 444 $result = wp_update_post($postdata); 445 446 if (!$result) { 447 return new IXR_Error(500, 'For some strange yet very annoying reason, this post could not be edited.'); 448 } 449 $this->attach_uploads( $ID, $post_content ); 450 451 return true; 452 } 453 454 455 /* blogger.deletePost ...deletes a post */ 456 function blogger_deletePost($args) { 457 458 global $wpdb; 459 460 $this->escape($args); 461 462 $post_ID = $args[1]; 463 $user_login = $args[2]; 464 $user_pass = $args[3]; 465 $publish = $args[4]; 466 467 if (!$this->login_pass_ok($user_login, $user_pass)) { 468 return $this->error; 469 } 470 471 $actual_post = wp_get_single_post($post_ID,ARRAY_A); 472 473 if (!$actual_post) { 474 return new IXR_Error(404, 'Sorry, no such post.'); 475 } 476 477 set_current_user(0, $user_login); 478 if ( !current_user_can('edit_post', $post_ID) ) 479 return new IXR_Error(401, 'Sorry, you do not have the right to delete this post.'); 480 481 $result = wp_delete_post($post_ID); 482 483 if (!$result) { 484 return new IXR_Error(500, 'For some strange yet very annoying reason, this post could not be deleted.'); 485 } 486 487 return true; 488 } 489 490 491 492 /* MetaWeblog API functions 493 * specs on wherever Dave Winer wants them to be 494 */ 495 496 /* metaweblog.newPost creates a post */ 497 function mw_newPost($args) { 498 499 global $wpdb, $post_default_category; 500 501 $this->escape($args); 502 503 $blog_ID = $args[0]; // we will support this in the near future 504 $user_login = $args[1]; 505 $user_pass = $args[2]; 506 $content_struct = $args[3]; 507 $publish = $args[4]; 508 509 if (!$this->login_pass_ok($user_login, $user_pass)) { 510 return $this->error; 511 } 512 513 $user = set_current_user(0, $user_login); 514 if ( !current_user_can('publish_posts') ) 515 return new IXR_Error(401, 'Sorry, you can not post on this weblog or category.'); 516 517 $post_author = $user->ID; 518 519 $post_title = $content_struct['title']; 520 $post_content = apply_filters( 'content_save_pre', $content_struct['description'] ); 521 $post_status = $publish ? 'publish' : 'draft'; 522 523 $post_excerpt = $content_struct['mt_excerpt']; 524 $post_more = $content_struct['mt_text_more']; 525 526 $comment_status = (empty($content_struct['mt_allow_comments'])) ? 527 get_option('default_comment_status') 528 : $content_struct['mt_allow_comments']; 529 530 $ping_status = (empty($content_struct['mt_allow_pings'])) ? 531 get_option('default_ping_status') 532 : $content_struct['mt_allow_pings']; 533 534 if ($post_more) { 535 $post_content = $post_content . "\n<!--more-->\n" . $post_more; 536 } 537 538 $to_ping = $content_struct['mt_tb_ping_urls']; 539 if ( is_array($to_ping) ) 540 $to_ping = implode(' ', $to_ping); 541 542 // Do some timestamp voodoo 543 $dateCreatedd = $content_struct['dateCreated']; 544 if (!empty($dateCreatedd)) { 545 $dateCreated = $dateCreatedd->getIso(); 546 $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); 547 $post_date_gmt = iso8601_to_datetime($dateCreated, GMT); 548 } else { 549 $post_date = current_time('mysql'); 550 $post_date_gmt = current_time('mysql', 1); 551 } 552 553 $catnames = $content_struct['categories']; 554 logIO('O', 'Post cats: ' . printr($catnames,true)); 555 $post_category = array(); 556 557 if (is_array($catnames)) { 558 foreach ($catnames as $cat) { 559 $post_category[] = get_cat_ID($cat); 560 } 561 } 562 563 // We've got all the data -- post it: 564 $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'); 565 566 $post_ID = wp_insert_post($postdata); 567 568 if (!$post_ID) { 569 return new IXR_Error(500, 'Sorry, your entry could not be posted. Something wrong happened.'); 570 } 571 572 $this->attach_uploads( $post_ID, $post_content ); 573 574 logIO('O', "Posted ! ID: $post_ID"); 575 576 return strval($post_ID); 577 } 578 579 function attach_uploads( $post_ID, $post_content ) { 580 global $wpdb; 581 582 // find any unattached files 583 $attachments = $wpdb->get_results( "SELECT ID, guid FROM {$wpdb->posts} WHERE post_parent = '-1' AND post_type = 'attachment'" ); 584 if( is_array( $attachments ) ) { 585 foreach( $attachments as $file ) { 586 if( strpos( $post_content, $file->guid ) !== false ) { 587 $wpdb->query( "UPDATE {$wpdb->posts} SET post_parent = '$post_ID' WHERE ID = '{$file->ID}'" ); 588 } 589 } 590 } 591 } 592 593 /* metaweblog.editPost ...edits a post */ 594 function mw_editPost($args) { 595 596 global $wpdb, $post_default_category; 597 598 $this->escape($args); 599 600 $post_ID = $args[0]; 601 $user_login = $args[1]; 602 $user_pass = $args[2]; 603 $content_struct = $args[3]; 604 $publish = $args[4]; 605 606 if (!$this->login_pass_ok($user_login, $user_pass)) { 607 return $this->error; 608 } 609 610 set_current_user(0, $user_login); 611 if ( !current_user_can('edit_post', $post_ID) ) 612 return new IXR_Error(401, 'Sorry, you can not edit this post.'); 613 614 $postdata = wp_get_single_post($post_ID, ARRAY_A); 615 extract($postdata); 616 $this->escape($postdata); 617 618 $post_title = $content_struct['title']; 619 $post_content = apply_filters( 'content_save_pre', $content_struct['description'] ); 620 $catnames = $content_struct['categories']; 621 622 $post_category = array(); 623 624 if (is_array($catnames)) { 625 foreach ($catnames as $cat) { 626 $post_category[] = get_cat_ID($cat); 627 } 628 } 629 630 $post_excerpt = $content_struct['mt_excerpt']; 631 $post_more = $content_struct['mt_text_more']; 632 $post_status = $publish ? 'publish' : 'draft'; 633 634 if ($post_more) { 635 $post_content = $post_content . "\n<!--more-->\n" . $post_more; 636 } 637 638 $to_ping = $content_struct['mt_tb_ping_urls']; 639 if ( is_array($to_ping) ) 640 $to_ping = implode(' ', $to_ping); 641 642 $comment_status = (empty($content_struct['mt_allow_comments'])) ? 643 get_option('default_comment_status') 644 : $content_struct['mt_allow_comments']; 645 646 $ping_status = (empty($content_struct['mt_allow_pings'])) ? 647 get_option('default_ping_status') 648 : $content_struct['mt_allow_pings']; 649 650 // Do some timestamp voodoo 651 $dateCreatedd = $content_struct['dateCreated']; 652 if (!empty($dateCreatedd)) { 653 $dateCreated = $dateCreatedd->getIso(); 654 $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); 655 $post_date_gmt = iso8601_to_datetime($dateCreated, GMT); 656 } else { 657 $post_date = $postdata['post_date']; 658 $post_date_gmt = $postdata['post_date_gmt']; 659 } 660 661 // We've got all the data -- post it: 662 $newpost = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'post_date', 'post_date_gmt', 'to_ping'); 663 664 $result = wp_update_post($newpost); 665 if (!$result) { 666 return new IXR_Error(500, 'Sorry, your entry could not be edited. Something wrong happened.'); 667 } 668 $this->attach_uploads( $ID, $post_content ); 669 670 logIO('O',"(MW) Edited ! ID: $post_ID"); 671 672 return true; 673 } 674 675 676 /* metaweblog.getPost ...returns a post */ 677 function mw_getPost($args) { 678 679 global $wpdb; 680 681 $this->escape($args); 682 683 $post_ID = $args[0]; 684 $user_login = $args[1]; 685 $user_pass = $args[2]; 686 687 if (!$this->login_pass_ok($user_login, $user_pass)) { 688 return $this->error; 689 } 690 691 $postdata = wp_get_single_post($post_ID, ARRAY_A); 692 693 if ($postdata['post_date'] != '') { 694 695 $post_date = mysql2date('Ymd\TH:i:s', $postdata['post_date']); 696 697 $categories = array(); 698 $catids = wp_get_post_categories($post_ID); 699 foreach($catids as $catid) { 700 $categories[] = get_cat_name($catid); 701 } 702 703 $post = get_extended($postdata['post_content']); 704 $link = post_permalink($postdata['ID']); 705 706 $allow_comments = ('open' == $postdata['comment_status']) ? 1 : 0; 707 $allow_pings = ('open' == $postdata['ping_status']) ? 1 : 0; 708 709 $resp = array( 710 'dateCreated' => new IXR_Date($post_date), 711 'userid' => $postdata['post_author'], 712 'postid' => $postdata['ID'], 713 'description' => $post['main'], 714 'title' => $postdata['post_title'], 715 'link' => $link, 716 'permaLink' => $link, 717 // commented out because no other tool seems to use this 718 // 'content' => $entry['post_content'], 719 'categories' => $categories, 720 'mt_excerpt' => $postdata['post_excerpt'], 721 'mt_text_more' => $post['extended'], 722 'mt_allow_comments' => $allow_comments, 723 'mt_allow_pings' => $allow_pings 724 ); 725 726 return $resp; 727 } else { 728 return new IXR_Error(404, 'Sorry, no such post.'); 729 } 730 } 731 732 733 /* metaweblog.getRecentPosts ...returns recent posts */ 734 function mw_getRecentPosts($args) { 735 736 $this->escape($args); 737 738 $blog_ID = $args[0]; 739 $user_login = $args[1]; 740 $user_pass = $args[2]; 741 $num_posts = $args[3]; 742 743 if (!$this->login_pass_ok($user_login, $user_pass)) { 744 return $this->error; 745 } 746 747 $posts_list = wp_get_recent_posts($num_posts); 748 749 if (!$posts_list) { 750 $this->error = new IXR_Error(500, 'Either there are no posts, or something went wrong.'); 751 return $this->error; 752 } 753 754 foreach ($posts_list as $entry) { 755 756 $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']); 757 $categories = array(); 758 $catids = wp_get_post_categories($entry['ID']); 759 foreach($catids as $catid) { 760 $categories[] = get_cat_name($catid); 761 } 762 763 $post = get_extended($entry['post_content']); 764 $link = post_permalink($entry['ID']); 765 766 $allow_comments = ('open' == $entry['comment_status']) ? 1 : 0; 767 $allow_pings = ('open' == $entry['ping_status']) ? 1 : 0; 768 769 $struct[] = array( 770 'dateCreated' => new IXR_Date($post_date), 771 'userid' => $entry['post_author'], 772 'postid' => $entry['ID'], 773 'description' => $post['main'], 774 'title' => $entry['post_title'], 775 'link' => $link, 776 'permaLink' => $link, 777 // commented out because no other tool seems to use this 778 // 'content' => $entry['post_content'], 779 'categories' => $categories, 780 'mt_excerpt' => $entry['post_excerpt'], 781 'mt_text_more' => $post['extended'], 782 'mt_allow_comments' => $allow_comments, 783 'mt_allow_pings' => $allow_pings 784 ); 785 786 } 787 788 $recent_posts = array(); 789 for ($j=0; $j<count($struct); $j++) { 790 array_push($recent_posts, $struct[$j]); 791 } 792 793 return $recent_posts; 794 } 795 796 797 /* metaweblog.getCategories ...returns the list of categories on a given weblog */ 798 function mw_getCategories($args) { 799 800 global $wpdb; 801 802 $this->escape($args); 803 804 $blog_ID = $args[0]; 805 $user_login = $args[1]; 806 $user_pass = $args[2]; 807 808 if (!$this->login_pass_ok($user_login, $user_pass)) { 809 return $this->error; 810 } 811 812 $categories_struct = array(); 813 814 // FIXME: can we avoid using direct SQL there? 815 if ($cats = $wpdb->get_results("SELECT cat_ID,cat_name FROM $wpdb->categories", ARRAY_A)) { 816 foreach ($cats as $cat) { 817 $struct['categoryId'] = $cat['cat_ID']; 818 $struct['description'] = $cat['cat_name']; 819 $struct['categoryName'] = $cat['cat_name']; 820 $struct['htmlUrl'] = wp_specialchars(get_category_link($cat['cat_ID'])); 821 $struct['rssUrl'] = wp_specialchars(get_category_rss_link(false, $cat['cat_ID'], $cat['cat_name'])); 822 823 $categories_struct[] = $struct; 824 } 825 } 826 827 return $categories_struct; 828 } 829 830 831 /* metaweblog.newMediaObject uploads a file, following your settings */ 832 function mw_newMediaObject($args) { 833 // adapted from a patch by Johann Richard 834 // http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/ 835 836 global $wpdb; 837 838 $blog_ID = $wpdb->escape($args[0]); 839 $user_login = $wpdb->escape($args[1]); 840 $user_pass = $wpdb->escape($args[2]); 841 $data = $args[3]; 842 843 $name = sanitize_file_name( $data['name'] ); 844 $type = $data['type']; 845 $bits = $data['bits']; 846 847 logIO('O', '(MW) Received '.strlen($bits).' bytes'); 848 849 if ( !$this->login_pass_ok($user_login, $user_pass) ) 850 return $this->error; 851 852 set_current_user(0, $user_login); 853 if ( !current_user_can('upload_files') ) { 854 logIO('O', '(MW) User does not have upload_files capability'); 855 $this->error = new IXR_Error(401, 'You are not allowed to upload files to this site.'); 856 return $this->error; 857 } 858 859 if ( $upload_err = apply_filters( "pre_upload_error", false ) ) 860 return new IXR_Error(500, $upload_err); 861 862 $upload = wp_upload_bits($name, $type, $bits); 863 if ( ! empty($upload['error']) ) { 864 logIO('O', '(MW) Could not write file '.$name); 865 return new IXR_Error(500, 'Could not write file '.$name); 866 } 867 // Construct the attachment array 868 // attach to post_id -1 869 $post_id = -1; 870 $attachment = array( 871 'post_title' => $name, 872 'post_content' => '', 873 'post_type' => 'attachment', 874 'post_parent' => $post_id, 875 'post_mime_type' => $type, 876 'guid' => $upload[ 'url' ] 877 ); 878 // Save the data 879 $id = wp_insert_attachment( $attachment, $upload[ 'file' ], $post_id ); 880 wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) ); 881 882 return apply_filters( 'wp_handle_upload', array( 'file' => $upload[ 'file' ], 'url' => $upload[ 'url' ], 'type' => $type ) ); 883 } 884 885 886 /* MovableType API functions 887 * specs on http://www.movabletype.org/docs/mtmanual_programmatic.html 888 */ 889 890 /* mt.getRecentPostTitles ...returns recent posts' titles */ 891 function mt_getRecentPostTitles($args) { 892 893 $this->escape($args); 894 895 $blog_ID = $args[0]; 896 $user_login = $args[1]; 897 $user_pass = $args[2]; 898 $num_posts = $args[3]; 899 900 if (!$this->login_pass_ok($user_login, $user_pass)) { 901 return $this->error; 902 } 903 904 $posts_list = wp_get_recent_posts($num_posts); 905 906 if (!$posts_list) { 907 $this->error = new IXR_Error(500, 'Either there are no posts, or something went wrong.'); 908 return $this->error; 909 } 910 911 foreach ($posts_list as $entry) { 912 913 $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']); 914 915 $struct[] = array( 916 'dateCreated' => new IXR_Date($post_date), 917 'userid' => $entry['post_author'], 918 'postid' => $entry['ID'], 919 'title' => $entry['post_title'], 920 ); 921 922 } 923 924 $recent_posts = array(); 925 for ($j=0; $j<count($struct); $j++) { 926 array_push($recent_posts, $struct[$j]); 927 } 928 929 return $recent_posts; 930 } 931 932 933 /* mt.getCategoryList ...returns the list of categories on a given weblog */ 934 function mt_getCategoryList($args) { 935 936 global $wpdb; 937 938 $this->escape($args); 939 940 $blog_ID = $args[0]; 941 $user_login = $args[1]; 942 $user_pass = $args[2]; 943 944 if (!$this->login_pass_ok($user_login, $user_pass)) { 945 return $this->error; 946 } 947 948 $categories_struct = array(); 949 950 // FIXME: can we avoid using direct SQL there? 951 if ($cats = $wpdb->get_results("SELECT cat_ID, cat_name FROM $wpdb->categories", ARRAY_A)) { 952 foreach ($cats as $cat) { 953 $struct['categoryId'] = $cat['cat_ID']; 954 $struct['categoryName'] = $cat['cat_name']; 955 956 $categories_struct[] = $struct; 957 } 958 } 959 960 return $categories_struct; 961 } 962 963 964 /* mt.getPostCategories ...returns a post's categories */ 965 function mt_getPostCategories($args) { 966 967 $this->escape($args); 968 969 $post_ID = $args[0]; 970 $user_login = $args[1]; 971 $user_pass = $args[2]; 972 973 if (!$this->login_pass_ok($user_login, $user_pass)) { 974 return $this->error; 975 } 976 977 $categories = array(); 978 $catids = wp_get_post_categories(intval($post_ID)); 979 // first listed category will be the primary category 980 $isPrimary = true; 981 foreach($catids as $catid) { 982 $categories[] = array( 983 'categoryName' => get_cat_name($catid), 984 'categoryId' => (string) $catid, 985 'isPrimary' => $isPrimary 986 ); 987 $isPrimary = false; 988 } 989 990 return $categories; 991 } 992 993 994 /* mt.setPostCategories ...sets a post's categories */ 995 function mt_setPostCategories($args) { 996 997 $this->escape($args); 998 999 $post_ID = $args[0]; 1000 $user_login = $args[1]; 1001 $user_pass = $args[2]; 1002 $categories = $args[3]; 1003 1004 if (!$this->login_pass_ok($user_login, $user_pass)) { 1005 return $this->error; 1006 } 1007 1008 set_current_user(0, $user_login); 1009 if ( !current_user_can('edit_post', $post_ID) ) 1010 return new IXR_Error(401, 'Sorry, you can not edit this post.'); 1011 1012 foreach($categories as $cat) { 1013 $catids[] = $cat['categoryId']; 1014 } 1015 1016 wp_set_post_categories($post_ID, $catids); 1017 1018 return true; 1019 } 1020 1021 1022 /* mt.supportedMethods ...returns an array of methods supported by this server */ 1023 function mt_supportedMethods($args) { 1024 1025 $supported_methods = array(); 1026 foreach($this->methods as $key=>$value) { 1027 $supported_methods[] = $key; 1028 } 1029 1030 return $supported_methods; 1031 } 1032 1033 1034 /* mt.supportedTextFilters ...returns an empty array because we don't 1035 support per-post text filters yet */ 1036 function mt_supportedTextFilters($args) { 1037 return array(); 1038 } 1039 1040 1041 /* mt.getTrackbackPings ...returns trackbacks sent to a given post */ 1042 function mt_getTrackbackPings($args) { 1043 1044 global $wpdb; 1045 1046 $post_ID = intval($args); 1047 1048 $actual_post = wp_get_single_post($post_ID, ARRAY_A); 1049 1050 if (!$actual_post) { 1051 return new IXR_Error(404, 'Sorry, no such post.'); 1052 } 1053 1054 $comments = $wpdb->get_results("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = $post_ID"); 1055 1056 if (!$comments) { 1057 return array(); 1058 } 1059 1060 $trackback_pings = array(); 1061 foreach($comments as $comment) { 1062 if ( 'trackback' == $comment->comment_type ) { 1063 $content = $comment->comment_content; 1064 $title = substr($content, 8, (strpos($content, '</strong>') - 8)); 1065 $trackback_pings[] = array( 1066 'pingTitle' => $title, 1067 'pingURL' => $comment->comment_author_url, 1068 'pingIP' => $comment->comment_author_IP 1069 ); 1070 } 1071 } 1072 1073 return $trackback_pings; 1074 } 1075 1076 1077 /* mt.publishPost ...sets a post's publish status to 'publish' */ 1078 function mt_publishPost($args) { 1079 1080 $this->escape($args); 1081 1082 $post_ID = $args[0]; 1083 $user_login = $args[1]; 1084 $user_pass = $args[2]; 1085 1086 if (!$this->login_pass_ok($user_login, $user_pass)) { 1087 return $this->error; 1088 } 1089 1090 set_current_user(0, $user_login); 1091 if ( !current_user_can('edit_post', $post_ID) ) 1092 return new IXR_Error(401, 'Sorry, you can not edit this post.'); 1093 1094 $postdata = wp_get_single_post($post_ID,ARRAY_A); 1095 1096 $postdata['post_status'] = 'publish'; 1097 1098 // retain old cats 1099 $cats = wp_get_post_categories($post_ID); 1100 $postdata['post_category'] = $cats; 1101 $this->escape($postdata); 1102 1103 $result = wp_update_post($postdata); 1104 1105 return $result; 1106 } 1107 1108 1109 1110 /* PingBack functions 1111 * specs on www.hixie.ch/specs/pingback/pingback 1112 */ 1113 1114 /* pingback.ping gets a pingback and registers it */ 1115 function pingback_ping($args) { 1116 global $wpdb, $wp_version; 1117 1118 $this->escape($args); 1119 1120 $pagelinkedfrom = $args[0]; 1121 $pagelinkedto = $args[1]; 1122 1123 $title = ''; 1124 1125 $pagelinkedfrom = str_replace('&', '&', $pagelinkedfrom); 1126 $pagelinkedto = preg_replace('#&([^amp\;])#is', '&$1', $pagelinkedto); 1127 1128 $error_code = -1; 1129 1130 // Check if the page linked to is in our site 1131 $pos1 = strpos($pagelinkedto, str_replace(array('http://www.','http://','https://www.','https://'), '', get_option('home'))); 1132 if( !$pos1 ) 1133 return new IXR_Error(0, 'Is there no link to us?'); 1134 1135 // let's find which post is linked to 1136 // FIXME: does url_to_postid() cover all these cases already? 1137 // if so, then let's use it and drop the old code. 1138 $urltest = parse_url($pagelinkedto); 1139 if ($post_ID = url_to_postid($pagelinkedto)) { 1140 $way = 'url_to_postid()'; 1141 } elseif (preg_match('#p/[0-9]{1,}#', $urltest['path'], $match)) { 1142 // the path defines the post_ID (archives/p/XXXX) 1143 $blah = explode('/', $match[0]); 1144 $post_ID = $blah[1]; 1145 $way = 'from the path'; 1146 } elseif (preg_match('#p=[0-9]{1,}#', $urltest['query'], $match)) { 1147 // the querystring defines the post_ID (?p=XXXX) 1148 $blah = explode('=', $match[0]); 1149 $post_ID = $blah[1]; 1150 $way = 'from the querystring'; 1151 } elseif (isset($urltest['fragment'])) { 1152 // an #anchor is there, it's either... 1153 if (intval($urltest['fragment'])) { 1154 // ...an integer #XXXX (simpliest case) 1155 $post_ID = $urltest['fragment']; 1156 $way = 'from the fragment (numeric)'; 1157 } elseif (preg_match('/post-[0-9]+/',$urltest['fragment'])) { 1158 // ...a post id in the form 'post-###' 1159 $post_ID = preg_replace('/[^0-9]+/', '', $urltest['fragment']); 1160 $way = 'from the fragment (post-###)'; 1161 } elseif (is_string($urltest['fragment'])) { 1162 // ...or a string #title, a little more complicated 1163 $title = preg_replace('/[^a-z0-9]/i', '.', $urltest['fragment']); 1164 $sql = "SELECT ID FROM $wpdb->posts WHERE post_title RLIKE '$title'"; 1165 if (! ($post_ID = $wpdb->get_var($sql)) ) { 1166 // returning unknown error '0' is better than die()ing 1167 return new IXR_Error(0, ''); 1168 } 1169 $way = 'from the fragment (title)'; 1170 } 1171 } else { 1172 // TODO: Attempt to extract a post ID from the given URL 1173 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.'); 1174 } 1175 $post_ID = (int) $post_ID; 1176 1177 1178 logIO("O","(PB) URL='$pagelinkedto' ID='$post_ID' Found='$way'"); 1179 1180 $post = get_post($post_ID); 1181 1182 if ( !$post ) // Post_ID not found 1183 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.'); 1184 1185 if ( $post_ID == url_to_postid($pagelinkedfrom) ) 1186 return new IXR_Error(0, 'The source URL and the target URL cannot both point to the same resource.'); 1187 1188 // Check if pings are on 1189 if ( 'closed' == $post->ping_status ) 1190 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.'); 1191 1192 // Let's check that the remote site didn't already pingback this entry 1193 $result = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE comment_post_ID = '$post_ID' AND comment_author_url = '$pagelinkedfrom'"); 1194 1195 if ( $wpdb->num_rows ) // We already have a Pingback from this URL 1196 return new IXR_Error(48, 'The pingback has already been registered.'); 1197 1198 // very stupid, but gives time to the 'from' server to publish ! 1199 sleep(1); 1200 1201 // Let's check the remote site 1202 $linea = wp_remote_fopen( $pagelinkedfrom ); 1203 if ( !$linea ) 1204 return new IXR_Error(16, 'The source URL does not exist.'); 1205 1206 // Work around bug in strip_tags(): 1207 $linea = str_replace('<!DOC', '<DOC', $linea); 1208 $linea = preg_replace( '/[\s\r\n\t]+/', ' ', $linea ); // normalize spaces 1209 $linea = preg_replace( "/ <(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/", "\n\n", $linea ); 1210 1211 preg_match('|<title>([^<]*?)</title>|is', $linea, $matchtitle); 1212 $title = $matchtitle[1]; 1213 if ( empty( $title ) ) 1214 return new IXR_Error(32, 'We cannot find a title on that page.'); 1215 1216 $linea = strip_tags( $linea, '<a>' ); // just keep the tag we need 1217 1218 $p = explode( "\n\n", $linea ); 1219 1220 $preg_target = preg_quote($pagelinkedto); 1221 1222 foreach ( $p as $para ) { 1223 if ( strpos($para, $pagelinkedto) !== false ) { // it exists, but is it a link? 1224 preg_match("|<a[^>]+?".$preg_target."[^>]*>([^>]+?)</a>|", $para, $context); 1225 1226 // If the URL isn't in a link context, keep looking 1227 if ( empty($context) ) 1228 continue; 1229 1230 // We're going to use this fake tag to mark the context in a bit 1231 // the marker is needed in case the link text appears more than once in the paragraph 1232 $excerpt = preg_replace('|\</?wpcontext\>|', '', $para); 1233 1234 // prevent really long link text 1235 if ( strlen($context[1]) > 100 ) 1236 $context[1] = substr($context[1], 0, 100) . '...'; 1237 1238 $marker = '<wpcontext>'.$context[1].'</wpcontext>'; // set up our marker 1239 $excerpt= str_replace($context[0], $marker, $excerpt); // swap out the link for our marker 1240 $excerpt = strip_tags($excerpt, '<wpcontext>'); // strip all tags but our context marker 1241 $excerpt = trim($excerpt); 1242 $preg_marker = preg_quote($marker); 1243 $excerpt = preg_replace("|.*?\s(.{0,100}$preg_marker.{0,100})\s.*|s", '$1', $excerpt); 1244 $excerpt = strip_tags($excerpt); // YES, again, to remove the marker wrapper 1245 break; 1246 } 1247 } 1248 1249 if ( empty($context) ) // Link to target not found 1250 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.'); 1251 1252 $pagelinkedfrom = preg_replace('#&([^amp\;])#is', '&$1', $pagelinkedfrom); 1253 1254 $context = '[...] ' . wp_specialchars( $excerpt ) . ' [...]'; 1255 $original_pagelinkedfrom = $pagelinkedfrom; 1256 $pagelinkedfrom = $wpdb->escape( $pagelinkedfrom ); 1257 $original_title = $title; 1258 1259 $comment_post_ID = (int) $post_ID; 1260 $comment_author = $title; 1261 $this->escape($comment_author); 1262 $comment_author_url = $pagelinkedfrom; 1263 $comment_content = $context; 1264 $this->escape($comment_content); 1265 $comment_type = 'pingback'; 1266 1267 $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_url', 'comment_content', 'comment_type'); 1268 1269 $comment_ID = wp_new_comment($commentdata); 1270 do_action('pingback_post', $comment_ID); 1271 1272 return "Pingback from $pagelinkedfrom to $pagelinkedto registered. Keep the web talking! :-)"; 1273 } 1274 1275 1276 /* pingback.extensions.getPingbacks returns an array of URLs 1277 that pingbacked the given URL 1278 specs on http://www.aquarionics.com/misc/archives/blogite/0198.html */ 1279 function pingback_extensions_getPingbacks($args) { 1280 1281 global $wpdb; 1282 1283 $this->escape($args); 1284 1285 $url = $args; 1286 1287 $post_ID = url_to_postid($url); 1288 if (!$post_ID) { 1289 // We aren't sure that the resource is available and/or pingback enabled 1290 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.'); 1291 } 1292 1293 $actual_post = wp_get_single_post($post_ID, ARRAY_A); 1294 1295 if (!$actual_post) { 1296 // No such post = resource not found 1297 return new IXR_Error(32, 'The specified target URL does not exist.'); 1298 } 1299 1300 $comments = $wpdb->get_results("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = $post_ID"); 1301 1302 if (!$comments) { 1303 return array(); 1304 } 1305 1306 $pingbacks = array(); 1307 foreach($comments as $comment) { 1308 if ( 'pingback' == $comment->comment_type ) 1309 $pingbacks[] = $comment->comment_author_url; 1310 } 1311 1312 return $pingbacks; 1313 } 1314 } 1315 1316 1317 $wp_xmlrpc_server = new wp_xmlrpc_server(); 1318 1319 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Fri Mar 30 19:41:27 2007 | par Balluche grâce à PHPXref 0.7 |