最近再次测试wordpress multisite(wordpress多站点,简称WPMU)通过XML-RPC管理博客,但是始终无法通过OpenLiveWriter/WindowsLiveWriter获取到博客信息,但是通过官方“Weblog_Client”中的BlogDesk,Chrysanth WebStory却能获取到博客信息,但是BlogDesk太过于古老,且不能很好的支持中文;Chrysanth WebStory收费,免费版带有小尾巴;BlogJet收费无法测试,所以只能转战其他离线软件,但是现在离线编辑博客时代(或者是博客的时代)已经过去,基本没有新出的博客写作软件了。于是,继续研究导致这个现象的原因,通过多次测试,终于发现原因:
wordpress xmlrpc.php文件存在错误!!
但是其他其他软件为什么却能获取到博客信息呢??
原因很简单,他们使用的XMLRPC method(API)不同,wordpress内部有多种管理博客的API:
- WordPress API
- Blogger API
- MetaWeblog API
- MovableType API等
OpenLiveWriter和WindowsLiveWriter是通过Blogger API获取博客信息的,也只有Blogger API存在错误,所以其他软件可以,但是OpenLiveWriter和WindowsLiveWriter不可以!!
Blogger API比WordPress API的getUsersBlogs方法多一个参数,在WPMU多站点版(multisite)获取博客信息时,如果采用Blogger API会直接调用WordPress API,但是调用时并没有去除多的那个参数,所以导致一直验证失败!!
public function wp_getUsersBlogs( $args ) { if ( ! $this->minimum_args( $args, 2 ) ) { return $this->error; } // If this isn't on WPMU then just use blogger_getUsersBlogs(). if ( ! is_multisite() ) { array_unshift( $args, 1 ); return $this->blogger_getUsersBlogs( $args ); } $this->escape( $args ); $username = $args[0]; $password = $args[1]; $user = $this->login( $username, $password ); if ( ! $user ) { return $this->error; } /** * Fires after the XML-RPC user has been authenticated but before the rest of * the method logic begins. * * All built-in XML-RPC methods use the action xmlrpc_call, with a parameter * equal to the method's name, e.g., wp.getUsersBlogs, wp.newPost, etc. * * @since 2.5.0 * @since 5.7.0 Added the `$args` and `$server` parameters. * * @param string $name The method name. * @param array|string $args The escaped arguments passed to the method. * @param wp_xmlrpc_server $server The XML-RPC server instance. */ do_action( 'xmlrpc_call', 'wp.getUsersBlogs', $args, $this ); $blogs = (array) get_blogs_of_user( $user->ID ); $struct = array(); $primary_blog_id = 0; $active_blog = get_active_blog_for_user( $user->ID ); if ( $active_blog ) { $primary_blog_id = (int) $active_blog->blog_id; } foreach ( $blogs as $blog ) { // Don't include blogs that aren't hosted at this site. if ( get_current_network_id() != $blog->site_id ) { continue; } $blog_id = $blog->userblog_id; switch_to_blog( $blog_id ); $is_admin = current_user_can( 'manage_options' ); $is_primary = ( (int) $blog_id === $primary_blog_id ); $struct[] = array( 'isAdmin' => $is_admin, 'isPrimary' => $is_primary, 'url' => home_url( '/' ), 'blogid' => (string) $blog_id, 'blogName' => get_option( 'blogname' ), 'xmlrpc' => site_url( 'xmlrpc.php', 'rpc' ), ); restore_current_blog(); } return $struct; }
1 public function blogger_getUsersBlogs( $args ) { 2 if ( ! $this->minimum_args( $args, 3 ) ) { 3 return $this->error; 4 } 5 6 if ( is_multisite() ) { 7 array_shift($args); 8 return $this->_multisite_getUsersBlogs( $args ); 9 } 10 11 $this->escape( $args ); 12 13 $username = $args[1]; 14 $password = $args[2]; 15 16 $user = $this->login( $username, $password ); 17 if ( ! $user ) { 18 return $this->error; 19 } 20 21 /** This action is documented in wp-includes/class-wp-xmlrpc-server.php */ 22 do_action( 'xmlrpc_call', 'blogger.getUsersBlogs', $args, $this ); 23 24 $is_admin = current_user_can( 'manage_options' ); 25 26 $struct = array( 27 'isAdmin' => $is_admin, 28 'url' => get_option( 'home' ) . '/', 29 'blogid' => '1', 30 'blogName' => get_option( 'blogname' ), 31 'xmlrpc' => site_url( 'xmlrpc.php', 'rpc' ), 32 ); 33 34 return array( $struct ); 35 }
1 protected function _multisite_getUsersBlogs( $args ) { 2 $current_blog = get_site(); 3 4 $domain = $current_blog->domain; 5 $path = $current_blog->path . 'xmlrpc.php'; 6 7 $blogs = $this->wp_getUsersBlogs( $args ); 8 if ( $blogs instanceof IXR_Error ) { 9 return $blogs; 10 } 11 12 if ( $_SERVER['HTTP_HOST'] == $domain && $_SERVER['REQUEST_URI'] == $path ) { 13 return $blogs; 14 } else { 15 foreach ( (array) $blogs as $blog ) { 16 if ( str_contains( $blog['url'], $_SERVER['HTTP_HOST'] ) ) { 17 return array( $blog ); 18 } 19 } 20 return array(); 21 } 22 }