Cheetah
xmlrpc.inc
Go to the documentation of this file.
1 <?php
2 // by Edd Dumbill (C) 1999-2002
3 // <edd@usefulinc.com>
4 // $Id: xmlrpc.inc,v 1.169 2008/03/06 18:47:24 ggiunta Exp $
5 
6 // Copyright (c) 1999,2000,2002 Edd Dumbill.
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
11 // are met:
12 //
13 // * Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 //
16 // * Redistributions in binary form must reproduce the above
17 // copyright notice, this list of conditions and the following
18 // disclaimer in the documentation and/or other materials provided
19 // with the distribution.
20 //
21 // * Neither the name of the "XML-RPC for PHP" nor the names of its
22 // contributors may be used to endorse or promote products derived
23 // from this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 // REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
36 // OF THE POSSIBILITY OF SUCH DAMAGE.
37 
38  if(!function_exists('xml_parser_create'))
39  {
40  // For PHP 4 onward, XML functionality is always compiled-in on windows:
41  // no more need to dl-open it. It might have been compiled out on *nix...
42  if(strtoupper(substr(PHP_OS, 0, 3) != 'WIN'))
43  {
44  dl('xml.so');
45  }
46  }
47 
48  // Try to be backward compat with php < 4.2 (are we not being nice ?)
49  $phpversion = phpversion();
50  if($phpversion[0] == '4' && $phpversion[2] < 2)
51  {
52  // give an opportunity to user to specify where to include other files from
53  if(!defined('PHP_XMLRPC_COMPAT_DIR'))
54  {
55  define('PHP_XMLRPC_COMPAT_DIR',dirname(__FILE__).'/compat/');
56  }
57  if($phpversion[2] == '0')
58  {
59  if($phpversion[4] < 6)
60  {
61  include(PHP_XMLRPC_COMPAT_DIR.'is_callable.php');
62  }
63  include(PHP_XMLRPC_COMPAT_DIR.'is_scalar.php');
64  include(PHP_XMLRPC_COMPAT_DIR.'array_key_exists.php');
65  include(PHP_XMLRPC_COMPAT_DIR.'version_compare.php');
66  }
67  include(PHP_XMLRPC_COMPAT_DIR.'var_export.php');
68  include(PHP_XMLRPC_COMPAT_DIR.'is_a.php');
69  }
70 
71  // G. Giunta 2005/01/29: declare global these variables,
72  // so that xmlrpc.inc will work even if included from within a function
73  // Milosch: 2005/08/07 - explicitly request these via $GLOBALS where used.
74  $GLOBALS['xmlrpcI4']='i4';
75  $GLOBALS['xmlrpcInt']='int';
76  $GLOBALS['xmlrpcBoolean']='boolean';
77  $GLOBALS['xmlrpcDouble']='double';
78  $GLOBALS['xmlrpcString']='string';
79  $GLOBALS['xmlrpcDateTime']='dateTime.iso8601';
80  $GLOBALS['xmlrpcBase64']='base64';
81  $GLOBALS['xmlrpcArray']='array';
82  $GLOBALS['xmlrpcStruct']='struct';
83  $GLOBALS['xmlrpcValue']='undefined';
84 
85  $GLOBALS['xmlrpcTypes']=array(
86  $GLOBALS['xmlrpcI4'] => 1,
87  $GLOBALS['xmlrpcInt'] => 1,
88  $GLOBALS['xmlrpcBoolean'] => 1,
89  $GLOBALS['xmlrpcString'] => 1,
90  $GLOBALS['xmlrpcDouble'] => 1,
91  $GLOBALS['xmlrpcDateTime'] => 1,
92  $GLOBALS['xmlrpcBase64'] => 1,
93  $GLOBALS['xmlrpcArray'] => 2,
94  $GLOBALS['xmlrpcStruct'] => 3
95  );
96 
97  $GLOBALS['xmlrpc_valid_parents'] = array(
98  'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT'),
99  'BOOLEAN' => array('VALUE'),
100  'I4' => array('VALUE'),
101  'INT' => array('VALUE'),
102  'STRING' => array('VALUE'),
103  'DOUBLE' => array('VALUE'),
104  'DATETIME.ISO8601' => array('VALUE'),
105  'BASE64' => array('VALUE'),
106  'MEMBER' => array('STRUCT'),
107  'NAME' => array('MEMBER'),
108  'DATA' => array('ARRAY'),
109  'ARRAY' => array('VALUE'),
110  'STRUCT' => array('VALUE'),
111  'PARAM' => array('PARAMS'),
112  'METHODNAME' => array('METHODCALL'),
113  'PARAMS' => array('METHODCALL', 'METHODRESPONSE'),
114  'FAULT' => array('METHODRESPONSE'),
115  'NIL' => array('VALUE') // only used when extension activated
116  );
117 
118  // define extra types for supporting NULL (useful for json or <NIL/>)
119  $GLOBALS['xmlrpcNull']='null';
120  $GLOBALS['xmlrpcTypes']['null']=1;
121 
122  // Not in use anymore since 2.0. Shall we remove it?
124  $GLOBALS['xmlEntities']=array(
125  'amp' => '&',
126  'quot' => '"',
127  'lt' => '<',
128  'gt' => '>',
129  'apos' => "'"
130  );
131 
132  // tables used for transcoding different charsets into us-ascii xml
133 
134  $GLOBALS['xml_iso88591_Entities']=array();
135  $GLOBALS['xml_iso88591_Entities']['in'] = array();
136  $GLOBALS['xml_iso88591_Entities']['out'] = array();
137  for ($i = 0; $i < 32; $i++)
138  {
139  $GLOBALS['xml_iso88591_Entities']['in'][] = chr($i);
140  $GLOBALS['xml_iso88591_Entities']['out'][] = '&#'.$i.';';
141  }
142  for ($i = 160; $i < 256; $i++)
143  {
144  $GLOBALS['xml_iso88591_Entities']['in'][] = chr($i);
145  $GLOBALS['xml_iso88591_Entities']['out'][] = '&#'.$i.';';
146  }
147 
151  /*
152  $GLOBALS['xml_cp1252_Entities']=array();
153  for ($i = 128; $i < 160; $i++)
154  {
155  $GLOBALS['xml_cp1252_Entities']['in'][] = chr($i);
156  }
157  $GLOBALS['xml_cp1252_Entities']['out'] = array(
158  '&#x20AC;', '?', '&#x201A;', '&#x0192;',
159  '&#x201E;', '&#x2026;', '&#x2020;', '&#x2021;',
160  '&#x02C6;', '&#x2030;', '&#x0160;', '&#x2039;',
161  '&#x0152;', '?', '&#x017D;', '?',
162  '?', '&#x2018;', '&#x2019;', '&#x201C;',
163  '&#x201D;', '&#x2022;', '&#x2013;', '&#x2014;',
164  '&#x02DC;', '&#x2122;', '&#x0161;', '&#x203A;',
165  '&#x0153;', '?', '&#x017E;', '&#x0178;'
166  );
167  */
168 
169  $GLOBALS['xmlrpcerr'] = array(
170  'unknown_method'=>1,
171  'invalid_return'=>2,
172  'incorrect_params'=>3,
173  'introspect_unknown'=>4,
174  'http_error'=>5,
175  'no_data'=>6,
176  'no_ssl'=>7,
177  'curl_fail'=>8,
178  'invalid_request'=>15,
179  'no_curl'=>16,
180  'server_error'=>17,
181  'multicall_error'=>18,
182  'multicall_notstruct'=>9,
183  'multicall_nomethod'=>10,
184  'multicall_notstring'=>11,
185  'multicall_recursion'=>12,
186  'multicall_noparams'=>13,
187  'multicall_notarray'=>14,
188 
189  'cannot_decompress'=>103,
190  'decompress_fail'=>104,
191  'dechunk_fail'=>105,
192  'server_cannot_decompress'=>106,
193  'server_decompress_fail'=>107
194  );
195 
196  $GLOBALS['xmlrpcstr'] = array(
197  'unknown_method'=>'Unknown method',
198  'invalid_return'=>'Invalid return payload: enable debugging to examine incoming payload',
199  'incorrect_params'=>'Incorrect parameters passed to method',
200  'introspect_unknown'=>"Can't introspect: method unknown",
201  'http_error'=>"Didn't receive 200 OK from remote server.",
202  'no_data'=>'No data received from server.',
203  'no_ssl'=>'No SSL support compiled in.',
204  'curl_fail'=>'CURL error',
205  'invalid_request'=>'Invalid request payload',
206  'no_curl'=>'No CURL support compiled in.',
207  'server_error'=>'Internal server error',
208  'multicall_error'=>'Received from server invalid multicall response',
209  'multicall_notstruct'=>'system.multicall expected struct',
210  'multicall_nomethod'=>'missing methodName',
211  'multicall_notstring'=>'methodName is not a string',
212  'multicall_recursion'=>'recursive system.multicall forbidden',
213  'multicall_noparams'=>'missing params',
214  'multicall_notarray'=>'params is not an array',
215 
216  'cannot_decompress'=>'Received from server compressed HTTP and cannot decompress',
217  'decompress_fail'=>'Received from server invalid compressed HTTP',
218  'dechunk_fail'=>'Received from server invalid chunked HTTP',
219  'server_cannot_decompress'=>'Received from client compressed HTTP request and cannot decompress',
220  'server_decompress_fail'=>'Received from client invalid compressed HTTP request'
221  );
222 
223  // The charset encoding used by the server for received messages and
224  // by the client for received responses when received charset cannot be determined
225  // or is not supported
226  $GLOBALS['xmlrpc_defencoding']='UTF-8';
227 
228  // The encoding used internally by PHP.
229  // String values received as xml will be converted to this, and php strings will be converted to xml
230  // as if having been coded with this
231  $GLOBALS['xmlrpc_internalencoding']='ISO-8859-1';
232 
233  $GLOBALS['xmlrpcName']='XML-RPC for PHP';
234  $GLOBALS['xmlrpcVersion']='2.2.1';
235 
236  // let user errors start at 800
237  $GLOBALS['xmlrpcerruser']=800;
238  // let XML parse errors start at 100
239  $GLOBALS['xmlrpcerrxml']=100;
240 
241  // formulate backslashes for escaping regexp
242  // Not in use anymore since 2.0. Shall we remove it?
244  $GLOBALS['xmlrpc_backslash']=chr(92).chr(92);
245 
246  // set to TRUE to enable correct decoding of <NIL/> values
247  $GLOBALS['xmlrpc_null_extension']=false;
248 
249  // used to store state during parsing
250  // quick explanation of components:
251  // ac - used to accumulate values
252  // isf - used to indicate a parsing fault (2) or xmlrpcresp fault (1)
253  // isf_reason - used for storing xmlrpcresp fault string
254  // lv - used to indicate "looking for a value": implements
255  // the logic to allow values with no types to be strings
256  // params - used to store parameters in method calls
257  // method - used to store method name
258  // stack - array with genealogy of xml elements names:
259  // used to validate nesting of xmlrpc elements
260  $GLOBALS['_xh']=null;
261 
276  function xmlrpc_encode_entitites($data, $src_encoding='', $dest_encoding='')
277  {
278  if ($src_encoding == '')
279  {
280  // lame, but we know no better...
281  $src_encoding = $GLOBALS['xmlrpc_internalencoding'];
282  }
283 
284  switch(strtoupper($src_encoding.'_'.$dest_encoding))
285  {
286  case 'ISO-8859-1_':
287  case 'ISO-8859-1_US-ASCII':
288  $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&amp;', '&quot;', '&apos;', '&lt;', '&gt;'), $data);
289  $escaped_data = str_replace($GLOBALS['xml_iso88591_Entities']['in'], $GLOBALS['xml_iso88591_Entities']['out'], $escaped_data);
290  break;
291  case 'ISO-8859-1_UTF-8':
292  $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&amp;', '&quot;', '&apos;', '&lt;', '&gt;'), $data);
293  $escaped_data = utf8_encode($escaped_data);
294  break;
295  case 'ISO-8859-1_ISO-8859-1':
296  case 'US-ASCII_US-ASCII':
297  case 'US-ASCII_UTF-8':
298  case 'US-ASCII_':
299  case 'US-ASCII_ISO-8859-1':
300  case 'UTF-8_UTF-8':
301  //case 'CP1252_CP1252':
302  $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&amp;', '&quot;', '&apos;', '&lt;', '&gt;'), $data);
303  break;
304  case 'UTF-8_':
305  case 'UTF-8_US-ASCII':
306  case 'UTF-8_ISO-8859-1':
307  // NB: this will choke on invalid UTF-8, going most likely beyond EOF
308  $escaped_data = '';
309  // be kind to users creating string xmlrpcvals out of different php types
310  $data = (string) $data;
311  $ns = strlen ($data);
312  for ($nn = 0; $nn < $ns; $nn++)
313  {
314  $ch = $data[$nn];
315  $ii = ord($ch);
316  //1 7 0bbbbbbb (127)
317  if ($ii < 128)
318  {
320  switch($ii){
321  case 34:
322  $escaped_data .= '&quot;';
323  break;
324  case 38:
325  $escaped_data .= '&amp;';
326  break;
327  case 39:
328  $escaped_data .= '&apos;';
329  break;
330  case 60:
331  $escaped_data .= '&lt;';
332  break;
333  case 62:
334  $escaped_data .= '&gt;';
335  break;
336  default:
337  $escaped_data .= $ch;
338  } // switch
339  }
340  //2 11 110bbbbb 10bbbbbb (2047)
341  else if ($ii>>5 == 6)
342  {
343  $b1 = ($ii & 31);
344  $ii = ord($data[$nn+1]);
345  $b2 = ($ii & 63);
346  $ii = ($b1 * 64) + $b2;
347  $ent = sprintf ('&#%d;', $ii);
348  $escaped_data .= $ent;
349  $nn += 1;
350  }
351  //3 16 1110bbbb 10bbbbbb 10bbbbbb
352  else if ($ii>>4 == 14)
353  {
354  $b1 = ($ii & 31);
355  $ii = ord($data[$nn+1]);
356  $b2 = ($ii & 63);
357  $ii = ord($data[$nn+2]);
358  $b3 = ($ii & 63);
359  $ii = ((($b1 * 64) + $b2) * 64) + $b3;
360  $ent = sprintf ('&#%d;', $ii);
361  $escaped_data .= $ent;
362  $nn += 2;
363  }
364  //4 21 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
365  else if ($ii>>3 == 30)
366  {
367  $b1 = ($ii & 31);
368  $ii = ord($data[$nn+1]);
369  $b2 = ($ii & 63);
370  $ii = ord($data[$nn+2]);
371  $b3 = ($ii & 63);
372  $ii = ord($data[$nn+3]);
373  $b4 = ($ii & 63);
374  $ii = ((((($b1 * 64) + $b2) * 64) + $b3) * 64) + $b4;
375  $ent = sprintf ('&#%d;', $ii);
376  $escaped_data .= $ent;
377  $nn += 3;
378  }
379  }
380  break;
381 /*
382  case 'CP1252_':
383  case 'CP1252_US-ASCII':
384  $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&amp;', '&quot;', '&apos;', '&lt;', '&gt;'), $data);
385  $escaped_data = str_replace($GLOBALS['xml_iso88591_Entities']['in'], $GLOBALS['xml_iso88591_Entities']['out'], $escaped_data);
386  $escaped_data = str_replace($GLOBALS['xml_cp1252_Entities']['in'], $GLOBALS['xml_cp1252_Entities']['out'], $escaped_data);
387  break;
388  case 'CP1252_UTF-8':
389  $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&amp;', '&quot;', '&apos;', '&lt;', '&gt;'), $data);
391  $escaped_data = str_replace($GLOBALS['xml_cp1252_Entities']['in'], $GLOBALS['xml_cp1252_Entities']['out'], $escaped_data);
392  $escaped_data = utf8_encode($escaped_data);
393  break;
394  case 'CP1252_ISO-8859-1':
395  $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&amp;', '&quot;', '&apos;', '&lt;', '&gt;'), $data);
396  // we might as well replave all funky chars with a '?' here, but we are kind and leave it to the receiving application layer to decide what to do with these weird entities...
397  $escaped_data = str_replace($GLOBALS['xml_cp1252_Entities']['in'], $GLOBALS['xml_cp1252_Entities']['out'], $escaped_data);
398  break;
399 */
400  default:
401  $escaped_data = '';
402  error_log("Converting from $src_encoding to $dest_encoding: not supported...");
403  }
404  return $escaped_data;
405  }
406 
408  function xmlrpc_se($parser, $name, $attrs, $accept_single_vals=false)
409  {
410  // if invalid xmlrpc already detected, skip all processing
411  if ($GLOBALS['_xh']['isf'] < 2)
412  {
413  // check for correct element nesting
414  // top level element can only be of 2 types
417  if (count($GLOBALS['_xh']['stack']) == 0)
418  {
419  if ($name != 'METHODRESPONSE' && $name != 'METHODCALL' && (
420  $name != 'VALUE' && !$accept_single_vals))
421  {
422  $GLOBALS['_xh']['isf'] = 2;
423  $GLOBALS['_xh']['isf_reason'] = 'missing top level xmlrpc element';
424  return;
425  }
426  else
427  {
428  $GLOBALS['_xh']['rt'] = strtolower($name);
429  }
430  }
431  else
432  {
433  // not top level element: see if parent is OK
434  $parent = end($GLOBALS['_xh']['stack']);
435  if (!array_key_exists($name, $GLOBALS['xmlrpc_valid_parents']) || !in_array($parent, $GLOBALS['xmlrpc_valid_parents'][$name]))
436  {
437  $GLOBALS['_xh']['isf'] = 2;
438  $GLOBALS['_xh']['isf_reason'] = "xmlrpc element $name cannot be child of $parent";
439  return;
440  }
441  }
442 
443  switch($name)
444  {
445  // optimize for speed switch cases: most common cases first
446  case 'VALUE':
448  $GLOBALS['_xh']['vt']='value'; // indicator: no value found yet
449  $GLOBALS['_xh']['ac']='';
450  $GLOBALS['_xh']['lv']=1;
451  $GLOBALS['_xh']['php_class']=null;
452  break;
453  case 'I4':
454  case 'INT':
455  case 'STRING':
456  case 'BOOLEAN':
457  case 'DOUBLE':
458  case 'DATETIME.ISO8601':
459  case 'BASE64':
460  if ($GLOBALS['_xh']['vt']!='value')
461  {
462  //two data elements inside a value: an error occurred!
463  $GLOBALS['_xh']['isf'] = 2;
464  $GLOBALS['_xh']['isf_reason'] = "$name element following a {$GLOBALS['_xh']['vt']} element inside a single value";
465  return;
466  }
467  $GLOBALS['_xh']['ac']=''; // reset the accumulator
468  break;
469  case 'STRUCT':
470  case 'ARRAY':
471  if ($GLOBALS['_xh']['vt']!='value')
472  {
473  //two data elements inside a value: an error occurred!
474  $GLOBALS['_xh']['isf'] = 2;
475  $GLOBALS['_xh']['isf_reason'] = "$name element following a {$GLOBALS['_xh']['vt']} element inside a single value";
476  return;
477  }
478  // create an empty array to hold child values, and push it onto appropriate stack
479  $cur_val = array();
480  $cur_val['values'] = array();
481  $cur_val['type'] = $name;
482  // check for out-of-band information to rebuild php objs
483  // and in case it is found, save it
484  if (@isset($attrs['PHP_CLASS']))
485  {
486  $cur_val['php_class'] = $attrs['PHP_CLASS'];
487  }
488  $GLOBALS['_xh']['valuestack'][] = $cur_val;
489  $GLOBALS['_xh']['vt']='data'; // be prepared for a data element next
490  break;
491  case 'DATA':
492  if ($GLOBALS['_xh']['vt']!='data')
493  {
494  //two data elements inside a value: an error occurred!
495  $GLOBALS['_xh']['isf'] = 2;
496  $GLOBALS['_xh']['isf_reason'] = "found two data elements inside an array element";
497  return;
498  }
499  case 'METHODCALL':
500  case 'METHODRESPONSE':
501  case 'PARAMS':
502  // valid elements that add little to processing
503  break;
504  case 'METHODNAME':
505  case 'NAME':
507  $GLOBALS['_xh']['ac']='';
508  break;
509  case 'FAULT':
510  $GLOBALS['_xh']['isf']=1;
511  break;
512  case 'MEMBER':
513  $GLOBALS['_xh']['valuestack'][count($GLOBALS['_xh']['valuestack'])-1]['name']=''; // set member name to null, in case we do not find in the xml later on
514  //$GLOBALS['_xh']['ac']='';
515  // Drop trough intentionally
516  case 'PARAM':
517  // clear value type, so we can check later if no value has been passed for this param/member
518  $GLOBALS['_xh']['vt']=null;
519  break;
520  case 'NIL':
521  if ($GLOBALS['xmlrpc_null_extension'])
522  {
523  if ($GLOBALS['_xh']['vt']!='value')
524  {
525  //two data elements inside a value: an error occurred!
526  $GLOBALS['_xh']['isf'] = 2;
527  $GLOBALS['_xh']['isf_reason'] = "$name element following a {$GLOBALS['_xh']['vt']} element inside a single value";
528  return;
529  }
530  $GLOBALS['_xh']['ac']=''; // reset the accumulator
531  break;
532  }
533  // we do not support the <NIL/> extension, so
534  // drop through intentionally
535  default:
537  $GLOBALS['_xh']['isf'] = 2;
538  $GLOBALS['_xh']['isf_reason'] = "found not-xmlrpc xml element $name";
539  break;
540  }
541 
542  // Save current element name to stack, to validate nesting
543  $GLOBALS['_xh']['stack'][] = $name;
544 
546  if($name!='VALUE')
547  {
548  $GLOBALS['_xh']['lv']=0;
549  }
550  }
551  }
552 
554  function xmlrpc_se_any($parser, $name, $attrs)
555  {
556  xmlrpc_se($parser, $name, $attrs, true);
557  }
558 
560  function xmlrpc_ee($parser, $name, $rebuild_xmlrpcvals = true)
561  {
562  if ($GLOBALS['_xh']['isf'] < 2)
563  {
564  // push this element name from stack
565  // NB: if XML validates, correct opening/closing is guaranteed and
566  // we do not have to check for $name == $curr_elem.
567  // we also checked for proper nesting at start of elements...
568  $curr_elem = array_pop($GLOBALS['_xh']['stack']);
569 
570  switch($name)
571  {
572  case 'VALUE':
573  // This if() detects if no scalar was inside <VALUE></VALUE>
574  if ($GLOBALS['_xh']['vt']=='value')
575  {
576  $GLOBALS['_xh']['value']=$GLOBALS['_xh']['ac'];
577  $GLOBALS['_xh']['vt']=$GLOBALS['xmlrpcString'];
578  }
579 
580  if ($rebuild_xmlrpcvals)
581  {
582  // build the xmlrpc val out of the data received, and substitute it
583  $temp = new xmlrpcval($GLOBALS['_xh']['value'], $GLOBALS['_xh']['vt']);
584  // in case we got info about underlying php class, save it
585  // in the object we're rebuilding
586  if (isset($GLOBALS['_xh']['php_class']))
587  $temp->_php_class = $GLOBALS['_xh']['php_class'];
588  // check if we are inside an array or struct:
589  // if value just built is inside an array, let's move it into array on the stack
590  $vscount = count($GLOBALS['_xh']['valuestack']);
591  if ($vscount && $GLOBALS['_xh']['valuestack'][$vscount-1]['type']=='ARRAY')
592  {
593  $GLOBALS['_xh']['valuestack'][$vscount-1]['values'][] = $temp;
594  }
595  else
596  {
597  $GLOBALS['_xh']['value'] = $temp;
598  }
599  }
600  else
601  {
605  if (isset($GLOBALS['_xh']['php_class']))
606  {
607  }
608 
609  // check if we are inside an array or struct:
610  // if value just built is inside an array, let's move it into array on the stack
611  $vscount = count($GLOBALS['_xh']['valuestack']);
612  if ($vscount && $GLOBALS['_xh']['valuestack'][$vscount-1]['type']=='ARRAY')
613  {
614  $GLOBALS['_xh']['valuestack'][$vscount-1]['values'][] = $GLOBALS['_xh']['value'];
615  }
616  }
617  break;
618  case 'BOOLEAN':
619  case 'I4':
620  case 'INT':
621  case 'STRING':
622  case 'DOUBLE':
623  case 'DATETIME.ISO8601':
624  case 'BASE64':
625  $GLOBALS['_xh']['vt']=strtolower($name);
628  if ($name=='STRING')
629  {
630  $GLOBALS['_xh']['value']=$GLOBALS['_xh']['ac'];
631  }
632  elseif ($name=='DATETIME.ISO8601')
633  {
634  if (!preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $GLOBALS['_xh']['ac']))
635  {
636  error_log('XML-RPC: invalid value received in DATETIME: '.$GLOBALS['_xh']['ac']);
637  }
638  $GLOBALS['_xh']['vt']=$GLOBALS['xmlrpcDateTime'];
639  $GLOBALS['_xh']['value']=$GLOBALS['_xh']['ac'];
640  }
641  elseif ($name=='BASE64')
642  {
644  $GLOBALS['_xh']['value']=base64_decode($GLOBALS['_xh']['ac']);
645  }
646  elseif ($name=='BOOLEAN')
647  {
648  // special case here: we translate boolean 1 or 0 into PHP
649  // constants true or false.
650  // Strings 'true' and 'false' are accepted, even though the
651  // spec never mentions them (see eg. Blogger api docs)
652  // NB: this simple checks helps a lot sanitizing input, ie no
653  // security problems around here
654  if ($GLOBALS['_xh']['ac']=='1' || strcasecmp($GLOBALS['_xh']['ac'], 'true') == 0)
655  {
656  $GLOBALS['_xh']['value']=true;
657  }
658  else
659  {
660  // log if receiveing something strange, even though we set the value to false anyway
661  if ($GLOBALS['_xh']['ac']!='0' && strcasecmp($_xh[$parser]['ac'], 'false') != 0)
662  error_log('XML-RPC: invalid value received in BOOLEAN: '.$GLOBALS['_xh']['ac']);
663  $GLOBALS['_xh']['value']=false;
664  }
665  }
666  elseif ($name=='DOUBLE')
667  {
668  // we have a DOUBLE
669  // we must check that only 0123456789-.<space> are characters here
670  // NOTE: regexp could be much stricter than this...
671  if (!preg_match('/^[+-eE0123456789 \t.]+$/', $GLOBALS['_xh']['ac']))
672  {
674  error_log('XML-RPC: non numeric value received in DOUBLE: '.$GLOBALS['_xh']['ac']);
675  $GLOBALS['_xh']['value']='ERROR_NON_NUMERIC_FOUND';
676  }
677  else
678  {
679  // it's ok, add it on
680  $GLOBALS['_xh']['value']=(double)$GLOBALS['_xh']['ac'];
681  }
682  }
683  else
684  {
685  // we have an I4/INT
686  // we must check that only 0123456789-<space> are characters here
687  if (!preg_match('/^[+-]?[0123456789 \t]+$/', $GLOBALS['_xh']['ac']))
688  {
690  error_log('XML-RPC: non numeric value received in INT: '.$GLOBALS['_xh']['ac']);
691  $GLOBALS['_xh']['value']='ERROR_NON_NUMERIC_FOUND';
692  }
693  else
694  {
695  // it's ok, add it on
696  $GLOBALS['_xh']['value']=(int)$GLOBALS['_xh']['ac'];
697  }
698  }
699  //$GLOBALS['_xh']['ac']=''; // is this necessary?
700  $GLOBALS['_xh']['lv']=3; // indicate we've found a value
701  break;
702  case 'NAME':
703  $GLOBALS['_xh']['valuestack'][count($GLOBALS['_xh']['valuestack'])-1]['name'] = $GLOBALS['_xh']['ac'];
704  break;
705  case 'MEMBER':
706  //$GLOBALS['_xh']['ac']=''; // is this necessary?
707  // add to array in the stack the last element built,
708  // unless no VALUE was found
709  if ($GLOBALS['_xh']['vt'])
710  {
711  $vscount = count($GLOBALS['_xh']['valuestack']);
712  $GLOBALS['_xh']['valuestack'][$vscount-1]['values'][$GLOBALS['_xh']['valuestack'][$vscount-1]['name']] = $GLOBALS['_xh']['value'];
713  } else
714  error_log('XML-RPC: missing VALUE inside STRUCT in received xml');
715  break;
716  case 'DATA':
717  //$GLOBALS['_xh']['ac']=''; // is this necessary?
718  $GLOBALS['_xh']['vt']=null; // reset this to check for 2 data elements in a row - even if they're empty
719  break;
720  case 'STRUCT':
721  case 'ARRAY':
722  // fetch out of stack array of values, and promote it to current value
723  $curr_val = array_pop($GLOBALS['_xh']['valuestack']);
724  $GLOBALS['_xh']['value'] = $curr_val['values'];
725  $GLOBALS['_xh']['vt']=strtolower($name);
726  if (isset($curr_val['php_class']))
727  {
728  $GLOBALS['_xh']['php_class'] = $curr_val['php_class'];
729  }
730  break;
731  case 'PARAM':
732  // add to array of params the current value,
733  // unless no VALUE was found
734  if ($GLOBALS['_xh']['vt'])
735  {
736  $GLOBALS['_xh']['params'][]=$GLOBALS['_xh']['value'];
737  $GLOBALS['_xh']['pt'][]=$GLOBALS['_xh']['vt'];
738  }
739  else
740  error_log('XML-RPC: missing VALUE inside PARAM in received xml');
741  break;
742  case 'METHODNAME':
743  $GLOBALS['_xh']['method']=preg_replace('/^[\n\r\t ]+/', '', $GLOBALS['_xh']['ac']);
744  break;
745  case 'NIL':
746  if ($GLOBALS['xmlrpc_null_extension'])
747  {
748  $GLOBALS['_xh']['vt']='null';
749  $GLOBALS['_xh']['value']=null;
750  $GLOBALS['_xh']['lv']=3;
751  break;
752  }
753  // drop through intentionally if nil extension not enabled
754  case 'PARAMS':
755  case 'FAULT':
756  case 'METHODCALL':
757  case 'METHORESPONSE':
758  break;
759  default:
760  // End of INVALID ELEMENT!
761  // shall we add an assert here for unreachable code???
762  break;
763  }
764  }
765  }
766 
768  function xmlrpc_ee_fast($parser, $name)
769  {
770  xmlrpc_ee($parser, $name, false);
771  }
772 
774  function xmlrpc_cd($parser, $data)
775  {
776  // skip processing if xml fault already detected
777  if ($GLOBALS['_xh']['isf'] < 2)
778  {
779  // "lookforvalue==3" means that we've found an entire value
780  // and should discard any further character data
781  if($GLOBALS['_xh']['lv']!=3)
782  {
783  // G. Giunta 2006-08-23: useless change of 'lv' from 1 to 2
784  //if($GLOBALS['_xh']['lv']==1)
785  //{
786  // if we've found text and we're just in a <value> then
787  // say we've found a value
788  //$GLOBALS['_xh']['lv']=2;
789  //}
790  // we always initialize the accumulator before starting parsing, anyway...
791  //if(!@isset($GLOBALS['_xh']['ac']))
792  //{
793  // $GLOBALS['_xh']['ac'] = '';
794  //}
795  $GLOBALS['_xh']['ac'].=$data;
796  }
797  }
798  }
799 
802  function xmlrpc_dh($parser, $data)
803  {
804  // skip processing if xml fault already detected
805  if ($GLOBALS['_xh']['isf'] < 2)
806  {
807  if(substr($data, 0, 1) == '&' && substr($data, -1, 1) == ';')
808  {
809  // G. Giunta 2006-08-25: useless change of 'lv' from 1 to 2
810  //if($GLOBALS['_xh']['lv']==1)
811  //{
812  // $GLOBALS['_xh']['lv']=2;
813  //}
814  $GLOBALS['_xh']['ac'].=$data;
815  }
816  }
817  return true;
818  }
819 
821  {
822  var $path;
823  var $server;
824  var $port=0;
825  var $method='http';
826  var $errno;
827  var $errstr;
828  var $debug=0;
829  var $username='';
830  var $password='';
831  var $authtype=1;
832  var $cert='';
833  var $certpass='';
834  var $cacert='';
835  var $cacertdir='';
836  var $key='';
837  var $keypass='';
838  var $verifypeer=true;
839  var $verifyhost=1;
840  var $no_multicall=false;
841  var $proxy='';
842  var $proxyport=0;
843  var $proxy_user='';
844  var $proxy_pass='';
846  var $cookies=array();
856  var $accepted_compression = array();
868  var $keepalive = false;
877  var $return_type = 'xmlrpcvals';
878 
885  function __construct($path, $server='', $port='', $method='')
886  {
887  // allow user to specify all params in $path
888  if($server == '' and $port == '' and $method == '')
889  {
890  $parts = parse_url($path);
891  $server = $parts['host'];
892  $path = isset($parts['path']) ? $parts['path'] : '';
893  if(isset($parts['query']))
894  {
895  $path .= '?'.$parts['query'];
896  }
897  if(isset($parts['fragment']))
898  {
899  $path .= '#'.$parts['fragment'];
900  }
901  if(isset($parts['port']))
902  {
903  $port = $parts['port'];
904  }
905  if(isset($parts['scheme']))
906  {
907  $method = $parts['scheme'];
908  }
909  if(isset($parts['user']))
910  {
911  $this->username = $parts['user'];
912  }
913  if(isset($parts['pass']))
914  {
915  $this->password = $parts['pass'];
916  }
917  }
918  if($path == '' || $path[0] != '/')
919  {
920  $this->path='/'.$path;
921  }
922  else
923  {
924  $this->path=$path;
925  }
926  $this->server=$server;
927  if($port != '')
928  {
929  $this->port=$port;
930  }
931  if($method != '')
932  {
933  $this->method=$method;
934  }
935 
936  // if ZLIB is enabled, let the client by default accept compressed responses
937  if(function_exists('gzinflate') || (
938  function_exists('curl_init') && (($info = curl_version()) &&
939  ((is_string($info) && strpos($info, 'zlib') !== null) || isset($info['libz_version'])))
940  ))
941  {
942  $this->accepted_compression = array('gzip', 'deflate');
943  }
944 
945  // keepalives: enabled by default ONLY for PHP >= 4.3.8
946  // (see http://curl.haxx.se/docs/faq.html#7.3)
947  if(version_compare(phpversion(), '4.3.8') >= 0)
948  {
949  $this->keepalive = true;
950  }
951 
952  // by default the xml parser can support these 3 charset encodings
953  $this->accepted_charset_encodings = array('UTF-8', 'ISO-8859-1', 'US-ASCII');
954  }
955 
961  function setDebug($in)
962  {
963  $this->debug=$in;
964  }
965 
973  function setCredentials($u, $p, $t=1)
974  {
975  $this->username=$u;
976  $this->password=$p;
977  $this->authtype=$t;
978  }
979 
987  {
988  $this->cert = $cert;
989  $this->certpass = $certpass;
990  }
991 
999  function setCaCertificate($cacert, $is_dir=false)
1000  {
1001  if ($is_dir)
1002  {
1003  $this->cacertdir = $cacert;
1004  }
1005  else
1006  {
1007  $this->cacert = $cacert;
1008  }
1009  }
1010 
1019  function setKey($key, $keypass)
1020  {
1021  $this->key = $key;
1022  $this->keypass = $keypass;
1023  }
1024 
1030  function setSSLVerifyPeer($i)
1031  {
1032  $this->verifypeer = $i;
1033  }
1034 
1040  function setSSLVerifyHost($i)
1041  {
1042  $this->verifyhost = $i;
1043  }
1044 
1054  function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 1)
1055  {
1056  $this->proxy = $proxyhost;
1057  $this->proxyport = $proxyport;
1058  $this->proxy_user = $proxyusername;
1059  $this->proxy_pass = $proxypassword;
1060  $this->proxy_authtype = $proxyauthtype;
1061  }
1062 
1071  function setAcceptedCompression($compmethod)
1072  {
1073  if ($compmethod == 'any')
1074  $this->accepted_compression = array('gzip', 'deflate');
1075  else
1076  $this->accepted_compression = array($compmethod);
1077  }
1078 
1086  function setRequestCompression($compmethod)
1087  {
1088  $this->request_compression = $compmethod;
1089  }
1090 
1104  function setCookie($name, $value='', $path='', $domain='', $port=null)
1105  {
1106  $this->cookies[$name]['value'] = urlencode($value);
1107  if ($path || $domain || $port)
1108  {
1109  $this->cookies[$name]['path'] = $path;
1110  $this->cookies[$name]['domain'] = $domain;
1111  $this->cookies[$name]['port'] = $port;
1112  $this->cookies[$name]['version'] = 1;
1113  }
1114  else
1115  {
1116  $this->cookies[$name]['version'] = 0;
1117  }
1118  }
1119 
1128  function& send($msg, $timeout=0, $method='')
1129  {
1130  // if user deos not specify http protocol, use native method of this client
1131  // (i.e. method set during call to constructor)
1132  if($method == '')
1133  {
1135  }
1136 
1137  if(is_array($msg))
1138  {
1139  // $msg is an array of xmlrpcmsg's
1140  $r = $this->multicall($msg, $timeout, $method);
1141  return $r;
1142  }
1143  elseif(is_string($msg))
1144  {
1145  $n = new xmlrpcmsg('');
1146  $n->payload = $msg;
1147  $msg = $n;
1148  }
1149 
1150  // where msg is an xmlrpcmsg
1151  $msg->debug=$this->debug;
1152 
1153  if($method == 'https')
1154  {
1155  $r =& $this->sendPayloadHTTPS(
1156  $msg,
1157  $this->server,
1158  $this->port,
1159  $timeout,
1160  $this->username,
1161  $this->password,
1162  $this->authtype,
1163  $this->cert,
1164  $this->certpass,
1165  $this->cacert,
1166  $this->cacertdir,
1167  $this->proxy,
1168  $this->proxyport,
1169  $this->proxy_user,
1170  $this->proxy_pass,
1171  $this->proxy_authtype,
1172  $this->keepalive,
1173  $this->key,
1174  $this->keypass
1175  );
1176  }
1177  elseif($method == 'http11')
1178  {
1179  $r =& $this->sendPayloadCURL(
1180  $msg,
1181  $this->server,
1182  $this->port,
1183  $timeout,
1184  $this->username,
1185  $this->password,
1186  $this->authtype,
1187  null,
1188  null,
1189  null,
1190  null,
1191  $this->proxy,
1192  $this->proxyport,
1193  $this->proxy_user,
1194  $this->proxy_pass,
1195  $this->proxy_authtype,
1196  'http',
1197  $this->keepalive
1198  );
1199  }
1200  else
1201  {
1202  $r =& $this->sendPayloadHTTP10(
1203  $msg,
1204  $this->server,
1205  $this->port,
1206  $timeout,
1207  $this->username,
1208  $this->password,
1209  $this->authtype,
1210  $this->proxy,
1211  $this->proxyport,
1212  $this->proxy_user,
1213  $this->proxy_pass,
1214  $this->proxy_authtype
1215  );
1216  }
1217 
1218  return $r;
1219  }
1220 
1224  function &sendPayloadHTTP10($msg, $server, $port, $timeout=0,
1225  $username='', $password='', $authtype=1, $proxyhost='',
1226  $proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1)
1227  {
1228  if($port==0)
1229  {
1230  $port=80;
1231  }
1232 
1233  // Only create the payload if it was not created previously
1234  if(empty($msg->payload))
1235  {
1236  $msg->createPayload($this->request_charset_encoding);
1237  }
1238 
1239  $payload = $msg->payload;
1240  // Deflate request body and set appropriate request headers
1241  if(function_exists('gzdeflate') && ($this->request_compression == 'gzip' || $this->request_compression == 'deflate'))
1242  {
1243  if($this->request_compression == 'gzip')
1244  {
1245  $a = @gzencode($payload);
1246  if($a)
1247  {
1248  $payload = $a;
1249  $encoding_hdr = "Content-Encoding: gzip\r\n";
1250  }
1251  }
1252  else
1253  {
1254  $a = @gzcompress($payload);
1255  if($a)
1256  {
1257  $payload = $a;
1258  $encoding_hdr = "Content-Encoding: deflate\r\n";
1259  }
1260  }
1261  }
1262  else
1263  {
1264  $encoding_hdr = '';
1265  }
1266 
1267  // thanks to Grant Rauscher <grant7@firstworld.net> for this
1268  $credentials='';
1269  if($username!='')
1270  {
1271  $credentials='Authorization: Basic ' . base64_encode($username . ':' . $password) . "\r\n";
1272  if ($authtype != 1)
1273  {
1274  error_log('XML-RPC: xmlrpc_client::send: warning. Only Basic auth is supported with HTTP 1.0');
1275  }
1276  }
1277 
1278  $accepted_encoding = '';
1279  if(is_array($this->accepted_compression) && count($this->accepted_compression))
1280  {
1281  $accepted_encoding = 'Accept-Encoding: ' . implode(', ', $this->accepted_compression) . "\r\n";
1282  }
1283 
1284  $proxy_credentials = '';
1285  if($proxyhost)
1286  {
1287  if($proxyport == 0)
1288  {
1289  $proxyport = 8080;
1290  }
1291  $connectserver = $proxyhost;
1292  $connectport = $proxyport;
1293  $uri = 'http://'.$server.':'.$port.$this->path;
1294  if($proxyusername != '')
1295  {
1296  if ($proxyauthtype != 1)
1297  {
1298  error_log('XML-RPC: xmlrpc_client::send: warning. Only Basic auth to proxy is supported with HTTP 1.0');
1299  }
1300  $proxy_credentials = 'Proxy-Authorization: Basic ' . base64_encode($proxyusername.':'.$proxypassword) . "\r\n";
1301  }
1302  }
1303  else
1304  {
1305  $connectserver = $server;
1306  $connectport = $port;
1307  $uri = $this->path;
1308  }
1309 
1310  // Cookie generation, as per rfc2965 (version 1 cookies) or
1311  // netscape's rules (version 0 cookies)
1312  $cookieheader='';
1313  if (count($this->cookies))
1314  {
1315  $version = '';
1316  foreach ($this->cookies as $name => $cookie)
1317  {
1318  if ($cookie['version'])
1319  {
1320  $version = ' $Version="' . $cookie['version'] . '";';
1321  $cookieheader .= ' ' . $name . '="' . $cookie['value'] . '";';
1322  if ($cookie['path'])
1323  $cookieheader .= ' $Path="' . $cookie['path'] . '";';
1324  if ($cookie['domain'])
1325  $cookieheader .= ' $Domain="' . $cookie['domain'] . '";';
1326  if ($cookie['port'])
1327  $cookieheader .= ' $Port="' . $cookie['port'] . '";';
1328  }
1329  else
1330  {
1331  $cookieheader .= ' ' . $name . '=' . $cookie['value'] . ";";
1332  }
1333  }
1334  $cookieheader = 'Cookie:' . $version . substr($cookieheader, 0, -1) . "\r\n";
1335  }
1336 
1337  $op= 'POST ' . $uri. " HTTP/1.0\r\n" .
1338  'User-Agent: ' . $GLOBALS['xmlrpcName'] . ' ' . $GLOBALS['xmlrpcVersion'] . "\r\n" .
1339  'Host: '. $server . ':' . $port . "\r\n" .
1340  $credentials .
1341  $proxy_credentials .
1342  $accepted_encoding .
1343  $encoding_hdr .
1344  'Accept-Charset: ' . implode(',', $this->accepted_charset_encodings) . "\r\n" .
1345  $cookieheader .
1346  'Content-Type: ' . $msg->content_type . "\r\nContent-Length: " .
1347  strlen($payload) . "\r\n\r\n" .
1348  $payload;
1349 
1350  if($this->debug > 1)
1351  {
1352  print "<PRE>\n---SENDING---\n" . htmlentities($op) . "\n---END---\n</PRE>";
1353  // let the client see this now in case http times out...
1354  flush();
1355  }
1356 
1357  if($timeout>0)
1358  {
1359  $fp=@fsockopen($connectserver, $connectport, $this->errno, $this->errstr, $timeout);
1360  }
1361  else
1362  {
1363  $fp=@fsockopen($connectserver, $connectport, $this->errno, $this->errstr);
1364  }
1365  if($fp)
1366  {
1367  if($timeout>0 && function_exists('stream_set_timeout'))
1368  {
1369  stream_set_timeout($fp, $timeout);
1370  }
1371  }
1372  else
1373  {
1374  $this->errstr='Connect error: '.$this->errstr;
1375  $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $this->errstr . ' (' . $this->errno . ')');
1376  return $r;
1377  }
1378 
1379  if(!fputs($fp, $op, strlen($op)))
1380  {
1381  $this->errstr='Write error';
1382  $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $this->errstr);
1383  return $r;
1384  }
1385  else
1386  {
1387  // reset errno and errstr on succesful socket connection
1388  $this->errstr = '';
1389  }
1390  // G. Giunta 2005/10/24: close socket before parsing.
1391  // should yeld slightly better execution times, and make easier recursive calls (e.g. to follow http redirects)
1392  $ipd='';
1393  while($data=fread($fp, 32768))
1394  {
1395  // shall we check for $data === FALSE?
1396  // as per the manual, it signals an error
1397  $ipd.=$data;
1398  }
1399  fclose($fp);
1400  $r =& $msg->parseResponse($ipd, false, $this->return_type);
1401  return $r;
1402 
1403  }
1404 
1408  function &sendPayloadHTTPS($msg, $server, $port, $timeout=0, $username='',
1409  $password='', $authtype=1, $cert='',$certpass='', $cacert='', $cacertdir='',
1410  $proxyhost='', $proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1,
1411  $keepalive=false, $key='', $keypass='')
1412  {
1413  $r =& $this->sendPayloadCURL($msg, $server, $port, $timeout, $username,
1415  $proxyusername, $proxypassword, $proxyauthtype, 'https', $keepalive, $key, $keypass);
1416  return $r;
1417  }
1418 
1425  function &sendPayloadCURL($msg, $server, $port, $timeout=0, $username='',
1426  $password='', $authtype=1, $cert='', $certpass='', $cacert='', $cacertdir='',
1427  $proxyhost='', $proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1, $method='https',
1428  $keepalive=false, $key='', $keypass='')
1429  {
1430  if(!function_exists('curl_init'))
1431  {
1432  $this->errstr='CURL unavailable on this install';
1433  $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_curl'], $GLOBALS['xmlrpcstr']['no_curl']);
1434  return $r;
1435  }
1436  if($method == 'https')
1437  {
1438  if(($info = curl_version()) &&
1439  ((is_string($info) && strpos($info, 'OpenSSL') === null) || (is_array($info) && !isset($info['ssl_version']))))
1440  {
1441  $this->errstr='SSL unavailable on this install';
1442  $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_ssl'], $GLOBALS['xmlrpcstr']['no_ssl']);
1443  return $r;
1444  }
1445  }
1446 
1447  if($port == 0)
1448  {
1449  if($method == 'http')
1450  {
1451  $port = 80;
1452  }
1453  else
1454  {
1455  $port = 443;
1456  }
1457  }
1458 
1459  // Only create the payload if it was not created previously
1460  if(empty($msg->payload))
1461  {
1462  $msg->createPayload($this->request_charset_encoding);
1463  }
1464 
1465  // Deflate request body and set appropriate request headers
1466  $payload = $msg->payload;
1467  if(function_exists('gzdeflate') && ($this->request_compression == 'gzip' || $this->request_compression == 'deflate'))
1468  {
1469  if($this->request_compression == 'gzip')
1470  {
1471  $a = @gzencode($payload);
1472  if($a)
1473  {
1474  $payload = $a;
1475  $encoding_hdr = 'Content-Encoding: gzip';
1476  }
1477  }
1478  else
1479  {
1480  $a = @gzcompress($payload);
1481  if($a)
1482  {
1483  $payload = $a;
1484  $encoding_hdr = 'Content-Encoding: deflate';
1485  }
1486  }
1487  }
1488  else
1489  {
1490  $encoding_hdr = '';
1491  }
1492 
1493  if($this->debug > 1)
1494  {
1495  print "<PRE>\n---SENDING---\n" . htmlentities($payload) . "\n---END---\n</PRE>";
1496  // let the client see this now in case http times out...
1497  flush();
1498  }
1499 
1500  if(!$keepalive || !$this->xmlrpc_curl_handle)
1501  {
1502  $curl = curl_init($method . '://' . $server . ':' . $port . $this->path);
1503  if($keepalive)
1504  {
1505  $this->xmlrpc_curl_handle = $curl;
1506  }
1507  }
1508  else
1509  {
1510  $curl = $this->xmlrpc_curl_handle;
1511  }
1512 
1513  // results into variable
1514  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
1515 
1516  if($this->debug)
1517  {
1518  curl_setopt($curl, CURLOPT_VERBOSE, 1);
1519  }
1520  curl_setopt($curl, CURLOPT_USERAGENT, $GLOBALS['xmlrpcName'].' '.$GLOBALS['xmlrpcVersion']);
1521  // required for XMLRPC: post the data
1522  curl_setopt($curl, CURLOPT_POST, 1);
1523  // the data
1524  curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
1525 
1526  // return the header too
1527  curl_setopt($curl, CURLOPT_HEADER, 1);
1528 
1529  // will only work with PHP >= 5.0
1530  // NB: if we set an empty string, CURL will add http header indicating
1531  // ALL methods it is supporting. This is possibly a better option than
1532  // letting the user tell what curl can / cannot do...
1533  if(is_array($this->accepted_compression) && count($this->accepted_compression))
1534  {
1535  //curl_setopt($curl, CURLOPT_ENCODING, implode(',', $this->accepted_compression));
1536  // empty string means 'any supported by CURL' (shall we catch errors in case CURLOPT_SSLKEY undefined ?)
1537  if (count($this->accepted_compression) == 1)
1538  {
1539  curl_setopt($curl, CURLOPT_ENCODING, $this->accepted_compression[0]);
1540  }
1541  else
1542  curl_setopt($curl, CURLOPT_ENCODING, '');
1543  }
1544  // extra headers
1545  $headers = array('Content-Type: ' . $msg->content_type , 'Accept-Charset: ' . implode(',', $this->accepted_charset_encodings));
1546  // if no keepalive is wanted, let the server know it in advance
1547  if(!$keepalive)
1548  {
1549  $headers[] = 'Connection: close';
1550  }
1551  // request compression header
1552  if($encoding_hdr)
1553  {
1554  $headers[] = $encoding_hdr;
1555  }
1556 
1557  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
1558  // timeout is borked
1559  if($timeout)
1560  {
1561  curl_setopt($curl, CURLOPT_TIMEOUT, $timeout == 1 ? 1 : $timeout - 1);
1562  }
1563 
1564  if($username && $password)
1565  {
1566  curl_setopt($curl, CURLOPT_USERPWD, $username.':'.$password);
1567  if (defined('CURLOPT_HTTPAUTH'))
1568  {
1569  curl_setopt($curl, CURLOPT_HTTPAUTH, $authtype);
1570  }
1571  else if ($authtype != 1)
1572  {
1573  error_log('XML-RPC: xmlrpc_client::send: warning. Only Basic auth is supported by the current PHP/curl install');
1574  }
1575  }
1576 
1577  if($method == 'https')
1578  {
1579  // set cert file
1580  if($cert)
1581  {
1582  curl_setopt($curl, CURLOPT_SSLCERT, $cert);
1583  }
1584  // set cert password
1585  if($certpass)
1586  {
1587  curl_setopt($curl, CURLOPT_SSLCERTPASSWD, $certpass);
1588  }
1589  // whether to verify remote host's cert
1590  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verifypeer);
1591  // set ca certificates file/dir
1592  if($cacert)
1593  {
1594  curl_setopt($curl, CURLOPT_CAINFO, $cacert);
1595  }
1596  if($cacertdir)
1597  {
1598  curl_setopt($curl, CURLOPT_CAPATH, $cacertdir);
1599  }
1600  // set key file (shall we catch errors in case CURLOPT_SSLKEY undefined ?)
1601  if($key)
1602  {
1603  curl_setopt($curl, CURLOPT_SSLKEY, $key);
1604  }
1605  // set key password (shall we catch errors in case CURLOPT_SSLKEY undefined ?)
1606  if($keypass)
1607  {
1608  curl_setopt($curl, CURLOPT_SSLKEYPASSWD, $keypass);
1609  }
1610  // 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
1611  curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $this->verifyhost);
1612  }
1613 
1614  // proxy info
1615  if($proxyhost)
1616  {
1617  if($proxyport == 0)
1618  {
1619  $proxyport = 8080; // NB: even for HTTPS, local connection is on port 8080
1620  }
1621  curl_setopt($curl, CURLOPT_PROXY, $proxyhost.':'.$proxyport);
1622  //curl_setopt($curl, CURLOPT_PROXYPORT,$proxyport);
1623  if($proxyusername)
1624  {
1625  curl_setopt($curl, CURLOPT_PROXYUSERPWD, $proxyusername.':'.$proxypassword);
1626  if (defined('CURLOPT_PROXYAUTH'))
1627  {
1628  curl_setopt($curl, CURLOPT_PROXYAUTH, $proxyauthtype);
1629  }
1630  else if ($proxyauthtype != 1)
1631  {
1632  error_log('XML-RPC: xmlrpc_client::send: warning. Only Basic auth to proxy is supported by the current PHP/curl install');
1633  }
1634  }
1635  }
1636 
1637  // NB: should we build cookie http headers by hand rather than let CURL do it?
1638  // the following code does not honour 'expires', 'path' and 'domain' cookie attributes
1639  // set to client obj the the user...
1640  if (count($this->cookies))
1641  {
1642  $cookieheader = '';
1643  foreach ($this->cookies as $name => $cookie)
1644  {
1645  $cookieheader .= $name . '=' . $cookie['value'] . '; ';
1646  }
1647  curl_setopt($curl, CURLOPT_COOKIE, substr($cookieheader, 0, -2));
1648  }
1649 
1650  $result = curl_exec($curl);
1651 
1652  if ($this->debug > 1)
1653  {
1654  print "<PRE>\n---CURL INFO---\n";
1655  foreach(curl_getinfo($curl) as $name => $val)
1656  print $name . ': ' . htmlentities($val). "\n";
1657  print "---END---\n</PRE>";
1658  }
1659 
1660  if(!$result)
1661  {
1662  $this->errstr='no response';
1663  $resp=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['curl_fail'], $GLOBALS['xmlrpcstr']['curl_fail']. ': '. curl_error($curl));
1664  curl_close($curl);
1665  if($keepalive)
1666  {
1667  $this->xmlrpc_curl_handle = null;
1668  }
1669  }
1670  else
1671  {
1672  if(!$keepalive)
1673  {
1674  curl_close($curl);
1675  }
1676  $resp =& $msg->parseResponse($result, true, $this->return_type);
1677  }
1678  return $resp;
1679  }
1680 
1703  function multicall($msgs, $timeout=0, $method='', $fallback=true)
1704  {
1705  if ($method == '')
1706  {
1708  }
1709  if(!$this->no_multicall)
1710  {
1711  $results = $this->_try_multicall($msgs, $timeout, $method);
1712  if(is_array($results))
1713  {
1714  // System.multicall succeeded
1715  return $results;
1716  }
1717  else
1718  {
1719  // either system.multicall is unsupported by server,
1720  // or call failed for some other reason.
1721  if ($fallback)
1722  {
1723  // Don't try it next time...
1724  $this->no_multicall = true;
1725  }
1726  else
1727  {
1728  if (is_a($results, 'xmlrpcresp'))
1729  {
1730  $result = $results;
1731  }
1732  else
1733  {
1734  $result = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['multicall_error'], $GLOBALS['xmlrpcstr']['multicall_error']);
1735  }
1736  }
1737  }
1738  }
1739  else
1740  {
1741  // override fallback, in case careless user tries to do two
1742  // opposite things at the same time
1743  $fallback = true;
1744  }
1745 
1746  $results = array();
1747  if ($fallback)
1748  {
1749  // system.multicall is (probably) unsupported by server:
1750  // emulate multicall via multiple requests
1751  foreach($msgs as $msg)
1752  {
1753  $results[] =& $this->send($msg, $timeout, $method);
1754  }
1755  }
1756  else
1757  {
1758  // user does NOT want to fallback on many single calls:
1759  // since we should always return an array of responses,
1760  // return an array with the same error repeated n times
1761  foreach($msgs as $msg)
1762  {
1763  $results[] = $result;
1764  }
1765  }
1766  return $results;
1767  }
1768 
1775  function _try_multicall($msgs, $timeout, $method)
1776  {
1777  // Construct multicall message
1778  $calls = array();
1779  foreach($msgs as $msg)
1780  {
1781  $call['methodName'] = new xmlrpcval($msg->method(),'string');
1782  $numParams = $msg->getNumParams();
1783  $params = array();
1784  for($i = 0; $i < $numParams; $i++)
1785  {
1786  $params[$i] = $msg->getParam($i);
1787  }
1788  $call['params'] = new xmlrpcval($params, 'array');
1789  $calls[] = new xmlrpcval($call, 'struct');
1790  }
1791  $multicall = new xmlrpcmsg('system.multicall');
1792  $multicall->addParam(new xmlrpcval($calls, 'array'));
1793 
1794  // Attempt RPC call
1795  $result =& $this->send($multicall, $timeout, $method);
1796 
1797  if($result->faultCode() != 0)
1798  {
1799  // call to system.multicall failed
1800  return $result;
1801  }
1802 
1803  // Unpack responses.
1804  $rets = $result->value();
1805 
1806  if ($this->return_type == 'xml')
1807  {
1808  return $rets;
1809  }
1810  else if ($this->return_type == 'phpvals')
1811  {
1813  $rets = $result->value();
1814  if(!is_array($rets))
1815  {
1816  return false; // bad return type from system.multicall
1817  }
1818  $numRets = count($rets);
1819  if($numRets != count($msgs))
1820  {
1821  return false; // wrong number of return values.
1822  }
1823 
1824  $response = array();
1825  for($i = 0; $i < $numRets; $i++)
1826  {
1827  $val = $rets[$i];
1828  if (!is_array($val)) {
1829  return false;
1830  }
1831  switch(count($val))
1832  {
1833  case 1:
1834  if(!isset($val[0]))
1835  {
1836  return false; // Bad value
1837  }
1838  // Normal return value
1839  $response[$i] = new xmlrpcresp($val[0], 0, '', 'phpvals');
1840  break;
1841  case 2:
1843  $code = @$val['faultCode'];
1844  if(!is_int($code))
1845  {
1846  return false;
1847  }
1848  $str = @$val['faultString'];
1849  if(!is_string($str))
1850  {
1851  return false;
1852  }
1853  $response[$i] = new xmlrpcresp(0, $code, $str);
1854  break;
1855  default:
1856  return false;
1857  }
1858  }
1859  return $response;
1860  }
1861  else // return type == 'xmlrpcvals'
1862  {
1863  $rets = $result->value();
1864  if($rets->kindOf() != 'array')
1865  {
1866  return false; // bad return type from system.multicall
1867  }
1868  $numRets = $rets->arraysize();
1869  if($numRets != count($msgs))
1870  {
1871  return false; // wrong number of return values.
1872  }
1873 
1874  $response = array();
1875  for($i = 0; $i < $numRets; $i++)
1876  {
1877  $val = $rets->arraymem($i);
1878  switch($val->kindOf())
1879  {
1880  case 'array':
1881  if($val->arraysize() != 1)
1882  {
1883  return false; // Bad value
1884  }
1885  // Normal return value
1886  $response[$i] = new xmlrpcresp($val->arraymem(0));
1887  break;
1888  case 'struct':
1889  $code = $val->structmem('faultCode');
1890  if($code->kindOf() != 'scalar' || $code->scalartyp() != 'int')
1891  {
1892  return false;
1893  }
1894  $str = $val->structmem('faultString');
1895  if($str->kindOf() != 'scalar' || $str->scalartyp() != 'string')
1896  {
1897  return false;
1898  }
1899  $response[$i] = new xmlrpcresp(0, $code->scalarval(), $str->scalarval());
1900  break;
1901  default:
1902  return false;
1903  }
1904  }
1905  return $response;
1906  }
1907  }
1908  } // end class xmlrpc_client
1909 
1911  {
1912  var $val = 0;
1913  var $valtyp;
1914  var $errno = 0;
1915  var $errstr = '';
1917  var $hdrs = array();
1918  var $_cookies = array();
1919  var $content_type = 'text/xml';
1920  var $raw_data = '';
1921 
1932  function __construct($val, $fcode = 0, $fstr = '', $valtyp='')
1933  {
1934  if($fcode != 0)
1935  {
1936  // error response
1937  $this->errno = $fcode;
1938  $this->errstr = $fstr;
1939  //$this->errstr = htmlspecialchars($fstr); // XXX: encoding probably shouldn't be done here; fix later.
1940  }
1941  else
1942  {
1943  // successful response
1944  $this->val = $val;
1945  if ($valtyp == '')
1946  {
1947  // user did not declare type of response value: try to guess it
1948  if (is_object($this->val) && is_a($this->val, 'xmlrpcval'))
1949  {
1950  $this->valtyp = 'xmlrpcvals';
1951  }
1952  else if (is_string($this->val))
1953  {
1954  $this->valtyp = 'xml';
1955 
1956  }
1957  else
1958  {
1959  $this->valtyp = 'phpvals';
1960  }
1961  }
1962  else
1963  {
1964  // user declares type of resp value: believe him
1965  $this->valtyp = $valtyp;
1966  }
1967  }
1968  }
1969 
1975  function faultCode()
1976  {
1977  return $this->errno;
1978  }
1979 
1985  function faultString()
1986  {
1987  return $this->errstr;
1988  }
1989 
1995  function value()
1996  {
1997  return $this->val;
1998  }
1999 
2011  function cookies()
2012  {
2013  return $this->_cookies;
2014  }
2015 
2022  function serialize($charset_encoding='')
2023  {
2024  if ($charset_encoding != '')
2025  $this->content_type = 'text/xml; charset=' . $charset_encoding;
2026  else
2027  $this->content_type = 'text/xml';
2028  $result = "<methodResponse>\n";
2029  if($this->errno)
2030  {
2031  // G. Giunta 2005/2/13: let non-ASCII response messages be tolerated by clients
2032  // by xml-encoding non ascii chars
2033  $result .= "<fault>\n" .
2034 "<value>\n<struct><member><name>faultCode</name>\n<value><int>" . $this->errno .
2035 "</int></value>\n</member>\n<member>\n<name>faultString</name>\n<value><string>" .
2036 xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $charset_encoding) . "</string></value>\n</member>\n" .
2037 "</struct>\n</value>\n</fault>";
2038  }
2039  else
2040  {
2041  if(!is_object($this->val) || !is_a($this->val, 'xmlrpcval'))
2042  {
2043  if (is_string($this->val) && $this->valtyp == 'xml')
2044  {
2045  $result .= "<params>\n<param>\n" .
2046  $this->val .
2047  "</param>\n</params>";
2048  }
2049  else
2050  {
2052  die('cannot serialize xmlrpcresp objects whose content is native php values');
2053  }
2054  }
2055  else
2056  {
2057  $result .= "<params>\n<param>\n" .
2058  $this->val->serialize($charset_encoding) .
2059  "</param>\n</params>";
2060  }
2061  }
2062  $result .= "\n</methodResponse>";
2063  $this->payload = $result;
2064  return $result;
2065  }
2066  }
2067 
2069  {
2072  var $params=array();
2073  var $debug=0;
2074  var $content_type = 'text/xml';
2075 
2080  function __construct($meth, $pars=0)
2081  {
2082  $this->methodname=$meth;
2083  if(is_array($pars) && count($pars)>0)
2084  {
2085  for($i=0; $i<count($pars); $i++)
2086  {
2087  $this->addParam($pars[$i]);
2088  }
2089  }
2090  }
2091 
2095  function xml_header($charset_encoding='')
2096  {
2097  if ($charset_encoding != '')
2098  {
2099  return "<?xml version=\"1.0\" encoding=\"$charset_encoding\" ?" . ">\n<methodCall>\n";
2100  }
2101  else
2102  {
2103  return "<?xml version=\"1.0\"?" . ">\n<methodCall>\n";
2104  }
2105  }
2106 
2110  function xml_footer()
2111  {
2112  return '</methodCall>';
2113  }
2114 
2118  function kindOf()
2119  {
2120  return 'msg';
2121  }
2122 
2126  function createPayload($charset_encoding='')
2127  {
2128  if ($charset_encoding != '')
2129  $this->content_type = 'text/xml; charset=' . $charset_encoding;
2130  else
2131  $this->content_type = 'text/xml';
2132  $this->payload=$this->xml_header($charset_encoding);
2133  $this->payload.='<methodName>' . $this->methodname . "</methodName>\n";
2134  $this->payload.="<params>\n";
2135  for($i=0; $i<count($this->params); $i++)
2136  {
2137  $p=$this->params[$i];
2138  $this->payload.="<param>\n" . $p->serialize($charset_encoding) .
2139  "</param>\n";
2140  }
2141  $this->payload.="</params>\n";
2142  $this->payload.=$this->xml_footer();
2143  }
2144 
2151  function method($meth='')
2152  {
2153  if($meth!='')
2154  {
2155  $this->methodname=$meth;
2156  }
2157  return $this->methodname;
2158  }
2159 
2165  function serialize($charset_encoding='')
2166  {
2167  $this->createPayload($charset_encoding);
2168  return $this->payload;
2169  }
2170 
2177  function addParam($par)
2178  {
2179  // add check: do not add to self params which are not xmlrpcvals
2180  if(is_object($par) && is_a($par, 'xmlrpcval'))
2181  {
2182  $this->params[]=$par;
2183  return true;
2184  }
2185  else
2186  {
2187  return false;
2188  }
2189  }
2190 
2197  function getParam($i) { return $this->params[$i]; }
2198 
2204  function getNumParams() { return count($this->params); }
2205 
2213  function &parseResponseFile($fp)
2214  {
2215  $ipd='';
2216  while($data=fread($fp, 32768))
2217  {
2218  $ipd.=$data;
2219  }
2220  //fclose($fp);
2221  $r =& $this->parseResponse($ipd);
2222  return $r;
2223  }
2224 
2229  function &parseResponseHeaders(&$data, $headers_processed=false)
2230  {
2231  // Support "web-proxy-tunelling" connections for https through proxies
2232  if(preg_match('/^HTTP\/1\.[0-1] 200 Connection established/', $data))
2233  {
2234  // Look for CR/LF or simple LF as line separator,
2235  // (even though it is not valid http)
2236  $pos = strpos($data,"\r\n\r\n");
2237  if($pos || is_int($pos))
2238  {
2239  $bd = $pos+4;
2240  }
2241  else
2242  {
2243  $pos = strpos($data,"\n\n");
2244  if($pos || is_int($pos))
2245  {
2246  $bd = $pos+2;
2247  }
2248  else
2249  {
2250  // No separation between response headers and body: fault?
2251  $bd = 0;
2252  }
2253  }
2254  if ($bd)
2255  {
2256  // this filters out all http headers from proxy.
2257  // maybe we could take them into account, too?
2258  $data = substr($data, $bd);
2259  }
2260  else
2261  {
2262  error_log('XML-RPC: xmlrpcmsg::parseResponse: HTTPS via proxy error, tunnel connection possibly failed');
2263  $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $GLOBALS['xmlrpcstr']['http_error']. ' (HTTPS via proxy error, tunnel connection possibly failed)');
2264  return $r;
2265  }
2266  }
2267 
2268  // Strip HTTP 1.1 100 Continue header if present
2269  while(preg_match('/^HTTP\/1\.1 1[0-9]{2} /', $data))
2270  {
2271  $pos = strpos($data, 'HTTP', 12);
2272  // server sent a Continue header without any (valid) content following...
2273  // give the client a chance to know it
2274  if(!$pos && !is_int($pos)) // works fine in php 3, 4 and 5
2275  {
2276  break;
2277  }
2278  $data = substr($data, $pos);
2279  }
2280  if(!preg_match('/^HTTP\/[0-9.]+ 200 /', $data))
2281  {
2282  $errstr= substr($data, 0, strpos($data, "\n")-1);
2283  error_log('XML-RPC: xmlrpcmsg::parseResponse: HTTP error, got response: ' .$errstr);
2284  $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $GLOBALS['xmlrpcstr']['http_error']. ' (' . $errstr . ')');
2285  return $r;
2286  }
2287 
2288  $GLOBALS['_xh']['headers'] = array();
2289  $GLOBALS['_xh']['cookies'] = array();
2290 
2291  // be tolerant to usage of \n instead of \r\n to separate headers and data
2292  // (even though it is not valid http)
2293  $pos = strpos($data,"\r\n\r\n");
2294  if($pos || is_int($pos))
2295  {
2296  $bd = $pos+4;
2297  }
2298  else
2299  {
2300  $pos = strpos($data,"\n\n");
2301  if($pos || is_int($pos))
2302  {
2303  $bd = $pos+2;
2304  }
2305  else
2306  {
2307  // No separation between response headers and body: fault?
2308  // we could take some action here instead of going on...
2309  $bd = 0;
2310  }
2311  }
2312  // be tolerant to line endings, and extra empty lines
2313  $ar = preg_split("/\r?\n/", trim(substr($data, 0, $pos)));
2314  while(list(,$line) = @each($ar))
2315  {
2316  // take care of multi-line headers and cookies
2317  $arr = explode(':',$line,2);
2318  if(count($arr) > 1)
2319  {
2320  $header_name = strtolower(trim($arr[0]));
2325  if ($header_name == 'set-cookie' || $header_name == 'set-cookie2')
2326  {
2327  if ($header_name == 'set-cookie2')
2328  {
2329  // version 2 cookies:
2330  // there could be many cookies on one line, comma separated
2331  $cookies = explode(',', $arr[1]);
2332  }
2333  else
2334  {
2335  $cookies = array($arr[1]);
2336  }
2337  foreach ($cookies as $cookie)
2338  {
2339  // glue together all received cookies, using a comma to separate them
2340  // (same as php does with getallheaders())
2341  if (isset($GLOBALS['_xh']['headers'][$header_name]))
2342  $GLOBALS['_xh']['headers'][$header_name] .= ', ' . trim($cookie);
2343  else
2344  $GLOBALS['_xh']['headers'][$header_name] = trim($cookie);
2345  // parse cookie attributes, in case user wants to correctly honour them
2346  // feature creep: only allow rfc-compliant cookie attributes?
2347  // @todo support for server sending multiple time cookie with same name, but using different PATHs
2348  $cookie = explode(';', $cookie);
2349  foreach ($cookie as $pos => $val)
2350  {
2351  $val = explode('=', $val, 2);
2352  $tag = trim($val[0]);
2353  $val = trim(@$val[1]);
2355  if ($pos == 0)
2356  {
2357  $cookiename = $tag;
2358  $GLOBALS['_xh']['cookies'][$tag] = array();
2359  $GLOBALS['_xh']['cookies'][$cookiename]['value'] = urldecode($val);
2360  }
2361  else
2362  {
2363  if ($tag != 'value')
2364  {
2365  $GLOBALS['_xh']['cookies'][$cookiename][$tag] = $val;
2366  }
2367  }
2368  }
2369  }
2370  }
2371  else
2372  {
2373  $GLOBALS['_xh']['headers'][$header_name] = trim($arr[1]);
2374  }
2375  }
2376  elseif(isset($header_name))
2377  {
2379  $GLOBALS['_xh']['headers'][$header_name] .= ' ' . trim($line);
2380  }
2381  }
2382 
2383  $data = substr($data, $bd);
2384 
2385  if($this->debug && count($GLOBALS['_xh']['headers']))
2386  {
2387  print '<PRE>';
2388  foreach($GLOBALS['_xh']['headers'] as $header => $value)
2389  {
2390  print htmlentities("HEADER: $header: $value\n");
2391  }
2392  foreach($GLOBALS['_xh']['cookies'] as $header => $value)
2393  {
2394  print htmlentities("COOKIE: $header={$value['value']}\n");
2395  }
2396  print "</PRE>\n";
2397  }
2398 
2399  // if CURL was used for the call, http headers have been processed,
2400  // and dechunking + reinflating have been carried out
2401  if(!$headers_processed)
2402  {
2403  // Decode chunked encoding sent by http 1.1 servers
2404  if(isset($GLOBALS['_xh']['headers']['transfer-encoding']) && $GLOBALS['_xh']['headers']['transfer-encoding'] == 'chunked')
2405  {
2406  if(!$data = decode_chunked($data))
2407  {
2408  error_log('XML-RPC: xmlrpcmsg::parseResponse: errors occurred when trying to rebuild the chunked data received from server');
2409  $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['dechunk_fail'], $GLOBALS['xmlrpcstr']['dechunk_fail']);
2410  return $r;
2411  }
2412  }
2413 
2414  // Decode gzip-compressed stuff
2415  // code shamelessly inspired from nusoap library by Dietrich Ayala
2416  if(isset($GLOBALS['_xh']['headers']['content-encoding']))
2417  {
2418  $GLOBALS['_xh']['headers']['content-encoding'] = str_replace('x-', '', $GLOBALS['_xh']['headers']['content-encoding']);
2419  if($GLOBALS['_xh']['headers']['content-encoding'] == 'deflate' || $GLOBALS['_xh']['headers']['content-encoding'] == 'gzip')
2420  {
2421  // if decoding works, use it. else assume data wasn't gzencoded
2422  if(function_exists('gzinflate'))
2423  {
2424  if($GLOBALS['_xh']['headers']['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data))
2425  {
2426  $data = $degzdata;
2427  if($this->debug)
2428  print "<PRE>---INFLATED RESPONSE---[".strlen($data)." chars]---\n" . htmlentities($data) . "\n---END---</PRE>";
2429  }
2430  elseif($GLOBALS['_xh']['headers']['content-encoding'] == 'gzip' && $degzdata = @gzinflate(substr($data, 10)))
2431  {
2432  $data = $degzdata;
2433  if($this->debug)
2434  print "<PRE>---INFLATED RESPONSE---[".strlen($data)." chars]---\n" . htmlentities($data) . "\n---END---</PRE>";
2435  }
2436  else
2437  {
2438  error_log('XML-RPC: xmlrpcmsg::parseResponse: errors occurred when trying to decode the deflated data received from server');
2439  $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['decompress_fail'], $GLOBALS['xmlrpcstr']['decompress_fail']);
2440  return $r;
2441  }
2442  }
2443  else
2444  {
2445  error_log('XML-RPC: xmlrpcmsg::parseResponse: the server sent deflated data. Your php install must have the Zlib extension compiled in to support this.');
2446  $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['cannot_decompress'], $GLOBALS['xmlrpcstr']['cannot_decompress']);
2447  return $r;
2448  }
2449  }
2450  }
2451  } // end of 'if needed, de-chunk, re-inflate response'
2452 
2453  // real stupid hack to avoid PHP 4 complaining about returning NULL by ref
2454  $r = null;
2455  $r =& $r;
2456  return $r;
2457  }
2458 
2467  function &parseResponse($data='', $headers_processed=false, $return_type='xmlrpcvals')
2468  {
2469  if($this->debug)
2470  {
2471  //by maHo, replaced htmlspecialchars with htmlentities
2472  print "<PRE>---GOT---\n" . htmlentities($data) . "\n---END---\n</PRE>";
2473  }
2474 
2475  if($data == '')
2476  {
2477  error_log('XML-RPC: xmlrpcmsg::parseResponse: no response received from server.');
2478  $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_data'], $GLOBALS['xmlrpcstr']['no_data']);
2479  return $r;
2480  }
2481 
2482  $GLOBALS['_xh']=array();
2483 
2484  $raw_data = $data;
2485  // parse the HTTP headers of the response, if present, and separate them from data
2486  if(substr($data, 0, 4) == 'HTTP')
2487  {
2488  $r =& $this->parseResponseHeaders($data, $headers_processed);
2489  if ($r)
2490  {
2491  // failed processing of HTTP response headers
2492  // save into response obj the full payload received, for debugging
2493  $r->raw_data = $data;
2494  return $r;
2495  }
2496  }
2497  else
2498  {
2499  $GLOBALS['_xh']['headers'] = array();
2500  $GLOBALS['_xh']['cookies'] = array();
2501  }
2502 
2503  if($this->debug)
2504  {
2505  $start = strpos($data, '<!-- SERVER DEBUG INFO (BASE64 ENCODED):');
2506  if ($start)
2507  {
2508  $start += strlen('<!-- SERVER DEBUG INFO (BASE64 ENCODED):');
2509  $end = strpos($data, '-->', $start);
2510  $comments = substr($data, $start, $end-$start);
2511  print "<PRE>---SERVER DEBUG INFO (DECODED) ---\n\t".htmlentities(str_replace("\n", "\n\t", base64_decode($comments)))."\n---END---\n</PRE>";
2512  }
2513  }
2514 
2515  // be tolerant of extra whitespace in response body
2516  $data = trim($data);
2517 
2519 
2520  // be tolerant of junk after methodResponse (e.g. javascript ads automatically inserted by free hosts)
2521  // idea from Luca Mariano <luca.mariano@email.it> originally in PEARified version of the lib
2522  $bd = false;
2523  // Poor man's version of strrpos for php 4...
2524  $pos = strpos($data, '</methodResponse>');
2525  while($pos || is_int($pos))
2526  {
2527  $bd = $pos+17;
2528  $pos = strpos($data, '</methodResponse>', $bd);
2529  }
2530  if($bd)
2531  {
2532  $data = substr($data, 0, $bd);
2533  }
2534 
2535  // if user wants back raw xml, give it to him
2536  if ($return_type == 'xml')
2537  {
2538  $r = new xmlrpcresp($data, 0, '', 'xml');
2539  $r->hdrs = $GLOBALS['_xh']['headers'];
2540  $r->_cookies = $GLOBALS['_xh']['cookies'];
2541  $r->raw_data = $raw_data;
2542  return $r;
2543  }
2544 
2545  // try to 'guestimate' the character encoding of the received response
2546  $resp_encoding = guess_encoding(@$GLOBALS['_xh']['headers']['content-type'], $data);
2547 
2548  $GLOBALS['_xh']['ac']='';
2549  //$GLOBALS['_xh']['qt']=''; //unused...
2550  $GLOBALS['_xh']['stack'] = array();
2551  $GLOBALS['_xh']['valuestack'] = array();
2552  $GLOBALS['_xh']['isf']=0; // 0 = OK, 1 for xmlrpc fault responses, 2 = invalid xmlrpc
2553  $GLOBALS['_xh']['isf_reason']='';
2554  $GLOBALS['_xh']['rt']=''; // 'methodcall or 'methodresponse'
2555 
2556  // if response charset encoding is not known / supported, try to use
2557  // the default encoding and parse the xml anyway, but log a warning...
2558  if (!in_array($resp_encoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII')))
2559  // the following code might be better for mb_string enabled installs, but
2560  // makes the lib about 200% slower...
2561  //if (!is_valid_charset($resp_encoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII')))
2562  {
2563  error_log('XML-RPC: xmlrpcmsg::parseResponse: invalid charset encoding of received response: '.$resp_encoding);
2564  $resp_encoding = $GLOBALS['xmlrpc_defencoding'];
2565  }
2566  $parser = xml_parser_create($resp_encoding);
2567  xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
2568  // G. Giunta 2005/02/13: PHP internally uses ISO-8859-1, so we have to tell
2569  // the xml parser to give us back data in the expected charset.
2570  // What if internal encoding is not in one of the 3 allowed?
2571  // we use the broadest one, ie. utf8
2572  // This allows to send data which is native in various charset,
2573  // by extending xmlrpc_encode_entitites() and setting xmlrpc_internalencoding
2574  if (!in_array($GLOBALS['xmlrpc_internalencoding'], array('UTF-8', 'ISO-8859-1', 'US-ASCII')))
2575  {
2576  xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
2577  }
2578  else
2579  {
2580  xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $GLOBALS['xmlrpc_internalencoding']);
2581  }
2582 
2583  if ($return_type == 'phpvals')
2584  {
2585  xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee_fast');
2586  }
2587  else
2588  {
2589  xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee');
2590  }
2591 
2592  xml_set_character_data_handler($parser, 'xmlrpc_cd');
2593  xml_set_default_handler($parser, 'xmlrpc_dh');
2594 
2595  // first error check: xml not well formed
2596  if(!xml_parse($parser, $data, count($data)))
2597  {
2598  // thanks to Peter Kocks <peter.kocks@baygate.com>
2599  if((xml_get_current_line_number($parser)) == 1)
2600  {
2601  $errstr = 'XML error at line 1, check URL';
2602  }
2603  else
2604  {
2605  $errstr = sprintf('XML error: %s at line %d, column %d',
2606  xml_error_string(xml_get_error_code($parser)),
2607  xml_get_current_line_number($parser), xml_get_current_column_number($parser));
2608  }
2609  error_log($errstr);
2610  $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcstr']['invalid_return'].' ('.$errstr.')');
2611  xml_parser_free($parser);
2612  if($this->debug)
2613  {
2614  print $errstr;
2615  }
2616  $r->hdrs = $GLOBALS['_xh']['headers'];
2617  $r->_cookies = $GLOBALS['_xh']['cookies'];
2618  $r->raw_data = $raw_data;
2619  return $r;
2620  }
2621  xml_parser_free($parser);
2622  // second error check: xml well formed but not xml-rpc compliant
2623  if ($GLOBALS['_xh']['isf'] > 1)
2624  {
2625  if ($this->debug)
2626  {
2628  }
2629 
2630  $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'],
2631  $GLOBALS['xmlrpcstr']['invalid_return'] . ' ' . $GLOBALS['_xh']['isf_reason']);
2632  }
2633  // third error check: parsing of the response has somehow gone boink.
2634  // NB: shall we omit this check, since we trust the parsing code?
2635  elseif ($return_type == 'xmlrpcvals' && !is_object($GLOBALS['_xh']['value']))
2636  {
2637  // something odd has happened
2638  // and it's time to generate a client side error
2639  // indicating something odd went on
2640  $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'],
2641  $GLOBALS['xmlrpcstr']['invalid_return']);
2642  }
2643  else
2644  {
2645  if ($this->debug)
2646  {
2647  print "<PRE>---PARSED---\n";
2648  // somehow htmlentities chokes on var_export, and some full html string...
2649  //print htmlentitites(var_export($GLOBALS['_xh']['value'], true));
2650  print htmlspecialchars(var_export($GLOBALS['_xh']['value'], true));
2651  print "\n---END---</PRE>";
2652  }
2653 
2654  // note that using =& will raise an error if $GLOBALS['_xh']['st'] does not generate an object.
2655  $v =& $GLOBALS['_xh']['value'];
2656 
2657  if($GLOBALS['_xh']['isf'])
2658  {
2661  if ($return_type == 'xmlrpcvals')
2662  {
2663  $errno_v = $v->structmem('faultCode');
2664  $errstr_v = $v->structmem('faultString');
2665  $errno = $errno_v->scalarval();
2666  $errstr = $errstr_v->scalarval();
2667  }
2668  else
2669  {
2670  $errno = $v['faultCode'];
2671  $errstr = $v['faultString'];
2672  }
2673 
2674  if($errno == 0)
2675  {
2676  // FAULT returned, errno needs to reflect that
2677  $errno = -1;
2678  }
2679 
2680  $r = new xmlrpcresp(0, $errno, $errstr);
2681  }
2682  else
2683  {
2684  $r=new xmlrpcresp($v, 0, '', $return_type);
2685  }
2686  }
2687 
2688  $r->hdrs = $GLOBALS['_xh']['headers'];
2689  $r->_cookies = $GLOBALS['_xh']['cookies'];
2690  $r->raw_data = $raw_data;
2691  return $r;
2692  }
2693  }
2694 
2696  {
2697  var $me=array();
2698  var $mytype=0;
2699  var $_php_class=null;
2700 
2705  function __construct($val=-1, $type='')
2706  {
2709  if($val!==-1 || $type!='')
2710  {
2711  // optimization creep: inlined all work done by constructor
2712  switch($type)
2713  {
2714  case '':
2715  $this->mytype=1;
2716  $this->me['string']=$val;
2717  break;
2718  case 'i4':
2719  case 'int':
2720  case 'double':
2721  case 'string':
2722  case 'boolean':
2723  case 'dateTime.iso8601':
2724  case 'base64':
2725  case 'null':
2726  $this->mytype=1;
2727  $this->me[$type]=$val;
2728  break;
2729  case 'array':
2730  $this->mytype=2;
2731  $this->me['array']=$val;
2732  break;
2733  case 'struct':
2734  $this->mytype=3;
2735  $this->me['struct']=$val;
2736  break;
2737  default:
2738  error_log("XML-RPC: xmlrpcval::xmlrpcval: not a known type ($type)");
2739  }
2740  /*if($type=='')
2741  {
2742  $type='string';
2743  }
2744  if($GLOBALS['xmlrpcTypes'][$type]==1)
2745  {
2746  $this->addScalar($val,$type);
2747  }
2748  elseif($GLOBALS['xmlrpcTypes'][$type]==2)
2749  {
2750  $this->addArray($val);
2751  }
2752  elseif($GLOBALS['xmlrpcTypes'][$type]==3)
2753  {
2754  $this->addStruct($val);
2755  }*/
2756  }
2757  }
2758 
2765  function addScalar($val, $type='string')
2766  {
2767  $typeof=@$GLOBALS['xmlrpcTypes'][$type];
2768  if($typeof!=1)
2769  {
2770  error_log("XML-RPC: xmlrpcval::addScalar: not a scalar type ($type)");
2771  return 0;
2772  }
2773 
2774  // coerce booleans into correct values
2775  // NB: we should iether do it for datetimes, integers and doubles, too,
2776  // or just plain remove this check, implemnted on booleans only...
2777  if($type==$GLOBALS['xmlrpcBoolean'])
2778  {
2779  if(strcasecmp($val,'true')==0 || $val==1 || ($val==true && strcasecmp($val,'false')))
2780  {
2781  $val=true;
2782  }
2783  else
2784  {
2785  $val=false;
2786  }
2787  }
2788 
2789  switch($this->mytype)
2790  {
2791  case 1:
2792  error_log('XML-RPC: xmlrpcval::addScalar: scalar xmlrpcval can have only one value');
2793  return 0;
2794  case 3:
2795  error_log('XML-RPC: xmlrpcval::addScalar: cannot add anonymous scalar to struct xmlrpcval');
2796  return 0;
2797  case 2:
2798  // we're adding a scalar value to an array here
2799  //$ar=$this->me['array'];
2800  //$ar[]=new xmlrpcval($val, $type);
2801  //$this->me['array']=$ar;
2802  // Faster (?) avoid all the costly array-copy-by-val done here...
2803  $this->me['array'][]=new xmlrpcval($val, $type);
2804  return 1;
2805  default:
2806  // a scalar, so set the value and remember we're scalar
2807  $this->me[$type]=$val;
2808  $this->mytype=$typeof;
2809  return 1;
2810  }
2811  }
2812 
2821  function addArray($vals)
2822  {
2823  if($this->mytype==0)
2824  {
2825  $this->mytype=$GLOBALS['xmlrpcTypes']['array'];
2826  $this->me['array']=$vals;
2827  return 1;
2828  }
2829  elseif($this->mytype==2)
2830  {
2831  // we're adding to an array here
2832  $this->me['array'] = array_merge($this->me['array'], $vals);
2833  return 1;
2834  }
2835  else
2836  {
2837  error_log('XML-RPC: xmlrpcval::addArray: already initialized as a [' . $this->kindOf() . ']');
2838  return 0;
2839  }
2840  }
2841 
2850  function addStruct($vals)
2851  {
2852  if($this->mytype==0)
2853  {
2854  $this->mytype=$GLOBALS['xmlrpcTypes']['struct'];
2855  $this->me['struct']=$vals;
2856  return 1;
2857  }
2858  elseif($this->mytype==3)
2859  {
2860  // we're adding to a struct here
2861  $this->me['struct'] = array_merge($this->me['struct'], $vals);
2862  return 1;
2863  }
2864  else
2865  {
2866  error_log('XML-RPC: xmlrpcval::addStruct: already initialized as a [' . $this->kindOf() . ']');
2867  return 0;
2868  }
2869  }
2870 
2871  // poor man's version of print_r ???
2872  // DEPRECATED!
2873  function dump($ar)
2874  {
2875  foreach($ar as $key => $val)
2876  {
2877  echo "$key => $val<br />";
2878  if($key == 'array')
2879  {
2880  while(list($key2, $val2) = each($val))
2881  {
2882  echo "-- $key2 => $val2<br />";
2883  }
2884  }
2885  }
2886  }
2887 
2893  function kindOf()
2894  {
2895  switch($this->mytype)
2896  {
2897  case 3:
2898  return 'struct';
2899  break;
2900  case 2:
2901  return 'array';
2902  break;
2903  case 1:
2904  return 'scalar';
2905  break;
2906  default:
2907  return 'undef';
2908  }
2909  }
2910 
2914  function serializedata($typ, $val, $charset_encoding='')
2915  {
2916  $rs='';
2917  switch(@$GLOBALS['xmlrpcTypes'][$typ])
2918  {
2919  case 1:
2920  switch($typ)
2921  {
2922  case $GLOBALS['xmlrpcBase64']:
2923  $rs.="<${typ}>" . base64_encode($val) . "</${typ}>";
2924  break;
2925  case $GLOBALS['xmlrpcBoolean']:
2926  $rs.="<${typ}>" . ($val ? '1' : '0') . "</${typ}>";
2927  break;
2928  case $GLOBALS['xmlrpcString']:
2929  // G. Giunta 2005/2/13: do NOT use htmlentities, since
2930  // it will produce named html entities, which are invalid xml
2931  $rs.="<${typ}>" . xmlrpc_encode_entitites($val, $GLOBALS['xmlrpc_internalencoding'], $charset_encoding). "</${typ}>";
2932  break;
2933  case $GLOBALS['xmlrpcInt']:
2934  case $GLOBALS['xmlrpcI4']:
2935  $rs.="<${typ}>".(int)$val."</${typ}>";
2936  break;
2937  case $GLOBALS['xmlrpcDouble']:
2938  $rs.="<${typ}>".(double)$val."</${typ}>";
2939  break;
2940  case $GLOBALS['xmlrpcNull']:
2941  $rs.="<nil/>";
2942  break;
2943  default:
2944  // no standard type value should arrive here, but provide a possibility
2945  // for xmlrpcvals of unknown type...
2946  $rs.="<${typ}>${val}</${typ}>";
2947  }
2948  break;
2949  case 3:
2950  // struct
2951  if ($this->_php_class)
2952  {
2953  $rs.='<struct php_class="' . $this->_php_class . "\">\n";
2954  }
2955  else
2956  {
2957  $rs.="<struct>\n";
2958  }
2959  foreach($val as $key2 => $val2)
2960  {
2961  $rs.='<member><name>'.xmlrpc_encode_entitites($key2, $GLOBALS['xmlrpc_internalencoding'], $charset_encoding)."</name>\n";
2962  //$rs.=$this->serializeval($val2);
2963  $rs.=$val2->serialize($charset_encoding);
2964  $rs.="</member>\n";
2965  }
2966  $rs.='</struct>';
2967  break;
2968  case 2:
2969  // array
2970  $rs.="<array>\n<data>\n";
2971  for($i=0; $i<count($val); $i++)
2972  {
2973  //$rs.=$this->serializeval($val[$i]);
2974  $rs.=$val[$i]->serialize($charset_encoding);
2975  }
2976  $rs.="</data>\n</array>";
2977  break;
2978  default:
2979  break;
2980  }
2981  return $rs;
2982  }
2983 
2990  function serialize($charset_encoding='')
2991  {
2992  // add check? slower, but helps to avoid recursion in serializing broken xmlrpcvals...
2993  //if (is_object($o) && (get_class($o) == 'xmlrpcval' || is_subclass_of($o, 'xmlrpcval')))
2994  //{
2995  reset($this->me);
2996  list($typ, $val) = each($this->me);
2997  return '<value>' . $this->serializedata($typ, $val, $charset_encoding) . "</value>\n";
2998  //}
2999  }
3000 
3001  // DEPRECATED
3002  function serializeval($o)
3003  {
3004  // add check? slower, but helps to avoid recursion in serializing broken xmlrpcvals...
3005  //if (is_object($o) && (get_class($o) == 'xmlrpcval' || is_subclass_of($o, 'xmlrpcval')))
3006  //{
3007  $ar=$o->me;
3008  reset($ar);
3009  list($typ, $val) = each($ar);
3010  return '<value>' . $this->serializedata($typ, $val) . "</value>\n";
3011  //}
3012  }
3013 
3021  function structmemexists($m)
3022  {
3023  return array_key_exists($m, $this->me['struct']);
3024  }
3025 
3033  function structmem($m)
3034  {
3035  return $this->me['struct'][$m];
3036  }
3037 
3042  function structreset()
3043  {
3044  reset($this->me['struct']);
3045  }
3046 
3052  function structeach()
3053  {
3054  return each($this->me['struct']);
3055  }
3056 
3057  // DEPRECATED! this code looks like it is very fragile and has not been fixed
3058  // for a long long time. Shall we remove it for 2.0?
3059  function getval()
3060  {
3061  // UNSTABLE
3062  reset($this->me);
3063  list($a,$b)=each($this->me);
3064  // contributed by I Sofer, 2001-03-24
3065  // add support for nested arrays to scalarval
3066  // i've created a new method here, so as to
3067  // preserve back compatibility
3068 
3069  if(is_array($b))
3070  {
3071  @reset($b);
3072  while(list($id,$cont) = @each($b))
3073  {
3074  $b[$id] = $cont->scalarval();
3075  }
3076  }
3077 
3078  // add support for structures directly encoding php objects
3079  if(is_object($b))
3080  {
3081  $t = get_object_vars($b);
3082  @reset($t);
3083  while(list($id,$cont) = @each($t))
3084  {
3085  $t[$id] = $cont->scalarval();
3086  }
3087  @reset($t);
3088  while(list($id,$cont) = @each($t))
3089  {
3090  @$b->$id = $cont;
3091  }
3092  }
3093  // end contrib
3094  return $b;
3095  }
3096 
3102  function scalarval()
3103  {
3104  reset($this->me);
3105  list(,$b)=each($this->me);
3106  return $b;
3107  }
3108 
3115  function scalartyp()
3116  {
3117  reset($this->me);
3118  list($a,)=each($this->me);
3119  if($a==$GLOBALS['xmlrpcI4'])
3120  {
3121  $a=$GLOBALS['xmlrpcInt'];
3122  }
3123  return $a;
3124  }
3125 
3132  function arraymem($m)
3133  {
3134  return $this->me['array'][$m];
3135  }
3136 
3142  function arraysize()
3143  {
3144  return count($this->me['array']);
3145  }
3146 
3152  function structsize()
3153  {
3154  return count($this->me['struct']);
3155  }
3156  }
3157 
3158 
3159  // date helpers
3160 
3178  function iso8601_encode($timet, $utc=0)
3179  {
3180  if(!$utc)
3181  {
3182  $t=strftime("%Y%m%dT%H:%M:%S", $timet);
3183  }
3184  else
3185  {
3186  if(function_exists('gmstrftime'))
3187  {
3188  // gmstrftime doesn't exist in some versions
3189  // of PHP
3190  $t=gmstrftime("%Y%m%dT%H:%M:%S", $timet);
3191  }
3192  else
3193  {
3194  $t=strftime("%Y%m%dT%H:%M:%S", $timet-date('Z'));
3195  }
3196  }
3197  return $t;
3198  }
3199 
3206  function iso8601_decode($idate, $utc=0)
3207  {
3208  $t=0;
3209  if(preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $idate, $regs))
3210  {
3211  if($utc)
3212  {
3213  $t=gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
3214  }
3215  else
3216  {
3217  $t=mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
3218  }
3219  }
3220  return $t;
3221  }
3222 
3244  function php_xmlrpc_decode($xmlrpc_val, $options=array())
3245  {
3246  switch($xmlrpc_val->kindOf())
3247  {
3248  case 'scalar':
3249  if (in_array('extension_api', $options))
3250  {
3251  reset($xmlrpc_val->me);
3252  list($typ,$val) = each($xmlrpc_val->me);
3253  switch ($typ)
3254  {
3255  case 'dateTime.iso8601':
3256  $xmlrpc_val->scalar = $val;
3257  $xmlrpc_val->xmlrpc_type = 'datetime';
3258  $xmlrpc_val->timestamp = iso8601_decode($val);
3259  return $xmlrpc_val;
3260  case 'base64':
3261  $xmlrpc_val->scalar = $val;
3262  $xmlrpc_val->type = $typ;
3263  return $xmlrpc_val;
3264  default:
3265  return $xmlrpc_val->scalarval();
3266  }
3267  }
3268  return $xmlrpc_val->scalarval();
3269  case 'array':
3270  $size = $xmlrpc_val->arraysize();
3271  $arr = array();
3272  for($i = 0; $i < $size; $i++)
3273  {
3274  $arr[] = php_xmlrpc_decode($xmlrpc_val->arraymem($i), $options);
3275  }
3276  return $arr;
3277  case 'struct':
3278  $xmlrpc_val->structreset();
3279  // If user said so, try to rebuild php objects for specific struct vals.
3281  // shall we check for proper subclass of xmlrpcval instead of
3282  // presence of _php_class to detect what we can do?
3283  if (in_array('decode_php_objs', $options) && $xmlrpc_val->_php_class != ''
3284  && class_exists($xmlrpc_val->_php_class))
3285  {
3286  $obj = @new $xmlrpc_val->_php_class;
3287  while(list($key,$value)=$xmlrpc_val->structeach())
3288  {
3289  $obj->$key = php_xmlrpc_decode($value, $options);
3290  }
3291  return $obj;
3292  }
3293  else
3294  {
3295  $arr = array();
3296  while(list($key,$value)=$xmlrpc_val->structeach())
3297  {
3298  $arr[$key] = php_xmlrpc_decode($value, $options);
3299  }
3300  return $arr;
3301  }
3302  case 'msg':
3303  $paramcount = $xmlrpc_val->getNumParams();
3304  $arr = array();
3305  for($i = 0; $i < $paramcount; $i++)
3306  {
3307  $arr[] = php_xmlrpc_decode($xmlrpc_val->getParam($i));
3308  }
3309  return $arr;
3310  }
3311  }
3312 
3313  // This constant left here only for historical reasons...
3314  // it was used to decide if we have to define xmlrpc_encode on our own, but
3315  // we do not do it anymore
3316  if(function_exists('xmlrpc_decode'))
3317  {
3318  define('XMLRPC_EPI_ENABLED','1');
3319  }
3320  else
3321  {
3322  define('XMLRPC_EPI_ENABLED','0');
3323  }
3324 
3342  function &php_xmlrpc_encode($php_val, $options=array())
3343  {
3344  $type = gettype($php_val);
3345  switch($type)
3346  {
3347  case 'string':
3348  if (in_array('auto_dates', $options) && preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $php_val))
3349  $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcDateTime']);
3350  else
3351  $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcString']);
3352  break;
3353  case 'integer':
3354  $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcInt']);
3355  break;
3356  case 'double':
3357  $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcDouble']);
3358  break;
3359  // <G_Giunta_2001-02-29>
3360  // Add support for encoding/decoding of booleans, since they are supported in PHP
3361  case 'boolean':
3362  $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcBoolean']);
3363  break;
3364  // </G_Giunta_2001-02-29>
3365  case 'array':
3366  // PHP arrays can be encoded to either xmlrpc structs or arrays,
3367  // depending on wheter they are hashes or plain 0..n integer indexed
3368  // A shorter one-liner would be
3369  // $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1));
3370  // but execution time skyrockets!
3371  $j = 0;
3372  $arr = array();
3373  $ko = false;
3374  foreach($php_val as $key => $val)
3375  {
3376  $arr[$key] =& php_xmlrpc_encode($val, $options);
3377  if(!$ko && $key !== $j)
3378  {
3379  $ko = true;
3380  }
3381  $j++;
3382  }
3383  if($ko)
3384  {
3385  $xmlrpc_val = new xmlrpcval($arr, $GLOBALS['xmlrpcStruct']);
3386  }
3387  else
3388  {
3389  $xmlrpc_val = new xmlrpcval($arr, $GLOBALS['xmlrpcArray']);
3390  }
3391  break;
3392  case 'object':
3393  if(is_a($php_val, 'xmlrpcval'))
3394  {
3395  $xmlrpc_val = $php_val;
3396  }
3397  else
3398  {
3399  $arr = array();
3400  while(list($k,$v) = each($php_val))
3401  {
3402  $arr[$k] = php_xmlrpc_encode($v, $options);
3403  }
3404  $xmlrpc_val = new xmlrpcval($arr, $GLOBALS['xmlrpcStruct']);
3405  if (in_array('encode_php_objs', $options))
3406  {
3407  // let's save original class name into xmlrpcval:
3408  // might be useful later on...
3409  $xmlrpc_val->_php_class = get_class($php_val);
3410  }
3411  }
3412  break;
3413  case 'NULL':
3414  if (in_array('extension_api', $options))
3415  {
3416  $xmlrpc_val = new xmlrpcval('', $GLOBALS['xmlrpcString']);
3417  }
3418  if (in_array('null_extension', $options))
3419  {
3420  $xmlrpc_val = new xmlrpcval('', $GLOBALS['xmlrpcNull']);
3421  }
3422  else
3423  {
3424  $xmlrpc_val = new xmlrpcval();
3425  }
3426  break;
3427  case 'resource':
3428  if (in_array('extension_api', $options))
3429  {
3430  $xmlrpc_val = new xmlrpcval((int)$php_val, $GLOBALS['xmlrpcInt']);
3431  }
3432  else
3433  {
3434  $xmlrpc_val = new xmlrpcval();
3435  }
3436  // catch "user function", "unknown type"
3437  default:
3438  // giancarlo pinerolo <ping@alt.it>
3439  // it has to return
3440  // an empty object in case, not a boolean.
3441  $xmlrpc_val = new xmlrpcval();
3442  break;
3443  }
3444  return $xmlrpc_val;
3445  }
3446 
3454  function php_xmlrpc_decode_xml($xml_val, $options=array())
3455  {
3456  $GLOBALS['_xh'] = array();
3457  $GLOBALS['_xh']['ac'] = '';
3458  $GLOBALS['_xh']['stack'] = array();
3459  $GLOBALS['_xh']['valuestack'] = array();
3460  $GLOBALS['_xh']['params'] = array();
3461  $GLOBALS['_xh']['pt'] = array();
3462  $GLOBALS['_xh']['isf'] = 0;
3463  $GLOBALS['_xh']['isf_reason'] = '';
3464  $GLOBALS['_xh']['method'] = false;
3465  $GLOBALS['_xh']['rt'] = '';
3467  $parser = xml_parser_create();
3468  xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
3469  // What if internal encoding is not in one of the 3 allowed?
3470  // we use the broadest one, ie. utf8!
3471  if (!in_array($GLOBALS['xmlrpc_internalencoding'], array('UTF-8', 'ISO-8859-1', 'US-ASCII')))
3472  {
3473  xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
3474  }
3475  else
3476  {
3477  xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $GLOBALS['xmlrpc_internalencoding']);
3478  }
3479  xml_set_element_handler($parser, 'xmlrpc_se_any', 'xmlrpc_ee');
3480  xml_set_character_data_handler($parser, 'xmlrpc_cd');
3481  xml_set_default_handler($parser, 'xmlrpc_dh');
3482  if(!xml_parse($parser, $xml_val, 1))
3483  {
3484  $errstr = sprintf('XML error: %s at line %d, column %d',
3485  xml_error_string(xml_get_error_code($parser)),
3486  xml_get_current_line_number($parser), xml_get_current_column_number($parser));
3487  error_log($errstr);
3488  xml_parser_free($parser);
3489  return false;
3490  }
3491  xml_parser_free($parser);
3492  if ($GLOBALS['_xh']['isf'] > 1) // test that $GLOBALS['_xh']['value'] is an obj, too???
3493  {
3494  error_log($GLOBALS['_xh']['isf_reason']);
3495  return false;
3496  }
3497  switch ($GLOBALS['_xh']['rt'])
3498  {
3499  case 'methodresponse':
3500  $v =& $GLOBALS['_xh']['value'];
3501  if ($GLOBALS['_xh']['isf'] == 1)
3502  {
3503  $vc = $v->structmem('faultCode');
3504  $vs = $v->structmem('faultString');
3505  $r = new xmlrpcresp(0, $vc->scalarval(), $vs->scalarval());
3506  }
3507  else
3508  {
3509  $r = new xmlrpcresp($v);
3510  }
3511  return $r;
3512  case 'methodcall':
3513  $m = new xmlrpcmsg($GLOBALS['_xh']['method']);
3514  for($i=0; $i < count($GLOBALS['_xh']['params']); $i++)
3515  {
3516  $m->addParam($GLOBALS['_xh']['params'][$i]);
3517  }
3518  return $m;
3519  case 'value':
3520  return $GLOBALS['_xh']['value'];
3521  default:
3522  return false;
3523  }
3524  }
3525 
3534  function decode_chunked($buffer)
3535  {
3536  // length := 0
3537  $length = 0;
3538  $new = '';
3539 
3540  // read chunk-size, chunk-extension (if any) and crlf
3541  // get the position of the linebreak
3542  $chunkend = strpos($buffer,"\r\n") + 2;
3543  $temp = substr($buffer,0,$chunkend);
3544  $chunk_size = hexdec( trim($temp) );
3545  $chunkstart = $chunkend;
3546  while($chunk_size > 0)
3547  {
3548  $chunkend = strpos($buffer, "\r\n", $chunkstart + $chunk_size);
3549 
3550  // just in case we got a broken connection
3551  if($chunkend == false)
3552  {
3553  $chunk = substr($buffer,$chunkstart);
3554  // append chunk-data to entity-body
3555  $new .= $chunk;
3556  $length += strlen($chunk);
3557  break;
3558  }
3559 
3560  // read chunk-data and crlf
3561  $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3562  // append chunk-data to entity-body
3563  $new .= $chunk;
3564  // length := length + chunk-size
3565  $length += strlen($chunk);
3566  // read chunk-size and crlf
3567  $chunkstart = $chunkend + 2;
3568 
3569  $chunkend = strpos($buffer,"\r\n",$chunkstart)+2;
3570  if($chunkend == false)
3571  {
3572  break; //just in case we got a broken connection
3573  }
3574  $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3575  $chunk_size = hexdec( trim($temp) );
3576  $chunkstart = $chunkend;
3577  }
3578  return $new;
3579  }
3580 
3595  function guess_encoding($httpheader='', $xmlchunk='', $encoding_prefs=null)
3596  {
3597  // discussion: see http://www.yale.edu/pclt/encoding/
3598  // 1 - test if encoding is specified in HTTP HEADERS
3599 
3600  //Details:
3601  // LWS: (\13\10)?( |\t)+
3602  // token: (any char but excluded stuff)+
3603  // header: Content-type = ...; charset=value(; ...)*
3604  // where value is of type token, no LWS allowed between 'charset' and value
3605  // Note: we do not check for invalid chars in VALUE:
3606  // this had better be done using pure ereg as below
3607 
3609  $matches = array();
3610  if(preg_match('/;\s*charset=([^;]+)/i', $httpheader, $matches))
3611  {
3612  return strtoupper(trim($matches[1]));
3613  }
3614 
3615  // 2 - scan the first bytes of the data for a UTF-16 (or other) BOM pattern
3616  // (source: http://www.w3.org/TR/2000/REC-xml-20001006)
3617  // NOTE: actually, according to the spec, even if we find the BOM and determine
3618  // an encoding, we should check if there is an encoding specified
3619  // in the xml declaration, and verify if they match.
3622  if(preg_match('/^(\x00\x00\xFE\xFF|\xFF\xFE\x00\x00|\x00\x00\xFF\xFE|\xFE\xFF\x00\x00)/', $xmlchunk))
3623  {
3624  return 'UCS-4';
3625  }
3626  elseif(preg_match('/^(\xFE\xFF|\xFF\xFE)/', $xmlchunk))
3627  {
3628  return 'UTF-16';
3629  }
3630  elseif(preg_match('/^(\xEF\xBB\xBF)/', $xmlchunk))
3631  {
3632  return 'UTF-8';
3633  }
3634 
3635  // 3 - test if encoding is specified in the xml declaration
3636  // Details:
3637  // SPACE: (#x20 | #x9 | #xD | #xA)+ === [ \x9\xD\xA]+
3638  // EQ: SPACE?=SPACE? === [ \x9\xD\xA]*=[ \x9\xD\xA]*
3639  if (preg_match('/^<\?xml\s+version\s*=\s*'. "((?:\"[a-zA-Z0-9_.:-]+\")|(?:'[a-zA-Z0-9_.:-]+'))".
3640  '\s+encoding\s*=\s*' . "((?:\"[A-Za-z][A-Za-z0-9._-]*\")|(?:'[A-Za-z][A-Za-z0-9._-]*'))/",
3641  $xmlchunk, $matches))
3642  {
3643  return strtoupper(substr($matches[2], 1, -1));
3644  }
3645 
3646  // 4 - if mbstring is available, let it do the guesswork
3647  // NB: we favour finding an encoding that is compatible with what we can process
3648  if(extension_loaded('mbstring'))
3649  {
3650  if($encoding_prefs)
3651  {
3652  $enc = mb_detect_encoding($xmlchunk, $encoding_prefs);
3653  }
3654  else
3655  {
3656  $enc = mb_detect_encoding($xmlchunk);
3657  }
3658  // NB: mb_detect likes to call it ascii, xml parser likes to call it US_ASCII...
3659  // IANA also likes better US-ASCII, so go with it
3660  if($enc == 'ASCII')
3661  {
3662  $enc = 'US-'.$enc;
3663  }
3664  return $enc;
3665  }
3666  else
3667  {
3668  // no encoding specified: as per HTTP1.1 assume it is iso-8859-1?
3669  // Both RFC 2616 (HTTP 1.1) and 1945(http 1.0) clearly state that for text/xxx content types
3670  // this should be the standard. And we should be getting text/xml as request and response.
3671  // BUT we have to be backward compatible with the lib, which always used UTF-8 as default...
3672  return $GLOBALS['xmlrpc_defencoding'];
3673  }
3674  }
3675 
3682  function is_valid_charset($encoding, $validlist)
3683  {
3684  $charset_supersets = array(
3685  'US-ASCII' => array ('ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4',
3686  'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8',
3687  'ISO-8859-9', 'ISO-8859-10', 'ISO-8859-11', 'ISO-8859-12',
3688  'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'UTF-8',
3689  'EUC-JP', 'EUC-', 'EUC-KR', 'EUC-CN')
3690  );
3691  if (is_string($validlist))
3692  $validlist = explode(',', $validlist);
3693  if (@in_array(strtoupper($encoding), $validlist))
3694  return true;
3695  else
3696  {
3697  if (array_key_exists($encoding, $charset_supersets))
3698  foreach ($validlist as $allowed)
3699  if (in_array($allowed, $charset_supersets[$encoding]))
3700  return true;
3701  return false;
3702  }
3703  }
3704 
3705 ?>
xmlrpc_client\setSSLVerifyHost
setSSLVerifyHost($i)
Definition: xmlrpc.inc:1040
xmlrpc_se_any
xmlrpc_se_any($parser, $name, $attrs)
Used in decoding xml chunks that might represent single xmlrpc values.
Definition: xmlrpc.inc:554
xmlrpc_client\$proxy_pass
$proxy_pass
Definition: xmlrpc.inc:844
xmlrpcmsg\xml_footer
xml_footer()
Definition: xmlrpc.inc:2110
xmlrpcmsg\getNumParams
getNumParams()
Definition: xmlrpc.inc:2204
xmlrpcresp\value
value()
Definition: xmlrpc.inc:1995
xmlrpcmsg\createPayload
createPayload($charset_encoding='')
Definition: xmlrpc.inc:2126
$b1
$b1
Definition: ChWsbAdminTools.php:813
xmlrpc_client\$return_type
$return_type
Definition: xmlrpc.inc:877
xmlrpcmsg\method
method($meth='')
Definition: xmlrpc.inc:2151
xmlrpcmsg\serialize
serialize($charset_encoding='')
Definition: xmlrpc.inc:2165
xmlrpc_client\setCaCertificate
setCaCertificate($cacert, $is_dir=false)
Definition: xmlrpc.inc:999
xmlrpc_client\setDebug
setDebug($in)
Definition: xmlrpc.inc:961
xmlrpcresp\$_cookies
$_cookies
Definition: xmlrpc.inc:1918
xmlrpcval\structmem
structmem($m)
Definition: xmlrpc.inc:3033
xmlrpc_ee
xmlrpc_ee($parser, $name, $rebuild_xmlrpcvals=true)
xml parser handler function for close element tags
Definition: xmlrpc.inc:560
xmlrpcval\structsize
structsize()
Definition: xmlrpc.inc:3152
decode_chunked
decode_chunked($buffer)
Definition: xmlrpc.inc:3534
xmlrpc_client\$verifyhost
$verifyhost
Definition: xmlrpc.inc:839
xmlrpc_client\$keepalive
$keepalive
Wheter to use persistent connections for http 1.1 and https.
Definition: xmlrpc.inc:868
xmlrpcmsg\parseResponseHeaders
& parseResponseHeaders(&$data, $headers_processed=false)
Definition: xmlrpc.inc:2229
xmlrpc_client\$verifypeer
$verifypeer
Definition: xmlrpc.inc:838
xmlrpc_dh
xmlrpc_dh($parser, $data)
Definition: xmlrpc.inc:802
xmlrpcval\scalartyp
scalartyp()
Definition: xmlrpc.inc:3115
xmlrpc_client\$port
$port
Definition: xmlrpc.inc:824
xmlrpcresp\$raw_data
$raw_data
Definition: xmlrpc.inc:1920
xmlrpc_client\setProxy
setProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='', $proxyauthtype=1)
Definition: xmlrpc.inc:1054
xmlrpcval\addStruct
addStruct($vals)
Definition: xmlrpc.inc:2850
xmlrpcval\addArray
addArray($vals)
Definition: xmlrpc.inc:2821
xmlrpc_client\$cookies
$cookies
Definition: xmlrpc.inc:846
xmlrpcmsg\$methodname
$methodname
Definition: xmlrpc.inc:2071
$fallback
$fallback
Definition: en-x-test.php:5
php_xmlrpc_decode
php_xmlrpc_decode($xmlrpc_val, $options=array())
Definition: xmlrpc.inc:3244
xmlrpcresp\serialize
serialize($charset_encoding='')
Definition: xmlrpc.inc:2022
xmlrpc_client\setCookie
setCookie($name, $value='', $path='', $domain='', $port=null)
Definition: xmlrpc.inc:1104
xmlrpcval
Definition: xmlrpc.inc:2696
xmlrpcmsg\addParam
addParam($par)
Definition: xmlrpc.inc:2177
xmlrpc_client\$keypass
$keypass
Definition: xmlrpc.inc:837
xmlrpc_client\multicall
multicall($msgs, $timeout=0, $method='', $fallback=true)
Definition: xmlrpc.inc:1703
xmlrpc_client\$request_charset_encoding
$request_charset_encoding
Charset encoding to be used in serializing request. NULL = use ASCII.
Definition: xmlrpc.inc:872
xmlrpc_client\$password
$password
Definition: xmlrpc.inc:830
php
xmlrpc_client\__construct
__construct($path, $server='', $port='', $method='')
Definition: xmlrpc.inc:885
xmlrpc_client\$key
$key
Definition: xmlrpc.inc:836
xmlrpcresp\$errno
$errno
Definition: xmlrpc.inc:1914
xmlrpcresp\$content_type
$content_type
Definition: xmlrpc.inc:1919
php_xmlrpc_decode_xml
php_xmlrpc_decode_xml($xml_val, $options=array())
Definition: xmlrpc.inc:3454
xmlrpcval\dump
dump($ar)
Definition: xmlrpc.inc:2873
xmlrpcresp\$val
$val
Definition: xmlrpc.inc:1912
xmlrpcval\$_php_class
$_php_class
Definition: xmlrpc.inc:2699
xmlrpc_encode_entitites
xmlrpc_encode_entitites($data, $src_encoding='', $dest_encoding='')
Definition: xmlrpc.inc:276
xmlrpcmsg\parseResponseFile
& parseResponseFile($fp)
Definition: xmlrpc.inc:2213
php_xmlrpc_encode
& php_xmlrpc_encode($php_val, $options=array())
Definition: xmlrpc.inc:3342
xmlrpcmsg
Definition: xmlrpc.inc:2069
xmlrpc_se
xmlrpc_se($parser, $name, $attrs, $accept_single_vals=false)
xml parser handler function for opening element tags
Definition: xmlrpc.inc:408
xmlrpcresp\faultString
faultString()
Definition: xmlrpc.inc:1985
xmlrpcresp\cookies
cookies()
Definition: xmlrpc.inc:2011
xmlrpcval\serializeval
serializeval($o)
Definition: xmlrpc.inc:3002
and
and
Definition: license.txt:18
xmlrpc_client\$errstr
$errstr
Definition: xmlrpc.inc:827
xmlrpcval\scalarval
scalarval()
Definition: xmlrpc.inc:3102
xmlrpc_client\$authtype
$authtype
Definition: xmlrpc.inc:831
xmlrpcval\kindOf
kindOf()
Definition: xmlrpc.inc:2893
xmlrpc_client\$no_multicall
$no_multicall
Definition: xmlrpc.inc:840
xmlrpc_client\setRequestCompression
setRequestCompression($compmethod)
Definition: xmlrpc.inc:1086
xmlrpcmsg\kindOf
kindOf()
Definition: xmlrpc.inc:2118
xmlrpcval\getval
getval()
Definition: xmlrpc.inc:3059
xmlrpcmsg\parseResponse
& parseResponse($data='', $headers_processed=false, $return_type='xmlrpcvals')
Definition: xmlrpc.inc:2467
xmlrpcval\structmemexists
structmemexists($m)
Definition: xmlrpc.inc:3021
xmlrpc_client\setKey
setKey($key, $keypass)
Definition: xmlrpc.inc:1019
$phpversion
if(!function_exists('xml_parser_create')) $phpversion
Definition: xmlrpc.inc:49
xmlrpc_client\$server
$server
Definition: xmlrpc.inc:823
xmlrpcmsg\getParam
getParam($i)
Definition: xmlrpc.inc:2197
xmlrpcval\arraysize
arraysize()
Definition: xmlrpc.inc:3142
xmlrpcval\$mytype
$mytype
Definition: xmlrpc.inc:2698
xmlrpcval\__construct
__construct($val=-1, $type='')
Definition: xmlrpc.inc:2705
is_valid_charset
is_valid_charset($encoding, $validlist)
Definition: xmlrpc.inc:3682
guess_encoding
guess_encoding($httpheader='', $xmlchunk='', $encoding_prefs=null)
Definition: xmlrpc.inc:3595
$GLOBALS
if($phpversion[0]=='4' && $phpversion[2]< 2) $GLOBALS['xmlrpcI4']
Definition: xmlrpc.inc:74
xmlrpcmsg\$payload
$payload
Definition: xmlrpc.inc:2070
xmlrpcresp\$errstr
$errstr
Definition: xmlrpc.inc:1915
xmlrpcmsg\$content_type
$content_type
Definition: xmlrpc.inc:2074
xmlrpcval\serializedata
serializedata($typ, $val, $charset_encoding='')
Definition: xmlrpc.inc:2914
xmlrpc_ee_fast
xmlrpc_ee_fast($parser, $name)
Used in decoding xmlrpc requests/responses without rebuilding xmlrpc values.
Definition: xmlrpc.inc:768
method
and that you are informed that you can do these things To protect your we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it For if you distribute copies of the whether gratis or for a you must give the recipients all the rights that we gave you You must make sure that receive or can get the source code If you link other code with the you must provide complete object files to the so that they can relink them with the library after making changes to the library and recompiling it And you must show them these terms so they know their rights We protect your rights with a two step method
Definition: license.txt:49
xmlrpc_client\sendPayloadHTTP10
& sendPayloadHTTP10($msg, $server, $port, $timeout=0, $username='', $password='', $authtype=1, $proxyhost='', $proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1)
Definition: xmlrpc.inc:1224
$b2
$b2
Definition: ChWsbAdminTools.php:814
xmlrpc_client\sendPayloadHTTPS
& sendPayloadHTTPS($msg, $server, $port, $timeout=0, $username='', $password='', $authtype=1, $cert='', $certpass='', $cacert='', $cacertdir='', $proxyhost='', $proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1, $keepalive=false, $key='', $keypass='')
Definition: xmlrpc.inc:1408
xmlrpc_client\$cert
$cert
Definition: xmlrpc.inc:832
xmlrpcval\arraymem
arraymem($m)
Definition: xmlrpc.inc:3132
xmlrpc_client\$proxy
$proxy
Definition: xmlrpc.inc:841
xmlrpc_client\$cacert
$cacert
Definition: xmlrpc.inc:834
xmlrpc_client\sendPayloadCURL
& sendPayloadCURL($msg, $server, $port, $timeout=0, $username='', $password='', $authtype=1, $cert='', $certpass='', $cacert='', $cacertdir='', $proxyhost='', $proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1, $method='https', $keepalive=false, $key='', $keypass='')
Definition: xmlrpc.inc:1425
xmlrpc_client
Definition: xmlrpc.inc:821
xmlrpcval\structeach
structeach()
Definition: xmlrpc.inc:3052
xmlrpcresp\faultCode
faultCode()
Definition: xmlrpc.inc:1975
xmlrpc_client\setCertificate
setCertificate($cert, $certpass)
Definition: xmlrpc.inc:986
iso8601_decode
iso8601_decode($idate, $utc=0)
Definition: xmlrpc.inc:3206
xmlrpcval\structreset
structreset()
Definition: xmlrpc.inc:3042
xmlrpc_client\$method
$method
Definition: xmlrpc.inc:825
xmlrpc_client\setCredentials
setCredentials($u, $p, $t=1)
Definition: xmlrpc.inc:973
xmlrpc_client\$errno
$errno
Definition: xmlrpc.inc:826
xmlrpc_client\$debug
$debug
Definition: xmlrpc.inc:828
xmlrpcresp
Definition: xmlrpc.inc:1911
xmlrpc_client\$certpass
$certpass
Definition: xmlrpc.inc:833
xmlrpc_client\setAcceptedCompression
setAcceptedCompression($compmethod)
Definition: xmlrpc.inc:1071
xmlrpc_client\$accepted_compression
$accepted_compression
Definition: xmlrpc.inc:856
xmlrpc_client\$proxy_user
$proxy_user
Definition: xmlrpc.inc:843
xmlrpc_client\_try_multicall
_try_multicall($msgs, $timeout, $method)
Definition: xmlrpc.inc:1775
xmlrpc_client\$accepted_charset_encodings
$accepted_charset_encodings
Charset encodings that can be decoded without problems by the client.
Definition: xmlrpc.inc:870
xmlrpc_client\$cacertdir
$cacertdir
Definition: xmlrpc.inc:835
xmlrpc_client\$xmlrpc_curl_handle
$xmlrpc_curl_handle
Definition: xmlrpc.inc:866
xmlrpc_client\$username
$username
Definition: xmlrpc.inc:829
xmlrpcmsg\$debug
$debug
Definition: xmlrpc.inc:2073
xmlrpc_client\$proxyport
$proxyport
Definition: xmlrpc.inc:842
xmlrpcresp\$payload
$payload
Definition: xmlrpc.inc:1916
xmlrpc_client\$path
$path
Definition: xmlrpc.inc:822
empty
Attr AllowedRel this is empty
Definition: Attr.AllowedRel.txt:7
$o
$o
Definition: cmd.php:193
xmlrpc_cd
xmlrpc_cd($parser, $data)
xml parser handler function for character data
Definition: xmlrpc.inc:774
xmlrpc_client\setSSLVerifyPeer
setSSLVerifyPeer($i)
Definition: xmlrpc.inc:1030
as
as
Definition: Filter.ExtractStyleBlocks.Escaping.txt:10
xmlrpcresp\$hdrs
$hdrs
Definition: xmlrpc.inc:1917
xmlrpcmsg\xml_header
xml_header($charset_encoding='')
Definition: xmlrpc.inc:2095
xmlrpcmsg\$params
$params
Definition: xmlrpc.inc:2072
xmlrpcresp\$valtyp
$valtyp
Definition: xmlrpc.inc:1913
xmlrpcval\addScalar
addScalar($val, $type='string')
Definition: xmlrpc.inc:2765
xmlrpcresp\__construct
__construct($val, $fcode=0, $fstr='', $valtyp='')
Definition: xmlrpc.inc:1932
xmlrpcval\$me
$me
Definition: xmlrpc.inc:2697
xmlrpcval\serialize
serialize($charset_encoding='')
Definition: xmlrpc.inc:2990
xmlrpcmsg\__construct
__construct($meth, $pars=0)
Definition: xmlrpc.inc:2080
xmlrpc_client\$request_compression
$request_compression
Definition: xmlrpc.inc:861
iso8601_encode
iso8601_encode($timet, $utc=0)
Definition: xmlrpc.inc:3178
xmlrpc_client\$proxy_authtype
$proxy_authtype
Definition: xmlrpc.inc:845
xmlrpc_client\send
& send($msg, $timeout=0, $method='')
Definition: xmlrpc.inc:1128