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