📄 xmlrpc.php
字号:
} } else { // user does NOT want to fallback on many single calls: // since we should always return an array of responses, // return an array with the same error repeated n times foreach($msgs as $msg) { $results[] = $result; } } return $results; } /** * Attempt to boxcar $msgs via system.multicall. * Returns either an array of xmlrpcreponses, an xmlrpc error response * or false (when received response does not respect valid multicall syntax) * @access private */ function _try_multicall($msgs, $timeout, $method) { // Construct multicall message $calls = array(); foreach($msgs as $msg) { $call['methodName'] =& new xmlrpcval($msg->method(),'string'); $numParams = $msg->getNumParams(); $params = array(); for($i = 0; $i < $numParams; $i++) { $params[$i] = $msg->getParam($i); } $call['params'] =& new xmlrpcval($params, 'array'); $calls[] =& new xmlrpcval($call, 'struct'); } $multicall =& new xmlrpcmsg('system.multicall'); $multicall->addParam(new xmlrpcval($calls, 'array')); // Attempt RPC call $result =& $this->send($multicall, $timeout, $method); if($result->faultCode() != 0) { // call to system.multicall failed return $result; } // Unpack responses. $rets = $result->value(); if ($this->return_type == 'xml') { return $rets; } else if ($this->return_type == 'phpvals') { ///@todo test this code branch... $rets = $result->value(); if(!is_array($rets)) { return false; // bad return type from system.multicall } $numRets = count($rets); if($numRets != count($msgs)) { return false; // wrong number of return values. } $response = array(); for($i = 0; $i < $numRets; $i++) { $val = $rets[$i]; if (!is_array($val)) { return false; } switch(count($val)) { case 1: if(!isset($val[0])) { return false; // Bad value } // Normal return value $response[$i] =& new xmlrpcresp($val[0], 0, '', 'phpvals'); break; case 2: /// @todo remove usage of @: it is apparently quite slow $code = @$val['faultCode']; if(!is_int($code)) { return false; } $str = @$val['faultString']; if(!is_string($str)) { return false; } $response[$i] =& new xmlrpcresp(0, $code, $str); break; default: return false; } } return $response; } else // return type == 'xmlrpcvals' { $rets = $result->value(); if($rets->kindOf() != 'array') { return false; // bad return type from system.multicall } $numRets = $rets->arraysize(); if($numRets != count($msgs)) { return false; // wrong number of return values. } $response = array(); for($i = 0; $i < $numRets; $i++) { $val = $rets->arraymem($i); switch($val->kindOf()) { case 'array': if($val->arraysize() != 1) { return false; // Bad value } // Normal return value $response[$i] =& new xmlrpcresp($val->arraymem(0)); break; case 'struct': $code = $val->structmem('faultCode'); if($code->kindOf() != 'scalar' || $code->scalartyp() != 'int') { return false; } $str = $val->structmem('faultString'); if($str->kindOf() != 'scalar' || $str->scalartyp() != 'string') { return false; } $response[$i] =& new xmlrpcresp(0, $code->scalarval(), $str->scalarval()); break; default: return false; } } return $response; } } } // end class xmlrpc_client class xmlrpcresp { var $val = 0; var $valtyp; var $errno = 0; var $errstr = ''; var $payload; var $hdrs = array(); var $_cookies = array(); var $content_type = 'text/xml'; var $raw_data = ''; /** * @param mixed $val either an xmlrpcval obj, a php value or the xml serialization of an xmlrpcval (a string) * @param integer $fcode set it to anything but 0 to create an error response * @param string $fstr the error string, in case of an error response * @param string $valtyp either 'xmlrpcvals', 'phpvals' or 'xml' * * @todo add check that $val / $fcode / $fstr is of correct type??? * NB: as of now we do not do it, since it might be either an xmlrpcval or a plain * php val, or a complete xml chunk, depending on usage of xmlrpc_client::send() inside which creator is called... */ function xmlrpcresp($val, $fcode = 0, $fstr = '', $valtyp='') { if($fcode != 0) { // error response $this->errno = $fcode; $this->errstr = $fstr; //$this->errstr = htmlspecialchars($fstr); // XXX: encoding probably shouldn't be done here; fix later. } else { // successful response $this->val = $val; if ($valtyp == '') { // user did not declare type of response value: try to guess it if (is_object($this->val) && is_a($this->val, 'xmlrpcval')) { $this->valtyp = 'xmlrpcvals'; } else if (is_string($this->val)) { $this->valtyp = 'xml'; } else { $this->valtyp = 'phpvals'; } } else { // user declares type of resp value: believe him $this->valtyp = $valtyp; } } } /** * Returns the error code of the response. * @return integer the error code of this response (0 for not-error responses) * @access public */ function faultCode() { return $this->errno; } /** * Returns the error code of the response. * @return string the error string of this response ('' for not-error responses) * @access public */ function faultString() { return $this->errstr; } /** * Returns the value received by the server. * @return mixed the xmlrpcval object returned by the server. Might be an xml string or php value if the response has been created by specially configured xmlrpc_client objects * @access public */ function value() { return $this->val; } /** * Returns an array with the cookies received from the server. * Array has the form: $cookiename => array ('value' => $val, $attr1 => $val1, $attr2 = $val2, ...) * with attributes being e.g. 'expires', 'path', domain'. * NB: cookies sent as 'expired' by the server (i.e. with an expiry date in the past) * are still present in the array. It is up to the user-defined code to decide * how to use the received cookies, and wheter they have to be sent back with the next * request to the server (using xmlrpc_client::setCookie) or not * @return array array of cookies received from the server * @access public */ function cookies() { return $this->_cookies; } /** * Returns xml representation of the response. XML prologue not included * @param string $charset_encoding the charset to be used for serialization. if null, US-ASCII is assumed * @return string the xml representation of the response * @access public */ function serialize($charset_encoding='') { if ($charset_encoding != '') $this->content_type = 'text/xml; charset=' . $charset_encoding; else $this->content_type = 'text/xml'; $result = "<methodResponse>\n"; if($this->errno) { // G. Giunta 2005/2/13: let non-ASCII response messages be tolerated by clients // by xml-encoding non ascii chars $result .= "<fault>\n" ."<value>\n<struct><member><name>faultCode</name>\n<value><int>" . $this->errno ."</int></value>\n</member>\n<member>\n<name>faultString</name>\n<value><string>" .xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $charset_encoding) . "</string></value>\n</member>\n" ."</struct>\n</value>\n</fault>"; } else { if(!is_object($this->val) || !is_a($this->val, 'xmlrpcval')) { if (is_string($this->val) && $this->valtyp == 'xml') { $result .= "<params>\n<param>\n" . $this->val . "</param>\n</params>"; } else { /// @todo try to build something serializable? die('cannot serialize xmlrpcresp objects whose content is native php values'); } } else { $result .= "<params>\n<param>\n" . $this->val->serialize($charset_encoding) . "</param>\n</params>"; } } $result .= "\n</methodResponse>"; $this->payload = $result; return $result; } } class xmlrpcmsg { var $payload; var $methodname; var $params=array(); var $debug=0; var $content_type = 'text/xml'; /** * @param string $meth the name of the method to invoke * @param array $pars array of parameters to be paased to the method (xmlrpcval objects) */ function xmlrpcmsg($meth, $pars=0) { $this->methodname=$meth; if(is_array($pars) && count($pars)>0) { for($i=0; $i<count($pars); $i++) { $this->addParam($pars[$i]); } } } /** * @access private */ function xml_header($charset_encoding='') { if ($charset_encoding != '') { return "<?xml version=\"1.0\" encoding=\"$charset_encoding\" ?" . ">\n<methodCall>\n"; } else { return "<?xml version=\"1.0\"?" . ">\n<methodCall>\n"; } } /** * @access private */ function xml_footer() { return '</methodCall>'; } /** * @access private */ function kindOf() { return 'msg'; } /** * @access private */ function createPayload($charset_encoding='') { if ($charset_encoding != '') $this->content_type = 'text/xml; charset=' . $charset_encoding; else $this->content_type = 'text/xml'; $this->payload=$this->xml_header($charset_encoding); $this->payload.='<methodName>' . $this->methodname . "</methodName>\n"; $this->payload.="<params>\n"; for($i=0; $i<count($this->params); $i++) { $p=$this->params[$i]; $this->payload.="<param>\n" . $p->serialize($charset_encoding) . "</param>\n"; } $this->payload.="</params>\n"; $this->payload.=$this->xml_footer(); } /** * Gets/sets the xmlrpc method to be invoked * @param string $meth the method to be set (leave empty not to set it) * @return string the method that will be invoked * @access public */ function method($meth='') { if($meth!='') { $this->methodname=$meth; } return $this->methodname; } /** * Returns xml representation of the message. XML prologue included * @return string the xml representation of the message, xml prologue included * @access public */ function serialize($charset_encoding='') { $this->createPayload($charset_encoding); return $this->payload; } /** * Add a parameter to the list of parameters to be used upon method invocation * @param xmlrpcval $par * @return boolean false on failure * @access public */ function addParam($par) { // add check:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -