⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlrpc.inc

📁 这个包主要用来帮助我们了解carrot2的格式
💻 INC
📖 第 1 页 / 共 5 页
字号:
			}

			// Only create the payload if it was not created previously
			if(empty($msg->payload))
			{
				$msg->createPayload();
			}

			// Deflate request body and set appropriate request headers
			if(function_exists('gzdeflate') && ($this->request_compression == 'gzip' || $this->request_compression == 'deflate'))
			{
				if($this->request_compression == 'gzip')
				{
					$a = @gzencode($msg->payload);
					if($a)
					{
						$msg->payload = $a;
						$encoding_hdr = "Content-Encoding: gzip";
					}
				}
				else
				{
					$a = @gzdeflate($msg->payload);
					if($a)
					{
						$msg->payload = $a;
						$encoding_hdr = "Content-Encoding: deflate";
					}
				}
			}
			else
			{
				$encoding_hdr = '';
			}

			if(!$keepalive || !$this->xmlrpc_curl_handle)
			{
				$curl = curl_init($method . '://' . $server . ':' . $port . $this->path);
				if($keepalive)
				{
					$this->xmlrpc_curl_handle = $curl;
				}
			}
			else
			{
				$curl = $this->xmlrpc_curl_handle;
			}

			// results into variable
			curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

			if($this->debug)
			{
				curl_setopt($curl, CURLOPT_VERBOSE, 1);
			}
			curl_setopt($curl, CURLOPT_USERAGENT, $GLOBALS['xmlrpcName'].' '.$GLOBALS['xmlrpcVersion']);
			// required for XMLRPC: post the data
			curl_setopt($curl, CURLOPT_POST, 1);
			// the data
			curl_setopt($curl, CURLOPT_POSTFIELDS, $msg->payload);

			// return the header too
			curl_setopt($curl, CURLOPT_HEADER, 1);

			// will only work with PHP >= 5.0
			// NB: if we set an empty string, CURL will add http header indicating
			// ALL methods it is supporting. This is possibly a better option than
			// letting the user tell what curl can / cannot do...
			if(is_array($this->accepted_compression) && count($this->accepted_compression))
			{
				//curl_setopt($curl, CURLOPT_ENCODING, implode(',', $this->accepted_compression));
				// empty string means 'any supported by CURL' (shall we catch errors in case CURLOPT_SSLKEY undefined ?)
				curl_setopt($curl, CURLOPT_ENCODING, '');
			}
			// extra headers
			$headers = array('Content-Type: ' . $msg->content_type , 'Accept-Charset: ' . implode(',', $this->accepted_charset_encodings));
			// if no keepalive is wanted, let the server know it in advance
			if(!$keepalive)
			{
				$headers[] = 'Connection: close';
			}
			// request compression header
			if($encoding_hdr)
			{
				$headers[] = $encoding_hdr;
			}

			curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
			// timeout is borked
			if($timeout)
			{
				curl_setopt($curl, CURLOPT_TIMEOUT, $timeout == 1 ? 1 : $timeout - 1);
			}

			if($username && $password)
			{
				curl_setopt($curl, CURLOPT_USERPWD,"$username:$password");
			}

			if($method == 'https')
			{
				// set cert file
				if($cert)
				{
					curl_setopt($curl, CURLOPT_SSLCERT, $cert);
				}
				// set cert password
				if($certpass)
				{
					curl_setopt($curl, CURLOPT_SSLCERTPASSWD, $certpass);
				}
				// set key file (shall we catch errors in case CURLOPT_SSLKEY undefined ?)
				if($key)
				{
					curl_setopt($curl, CURLOPT_SSLKEY, $key);
				}
				// set key password (shall we catch errors in case CURLOPT_SSLKEY undefined ?)
				if($keypass)
				{
					curl_setopt($curl, CURLOPT_SSLKEYPASSWD, $keypass);
				}
				// whether to verify remote host's cert
				curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verifypeer);
				// whether to verify cert's common name (CN); 0 for no, 1 to verify that it exists, and 2 to verify that it matches the hostname used
				curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $this->verifyhost);
			}

			// proxy info
			if($proxyhost)
			{
				if($proxyport == 0)
				{
					$proxyport = 8080; // NB: even for HTTPS, local connection is on port 8080
				}
				curl_setopt($curl, CURLOPT_PROXY,$proxyhost.':'.$proxyport);
				//curl_setopt($curl, CURLOPT_PROXYPORT,$proxyport);
				if($proxyusername)
				{
					curl_setopt($curl, CURLOPT_PROXYUSERPWD, $proxyusername.':'.$proxypassword);
				}
			}

			// NB: should we build cookie http headers by hand rather than let CURL do it?
			// the following code does not honour 'expires', 'path' and 'domain' cookie attributes
			// set to clint obj the the user...
			if (count($this->cookies))
			{
				$cookieheader = '';
				foreach ($this->cookies as $name => $cookie)
				{
					$cookieheader .= $name . '=' . $cookie['value'] . ', ';
				}
				curl_setopt($curl, CURLOPT_COOKIE, substr($cookieheader, 0, -2));
			}

			$result = curl_exec($curl);

			if(!$result)
			{
				$this->errstr='no response';
				$resp=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['curl_fail'], $GLOBALS['xmlrpcstr']['curl_fail']. ': '. curl_error($curl));
				if(!$keepalive)
				{
					curl_close($curl);
				}
			}
			else
			{
				if(!$keepalive)
				{
					curl_close($curl);
				}
				$resp =& $msg->parseResponse($result, true, $this->return_type);
			}
			return $resp;
		}

		/**
		* Send an array of request messages and return an array of responses.
		* Unless $this->no_multicall has been set to true, it will try first
		* to use one single xmlrpc call to server method system.multicall, and
		* revert to sending many successive calls in case of failure.
		* This failure is also stored in $this->no_multicall for subsequent calls.
		* Unfortunately, there is no server error code universally used to denote
		* the fact that multicall is unsupported, so there is no way to reliably
		* distinguish between that and a temporary failure.
		* If you are sure that server supports multicall and do not want to
		* fallback to using many single calls, set the fourth parameter to FALSE.
		*
		* NB: trying to shoehorn extra functionality into existing syntax has resulted
		* in pretty much convoluted code...
		*
		* @access public
		* @todo interesting things happen when
		*/
		function multicall($msgs, $timeout=0, $method='http', $fallback=true)
		{
			if(!$this->no_multicall)
			{
				$results = $this->_try_multicall($msgs, $timeout, $method);
				if(is_array($results))
				{
					// System.multicall succeeded
					return $results;
				}
				else
				{
					// either system.multicall is unsupported by server,
					// or call failed for some other reason.
					if ($fallback)
					{
						// Don't try it next time...
						$this->no_multicall = true;
					}
					else
					{
						if (is_a($result, 'xmlrpcresp'))
						{
							$result = $results;
						}
						else
						{
							$result =& new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['multicall_error'], $GLOBALS['xmlrpcstr']['multicall_error']);
						}
					}
				}
			}
			else
			{
				// override fallback, in case careless user tries to do two
				// opposite things at the same time
				$fallback = true;
			}

			$results = array();
			if ($fallback)
			{
				// system.multicall is (probably) unsupported by server:
				// emulate multicall via multiple requests
				foreach($msgs as $msg)
				{
					$results[] =& $this->send($msg, $timeout, $method);
				}
			}
			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 recived response does not respect valid multiccall 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(!is_object($result))
			//{
			//	return ($result || 0); // transport failed
			//}

			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:
							$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 $hdrs = array();
		var $_cookies = array();
		var $content_type = 'text/xml';

		/**
		* @param mixed  $val    either an xmlrpcval obj, a php value or the xml serialization of an xmlrpcval (a string)
		* @param int    $fcode
		* @param string $fstr
		* @param string $valtyp either 'xmlrpcvals', 'phpvals' or 'xml'
		*
		* @todo add check that $val 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)
			{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -