📄 xmlrpc.php
字号:
$pieces = parse_url($server); $this->method = $pieces['scheme']; $this->server = $pieces['host']; $this->port = (int)isset($pieces['port']) ? $pieces['port'] : 80; $this->path = isset($pieces['path']) ? $pieces['path'] : '/'; // Make absolutely sure we have a path if(!$this->path) { $this->path = '/'; } } else { $this->server = $server; $this->path = $path; $this->port = (int)$port; } $this->useragent = 'BTG XMLRPC PHP Client/The Incutio XML-RPC PHP Library'; $this->timeout = $timeout; if(function_exists('gzuncompress') && function_exists('gzcompress')) $this->gzip_available = true; } /** * Enabler/Disable debug mode */ function setDebug($debug) { $this->debug = (boolean)$debug; } /** * Set timeout */ function setTimeout($timeout) { $this->timeout = (int)$timeout; } /** * Enable/disable GZIP compression of sent data. */ function enableGZIP($enable) { if(!$this->gzip_available) return false; $this->use_gzip = $enable; return true; } /** * Set SSL parameters (used when a URL in form https:// is used). * The params are ssl_ca_cert, path to the the Certificate Authority cert * and ssl_client_cert, which is path to this clients certificate, PEM encoded, without encryption. */ function setSSLparams($ca_cert, $client_cert) { if(!in_array("sslv3", stream_get_transports())) { $this->error = new XMLRPC_Error(XMLRPC_Error::CONNECT_FAILED, "This PHP version does not have SSL support."); return false; } $this->ssl_ca_cert = $ca_cert; $this->ssl_client_cert = $client_cert; return true; } /** * Close any connection and clear out buffer. */ function close() { if($this->fp) { fclose($this->fp); $this->fp = null; } $this->rxbuff=""; } /** * Perform a query. Takes an unspecified number of arguments. * First argument should be method name to call. * The follow arguments will be passed to the remote server as * arguments to the method call. */ function query() { $args = func_get_args(); $this->query_arg($args); } /** * Another way to perform a query, with an array having all parameters. * Works the same way as query(), first item in array should be method name, * any subsequent items will be passed to remote server. */ function query_arg($args) { $method = array_shift($args); // Create the request and encode it $request = new XMLRPC_Request($method, $args); $xml = $request->getXml(); if($this->use_gzip) { $xml = (pack("C1C1C1C1VC1C1", 0x1f, 0x8b, 8, 0, 0, 2, 0xFF) . gzdeflate($xml) . pack("VV", crc32($xml), strlen($xml))); } $length = strlen($xml); // HTTP uses \r\n for lineendings $r = "\r\n"; $request = "POST {$this->path} HTTP/1.0$r"; $request.= "Host: {$this->server}$r"; $request.= "Content-Type: text/xml$r"; $request.= "User-Agent: {$this->useragent}$r"; if($this->gzip_available) $request.= "Accept-Encoding: gzip;q=1, identity;1=0.5$r"; // We can decode gzip which we prefer. identify (clear) works too if($this->use_gzip) $request.= "Content-Encoding: gzip$r"; // Send content gziped $request.= "Content-Length: {$length}$r$r"; $request.= $xml; //Now send the request if($this->debug) { echo '<pre>'.$request."</pre>\n\n"; } $errno = 0; $errstr = ""; if(!$this->fp) { if($this->method == "https") { if(!is_readable($this->ssl_ca_cert)) { $this->error = new XMLRPC_Error(XMLRPC_Error::CONNECT_FAILED, "SSL CA cert is missing or isnt readable."); return false; } if(!is_readable($this->ssl_client_cert)) { $this->error = new XMLRPC_Error(XMLRPC_Error::CONNECT_FAILED, "SSL client cert missing or isnt readable."); return false; } // HTTPs connection $this->context = stream_context_create( array('ssl'=>array( 'cafile'=>$this->ssl_ca_cert, 'local_cert'=>$this->ssl_client_cert )) ); $this->fp = @stream_socket_client("tls://".$this->server.":".$this->port."/", $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $this->context); } else { $this->fp = @fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout); } } if(!$this->fp) { $this->error = new XMLRPC_Error(XMLRPC_Error::CONNECT_FAILED, "Failed to connect to ".$this->server.":".$this->port.": $errstr."); return false; } fputs($this->fp, $request); $contents = ''; $headers = array(); $gotFirstLine = false; $gettingHeaders = true; $contentLength = 0; // We want blocking on first request stream_set_blocking ( $this->fp, true); while (1) { $buff = fread($this->fp, 1024); // But if we got more data queued we dont want to block... stream_set_blocking ( $this->fp, false); $this->rxbuff.= $buff; if($gettingHeaders) { while (1) { $pos = strpos($this->rxbuff, "\r\n"); if($pos === false) break; $line = trim(substr($this->rxbuff, 0, $pos)); $this->rxbuff = substr($this->rxbuff, strlen($line) + 2); if(!$gotFirstLine) { //Check line for '200' if(strstr($line, '200') === false) { $this->error = new XMLRPC_Error(XMLRPC_Error::INVALID_STATUS_CODE, 'Failed to received XMLRPC response. HTTP status code was not 200'); return false; } $gotFirstLine = true; continue; } if($line == '') { $gettingHeaders = false; $contentLength = $headers['Content-Length']; break; } list($k, $v) = explode(":", $line); $headers[trim($k)] = trim($v); } if($gettingHeaders) continue; } if(strlen($this->rxbuff) >= $contentLength) { $contents = substr($this->rxbuff, 0, $contentLength); $this->rxbuff = substr($this->rxbuff, $contentLength); break; } } if($this->gzip_available && array_key_exists("Content-Encoding", $headers)) { if($headers['Content-Encoding'] == "gzip") { $ret = gzinflate(substr($contents,10)); if($ret === false) { // The decoding failed! $this->error = new XMLRPC_Error(XMLRPC_Error::BROKEN_GZIP, 'XMLRPC response headers specified gzip encoding, failed to decompress.'); return false; } $contents = $ret; }else { // What encoding is this?! $this->error = new XMLRPC_Error(XMLRPC_Error::UNKNOWN_ENCODING, 'XLMRPC response headers specified unknown encoding: '.$headers['Content-Encoding'].'. Cannot decompress..'); return false; } } if($this->debug) { echo '<pre>'.$contents."</pre>\n\n"; } // Now parse what we 've got back $this->message = new XMLRPC_Message($contents); if(!$this->message->parse()) { // XML error if($this->debug) $this->error = new XMLRPC_Error(XMLRPC_Error::PARSE_ERROR, 'XMLRPC response parse error. Not well formed. Error: '.$this->message->parseError); else $this->error = new XMLRPC_Error(XMLRPC_Error::PARSE_ERROR, 'XMLRPC response parse error. Not well formed.'); return false; } // Is the message a fault ? if($this->message->messageType == 'fault') { $this->error = new XMLRPC_Error($this->message->faultCode, $this->message->faultString); return false; } // Message must be OK return true; } function getResponse() { // methodResponses can only have one param - return that return $this->message->params[0]; } function isError() { return (is_object($this->error)); } function getErrorCode() { return $this->error->code; } function getErrorMessage() { return $this->error->message; }}/** * A class containing either an XMLRPC fault or an internal error. * For internal error codes check $code against the constants defined below. */class XMLRPC_Error{ const CONNECT_FAILED = -32300; // Failed to open socket. const INVALID_STATUS_CODE = -32301; // Invalid (non 200) status code returned. const BROKEN_GZIP = -32302; // GZIP failed to decompress. const UNKNOWN_ENCODING = -32303; // Unknown encoding const PARSE_ERROR = -32304; // Parse error. public $code; public $message; function XMLRPC_Error($code, $message) { $this->code = $code; $this->message = $message; } function getXml() { $xml = <<<EOD<methodResponse><fault><value><struct><member><name>faultCode</name><value><int>{$this->code}</int></value></member><member><name>faultString</name><value>< tring> {$this->message}</string></value></member></struct></value></fault></methodResponse>EOD; return $xml; }}/** * Wrapper class for a date value */class XMLRPC_Date{ private $year; private $month; private $day; private $hour; private $minute; private $second; function XMLRPC_Date($time) { //$time can be a PHP timestamp or an ISO one if(is_numeric($time)) { $this->parseTimestamp($time); } else { $this->parseIso($time); } } function parseTimestamp($timestamp) { $this->year = date('Y', $timestamp); $this->month = date('Y', $timestamp); $this->day = date('Y', $timestamp); $this->hour = date('H', $timestamp); $this->minute = date('i', $timestamp); $this->second = date('s', $timestamp); } function parseIso($iso) { $this->year = substr($iso, 0, 4); $this->month = substr($iso, 4, 2); $this->day = substr($iso, 6, 2); $this->hour = substr($iso, 9, 2); $this->minute = substr($iso, 12, 2); $this->second = substr($iso, 15, 2); } function getIso() { return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second; } function getXml() { return '<dateTime.iso8601>'.$this->getIso().'</dateTime.iso8601>'; } function getTimestamp() { return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year); }}/** * Wrapper class for a base64 value */class XMLRPC_Base64{ private $data; function XMLRPC_Base64($data) { $this->data = $data; } function getXml() { return '<base64>'.base64_encode($this->data).'</base64>'; }}?>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -