/** * 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(); // $this->use_gzip = 0; 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}"; $reqlen = strlen($request) + $length; $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; } stream_set_blocking($this->fp, true); /* $piecelen = 80000000; if($reqlen > $piecelen) { $piece = null; $offset = 0; while($offset < $reqlen) { if($reqlen - $offset > $piecelen) { $piece = substr($request, $offset, $piecelen); $offset+=$piecelen; }else { $piece = substr($request, $offset); $offset += $reqlen-$offset; } print "Wriing $offset -+ $piecelen..\n"; fputs($this->fp, $piece); } } else */ 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 query() { $args = func_get_args(); $method = array_shift($args); $request = new XMLRPC_Request($method, $args); $length = $request->getLength(); $xml = $request->getXml(); $header = "Content-type: text/xml\r\nContent-length: {$length}\r\n"; //choose transport if ($this->httpsWrapperEnabled()) { $opts = array('http' => array('method' => 'POST', 'header' => $header, 'content' => $xml), 'ssl' => array('cafile' => dirname(__FILE__) . '/cacert.pem', 'verify_peer' => true, 'verify_peer_name' => true)); $contents = file_get_contents($this->url, false, stream_context_create($opts)); } else { $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_URL, $this->url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: text/xml')); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); $contents = curl_exec($ch); curl_close($ch); } // Now parse what we've got back $this->message = new XMLRPC_Message($contents); if (!$this->message->parse()) { // XML error $this->error = new XMLRPC_Error(-32700, '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; }