10 public $method =
'http';
19 public $username =
'';
20 public $password =
'';
24 public $certpass =
'';
26 public $cacertdir =
'';
29 public $verifypeer =
true;
30 public $verifyhost = 2;
31 public $sslversion = 0;
34 public $proxyport = 0;
35 public $proxy_user =
'';
36 public $proxy_pass =
'';
37 public $proxy_authtype = 1;
39 public $cookies = array();
40 public $extracurlopts = array();
42 public $no_multicall =
false;
53 public $accepted_compression = array();
58 public $request_compression =
'';
63 public $xmlrpc_curl_handle =
null;
65 public $keepalive =
false;
67 public $accepted_charset_encodings = array();
69 public $request_charset_encoding =
'';
74 public $return_type =
'xmlrpcvals';
86 public function __construct($path, $server =
'', $port =
'', $method =
'')
89 if ($server ==
'' and $port ==
'' and $method ==
'') {
90 $parts = parse_url($path);
91 $server = $parts[
'host'];
92 $path = isset($parts[
'path']) ? $parts[
'path'] :
'';
93 if (isset($parts[
'query'])) {
94 $path .=
'?' . $parts[
'query'];
96 if (isset($parts[
'fragment'])) {
97 $path .=
'#' . $parts[
'fragment'];
99 if (isset($parts[
'port'])) {
100 $port = $parts[
'port'];
102 if (isset($parts[
'scheme'])) {
103 $method = $parts[
'scheme'];
105 if (isset($parts[
'user'])) {
106 $this->username = $parts[
'user'];
108 if (isset($parts[
'pass'])) {
109 $this->password = $parts[
'pass'];
112 if ($path ==
'' || $path[0] !=
'/') {
113 $this->path =
'/' . $path;
117 $this->server = $server;
122 $this->method = $method;
126 if (function_exists(
'gzinflate') || (
127 function_exists(
'curl_init') && (($info = curl_version()) &&
128 ((is_string($info) && strpos($info,
'zlib') !==
null) || isset($info[
'libz_version'])))
131 $this->accepted_compression = array(
'gzip',
'deflate');
135 $this->keepalive =
true;
138 $this->accepted_charset_encodings = array(
'UTF-8',
'ISO-8859-1',
'US-ASCII');
151 $this->user_agent = PhpXmlRpc::$xmlrpcName .
' ' . PhpXmlRpc::$xmlrpcVersion;
173 $this->username = $u;
174 $this->password = $p;
175 $this->authtype = $t;
187 $this->certpass = $certPass;
200 $this->cacertdir = $caCert;
202 $this->cacert = $caCert;
217 $this->keypass = $keyPass;
227 $this->verifypeer = $i;
237 $this->verifyhost = $i;
247 $this->sslversion = $i;
259 public function setProxy($proxyHost, $proxyPort, $proxyUsername =
'', $proxyPassword =
'', $proxyAuthType = 1)
261 $this->proxy = $proxyHost;
262 $this->proxyport = $proxyPort;
263 $this->proxy_user = $proxyUsername;
264 $this->proxy_pass = $proxyPassword;
265 $this->proxy_authtype = $proxyAuthType;
278 if ($compMethod ==
'any') {
279 $this->accepted_compression = array(
'gzip',
'deflate');
280 } elseif ($compMethod ==
false) {
281 $this->accepted_compression = array();
283 $this->accepted_compression = array($compMethod);
296 $this->request_compression = $compMethod;
312 public function setCookie($name, $value =
'', $path =
'', $domain =
'', $port =
null)
314 $this->cookies[$name][
'value'] = urlencode($value);
315 if ($path || $domain || $port) {
316 $this->cookies[$name][
'path'] = $path;
317 $this->cookies[$name][
'domain'] = $domain;
318 $this->cookies[$name][
'port'] = $port;
319 $this->cookies[$name][
'version'] = 1;
321 $this->cookies[$name][
'version'] = 0;
333 $this->extracurlopts = $options;
344 $this->user_agent = $agentString;
356 public function send($req, $timeout = 0, $method =
'')
361 $method = $this->method;
364 if (is_array($req)) {
366 $r = $this->multicall($req, $timeout, $method);
369 } elseif (is_string($req)) {
376 $req->setDebug($this->debug);
378 if ($method ==
'https') {
379 $r = $this->sendPayloadHTTPS(
395 $this->proxy_authtype,
401 } elseif ($method ==
'http11') {
402 $r = $this->sendPayloadCURL(
418 $this->proxy_authtype,
423 $r = $this->sendPayloadHTTP10(
435 $this->proxy_authtype,
460 $username =
'', $password =
'', $authType = 1, $proxyHost =
'',
461 $proxyPort = 0, $proxyUsername =
'', $proxyPassword =
'', $proxyAuthType = 1,
465 $port = ( $method ===
"https" ) ? 443 : 80;
469 if (empty($req->payload)) {
470 $req->createPayload($this->request_charset_encoding);
473 $payload = $req->payload;
475 if (function_exists(
'gzdeflate') && ($this->request_compression ==
'gzip' || $this->request_compression ==
'deflate')) {
476 if ($this->request_compression ==
'gzip') {
477 $a = @gzencode($payload);
480 $encodingHdr =
"Content-Encoding: gzip\r\n";
483 $a = @gzcompress($payload);
486 $encodingHdr =
"Content-Encoding: deflate\r\n";
495 if ($username !=
'') {
496 $credentials =
'Authorization: Basic ' . base64_encode($username .
':' . $password) .
"\r\n";
497 if ($authType != 1) {
498 error_log(
'XML-RPC: ' . __METHOD__ .
': warning. Only Basic auth is supported with HTTP 1.0');
502 $acceptedEncoding =
'';
503 if (is_array($this->accepted_compression) && count($this->accepted_compression)) {
504 $acceptedEncoding =
'Accept-Encoding: ' . implode(
', ', $this->accepted_compression) .
"\r\n";
507 $proxyCredentials =
'';
509 if ($proxyPort == 0) {
512 $connectServer = $proxyHost;
513 $connectPort = $proxyPort;
515 $uri =
'http://' . $server .
':' . $port . $this->path;
516 if ($proxyUsername !=
'') {
517 if ($proxyAuthType != 1) {
518 error_log(
'XML-RPC: ' . __METHOD__ .
': warning. Only Basic auth to proxy is supported with HTTP 1.0');
520 $proxyCredentials =
'Proxy-Authorization: Basic ' . base64_encode($proxyUsername .
':' . $proxyPassword) .
"\r\n";
523 $connectServer = $server;
524 $connectPort = $port;
526 $transport = ( $method ===
"https" ) ?
"tls" :
"tcp";
533 if (count($this->cookies)) {
535 foreach ($this->cookies as $name => $cookie) {
536 if ($cookie[
'version']) {
537 $version =
' $Version="' . $cookie[
'version'] .
'";';
538 $cookieHeader .=
' ' . $name .
'="' . $cookie[
'value'] .
'";';
539 if ($cookie[
'path']) {
540 $cookieHeader .=
' $Path="' . $cookie[
'path'] .
'";';
542 if ($cookie[
'domain']) {
543 $cookieHeader .=
' $Domain="' . $cookie[
'domain'] .
'";';
545 if ($cookie[
'port']) {
546 $cookieHeader .=
' $Port="' . $cookie[
'port'] .
'";';
549 $cookieHeader .=
' ' . $name .
'=' . $cookie[
'value'] .
";";
552 $cookieHeader =
'Cookie:' . $version . substr($cookieHeader, 0, -1) .
"\r\n";
556 $port = ($port == 80) ?
'' : (
':' . $port);
558 $op =
'POST ' . $uri .
" HTTP/1.0\r\n" .
559 'User-Agent: ' . $this->user_agent .
"\r\n" .
560 'Host: ' . $server . $port .
"\r\n" .
565 'Accept-Charset: ' . implode(
',', $this->accepted_charset_encodings) .
"\r\n" .
567 'Content-Type: ' . $req->content_type .
"\r\nContent-Length: " .
568 strlen($payload) .
"\r\n\r\n" .
571 if ($this->debug > 1) {
572 Logger::instance()->debugMessage(
"---SENDING---\n$op\n---END---");
576 $fp = @stream_socket_client(
"$transport://$connectServer:$connectPort", $this->errno, $this->errstr, $timeout);
578 $fp = @stream_socket_client(
"$transport://$connectServer:$connectPort", $this->errno, $this->errstr);
582 stream_set_timeout($fp, $timeout);
585 $this->errstr =
'Connect error: ' . $this->errstr;
586 $r =
new Response(0, PhpXmlRpc::$xmlrpcerr[
'http_error'], $this->errstr .
' (' . $this->errno .
')');
591 if (!fputs($fp,
$op, strlen(
$op))) {
593 $this->errstr =
'Write error';
594 $r =
new Response(0, PhpXmlRpc::$xmlrpcerr[
'http_error'], $this->errstr);
607 $ipd .= fread($fp, 32768);
608 }
while (!feof($fp));
610 $r = $req->parseResponse($ipd,
false, $this->return_type);
639 $password =
'', $authType = 1, $cert =
'', $certPass =
'', $caCert =
'', $caCertDir =
'',
640 $proxyHost =
'', $proxyPort = 0, $proxyUsername =
'', $proxyPassword =
'', $proxyAuthType = 1,
641 $keepAlive =
false, $key =
'', $keyPass =
'', $sslVersion = 0)
643 return $this->sendPayloadCURL($req, $server, $port, $timeout, $username,
644 $password, $authType, $cert, $certPass, $caCert, $caCertDir, $proxyHost, $proxyPort,
645 $proxyUsername, $proxyPassword, $proxyAuthType,
'https', $keepAlive, $key, $keyPass, $sslVersion);
676 protected function sendPayloadCURL($req, $server, $port, $timeout = 0, $username =
'',
677 $password =
'', $authType = 1, $cert =
'', $certPass =
'', $caCert =
'', $caCertDir =
'',
678 $proxyHost =
'', $proxyPort = 0, $proxyUsername =
'', $proxyPassword =
'', $proxyAuthType = 1, $method =
'https',
679 $keepAlive =
false, $key =
'', $keyPass =
'', $sslVersion = 0)
681 if (!function_exists(
'curl_init')) {
682 $this->errstr =
'CURL unavailable on this install';
683 return new Response(0, PhpXmlRpc::$xmlrpcerr[
'no_curl'], PhpXmlRpc::$xmlrpcstr[
'no_curl']);
685 if ($method ==
'https') {
686 if (($info = curl_version()) &&
687 ((is_string($info) && strpos($info,
'OpenSSL') ===
null) || (is_array($info) && !isset($info[
'ssl_version'])))
689 $this->errstr =
'SSL unavailable on this install';
690 return new Response(0, PhpXmlRpc::$xmlrpcerr[
'no_ssl'], PhpXmlRpc::$xmlrpcstr[
'no_ssl']);
695 if ($method ==
'http') {
703 if (empty($req->payload)) {
704 $req->createPayload($this->request_charset_encoding);
708 $payload = $req->payload;
709 if (function_exists(
'gzdeflate') && ($this->request_compression ==
'gzip' || $this->request_compression ==
'deflate')) {
710 if ($this->request_compression ==
'gzip') {
711 $a = @gzencode($payload);
714 $encodingHdr =
'Content-Encoding: gzip';
717 $a = @gzcompress($payload);
720 $encodingHdr =
'Content-Encoding: deflate';
727 if ($this->debug > 1) {
728 Logger::instance()->debugMessage(
"---SENDING---\n$payload\n---END---");
731 if (!$keepAlive || !$this->xmlrpc_curl_handle) {
732 $curl = curl_init($method .
'://' . $server .
':' . $port . $this->path);
734 $this->xmlrpc_curl_handle = $curl;
737 $curl = $this->xmlrpc_curl_handle;
741 curl_setopt($curl, CURLOPT_RETURNTRANSFER,
true);
743 if ($this->debug > 1) {
744 curl_setopt($curl, CURLOPT_VERBOSE,
true);
747 curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent);
749 curl_setopt($curl, CURLOPT_POST, 1);
751 curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
754 curl_setopt($curl, CURLOPT_HEADER, 1);
759 if (is_array($this->accepted_compression) && count($this->accepted_compression)) {
762 if (count($this->accepted_compression) == 1) {
763 curl_setopt($curl, CURLOPT_ENCODING, $this->accepted_compression[0]);
765 curl_setopt($curl, CURLOPT_ENCODING,
'');
769 $headers = array(
'Content-Type: ' . $req->content_type,
'Accept-Charset: ' . implode(
',', $this->accepted_charset_encodings));
772 $headers[] =
'Connection: close';
776 $headers[] = $encodingHdr;
779 curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
782 curl_setopt($curl, CURLOPT_TIMEOUT, $timeout == 1 ? 1 : $timeout - 1);
785 if ($username && $password) {
786 curl_setopt($curl, CURLOPT_USERPWD, $username .
':' . $password);
787 if (defined(
'CURLOPT_HTTPAUTH')) {
788 curl_setopt($curl, CURLOPT_HTTPAUTH, $authType);
789 } elseif ($authType != 1) {
790 error_log(
'XML-RPC: ' . __METHOD__ .
': warning. Only Basic auth is supported by the current PHP/curl install');
794 if ($method ==
'https') {
797 curl_setopt($curl, CURLOPT_SSLCERT, $cert);
801 curl_setopt($curl, CURLOPT_SSLCERTPASSWD, $certPass);
804 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verifypeer);
807 curl_setopt($curl, CURLOPT_CAINFO, $caCert);
810 curl_setopt($curl, CURLOPT_CAPATH, $caCertDir);
814 curl_setopt($curl, CURLOPT_SSLKEY, $key);
818 curl_setopt($curl, CURLOPT_SSLKEYPASSWD, $keyPass);
821 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $this->verifyhost);
823 curl_setopt($curl, CURLOPT_SSLVERSION, $sslVersion);
828 if ($proxyPort == 0) {
831 curl_setopt($curl, CURLOPT_PROXY, $proxyHost .
':' . $proxyPort);
832 if ($proxyUsername) {
833 curl_setopt($curl, CURLOPT_PROXYUSERPWD, $proxyUsername .
':' . $proxyPassword);
834 if (defined(
'CURLOPT_PROXYAUTH')) {
835 curl_setopt($curl, CURLOPT_PROXYAUTH, $proxyAuthType);
836 } elseif ($proxyAuthType != 1) {
837 error_log(
'XML-RPC: ' . __METHOD__ .
': warning. Only Basic auth to proxy is supported by the current PHP/curl install');
845 if (count($this->cookies)) {
847 foreach ($this->cookies as $name => $cookie) {
848 $cookieHeader .= $name .
'=' . $cookie[
'value'] .
'; ';
850 curl_setopt($curl, CURLOPT_COOKIE, substr($cookieHeader, 0, -2));
853 foreach ($this->extracurlopts as $opt => $val) {
854 curl_setopt($curl, $opt, $val);
857 $result = curl_exec($curl);
859 if ($this->debug > 1) {
860 $message =
"---CURL INFO---\n";
861 foreach (curl_getinfo($curl) as $name => $val) {
862 if (is_array($val)) {
863 $val = implode(
"\n", $val);
865 $message .= $name .
': ' . $val .
"\n";
867 $message .=
"---END---";
868 Logger::instance()->debugMessage($message);
874 $this->errstr =
'no response';
875 $resp =
new Response(0, PhpXmlRpc::$xmlrpcerr[
'curl_fail'], PhpXmlRpc::$xmlrpcstr[
'curl_fail'] .
': ' . curl_error($curl));
878 $this->xmlrpc_curl_handle =
null;
884 $resp = $req->parseResponse($result,
true, $this->return_type);
886 if ($resp->faultCode() == PhpXmlRpc::$xmlrpcerr[
'http_error'] && $keepAlive) {
888 $this->xmlrpc_curl_handle =
null;
917 public function multicall($reqs, $timeout = 0, $method =
'', $fallback =
true)
920 $method = $this->method;
922 if (!$this->no_multicall) {
923 $results = $this->_try_multicall($reqs, $timeout, $method);
924 if (is_array($results)) {
932 $this->no_multicall =
true;
934 if (is_a($results,
'\PhpXmlRpc\Response')) {
937 $result =
new Response(0, PhpXmlRpc::$xmlrpcerr[
'multicall_error'], PhpXmlRpc::$xmlrpcstr[
'multicall_error']);
951 foreach ($reqs as $req) {
952 $results[] = $this->send($req, $timeout, $method);
958 foreach ($reqs as $req) {
959 $results[] = $result;
976 private function _try_multicall($reqs, $timeout, $method)
980 foreach ($reqs as $req) {
981 $call[
'methodName'] =
new Value($req->method(),
'string');
982 $numParams = $req->getNumParams();
984 for ($i = 0; $i < $numParams; $i++) {
985 $params[$i] = $req->getParam($i);
987 $call[
'params'] =
new Value($params,
'array');
988 $calls[] =
new Value($call,
'struct');
990 $multiCall =
new Request(
'system.multicall');
991 $multiCall->addParam(
new Value($calls,
'array'));
994 $result = $this->send($multiCall, $timeout, $method);
996 if ($result->faultCode() != 0) {
1002 $rets = $result->value();
1004 if ($this->return_type ==
'xml') {
1006 } elseif ($this->return_type ==
'phpvals') {
1008 $rets = $result->value();
1009 if (!is_array($rets)) {
1012 $numRets = count($rets);
1013 if ($numRets != count($reqs)) {
1017 $response = array();
1018 for ($i = 0; $i < $numRets; $i++) {
1020 if (!is_array($val)) {
1023 switch (count($val)) {
1025 if (!isset($val[0])) {
1029 $response[$i] =
new Response($val[0], 0,
'',
'phpvals');
1033 $code = @$val[
'faultCode'];
1034 if (!is_int($code)) {
1037 $str = @$val[
'faultString'];
1038 if (!is_string($str)) {
1041 $response[$i] =
new Response(0, $code, $str);
1052 $rets = $result->value();
1053 if ($rets->kindOf() !=
'array') {
1056 $numRets = $rets->count();
1057 if ($numRets != count($reqs)) {
1061 $response = array();
1062 foreach($rets as $val) {
1063 switch ($val->kindOf()) {
1065 if ($val->count() != 1) {
1069 $response[] =
new Response($val[0]);
1072 $code = $val[
'faultCode'];
1073 if ($code->kindOf() !=
'scalar' || $code->scalartyp() !=
'int') {
1076 $str = $val[
'faultString'];
1077 if ($str->kindOf() !=
'scalar' || $str->scalartyp() !=
'string') {
1080 $response[] =
new Response(0, $code->scalarval(), $str->scalarval());