00001 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 if ( ! function_exists('xml_parser_create'))
00017 {
00018 show_error('Your PHP installation does not support XML');
00019 }
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 class CI_Xmlrpc {
00034
00035 var $debug = FALSE;
00036 var $xmlrpcI4 = 'i4';
00037 var $xmlrpcInt = 'int';
00038 var $xmlrpcBoolean = 'boolean';
00039 var $xmlrpcDouble = 'double';
00040 var $xmlrpcString = 'string';
00041 var $xmlrpcDateTime = 'datetime.iso8601';
00042 var $xmlrpcBase64 = 'base64';
00043 var $xmlrpcArray = 'array';
00044 var $xmlrpcStruct = 'struct';
00045
00046 var $xmlrpcTypes = array();
00047 var $valid_parents = array();
00048 var $xmlrpcerr = array();
00049 var $xmlrpcstr = array();
00050
00051 var $xmlrpc_defencoding = 'UTF-8';
00052 var $xmlrpcName = 'XML-RPC for CodeIgniter';
00053 var $xmlrpcVersion = '1.1';
00054 var $xmlrpcerruser = 800;
00055 var $xmlrpcerrxml = 100;
00056 var $xmlrpc_backslash = '';
00057
00058 var $client;
00059 var $method;
00060 var $data;
00061 var $message = '';
00062 var $error = '';
00063 var $result;
00064 var $response = array();
00065
00066
00067
00068
00069
00070
00071 function CI_Xmlrpc ($config = array())
00072 {
00073 $this->xmlrpcName = $this->xmlrpcName;
00074 $this->xmlrpc_backslash = chr(92).chr(92);
00075
00076
00077 $this->xmlrpcTypes = array(
00078 $this->xmlrpcI4 => '1',
00079 $this->xmlrpcInt => '1',
00080 $this->xmlrpcBoolean => '1',
00081 $this->xmlrpcString => '1',
00082 $this->xmlrpcDouble => '1',
00083 $this->xmlrpcDateTime => '1',
00084 $this->xmlrpcBase64 => '1',
00085 $this->xmlrpcArray => '2',
00086 $this->xmlrpcStruct => '3'
00087 );
00088
00089
00090 $this->valid_parents = array('BOOLEAN' => array('VALUE'),
00091 'I4' => array('VALUE'),
00092 'INT' => array('VALUE'),
00093 'STRING' => array('VALUE'),
00094 'DOUBLE' => array('VALUE'),
00095 'DATETIME.ISO8601' => array('VALUE'),
00096 'BASE64' => array('VALUE'),
00097 'ARRAY' => array('VALUE'),
00098 'STRUCT' => array('VALUE'),
00099 'PARAM' => array('PARAMS'),
00100 'METHODNAME' => array('METHODCALL'),
00101 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'),
00102 'MEMBER' => array('STRUCT'),
00103 'NAME' => array('MEMBER'),
00104 'DATA' => array('ARRAY'),
00105 'FAULT' => array('METHODRESPONSE'),
00106 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT')
00107 );
00108
00109
00110
00111 $this->xmlrpcerr['unknown_method'] = '1';
00112 $this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';
00113 $this->xmlrpcerr['invalid_return'] = '2';
00114 $this->xmlrpcstr['invalid_return'] = 'The XML data receieved was either invalid or not in the correct form for XML-RPC. Turn on debugging to examine the XML data further.';
00115 $this->xmlrpcerr['incorrect_params'] = '3';
00116 $this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';
00117 $this->xmlrpcerr['introspect_unknown'] = '4';
00118 $this->xmlrpcstr['introspect_unknown'] = "Cannot inspect signature for request: method unknown";
00119 $this->xmlrpcerr['http_error'] = '5';
00120 $this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";
00121 $this->xmlrpcerr['no_data'] = '6';
00122 $this->xmlrpcstr['no_data'] ='No data received from server.';
00123
00124 $this->initialize($config);
00125
00126 log_message('debug', "XML-RPC Class Initialized");
00127 }
00128
00129
00130
00131
00132
00133
00134 function initialize($config = array())
00135 {
00136 if (sizeof($config) > 0)
00137 {
00138 foreach ($config as $key => $val)
00139 {
00140 if (isset($this->$key))
00141 {
00142 $this->$key = $val;
00143 }
00144 }
00145 }
00146 }
00147
00148
00149
00150
00151
00152
00153 function server($url, $port=80)
00154 {
00155 if (substr($url, 0, 4) != "http")
00156 {
00157 $url = "http://".$url;
00158 }
00159
00160 $parts = parse_url($url);
00161
00162 $path = ( ! isset($parts['path'])) ? '/' : $parts['path'];
00163
00164 if (isset($parts['query']) && $parts['query'] != '')
00165 {
00166 $path .= '?'.$parts['query'];
00167 }
00168
00169 $this->client = new XML_RPC_Client($path, $parts['host'], $port);
00170 }
00171
00172
00173
00174
00175
00176
00177 function timeout($seconds=5)
00178 {
00179 if ( ! is_null($this->client) && is_int($seconds))
00180 {
00181 $this->client->timeout = $seconds;
00182 }
00183 }
00184
00185
00186
00187
00188
00189
00190 function method($function)
00191 {
00192 $this->method = $function;
00193 }
00194
00195
00196
00197
00198
00199
00200 function request($incoming)
00201 {
00202 if ( ! is_array($incoming))
00203 {
00204
00205 }
00206
00207 $this->data = array();
00208
00209 foreach($incoming as $key => $value)
00210 {
00211 $this->data[$key] = $this->values_parsing($value);
00212 }
00213 }
00214
00215
00216
00217
00218
00219
00220
00221 function set_debug($flag = TRUE)
00222 {
00223 $this->debug = ($flag == TRUE) ? TRUE : FALSE;
00224 }
00225
00226
00227
00228
00229
00230 function values_parsing($value, $return = FALSE)
00231 {
00232 if (is_array($value) && isset($value['0']))
00233 {
00234 if ( ! isset($value['1']) OR ! isset($this->xmlrpcTypes[strtolower($value['1'])]))
00235 {
00236 if (is_array($value[0]))
00237 {
00238 $temp = new XML_RPC_Values($value['0'], 'array');
00239 }
00240 else
00241 {
00242 $temp = new XML_RPC_Values($value['0'], 'string');
00243 }
00244 }
00245 elseif(is_array($value['0']) && ($value['1'] == 'struct' OR $value['1'] == 'array'))
00246 {
00247 while (list($k) = each($value['0']))
00248 {
00249 $value['0'][$k] = $this->values_parsing($value['0'][$k], TRUE);
00250 }
00251
00252 $temp = new XML_RPC_Values($value['0'], $value['1']);
00253 }
00254 else
00255 {
00256 $temp = new XML_RPC_Values($value['0'], $value['1']);
00257 }
00258 }
00259 else
00260 {
00261 $temp = new XML_RPC_Values($value, 'string');
00262 }
00263
00264 return $temp;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273 function send_request()
00274 {
00275 $this->message = new XML_RPC_Message($this->method,$this->data);
00276 $this->message->debug = $this->debug;
00277
00278 if ( ! $this->result = $this->client->send($this->message))
00279 {
00280 $this->error = $this->result->errstr;
00281 return FALSE;
00282 }
00283 elseif( ! is_object($this->result->val))
00284 {
00285 $this->error = $this->result->errstr;
00286 return FALSE;
00287 }
00288
00289 $this->response = $this->result->decode();
00290
00291 return TRUE;
00292 }
00293
00294
00295
00296
00297
00298
00299 function display_error()
00300 {
00301 return $this->error;
00302 }
00303
00304
00305
00306
00307
00308
00309 function display_response()
00310 {
00311 return $this->response;
00312 }
00313
00314
00315
00316
00317
00318
00319 function send_error_message($number, $message)
00320 {
00321 return new XML_RPC_Response('0',$number, $message);
00322 }
00323
00324
00325
00326
00327
00328
00329
00330 function send_response($response)
00331 {
00332
00333
00334
00335 $response = $this->values_parsing($response);
00336
00337 return new XML_RPC_Response($response);
00338 }
00339
00340
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 class XML_RPC_Client extends CI_Xmlrpc
00353 {
00354 var $path = '';
00355 var $server = '';
00356 var $port = 80;
00357 var $errno = '';
00358 var $errstring = '';
00359 var $timeout = 5;
00360 var $no_multicall = false;
00361
00362 function XML_RPC_Client($path, $server, $port=80)
00363 {
00364 parent::CI_Xmlrpc();
00365
00366 $this->port = $port;
00367 $this->server = $server;
00368 $this->path = $path;
00369 }
00370
00371 function send($msg)
00372 {
00373 if (is_array($msg))
00374 {
00375
00376 $r = new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'],$this->xmlrpcstr['multicall_recursion']);
00377 return $r;
00378 }
00379
00380 return $this->sendPayload($msg);
00381 }
00382
00383 function sendPayload($msg)
00384 {
00385 $fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstr, $this->timeout);
00386
00387 if ( ! is_resource($fp))
00388 {
00389 error_log($this->xmlrpcstr['http_error']);
00390 $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'],$this->xmlrpcstr['http_error']);
00391 return $r;
00392 }
00393
00394 if(empty($msg->payload))
00395 {
00396
00397 $msg->createPayload();
00398 }
00399
00400 $r = "\r\n";
00401 $op = "POST {$this->path} HTTP/1.0$r";
00402 $op .= "Host: {$this->server}$r";
00403 $op .= "Content-Type: text/xml$r";
00404 $op .= "User-Agent: {$this->xmlrpcName}$r";
00405 $op .= "Content-Length: ".strlen($msg->payload). "$r$r";
00406 $op .= $msg->payload;
00407
00408
00409 if ( ! fputs($fp, $op, strlen($op)))
00410 {
00411 error_log($this->xmlrpcstr['http_error']);
00412 $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
00413 return $r;
00414 }
00415 $resp = $msg->parseResponse($fp);
00416 fclose($fp);
00417 return $resp;
00418 }
00419
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 class XML_RPC_Response
00431 {
00432 var $val = 0;
00433 var $errno = 0;
00434 var $errstr = '';
00435 var $headers = array();
00436
00437 function XML_RPC_Response($val, $code = 0, $fstr = '')
00438 {
00439 if ($code != 0)
00440 {
00441
00442 $this->errno = $code;
00443 $this->errstr = htmlentities($fstr);
00444 }
00445 else if ( ! is_object($val))
00446 {
00447
00448 error_log("Invalid type '" . gettype($val) . "' (value: $val) passed to XML_RPC_Response. Defaulting to empty value.");
00449 $this->val = new XML_RPC_Values();
00450 }
00451 else
00452 {
00453 $this->val = $val;
00454 }
00455 }
00456
00457 function faultCode()
00458 {
00459 return $this->errno;
00460 }
00461
00462 function faultString()
00463 {
00464 return $this->errstr;
00465 }
00466
00467 function value()
00468 {
00469 return $this->val;
00470 }
00471
00472 function prepare_response()
00473 {
00474 $result = "<methodResponse>\n";
00475 if ($this->errno)
00476 {
00477 $result .= '<fault>
00478 <value>
00479 <struct>
00480 <member>
00481 <name>faultCode</name>
00482 <value><int>' . $this->errno . '</int></value>
00483 </member>
00484 <member>
00485 <name>faultString</name>
00486 <value><string>' . $this->errstr . '</string></value>
00487 </member>
00488 </struct>
00489 </value>
00490 </fault>';
00491 }
00492 else
00493 {
00494 $result .= "<params>\n<param>\n" .
00495 $this->val->serialize_class() .
00496 "</param>\n</params>";
00497 }
00498 $result .= "\n</methodResponse>";
00499 return $result;
00500 }
00501
00502 function decode($array=FALSE)
00503 {
00504 $CI =& get_instance();
00505
00506 if ($array !== FALSE && is_array($array))
00507 {
00508 while (list($key) = each($array))
00509 {
00510 if (is_array($array[$key]))
00511 {
00512 $array[$key] = $this->decode($array[$key]);
00513 }
00514 else
00515 {
00516 $array[$key] = $CI->input->xss_clean($array[$key]);
00517 }
00518 }
00519
00520 $result = $array;
00521 }
00522 else
00523 {
00524 $result = $this->xmlrpc_decoder($this->val);
00525
00526 if (is_array($result))
00527 {
00528 $result = $this->decode($result);
00529 }
00530 else
00531 {
00532 $result = $CI->input->xss_clean($result);
00533 }
00534 }
00535
00536 return $result;
00537 }
00538
00539
00540
00541
00542
00543
00544
00545 function xmlrpc_decoder($xmlrpc_val)
00546 {
00547 $kind = $xmlrpc_val->kindOf();
00548
00549 if($kind == 'scalar')
00550 {
00551 return $xmlrpc_val->scalarval();
00552 }
00553 elseif($kind == 'array')
00554 {
00555 reset($xmlrpc_val->me);
00556 list($a,$b) = each($xmlrpc_val->me);
00557 $size = sizeof($b);
00558
00559 $arr = array();
00560
00561 for($i = 0; $i < $size; $i++)
00562 {
00563 $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
00564 }
00565 return $arr;
00566 }
00567 elseif($kind == 'struct')
00568 {
00569 reset($xmlrpc_val->me['struct']);
00570 $arr = array();
00571
00572 while(list($key,$value) = each($xmlrpc_val->me['struct']))
00573 {
00574 $arr[$key] = $this->xmlrpc_decoder($value);
00575 }
00576 return $arr;
00577 }
00578 }
00579
00580
00581
00582
00583
00584
00585 function iso8601_decode($time, $utc=0)
00586 {
00587
00588 $t = 0;
00589 if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
00590 {
00591 if ($utc == 1)
00592 $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
00593 else
00594 $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
00595 }
00596 return $t;
00597 }
00598
00599 }
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 class XML_RPC_Message extends CI_Xmlrpc
00611 {
00612 var $payload;
00613 var $method_name;
00614 var $params = array();
00615 var $xh = array();
00616
00617 function XML_RPC_Message($method, $pars=0)
00618 {
00619 parent::CI_Xmlrpc();
00620
00621 $this->method_name = $method;
00622 if (is_array($pars) && sizeof($pars) > 0)
00623 {
00624 for($i=0; $i<sizeof($pars); $i++)
00625 {
00626
00627 $this->params[] = $pars[$i];
00628 }
00629 }
00630 }
00631
00632
00633
00634
00635
00636 function createPayload()
00637 {
00638 $this->payload = "<?xml version=\"1.0\"?".">\r\n<methodCall>\r\n";
00639 $this->payload .= '<methodName>' . $this->method_name . "</methodName>\r\n";
00640 $this->payload .= "<params>\r\n";
00641
00642 for($i=0; $i<sizeof($this->params); $i++)
00643 {
00644
00645 $p = $this->params[$i];
00646 $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
00647 }
00648
00649 $this->payload .= "</params>\r\n</methodCall>\r\n";
00650 }
00651
00652
00653
00654
00655
00656 function parseResponse($fp)
00657 {
00658 $data = '';
00659
00660 while($datum = fread($fp, 4096))
00661 {
00662 $data .= $datum;
00663 }
00664
00665
00666
00667
00668
00669 if ($this->debug === TRUE)
00670 {
00671 echo "<pre>";
00672 echo "---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n";
00673 echo "</pre>";
00674 }
00675
00676
00677
00678
00679
00680 if($data == "")
00681 {
00682 error_log($this->xmlrpcstr['no_data']);
00683 $r = new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
00684 return $r;
00685 }
00686
00687
00688
00689
00690
00691
00692 if (strncmp($data, 'HTTP', 4) == 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
00693 {
00694 $errstr= substr($data, 0, strpos($data, "\n")-1);
00695 $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']. ' (' . $errstr . ')');
00696 return $r;
00697 }
00698
00699
00700
00701
00702
00703 $parser = xml_parser_create($this->xmlrpc_defencoding);
00704
00705 $this->xh[$parser] = array();
00706 $this->xh[$parser]['isf'] = 0;
00707 $this->xh[$parser]['ac'] = '';
00708 $this->xh[$parser]['headers'] = array();
00709 $this->xh[$parser]['stack'] = array();
00710 $this->xh[$parser]['valuestack'] = array();
00711 $this->xh[$parser]['isf_reason'] = 0;
00712
00713 xml_set_object($parser, $this);
00714 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
00715 xml_set_element_handler($parser, 'open_tag', 'closing_tag');
00716 xml_set_character_data_handler($parser, 'character_data');
00717
00718
00719
00720
00721
00722
00723
00724 $lines = explode("\r\n", $data);
00725 while (($line = array_shift($lines)))
00726 {
00727 if (strlen($line) < 1)
00728 {
00729 break;
00730 }
00731 $this->xh[$parser]['headers'][] = $line;
00732 }
00733 $data = implode("\r\n", $lines);
00734
00735
00736
00737
00738
00739
00740 if ( ! xml_parse($parser, $data, sizeof($data)))
00741 {
00742 $errstr = sprintf('XML error: %s at line %d',
00743 xml_error_string(xml_get_error_code($parser)),
00744 xml_get_current_line_number($parser));
00745
00746 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
00747 xml_parser_free($parser);
00748 return $r;
00749 }
00750 xml_parser_free($parser);
00751
00752
00753
00754
00755
00756 if ($this->xh[$parser]['isf'] > 1)
00757 {
00758 if ($this->debug === TRUE)
00759 {
00760 echo "---Invalid Return---\n";
00761 echo $this->xh[$parser]['isf_reason'];
00762 echo "---Invalid Return---\n\n";
00763 }
00764
00765 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
00766 return $r;
00767 }
00768 elseif ( ! is_object($this->xh[$parser]['value']))
00769 {
00770 $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
00771 return $r;
00772 }
00773
00774
00775
00776
00777
00778 if ($this->debug === TRUE)
00779 {
00780 echo "<pre>";
00781
00782 if (count($this->xh[$parser]['headers'] > 0))
00783 {
00784 echo "---HEADERS---\n";
00785 foreach ($this->xh[$parser]['headers'] as $header)
00786 {
00787 echo "$header\n";
00788 }
00789 echo "---END HEADERS---\n\n";
00790 }
00791
00792 echo "---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n";
00793
00794 echo "---PARSED---\n" ;
00795 var_dump($this->xh[$parser]['value']);
00796 echo "\n---END PARSED---</pre>";
00797 }
00798
00799
00800
00801
00802
00803 $v = $this->xh[$parser]['value'];
00804
00805 if ($this->xh[$parser]['isf'])
00806 {
00807 $errno_v = $v->me['struct']['faultCode'];
00808 $errstr_v = $v->me['struct']['faultString'];
00809 $errno = $errno_v->scalarval();
00810
00811 if ($errno == 0)
00812 {
00813
00814 $errno = -1;
00815 }
00816
00817 $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
00818 }
00819 else
00820 {
00821 $r = new XML_RPC_Response($v);
00822 }
00823
00824 $r->headers = $this->xh[$parser]['headers'];
00825 return $r;
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 function open_tag($the_parser, $name, $attrs)
00847 {
00848
00849 if ($this->xh[$the_parser]['isf'] > 1) return;
00850
00851
00852
00853 if (count($this->xh[$the_parser]['stack']) == 0)
00854 {
00855 if ($name != 'METHODRESPONSE' && $name != 'METHODCALL')
00856 {
00857 $this->xh[$the_parser]['isf'] = 2;
00858 $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
00859 return;
00860 }
00861 }
00862 else
00863 {
00864
00865 if ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
00866 {
00867 $this->xh[$the_parser]['isf'] = 2;
00868 $this->xh[$the_parser]['isf_reason'] = "XML-RPC element $name cannot be child of ".$this->xh[$the_parser]['stack'][0];
00869 return;
00870 }
00871 }
00872
00873 switch($name)
00874 {
00875 case 'STRUCT':
00876 case 'ARRAY':
00877
00878
00879 $cur_val = array('value' => array(),
00880 'type' => $name);
00881
00882 array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
00883 break;
00884 case 'METHODNAME':
00885 case 'NAME':
00886 $this->xh[$the_parser]['ac'] = '';
00887 break;
00888 case 'FAULT':
00889 $this->xh[$the_parser]['isf'] = 1;
00890 break;
00891 case 'PARAM':
00892 $this->xh[$the_parser]['value'] = null;
00893 break;
00894 case 'VALUE':
00895 $this->xh[$the_parser]['vt'] = 'value';
00896 $this->xh[$the_parser]['ac'] = '';
00897 $this->xh[$the_parser]['lv'] = 1;
00898 break;
00899 case 'I4':
00900 case 'INT':
00901 case 'STRING':
00902 case 'BOOLEAN':
00903 case 'DOUBLE':
00904 case 'DATETIME.ISO8601':
00905 case 'BASE64':
00906 if ($this->xh[$the_parser]['vt'] != 'value')
00907 {
00908
00909 $this->xh[$the_parser]['isf'] = 2;
00910 $this->xh[$the_parser]['isf_reason'] = "'Twas a $name element following a ".$this->xh[$the_parser]['vt']." element inside a single value";
00911 return;
00912 }
00913
00914 $this->xh[$the_parser]['ac'] = '';
00915 break;
00916 case 'MEMBER':
00917
00918 $this->xh[$the_parser]['valuestack'][0]['name'] = '';
00919
00920
00921 $this->xh[$the_parser]['value'] = null;
00922 break;
00923 case 'DATA':
00924 case 'METHODCALL':
00925 case 'METHODRESPONSE':
00926 case 'PARAMS':
00927
00928 break;
00929 default:
00930
00931 $this->xh[$the_parser]['isf'] = 2;
00932 $this->xh[$the_parser]['isf_reason'] = "Invalid XML-RPC element found: $name";
00933 break;
00934 }
00935
00936
00937 array_unshift($this->xh[$the_parser]['stack'], $name);
00938
00939 if ($name != 'VALUE') $this->xh[$the_parser]['lv'] = 0;
00940 }
00941
00942
00943
00944
00945
00946
00947
00948 function closing_tag($the_parser, $name)
00949 {
00950 if ($this->xh[$the_parser]['isf'] > 1) return;
00951
00952
00953
00954
00955
00956
00957 $curr_elem = array_shift($this->xh[$the_parser]['stack']);
00958
00959 switch($name)
00960 {
00961 case 'STRUCT':
00962 case 'ARRAY':
00963 $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
00964 $this->xh[$the_parser]['value'] = ( ! isset($cur_val['values'])) ? array() : $cur_val['values'];
00965 $this->xh[$the_parser]['vt'] = strtolower($name);
00966 break;
00967 case 'NAME':
00968 $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
00969 break;
00970 case 'BOOLEAN':
00971 case 'I4':
00972 case 'INT':
00973 case 'STRING':
00974 case 'DOUBLE':
00975 case 'DATETIME.ISO8601':
00976 case 'BASE64':
00977 $this->xh[$the_parser]['vt'] = strtolower($name);
00978
00979 if ($name == 'STRING')
00980 {
00981 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
00982 }
00983 elseif ($name=='DATETIME.ISO8601')
00984 {
00985 $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
00986 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
00987 }
00988 elseif ($name=='BASE64')
00989 {
00990 $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
00991 }
00992 elseif ($name=='BOOLEAN')
00993 {
00994
00995 if ($this->xh[$the_parser]['ac'] == '1')
00996 {
00997 $this->xh[$the_parser]['value'] = TRUE;
00998 }
00999 else
01000 {
01001 $this->xh[$the_parser]['value'] = FALSE;
01002 }
01003 }
01004 elseif ($name=='DOUBLE')
01005 {
01006
01007
01008 if ( ! preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac']))
01009 {
01010 $this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND';
01011 }
01012 else
01013 {
01014 $this->xh[$the_parser]['value'] = (double)$this->xh[$the_parser]['ac'];
01015 }
01016 }
01017 else
01018 {
01019
01020
01021 if ( ! preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac']))
01022 {
01023 $this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND';
01024 }
01025 else
01026 {
01027 $this->xh[$the_parser]['value'] = (int)$this->xh[$the_parser]['ac'];
01028 }
01029 }
01030 $this->xh[$the_parser]['ac'] = '';
01031 $this->xh[$the_parser]['lv'] = 3;
01032 break;
01033 case 'VALUE':
01034
01035 if ($this->xh[$the_parser]['vt']=='value')
01036 {
01037 $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
01038 $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
01039 }
01040
01041
01042 $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
01043
01044 if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] == 'ARRAY')
01045 {
01046
01047 $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
01048 }
01049 else
01050 {
01051
01052 $this->xh[$the_parser]['value'] = $temp;
01053 }
01054 break;
01055 case 'MEMBER':
01056 $this->xh[$the_parser]['ac']='';
01057
01058
01059 if ($this->xh[$the_parser]['value'])
01060 {
01061 $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
01062 }
01063 break;
01064 case 'DATA':
01065 $this->xh[$the_parser]['ac']='';
01066 break;
01067 case 'PARAM':
01068 if ($this->xh[$the_parser]['value'])
01069 {
01070 $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
01071 }
01072 break;
01073 case 'METHODNAME':
01074 $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
01075 break;
01076 case 'PARAMS':
01077 case 'FAULT':
01078 case 'METHODCALL':
01079 case 'METHORESPONSE':
01080
01081 break;
01082 default:
01083
01084 break;
01085 }
01086 }
01087
01088
01089
01090
01091
01092 function character_data($the_parser, $data)
01093 {
01094 if ($this->xh[$the_parser]['isf'] > 1) return;
01095
01096
01097 if ($this->xh[$the_parser]['lv'] != 3)
01098 {
01099 if ($this->xh[$the_parser]['lv'] == 1)
01100 {
01101 $this->xh[$the_parser]['lv'] = 2;
01102 }
01103
01104 if( ! @isset($this->xh[$the_parser]['ac']))
01105 {
01106 $this->xh[$the_parser]['ac'] = '';
01107 }
01108
01109 $this->xh[$the_parser]['ac'] .= $data;
01110 }
01111 }
01112
01113
01114 function addParam($par) { $this->params[]=$par; }
01115
01116 function output_parameters($array=FALSE)
01117 {
01118 $CI =& get_instance();
01119
01120 if ($array !== FALSE && is_array($array))
01121 {
01122 while (list($key) = each($array))
01123 {
01124 if (is_array($array[$key]))
01125 {
01126 $array[$key] = $this->output_parameters($array[$key]);
01127 }
01128 else
01129 {
01130 $array[$key] = $CI->input->xss_clean($array[$key]);
01131 }
01132 }
01133
01134 $parameters = $array;
01135 }
01136 else
01137 {
01138 $parameters = array();
01139
01140 for ($i = 0; $i < sizeof($this->params); $i++)
01141 {
01142 $a_param = $this->decode_message($this->params[$i]);
01143
01144 if (is_array($a_param))
01145 {
01146 $parameters[] = $this->output_parameters($a_param);
01147 }
01148 else
01149 {
01150 $parameters[] = $CI->input->xss_clean($a_param);
01151 }
01152 }
01153 }
01154
01155 return $parameters;
01156 }
01157
01158
01159 function decode_message($param)
01160 {
01161 $kind = $param->kindOf();
01162
01163 if($kind == 'scalar')
01164 {
01165 return $param->scalarval();
01166 }
01167 elseif($kind == 'array')
01168 {
01169 reset($param->me);
01170 list($a,$b) = each($param->me);
01171
01172 $arr = array();
01173
01174 for($i = 0; $i < sizeof($b); $i++)
01175 {
01176 $arr[] = $this->decode_message($param->me['array'][$i]);
01177 }
01178
01179 return $arr;
01180 }
01181 elseif($kind == 'struct')
01182 {
01183 reset($param->me['struct']);
01184
01185 $arr = array();
01186
01187 while(list($key,$value) = each($param->me['struct']))
01188 {
01189 $arr[$key] = $this->decode_message($value);
01190 }
01191
01192 return $arr;
01193 }
01194 }
01195
01196 }
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207 class XML_RPC_Values extends CI_Xmlrpc
01208 {
01209 var $me = array();
01210 var $mytype = 0;
01211
01212 function XML_RPC_Values($val=-1, $type='')
01213 {
01214 parent::CI_Xmlrpc();
01215
01216 if ($val != -1 OR $type != '')
01217 {
01218 $type = $type == '' ? 'string' : $type;
01219
01220 if ($this->xmlrpcTypes[$type] == 1)
01221 {
01222 $this->addScalar($val,$type);
01223 }
01224 elseif ($this->xmlrpcTypes[$type] == 2)
01225 {
01226 $this->addArray($val);
01227 }
01228 elseif ($this->xmlrpcTypes[$type] == 3)
01229 {
01230 $this->addStruct($val);
01231 }
01232 }
01233 }
01234
01235 function addScalar($val, $type='string')
01236 {
01237 $typeof = $this->xmlrpcTypes[$type];
01238
01239 if ($this->mytype==1)
01240 {
01241 echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
01242 return 0;
01243 }
01244
01245 if ($typeof != 1)
01246 {
01247 echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
01248 return 0;
01249 }
01250
01251 if ($type == $this->xmlrpcBoolean)
01252 {
01253 if (strcasecmp($val,'true')==0 OR $val==1 OR ($val==true && strcasecmp($val,'false')))
01254 {
01255 $val = 1;
01256 }
01257 else
01258 {
01259 $val=0;
01260 }
01261 }
01262
01263 if ($this->mytype == 2)
01264 {
01265
01266 $ar = $this->me['array'];
01267 $ar[] = new XML_RPC_Values($val, $type);
01268 $this->me['array'] = $ar;
01269 }
01270 else
01271 {
01272
01273 $this->me[$type] = $val;
01274 $this->mytype = $typeof;
01275 }
01276 return 1;
01277 }
01278
01279 function addArray($vals)
01280 {
01281 if ($this->mytype != 0)
01282 {
01283 echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
01284 return 0;
01285 }
01286
01287 $this->mytype = $this->xmlrpcTypes['array'];
01288 $this->me['array'] = $vals;
01289 return 1;
01290 }
01291
01292 function addStruct($vals)
01293 {
01294 if ($this->mytype != 0)
01295 {
01296 echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
01297 return 0;
01298 }
01299 $this->mytype = $this->xmlrpcTypes['struct'];
01300 $this->me['struct'] = $vals;
01301 return 1;
01302 }
01303
01304 function kindOf()
01305 {
01306 switch($this->mytype)
01307 {
01308 case 3:
01309 return 'struct';
01310 break;
01311 case 2:
01312 return 'array';
01313 break;
01314 case 1:
01315 return 'scalar';
01316 break;
01317 default:
01318 return 'undef';
01319 }
01320 }
01321
01322 function serializedata($typ, $val)
01323 {
01324 $rs = '';
01325
01326 switch($this->xmlrpcTypes[$typ])
01327 {
01328 case 3:
01329
01330 $rs .= "<struct>\n";
01331 reset($val);
01332 while(list($key2, $val2) = each($val))
01333 {
01334 $rs .= "<member>\n<name>{$key2}</name>\n";
01335 $rs .= $this->serializeval($val2);
01336 $rs .= "</member>\n";
01337 }
01338 $rs .= '</struct>';
01339 break;
01340 case 2:
01341
01342 $rs .= "<array>\n<data>\n";
01343 for($i=0; $i < sizeof($val); $i++)
01344 {
01345 $rs .= $this->serializeval($val[$i]);
01346 }
01347 $rs.="</data>\n</array>\n";
01348 break;
01349 case 1:
01350
01351 switch ($typ)
01352 {
01353 case $this->xmlrpcBase64:
01354 $rs .= "<{$typ}>" . base64_encode($val) . "</{$typ}>\n";
01355 break;
01356 case $this->xmlrpcBoolean:
01357 $rs .= "<{$typ}>" . ($val ? '1' : '0') . "</{$typ}>\n";
01358 break;
01359 case $this->xmlrpcString:
01360 $rs .= "<{$typ}>" . htmlspecialchars($val). "</{$typ}>\n";
01361 break;
01362 default:
01363 $rs .= "<{$typ}>{$val}</{$typ}>\n";
01364 break;
01365 }
01366 default:
01367 break;
01368 }
01369 return $rs;
01370 }
01371
01372 function serialize_class()
01373 {
01374 return $this->serializeval($this);
01375 }
01376
01377 function serializeval($o)
01378 {
01379 $ar = $o->me;
01380 reset($ar);
01381
01382 list($typ, $val) = each($ar);
01383 $rs = "<value>\n".$this->serializedata($typ, $val)."</value>\n";
01384 return $rs;
01385 }
01386
01387 function scalarval()
01388 {
01389 reset($this->me);
01390 list($a,$b) = each($this->me);
01391 return $b;
01392 }
01393
01394
01395
01396
01397
01398
01399
01400
01401 function iso8601_encode($time, $utc=0)
01402 {
01403 if ($utc == 1)
01404 {
01405 $t = strftime("%Y%m%dT%H:%M:%S", $time);
01406 }
01407 else
01408 {
01409 if (function_exists('gmstrftime'))
01410 $t = gmstrftime("%Y%m%dT%H:%M:%S", $time);
01411 else
01412 $t = strftime("%Y%m%dT%H:%M:%S", $time - date('Z'));
01413 }
01414 return $t;
01415 }
01416
01417 }
01418
01419
01420
01421