function on_xmlrpc_call($method) { $arr_methods_to_act_on = array("wp.deletePost"); $raw_post_data = null; $message = null; $context = array(); if (in_array($method, $arr_methods_to_act_on)) { // Setup common stuff $raw_post_data = file_get_contents("php://input"); $context["wp.deletePost.xmldata"] = $this->simpleHistory->json_encode($raw_post_data); $message = new IXR_Message($raw_post_data); if (!$message->parse()) { return; } $context["wp.deletePost.xmlrpc_message"] = $this->simpleHistory->json_encode($message); $context["wp.deletePost.xmlrpc_message.messageType"] = $this->simpleHistory->json_encode($message->messageType); $context["wp.deletePost.xmlrpc_message.methodName"] = $this->simpleHistory->json_encode($message->methodName); $context["wp.deletePost.xmlrpc_message.messageParams"] = $this->simpleHistory->json_encode($message->params); // Actions for delete post if ("wp.deletePost" == $method) { // 4 params, where the last is the post id if (!isset($message->params[3])) { return; } $post_ID = $message->params[3]; $post = get_post($post_ID); $context = array("post_id" => $post->ID, "post_type" => get_post_type($post), "post_title" => get_the_title($post)); $this->infoMessage("post_trashed", $context); } // if delete post } }
/** * 服务入口 * * @access private * @param mixed $data 输入参数 * @return void */ private function serve($data = false) { if (!isset($GLOBALS['HTTP_RAW_POST_DATA'])) { $GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents("php://input"); } if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) { $GLOBALS['HTTP_RAW_POST_DATA'] = trim($GLOBALS['HTTP_RAW_POST_DATA']); } if (!$data) { global $HTTP_RAW_POST_DATA; if (!$HTTP_RAW_POST_DATA) { die('XML-RPC server accepts POST requests only.'); } $data = $HTTP_RAW_POST_DATA; } $this->message = new IXR_Message($data); if (!$this->message->parse()) { $this->error(-32700, 'parse error. not well formed'); } if ($this->message->messageType != 'methodCall') { $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall'); } if (0 === strpos($this->message->methodName, 'hook.')) { die('THIS METHOD MUST BE CALLED INSIDE.'); } $result = $this->call($this->message->methodName, $this->message->params); // Is the result an error? if (is_a($result, 'IXR_Error')) { $this->error($result); } // Encode the result $r = new IXR_Value($result); $resultxml = $r->getXml(); // Create the XML $xml = <<<EOD <methodResponse> <params> <param> <value> {$resultxml} </value> </param> </params> </methodResponse> EOD; // hook if ($this->hasMethod('hook.beforeOutput')) { $this->call('hook.beforeOutput', array()); } // Send it $this->output($xml); }
function police_xmlrpc_action($method_name) { if (function_exists('is_content_administrator_rs') && is_content_administrator_rs()) { return; } switch ($method_name) { // This method has no business passing an empty array of categories. It usually means none are selected for a new post, and does not provide a hook for RS to filtering the default category prior to insertion case 'mt.setPostCategories': global $scoper_last_raw_post_data; if (empty($scoper_last_raw_post_data)) { return; } if (!$this->load_ixr()) { return; } $msg = new IXR_Message($scoper_last_raw_post_data); if ($msg->parse()) { // params[0] = object id, params[3] = categories if (is_array($msg->params) && !empty($msg->params[0]) && isset($msg->params[3]) && !$msg->params[3]) { if ($terms = wp_get_object_terms($msg->params[0], 'category', array('fields' => 'ids'))) { foreach ($terms as $key => $val) { $terms[$key] = (int) $val; } // otherwise wp_set_object_terms will store as a new category named "id" if (empty($this->scheduled_term_restoration)) { $this->scheduled_term_restoration = array(); add_action('set_object_terms', array(&$this, 'maybe_restore_object_terms'), 99, 6); } $this->scheduled_term_restoration[$msg->params[0]]['category'] = $terms; } } } break; // 'mt.setPostCategories' } // end switch }
/** * The metaWeblog.getPost xmlrpc_call action fires *after* get_post() is called. * So, we have to detect that method and prime the post cache early. * @return null */ protected function check_for_mwgetpost() { global $HTTP_RAW_POST_DATA; if (false === strpos($HTTP_RAW_POST_DATA, 'metaWeblog.getPost')) { return; } include_once ABSPATH . WPINC . '/class-IXR.php'; $message = new IXR_Message($HTTP_RAW_POST_DATA); $message->parse(); $this->prime_post_cache($message->params[0]); }
/** * metaWeblog.getPost and wp.getPage fire xmlrpc_call action *after* get_post() is called. * So, we have to detect those methods and prime the post cache early. * @return null */ protected function check_for_early_methods() { global $HTTP_RAW_POST_DATA; if (false === strpos($HTTP_RAW_POST_DATA, 'metaWeblog.getPost') && false === strpos($HTTP_RAW_POST_DATA, 'wp.getPage')) { return; } include_once ABSPATH . WPINC . '/class-IXR.php'; $message = new IXR_Message($HTTP_RAW_POST_DATA); $message->parse(); $post_id_position = 'metaWeblog.getPost' === $message->methodName ? 0 : 1; $this->prime_post_cache($message->params[$post_id_position]); }
function test_struct() { $xml = '<?xml version=\'1.0\'?> <methodCall> <methodName>wiki.putPage</methodName> <params> <param> <value><string>start</string></value> </param> <param> <value><string>test text</string></value> </param> <param> <value><struct> <member> <name>sum</name> <value><string>xmlrpc edit</string></value> </member> <member> <name>minor</name> <value><string>1</string></value> </member> </struct></value> </param> </params> </methodCall>'; $ixrmsg = new IXR_Message($xml); $ixrmsg->parse(); $this->assertEquals($ixrmsg->messageType, 'methodCall'); $this->assertEquals($ixrmsg->methodName, 'wiki.putPage'); $this->assertEquals($ixrmsg->params, array('start', 'test text', array('sum' => 'xmlrpc edit', 'minor' => '1'))); }
public function maybe_prime_post_data() { global $HTTP_RAW_POST_DATA; require_once ABSPATH . WPINC . '/class-IXR.php'; $message = new IXR_Message($HTTP_RAW_POST_DATA); if (!$message->parse()) { unset($message); return; } $methods_to_prime = array('metaWeblog.getPost', 'wp.getPost', 'wp.getPage'); if (!in_array($message->methodName, $methods_to_prime)) { unset($message); return; } // different ID arg for wp.getPage $post_id = 'wp.getPage' === $message->methodName ? $message->params[1] : array_shift($message->params); $post_id = (int) $post_id; // prime the post cache if ($this->is_markdown($post_id)) { $post = get_post($post_id); if (!empty($post->post_content_filtered)) { $post->post_content = $post->post_content_filtered; } wp_cache_delete($post->ID, 'posts'); wp_cache_add($post->ID, $post, 'posts'); } unset($message); }
/** * parameters: method and arguments * @return bool success or error */ function query() { $args = func_get_args(); $method = array_shift($args); $request = new IXR_Request($method, $args); $xml = $request->getXml(); $this->headers['Content-Type'] = 'text/xml'; if (!$this->sendRequest($this->posturl, $xml, 'POST')) { $this->xmlerror = new IXR_Error(-32300, 'transport error - ' . $this->error); return false; } // Check HTTP Response code if ($this->status < 200 || $this->status > 206) { $this->xmlerror = new IXR_Error(-32300, 'transport error - HTTP status ' . $this->status); return false; } // Now parse what we've got back $this->message = new IXR_Message($this->resp_body); if (!$this->message->parse()) { // XML error $this->xmlerror = new IXR_Error(-32700, 'parse error. not well formed'); return false; } // Is the message a fault? if ($this->message->messageType == 'fault') { $this->xmlerror = new IXR_Error($this->message->faultCode, $this->message->faultString); return false; } // Message must be OK return true; }
function readCB($timeout = 2000) { // timeout 2 ms if (!$this->socket || $this->protocol == 0) { $this->error = new IXR_Error(-32300, 'transport error - client not initialized'); return false; } if ($this->protocol == 1) { return false; } $something_received = count($this->cb_message) > 0; $contents = ''; $contents_length = 0; @stream_set_timeout($this->socket, 0, 10000); // timeout 10 ms (to read available data) // (assignment in arguments is forbidden since php 5.1.1) $read = array($this->socket); $write = NULL; $except = NULL; $nb = @stream_select($read, $write, $except, 0, $timeout); // workaround for stream_select bug with amd64 if ($nb !== false) { $nb = count($read); } while ($nb !== false && $nb > 0) { $timeout = 0; // we don't want to wait for the full time again, just flush the available data $size = 0; $recvhandle = 0; // Get result $contents = fread($this->socket, 8); if (strlen($contents) == 0) { $this->error = new IXR_Error(-32300, 'transport error - cannot read size/handle'); return false; } $array_result = unpack('Vsize/Vhandle', $contents); $size = $array_result['size']; $recvhandle = $array_result['handle']; if ($recvhandle == 0 || $size == 0) { $this->error = new IXR_Error(-32300, 'transport error - connection interrupted!'); return false; } if ($size > 4096 * 1024) { $this->error = new IXR_Error(-32300, "transport error - response too large ({$size})"); return false; } $contents = ''; $contents_length = 0; while ($contents_length < $size) { $contents .= fread($this->socket, $size - $contents_length); $contents_length = strlen($contents); } if (($recvhandle & 0x80000000) == 0) { // this is a callback. handle= $recvhandle, xml-rpc= $contents //echo 'CALLBACK('.$contents_length.')[ '.$contents.' ]' . LF; $new_cb_message = new IXR_Message($contents); if ($new_cb_message->parse() && $new_cb_message->messageType != 'fault') { array_push($this->cb_message, array($new_cb_message->methodName, $new_cb_message->params)); } $something_received = true; } // (assignment in arguments is forbidden since php 5.1.1) $read = array($this->socket); $write = NULL; $except = NULL; $nb = @stream_select($read, $write, $except, 0, $timeout); // workaround for stream_select bug with amd64 if ($nb !== false) { $nb = count($read); } } return $something_received; }