-
-{$this->method}
-
-
-EOD;
- foreach ($this->args as $arg) {
- $this->xml .= '';
- $v = new IXR_Value($arg);
- $this->xml .= $v->getXml();
- $this->xml .= "";
- }
- $this->xml .= '';
- }
- function getLength() {
- return strlen($this->xml);
- }
- function getXml() {
- return $this->xml;
- }
-}
-
-
-class IXR_Client {
- var $server;
- var $port;
- var $path;
- var $useragent;
- var $response;
- var $message = false;
- var $debug = false;
- // Storage place for an error message
- var $error = false;
- function IXR_Client($server, $path = false, $port = 80) {
- if (!$path) {
- // Assume we have been given a URL instead
- $bits = parse_url($server);
- $this->server = $bits['host'];
- $this->port = isset($bits['port']) ? $bits['port'] : 80;
- $this->path = isset($bits['path']) ? $bits['path'] : '/';
- // Make absolutely sure we have a path
- if (!$this->path) {
- $this->path = '/';
- }
- } else {
- $this->server = $server;
- $this->path = $path;
- $this->port = $port;
- }
- $this->useragent = 'The Incutio XML-RPC PHP Library';
- }
- function query() {
- $args = func_get_args();
- $method = array_shift($args);
- $request = new IXR_Request($method, $args);
- $length = $request->getLength();
- $xml = $request->getXml();
- $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";
- $request .= "Content-length: {$length}$r$r";
- $request .= $xml;
- // Now send the request
- if ($this->debug) {
- echo ''.htmlspecialchars($request)."\n
\n\n";
- }
- $fp = @fsockopen($this->server, $this->port);
- if (!$fp) {
- $this->error = new IXR_Error(-32300, 'transport error - could not open socket');
- return false;
- }
- fputs($fp, $request);
- $contents = '';
- $gotFirstLine = false;
- $gettingHeaders = true;
- while (!feof($fp)) {
- $line = fgets($fp, 4096);
- if (!$gotFirstLine) {
- // Check line for '200'
- if (strstr($line, '200') === false) {
- $this->error = new IXR_Error(-32300, 'transport error - HTTP status code was not 200');
- return false;
- }
- $gotFirstLine = true;
- }
- if (trim($line) == '') {
- $gettingHeaders = false;
- }
- if (!$gettingHeaders) {
- $contents .= trim($line)."\n";
- }
- }
- if ($this->debug) {
- echo ''.htmlspecialchars($contents)."\n
\n\n";
- }
- // Now parse what we've got back
- $this->message = new IXR_Message($contents);
- if (!$this->message->parse()) {
- // XML error
- $this->error = new IXR_Error(-32700, 'parse error. not well formed');
- return false;
- }
- // Is the message a fault?
- if ($this->message->messageType == 'fault') {
- $this->error = new IXR_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;
- }
-}
-
-
-class IXR_Error {
- var $code;
- var $message;
- function IXR_Error($code, $message) {
- $this->code = $code;
- $this->message = $message;
- }
- function getXml() {
- $xml = <<
-
-
-
-
- faultCode
- {$this->code}
-
-
- faultString
- {$this->message}
-
-
-
-
-
-
-EOD;
- return $xml;
- }
-}
-
-
-class IXR_Date {
- var $year;
- var $month;
- var $day;
- var $hour;
- var $minute;
- var $second;
- function IXR_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 ''.$this->getIso().'';
- }
- function getTimestamp() {
- return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
- }
-}
-
-class LLBlock {
- var $data;
- var $xml;
-
- function LLBlock($data) {
- $this->data = $data;
- }
-
- function getXml() {
- if(count($this->data)>0) {
- $this->xml="";
- foreach($this->data as $name => $value) {
- $this->xml=$this->xml."".$name."".$value."";
- }
- $this->xml=$this->xml."";
- return $this->xml;
- }
- }
-}
-
-class IXR_Base64 {
- var $data;
- function IXR_Base64($data) {
- $this->data = $data;
- }
- function getXml() {
- return ''.base64_encode($this->data).'';
- }
-}
-
-
-class IXR_IntrospectionServer extends IXR_Server {
- var $signatures;
- var $help;
- function IXR_IntrospectionServer() {
- $this->setCallbacks();
- $this->setCapabilities();
- $this->capabilities['introspection'] = array(
- 'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html',
- 'specVersion' => 1
- );
- $this->addCallback(
- 'system.methodSignature',
- 'this:methodSignature',
- array('array', 'string'),
- 'Returns an array describing the return type and required parameters of a method'
- );
- $this->addCallback(
- 'system.getCapabilities',
- 'this:getCapabilities',
- array('struct'),
- 'Returns a struct describing the XML-RPC specifications supported by this server'
- );
- $this->addCallback(
- 'system.listMethods',
- 'this:listMethods',
- array('array'),
- 'Returns an array of available methods on this server'
- );
- $this->addCallback(
- 'system.methodHelp',
- 'this:methodHelp',
- array('string', 'string'),
- 'Returns a documentation string for the specified method'
- );
- }
- function addCallback($method, $callback, $args, $help) {
- $this->callbacks[$method] = $callback;
- $this->signatures[$method] = $args;
- $this->help[$method] = $help;
- }
- function call($methodname, $args) {
- // Make sure it's in an array
- if ($args && !is_array($args)) {
- $args = array($args);
- }
- // Over-rides default call method, adds signature check
- if (!$this->hasMethod($methodname)) {
- return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.');
- }
- $method = $this->callbacks[$methodname];
- $signature = $this->signatures[$methodname];
- $returnType = array_shift($signature);
- // Check the number of arguments
- if (count($args) != count($signature)) {
- // print 'Num of args: '.count($args).' Num in signature: '.count($signature);
- return new IXR_Error(-32602, 'server error. wrong number of method parameters');
- }
- // Check the argument types
- $ok = true;
- $argsbackup = $args;
- for ($i = 0, $j = count($args); $i < $j; $i++) {
- $arg = array_shift($args);
- $type = array_shift($signature);
- switch ($type) {
- case 'int':
- case 'i4':
- if (is_array($arg) || !is_int($arg)) {
- $ok = false;
- }
- break;
- case 'base64':
- case 'string':
- if (!is_string($arg)) {
- $ok = false;
- }
- break;
- case 'boolean':
- if ($arg !== false && $arg !== true) {
- $ok = false;
- }
- break;
- case 'float':
- case 'double':
- if (!is_float($arg)) {
- $ok = false;
- }
- break;
- case 'date':
- case 'dateTime.iso8601':
- if (!is_a($arg, 'IXR_Date')) {
- $ok = false;
- }
- break;
- }
- if (!$ok) {
- return new IXR_Error(-32602, 'server error. invalid method parameters');
- }
- }
- // It passed the test - run the "real" method call
- return parent::call($methodname, $argsbackup);
- }
- function methodSignature($method) {
- if (!$this->hasMethod($method)) {
- return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.');
- }
- // We should be returning an array of types
- $types = $this->signatures[$method];
- $return = array();
- foreach ($types as $type) {
- switch ($type) {
- case 'string':
- $return[] = 'string';
- break;
- case 'int':
- case 'i4':
- $return[] = 42;
- break;
- case 'double':
- $return[] = 3.1415;
- break;
- case 'dateTime.iso8601':
- $return[] = new IXR_Date(time());
- break;
- case 'boolean':
- $return[] = true;
- break;
- case 'base64':
- $return[] = new IXR_Base64('base64');
- break;
- case 'array':
- $return[] = array('array');
- break;
- case 'struct':
- $return[] = array('struct' => 'struct');
- break;
- }
- }
- return $return;
- }
- function methodHelp($method) {
- return $this->help[$method];
- }
-}
-
-
-class IXR_ClientMulticall extends IXR_Client {
- var $calls = array();
- function IXR_ClientMulticall($server, $path = false, $port = 80) {
- parent::IXR_Client($server, $path, $port);
- $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)';
- }
- function addCall() {
- $args = func_get_args();
- $methodName = array_shift($args);
- $struct = array(
- 'methodName' => $methodName,
- 'params' => $args
- );
- $this->calls[] = $struct;
- }
- function query() {
- // Prepare multicall, then call the parent::query() method
- return parent::query('system.multicall', $this->calls);
- }
-}
-
-?>