1
|
|
|
<?php if ( ! defined('BASEPATH')) { |
2
|
|
|
exit('No direct script access allowed'); |
3
|
|
|
} |
4
|
|
|
/** |
5
|
|
|
* CodeIgniter |
6
|
|
|
* |
7
|
|
|
* An open source application development framework for PHP 5.1.6 or newer |
8
|
|
|
* |
9
|
|
|
* @package CodeIgniter |
10
|
|
|
* @author ExpressionEngine Dev Team |
11
|
|
|
* @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. |
12
|
|
|
* @license http://codeigniter.com/user_guide/license.html |
13
|
|
|
* @link http://codeigniter.com |
14
|
|
|
* @since Version 1.0 |
15
|
|
|
* @filesource |
16
|
|
|
*/ |
17
|
|
|
|
18
|
|
|
if ( ! function_exists('xml_parser_create')) |
19
|
|
|
{ |
20
|
|
|
show_error('Your PHP installation does not support XML'); |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
|
24
|
|
|
// ------------------------------------------------------------------------ |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* XML-RPC request handler class |
28
|
|
|
* |
29
|
|
|
* @package CodeIgniter |
30
|
|
|
* @subpackage Libraries |
31
|
|
|
* @category XML-RPC |
32
|
|
|
* @author ExpressionEngine Dev Team |
33
|
|
|
* @link http://codeigniter.com/user_guide/libraries/xmlrpc.html |
34
|
|
|
*/ |
35
|
|
|
class CI_Xmlrpc { |
36
|
|
|
|
37
|
|
|
var $debug = FALSE; // Debugging on or off |
38
|
|
|
var $xmlrpcI4 = 'i4'; |
39
|
|
|
var $xmlrpcInt = 'int'; |
40
|
|
|
var $xmlrpcBoolean = 'boolean'; |
41
|
|
|
var $xmlrpcDouble = 'double'; |
42
|
|
|
var $xmlrpcString = 'string'; |
43
|
|
|
var $xmlrpcDateTime = 'dateTime.iso8601'; |
44
|
|
|
var $xmlrpcBase64 = 'base64'; |
45
|
|
|
var $xmlrpcArray = 'array'; |
46
|
|
|
var $xmlrpcStruct = 'struct'; |
47
|
|
|
|
48
|
|
|
var $xmlrpcTypes = array(); |
49
|
|
|
var $valid_parents = array(); |
50
|
|
|
var $xmlrpcerr = array(); // Response numbers |
51
|
|
|
var $xmlrpcstr = array(); // Response strings |
52
|
|
|
|
53
|
|
|
var $xmlrpc_defencoding = 'UTF-8'; |
54
|
|
|
var $xmlrpcName = 'XML-RPC for CodeIgniter'; |
55
|
|
|
var $xmlrpcVersion = '1.1'; |
56
|
|
|
var $xmlrpcerruser = 800; // Start of user errors |
57
|
|
|
var $xmlrpcerrxml = 100; // Start of XML Parse errors |
58
|
|
|
var $xmlrpc_backslash = ''; // formulate backslashes for escaping regexp |
59
|
|
|
|
60
|
|
|
var $client; |
61
|
|
|
var $method; |
62
|
|
|
var $data; |
63
|
|
|
var $message = ''; |
64
|
|
|
var $error = ''; // Error string for request |
65
|
|
|
var $result; |
66
|
|
|
var $response = array(); // Response from remote server |
67
|
|
|
|
68
|
|
|
var $xss_clean = TRUE; |
69
|
|
|
|
70
|
|
|
//------------------------------------- |
71
|
|
|
// VALUES THAT MULTIPLE CLASSES NEED |
72
|
|
|
//------------------------------------- |
73
|
|
|
|
74
|
|
|
public function __construct($config = array()) |
75
|
|
|
{ |
76
|
|
|
$this->xmlrpcName = $this->xmlrpcName; |
77
|
|
|
$this->xmlrpc_backslash = chr(92).chr(92); |
78
|
|
|
|
79
|
|
|
// Types for info sent back and forth |
80
|
|
|
$this->xmlrpcTypes = array( |
81
|
|
|
$this->xmlrpcI4 => '1', |
82
|
|
|
$this->xmlrpcInt => '1', |
83
|
|
|
$this->xmlrpcBoolean => '1', |
84
|
|
|
$this->xmlrpcString => '1', |
85
|
|
|
$this->xmlrpcDouble => '1', |
86
|
|
|
$this->xmlrpcDateTime => '1', |
87
|
|
|
$this->xmlrpcBase64 => '1', |
88
|
|
|
$this->xmlrpcArray => '2', |
89
|
|
|
$this->xmlrpcStruct => '3' |
90
|
|
|
); |
91
|
|
|
|
92
|
|
|
// Array of Valid Parents for Various XML-RPC elements |
93
|
|
|
$this->valid_parents = array('BOOLEAN' => array('VALUE'), |
94
|
|
|
'I4' => array('VALUE'), |
95
|
|
|
'INT' => array('VALUE'), |
96
|
|
|
'STRING' => array('VALUE'), |
97
|
|
|
'DOUBLE' => array('VALUE'), |
98
|
|
|
'DATETIME.ISO8601' => array('VALUE'), |
99
|
|
|
'BASE64' => array('VALUE'), |
100
|
|
|
'ARRAY' => array('VALUE'), |
101
|
|
|
'STRUCT' => array('VALUE'), |
102
|
|
|
'PARAM' => array('PARAMS'), |
103
|
|
|
'METHODNAME' => array('METHODCALL'), |
104
|
|
|
'PARAMS' => array('METHODCALL', 'METHODRESPONSE'), |
105
|
|
|
'MEMBER' => array('STRUCT'), |
106
|
|
|
'NAME' => array('MEMBER'), |
107
|
|
|
'DATA' => array('ARRAY'), |
108
|
|
|
'FAULT' => array('METHODRESPONSE'), |
109
|
|
|
'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT') |
110
|
|
|
); |
111
|
|
|
|
112
|
|
|
|
113
|
|
|
// XML-RPC Responses |
114
|
|
|
$this->xmlrpcerr['unknown_method'] = '1'; |
115
|
|
|
$this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server'; |
116
|
|
|
$this->xmlrpcerr['invalid_return'] = '2'; |
117
|
|
|
$this->xmlrpcstr['invalid_return'] = 'The XML data received was either invalid or not in the correct form for XML-RPC. Turn on debugging to examine the XML data further.'; |
118
|
|
|
$this->xmlrpcerr['incorrect_params'] = '3'; |
119
|
|
|
$this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method'; |
120
|
|
|
$this->xmlrpcerr['introspect_unknown'] = '4'; |
121
|
|
|
$this->xmlrpcstr['introspect_unknown'] = "Cannot inspect signature for request: method unknown"; |
122
|
|
|
$this->xmlrpcerr['http_error'] = '5'; |
123
|
|
|
$this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server."; |
124
|
|
|
$this->xmlrpcerr['no_data'] = '6'; |
125
|
|
|
$this->xmlrpcstr['no_data'] = 'No data received from server.'; |
126
|
|
|
|
127
|
|
|
$this->initialize($config); |
128
|
|
|
|
129
|
|
|
log_message('debug', "XML-RPC Class Initialized"); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
|
133
|
|
|
//------------------------------------- |
134
|
|
|
// Initialize Prefs |
135
|
|
|
//------------------------------------- |
136
|
|
|
|
137
|
|
|
function initialize($config = array()) |
138
|
|
|
{ |
139
|
|
|
if (count($config) > 0) |
140
|
|
|
{ |
141
|
|
|
foreach ($config as $key => $val) |
142
|
|
|
{ |
143
|
|
|
if (isset($this->$key)) |
144
|
|
|
{ |
145
|
|
|
$this->$key = $val; |
146
|
|
|
} |
147
|
|
|
} |
148
|
|
|
} |
149
|
|
|
} |
150
|
|
|
// END |
151
|
|
|
|
152
|
|
|
//------------------------------------- |
153
|
|
|
// Take URL and parse it |
154
|
|
|
//------------------------------------- |
155
|
|
|
|
156
|
|
|
function server($url, $port = 80) |
157
|
|
|
{ |
158
|
|
|
if (substr($url, 0, 4) != "http") |
159
|
|
|
{ |
160
|
|
|
$url = "http://".$url; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
$parts = parse_url($url); |
164
|
|
|
|
165
|
|
|
$path = ( ! isset($parts['path'])) ? '/' : $parts['path']; |
166
|
|
|
|
167
|
|
|
if (isset($parts['query']) && $parts['query'] != '') |
168
|
|
|
{ |
169
|
|
|
$path .= '?'.$parts['query']; |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
$this->client = new XML_RPC_Client($path, $parts['host'], $port); |
173
|
|
|
} |
174
|
|
|
// END |
175
|
|
|
|
176
|
|
|
//------------------------------------- |
177
|
|
|
// Set Timeout |
178
|
|
|
//------------------------------------- |
179
|
|
|
|
180
|
|
|
function timeout($seconds = 5) |
181
|
|
|
{ |
182
|
|
|
if ( ! is_null($this->client) && is_int($seconds)) |
183
|
|
|
{ |
184
|
|
|
$this->client->timeout = $seconds; |
185
|
|
|
} |
186
|
|
|
} |
187
|
|
|
// END |
188
|
|
|
|
189
|
|
|
//------------------------------------- |
190
|
|
|
// Set Methods |
191
|
|
|
//------------------------------------- |
192
|
|
|
|
193
|
|
|
function method($function) |
194
|
|
|
{ |
195
|
|
|
$this->method = $function; |
196
|
|
|
} |
197
|
|
|
// END |
198
|
|
|
|
199
|
|
|
//------------------------------------- |
200
|
|
|
// Take Array of Data and Create Objects |
201
|
|
|
//------------------------------------- |
202
|
|
|
|
203
|
|
|
function request($incoming) |
204
|
|
|
{ |
205
|
|
|
if ( ! is_array($incoming)) |
|
|
|
|
206
|
|
|
{ |
207
|
|
|
// Send Error |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
$this->data = array(); |
211
|
|
|
|
212
|
|
|
foreach ($incoming as $key => $value) |
213
|
|
|
{ |
214
|
|
|
$this->data[$key] = $this->values_parsing($value); |
215
|
|
|
} |
216
|
|
|
} |
217
|
|
|
// END |
218
|
|
|
|
219
|
|
|
|
220
|
|
|
//------------------------------------- |
221
|
|
|
// Set Debug |
222
|
|
|
//------------------------------------- |
223
|
|
|
|
224
|
|
|
function set_debug($flag = TRUE) |
225
|
|
|
{ |
226
|
|
|
$this->debug = ($flag == TRUE) ? TRUE : FALSE; |
|
|
|
|
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
//------------------------------------- |
230
|
|
|
// Values Parsing |
231
|
|
|
//------------------------------------- |
232
|
|
|
|
233
|
|
|
function values_parsing($value, $return = FALSE) |
|
|
|
|
234
|
|
|
{ |
235
|
|
|
if (is_array($value) && array_key_exists(0, $value)) |
236
|
|
|
{ |
237
|
|
|
if ( ! isset($value['1']) OR ( ! isset($this->xmlrpcTypes[$value['1']]))) |
238
|
|
|
{ |
239
|
|
|
if (is_array($value[0])) |
240
|
|
|
{ |
241
|
|
|
$temp = new XML_RPC_Values($value['0'], 'array'); |
|
|
|
|
242
|
|
|
} else |
243
|
|
|
{ |
244
|
|
|
$temp = new XML_RPC_Values($value['0'], 'string'); |
245
|
|
|
} |
246
|
|
|
} elseif (is_array($value['0']) && ($value['1'] == 'struct' OR $value['1'] == 'array')) |
247
|
|
|
{ |
248
|
|
|
while (list($k) = each($value['0'])) |
249
|
|
|
{ |
250
|
|
|
$value['0'][$k] = $this->values_parsing($value['0'][$k], TRUE); |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
$temp = new XML_RPC_Values($value['0'], $value['1']); |
|
|
|
|
254
|
|
|
} else |
255
|
|
|
{ |
256
|
|
|
$temp = new XML_RPC_Values($value['0'], $value['1']); |
257
|
|
|
} |
258
|
|
|
} else |
259
|
|
|
{ |
260
|
|
|
$temp = new XML_RPC_Values($value, 'string'); |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
return $temp; |
264
|
|
|
} |
265
|
|
|
// END |
266
|
|
|
|
267
|
|
|
|
268
|
|
|
//------------------------------------- |
269
|
|
|
// Sends XML-RPC Request |
270
|
|
|
//------------------------------------- |
271
|
|
|
|
272
|
|
|
function send_request() |
273
|
|
|
{ |
274
|
|
|
$this->message = new XML_RPC_Message($this->method, $this->data); |
|
|
|
|
275
|
|
|
$this->message->debug = $this->debug; |
276
|
|
|
|
277
|
|
|
if ( ! $this->result = $this->client->send($this->message)) |
278
|
|
|
{ |
279
|
|
|
$this->error = $this->result->errstr; |
280
|
|
|
return FALSE; |
281
|
|
|
} elseif ( ! is_object($this->result->val)) |
282
|
|
|
{ |
283
|
|
|
$this->error = $this->result->errstr; |
284
|
|
|
return FALSE; |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
$this->response = $this->result->decode(); |
288
|
|
|
|
289
|
|
|
return TRUE; |
290
|
|
|
} |
291
|
|
|
// END |
292
|
|
|
|
293
|
|
|
//------------------------------------- |
294
|
|
|
// Returns Error |
295
|
|
|
//------------------------------------- |
296
|
|
|
|
297
|
|
|
function display_error() |
298
|
|
|
{ |
299
|
|
|
return $this->error; |
300
|
|
|
} |
301
|
|
|
// END |
302
|
|
|
|
303
|
|
|
//------------------------------------- |
304
|
|
|
// Returns Remote Server Response |
305
|
|
|
//------------------------------------- |
306
|
|
|
|
307
|
|
|
function display_response() |
308
|
|
|
{ |
309
|
|
|
return $this->response; |
310
|
|
|
} |
311
|
|
|
// END |
312
|
|
|
|
313
|
|
|
//------------------------------------- |
314
|
|
|
// Sends an Error Message for Server Request |
315
|
|
|
//------------------------------------- |
316
|
|
|
|
317
|
|
|
function send_error_message($number, $message) |
318
|
|
|
{ |
319
|
|
|
return new XML_RPC_Response('0', $number, $message); |
320
|
|
|
} |
321
|
|
|
// END |
322
|
|
|
|
323
|
|
|
|
324
|
|
|
//------------------------------------- |
325
|
|
|
// Send Response for Server Request |
326
|
|
|
//------------------------------------- |
327
|
|
|
|
328
|
|
|
function send_response($response) |
329
|
|
|
{ |
330
|
|
|
// $response should be array of values, which will be parsed |
331
|
|
|
// based on their data and type into a valid group of XML-RPC values |
332
|
|
|
|
333
|
|
|
$response = $this->values_parsing($response); |
334
|
|
|
|
335
|
|
|
return new XML_RPC_Response($response); |
336
|
|
|
} |
337
|
|
|
// END |
338
|
|
|
|
339
|
|
|
} // END XML_RPC Class |
340
|
|
|
|
341
|
|
|
|
342
|
|
|
|
343
|
|
|
/** |
344
|
|
|
* XML-RPC Client class |
345
|
|
|
* |
346
|
|
|
* @category XML-RPC |
347
|
|
|
* @author ExpressionEngine Dev Team |
348
|
|
|
* @link http://codeigniter.com/user_guide/libraries/xmlrpc.html |
349
|
|
|
*/ |
350
|
|
|
class XML_RPC_Client extends CI_Xmlrpc |
351
|
|
|
{ |
352
|
|
|
var $path = ''; |
353
|
|
|
var $server = ''; |
354
|
|
|
var $port = 80; |
355
|
|
|
var $errno = ''; |
356
|
|
|
var $errstring = ''; |
357
|
|
|
var $timeout = 5; |
358
|
|
|
var $no_multicall = FALSE; |
359
|
|
|
|
360
|
|
|
public function __construct($path, $server, $port = 80) |
361
|
|
|
{ |
362
|
|
|
parent::__construct(); |
363
|
|
|
|
364
|
|
|
$this->port = $port; |
365
|
|
|
$this->server = $server; |
366
|
|
|
$this->path = $path; |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
/** |
370
|
|
|
* @param XML_RPC_Message $msg |
371
|
|
|
*/ |
372
|
|
|
function send($msg) |
373
|
|
|
{ |
374
|
|
|
if (is_array($msg)) |
375
|
|
|
{ |
376
|
|
|
// Multi-call disabled |
377
|
|
|
$r = new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']); |
378
|
|
|
return $r; |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
return $this->sendPayload($msg); |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
function sendPayload($msg) |
385
|
|
|
{ |
386
|
|
|
$fp = @fsockopen($this->server, $this->port, $this->errno, $this->errstr, $this->timeout); |
|
|
|
|
387
|
|
|
|
388
|
|
|
if ( ! is_resource($fp)) |
389
|
|
|
{ |
390
|
|
|
error_log($this->xmlrpcstr['http_error']); |
391
|
|
|
$r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']); |
392
|
|
|
return $r; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
if (empty($msg->payload)) |
396
|
|
|
{ |
397
|
|
|
// $msg = XML_RPC_Messages |
398
|
|
|
$msg->createPayload(); |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
$r = "\r\n"; |
402
|
|
|
$op = "POST {$this->path} HTTP/1.0$r"; |
403
|
|
|
$op .= "Host: {$this->server}$r"; |
404
|
|
|
$op .= "Content-Type: text/xml$r"; |
405
|
|
|
$op .= "User-Agent: {$this->xmlrpcName}$r"; |
406
|
|
|
$op .= "Content-Length: ".strlen($msg->payload)."$r$r"; |
407
|
|
|
$op .= $msg->payload; |
408
|
|
|
|
409
|
|
|
|
410
|
|
|
if ( ! fputs($fp, $op, strlen($op))) |
411
|
|
|
{ |
412
|
|
|
error_log($this->xmlrpcstr['http_error']); |
413
|
|
|
$r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']); |
414
|
|
|
return $r; |
415
|
|
|
} |
416
|
|
|
$resp = $msg->parseResponse($fp); |
417
|
|
|
fclose($fp); |
418
|
|
|
return $resp; |
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
} // end class XML_RPC_Client |
422
|
|
|
|
423
|
|
|
|
424
|
|
|
/** |
425
|
|
|
* XML-RPC Response class |
426
|
|
|
* |
427
|
|
|
* @category XML-RPC |
428
|
|
|
* @author ExpressionEngine Dev Team |
429
|
|
|
* @link http://codeigniter.com/user_guide/libraries/xmlrpc.html |
430
|
|
|
*/ |
431
|
|
|
class XML_RPC_Response |
432
|
|
|
{ |
433
|
|
|
var $val = 0; |
434
|
|
|
var $errno = 0; |
435
|
|
|
var $errstr = ''; |
436
|
|
|
var $headers = array(); |
437
|
|
|
var $xss_clean = TRUE; |
438
|
|
|
|
439
|
|
|
public function __construct($val, $code = 0, $fstr = '') |
440
|
|
|
{ |
441
|
|
|
if ($code != 0) |
442
|
|
|
{ |
443
|
|
|
// error |
444
|
|
|
$this->errno = $code; |
445
|
|
|
$this->errstr = htmlentities($fstr); |
446
|
|
|
} |
447
|
|
|
else if ( ! is_object($val)) |
448
|
|
|
{ |
449
|
|
|
// programmer error, not an object |
450
|
|
|
error_log("Invalid type '".gettype($val)."' (value: $val) passed to XML_RPC_Response. Defaulting to empty value."); |
451
|
|
|
$this->val = new XML_RPC_Values(); |
|
|
|
|
452
|
|
|
} |
453
|
|
|
else |
454
|
|
|
{ |
455
|
|
|
$this->val = $val; |
|
|
|
|
456
|
|
|
} |
457
|
|
|
} |
458
|
|
|
|
459
|
|
|
function faultCode() |
460
|
|
|
{ |
461
|
|
|
return $this->errno; |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
function faultString() |
465
|
|
|
{ |
466
|
|
|
return $this->errstr; |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
function value() |
470
|
|
|
{ |
471
|
|
|
return $this->val; |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
function prepare_response() |
475
|
|
|
{ |
476
|
|
|
$result = "<methodResponse>\n"; |
477
|
|
|
if ($this->errno) |
478
|
|
|
{ |
479
|
|
|
$result .= '<fault> |
480
|
|
|
<value> |
481
|
|
|
<struct> |
482
|
|
|
<member> |
483
|
|
|
<name>faultCode</name> |
484
|
|
|
<value><int>' . $this->errno.'</int></value> |
485
|
|
|
</member> |
486
|
|
|
<member> |
487
|
|
|
<name>faultString</name> |
488
|
|
|
<value><string>' . $this->errstr.'</string></value> |
489
|
|
|
</member> |
490
|
|
|
</struct> |
491
|
|
|
</value> |
492
|
|
|
</fault>'; |
493
|
|
|
} else |
494
|
|
|
{ |
495
|
|
|
$result .= "<params>\n<param>\n". |
496
|
|
|
$this->val->serialize_class(). |
|
|
|
|
497
|
|
|
"</param>\n</params>"; |
498
|
|
|
} |
499
|
|
|
$result .= "\n</methodResponse>"; |
500
|
|
|
return $result; |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
function decode($array = FALSE) |
504
|
|
|
{ |
505
|
|
|
$CI = & get_instance(); |
506
|
|
|
|
507
|
|
|
if ($array !== FALSE && is_array($array)) |
508
|
|
|
{ |
509
|
|
View Code Duplication |
while (list($key) = each($array)) |
510
|
|
|
{ |
511
|
|
|
if (is_array($array[$key])) |
512
|
|
|
{ |
513
|
|
|
$array[$key] = $this->decode($array[$key]); |
514
|
|
|
} else |
515
|
|
|
{ |
516
|
|
|
$array[$key] = ($this->xss_clean) ? $CI->security->xss_clean($array[$key]) : $array[$key]; |
|
|
|
|
517
|
|
|
} |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
$result = $array; |
521
|
|
|
} else |
522
|
|
|
{ |
523
|
|
|
$result = $this->xmlrpc_decoder($this->val); |
524
|
|
|
|
525
|
|
|
if (is_array($result)) |
526
|
|
|
{ |
527
|
|
|
$result = $this->decode($result); |
|
|
|
|
528
|
|
|
} else |
529
|
|
|
{ |
530
|
|
|
$result = ($this->xss_clean) ? $CI->security->xss_clean($result) : $result; |
531
|
|
|
} |
532
|
|
|
} |
533
|
|
|
|
534
|
|
|
return $result; |
535
|
|
|
} |
536
|
|
|
|
537
|
|
|
|
538
|
|
|
|
539
|
|
|
//------------------------------------- |
540
|
|
|
// XML-RPC Object to PHP Types |
541
|
|
|
//------------------------------------- |
542
|
|
|
|
543
|
|
|
/** |
544
|
|
|
* @param integer $xmlrpc_val |
545
|
|
|
*/ |
546
|
|
View Code Duplication |
function xmlrpc_decoder($xmlrpc_val) |
547
|
|
|
{ |
548
|
|
|
$kind = $xmlrpc_val->kindOf(); |
|
|
|
|
549
|
|
|
|
550
|
|
|
if ($kind == 'scalar') |
551
|
|
|
{ |
552
|
|
|
return $xmlrpc_val->scalarval(); |
|
|
|
|
553
|
|
|
} elseif ($kind == 'array') |
554
|
|
|
{ |
555
|
|
|
reset($xmlrpc_val->me); |
556
|
|
|
list($a, $b) = each($xmlrpc_val->me); |
|
|
|
|
557
|
|
|
$size = count($b); |
558
|
|
|
|
559
|
|
|
$arr = array(); |
560
|
|
|
|
561
|
|
|
for ($i = 0; $i < $size; $i++) |
562
|
|
|
{ |
563
|
|
|
$arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]); |
564
|
|
|
} |
565
|
|
|
return $arr; |
566
|
|
|
} elseif ($kind == 'struct') |
567
|
|
|
{ |
568
|
|
|
reset($xmlrpc_val->me['struct']); |
569
|
|
|
$arr = array(); |
570
|
|
|
|
571
|
|
|
while (list($key, $value) = each($xmlrpc_val->me['struct'])) |
572
|
|
|
{ |
573
|
|
|
$arr[$key] = $this->xmlrpc_decoder($value); |
574
|
|
|
} |
575
|
|
|
return $arr; |
576
|
|
|
} |
577
|
|
|
} |
578
|
|
|
|
579
|
|
|
|
580
|
|
|
//------------------------------------- |
581
|
|
|
// ISO-8601 time to server or UTC time |
582
|
|
|
//------------------------------------- |
583
|
|
|
|
584
|
|
|
function iso8601_decode($time, $utc = 0) |
585
|
|
|
{ |
586
|
|
|
// return a timet in the localtime, or UTC |
587
|
|
|
$t = 0; |
588
|
|
|
if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs)) |
589
|
|
|
{ |
590
|
|
|
$fnc = ($utc == 1) ? 'gmmktime' : 'mktime'; |
591
|
|
|
$t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); |
592
|
|
|
} |
593
|
|
|
return $t; |
594
|
|
|
} |
595
|
|
|
|
596
|
|
|
} // End Response Class |
597
|
|
|
|
598
|
|
|
|
599
|
|
|
|
600
|
|
|
/** |
601
|
|
|
* XML-RPC Message class |
602
|
|
|
* |
603
|
|
|
* @category XML-RPC |
604
|
|
|
* @author ExpressionEngine Dev Team |
605
|
|
|
* @link http://codeigniter.com/user_guide/libraries/xmlrpc.html |
606
|
|
|
*/ |
607
|
|
|
class XML_RPC_Message extends CI_Xmlrpc |
608
|
|
|
{ |
609
|
|
|
var $payload; |
610
|
|
|
var $method_name; |
611
|
|
|
var $params = array(); |
612
|
|
|
var $xh = array(); |
613
|
|
|
|
614
|
|
|
public function __construct($method, $pars = 0) |
615
|
|
|
{ |
616
|
|
|
parent::__construct(); |
617
|
|
|
|
618
|
|
|
$this->method_name = $method; |
619
|
|
|
if (is_array($pars) && count($pars) > 0) |
620
|
|
|
{ |
621
|
|
|
for ($i = 0; $i < count($pars); $i++) |
|
|
|
|
622
|
|
|
{ |
623
|
|
|
// $pars[$i] = XML_RPC_Values |
|
|
|
|
624
|
|
|
$this->params[] = $pars[$i]; |
625
|
|
|
} |
626
|
|
|
} |
627
|
|
|
} |
628
|
|
|
|
629
|
|
|
//------------------------------------- |
630
|
|
|
// Create Payload to Send |
631
|
|
|
//------------------------------------- |
632
|
|
|
|
633
|
|
|
function createPayload() |
634
|
|
|
{ |
635
|
|
|
$this->payload = "<?xml version=\"1.0\"?".">\r\n<methodCall>\r\n"; |
636
|
|
|
$this->payload .= '<methodName>'.$this->method_name."</methodName>\r\n"; |
637
|
|
|
$this->payload .= "<params>\r\n"; |
638
|
|
|
|
639
|
|
|
for ($i = 0; $i < count($this->params); $i++) |
|
|
|
|
640
|
|
|
{ |
641
|
|
|
// $p = XML_RPC_Values |
642
|
|
|
$p = $this->params[$i]; |
643
|
|
|
$this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n"; |
644
|
|
|
} |
645
|
|
|
|
646
|
|
|
$this->payload .= "</params>\r\n</methodCall>\r\n"; |
647
|
|
|
} |
648
|
|
|
|
649
|
|
|
//------------------------------------- |
650
|
|
|
// Parse External XML-RPC Server's Response |
651
|
|
|
//------------------------------------- |
652
|
|
|
|
653
|
|
|
function parseResponse($fp) |
654
|
|
|
{ |
655
|
|
|
$data = ''; |
656
|
|
|
|
657
|
|
|
while ($datum = fread($fp, 4096)) |
658
|
|
|
{ |
659
|
|
|
$data .= $datum; |
660
|
|
|
} |
661
|
|
|
|
662
|
|
|
//------------------------------------- |
663
|
|
|
// DISPLAY HTTP CONTENT for DEBUGGING |
664
|
|
|
//------------------------------------- |
665
|
|
|
|
666
|
|
|
if ($this->debug === TRUE) |
667
|
|
|
{ |
668
|
|
|
echo "<pre>"; |
669
|
|
|
echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n"; |
670
|
|
|
echo "</pre>"; |
671
|
|
|
} |
672
|
|
|
|
673
|
|
|
//------------------------------------- |
674
|
|
|
// Check for data |
675
|
|
|
//------------------------------------- |
676
|
|
|
|
677
|
|
|
if ($data == "") |
678
|
|
|
{ |
679
|
|
|
error_log($this->xmlrpcstr['no_data']); |
680
|
|
|
$r = new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']); |
681
|
|
|
return $r; |
682
|
|
|
} |
683
|
|
|
|
684
|
|
|
|
685
|
|
|
//------------------------------------- |
686
|
|
|
// Check for HTTP 200 Response |
687
|
|
|
//------------------------------------- |
688
|
|
|
|
689
|
|
|
if (strncmp($data, 'HTTP', 4) == 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data)) |
690
|
|
|
{ |
691
|
|
|
$errstr = substr($data, 0, strpos($data, "\n") - 1); |
692
|
|
|
$r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')'); |
693
|
|
|
return $r; |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
//------------------------------------- |
697
|
|
|
// Create and Set Up XML Parser |
698
|
|
|
//------------------------------------- |
699
|
|
|
|
700
|
|
|
$parser = xml_parser_create($this->xmlrpc_defencoding); |
701
|
|
|
|
702
|
|
|
$this->xh[$parser] = array(); |
703
|
|
|
$this->xh[$parser]['isf'] = 0; |
704
|
|
|
$this->xh[$parser]['ac'] = ''; |
705
|
|
|
$this->xh[$parser]['headers'] = array(); |
706
|
|
|
$this->xh[$parser]['stack'] = array(); |
707
|
|
|
$this->xh[$parser]['valuestack'] = array(); |
708
|
|
|
$this->xh[$parser]['isf_reason'] = 0; |
709
|
|
|
|
710
|
|
|
xml_set_object($parser, $this); |
711
|
|
|
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); |
712
|
|
|
xml_set_element_handler($parser, 'open_tag', 'closing_tag'); |
713
|
|
|
xml_set_character_data_handler($parser, 'character_data'); |
714
|
|
|
//xml_set_default_handler($parser, 'default_handler'); |
|
|
|
|
715
|
|
|
|
716
|
|
|
|
717
|
|
|
//------------------------------------- |
718
|
|
|
// GET HEADERS |
719
|
|
|
//------------------------------------- |
720
|
|
|
|
721
|
|
|
$lines = explode("\r\n", $data); |
722
|
|
|
while (($line = array_shift($lines))) |
723
|
|
|
{ |
724
|
|
|
if (strlen($line) < 1) |
725
|
|
|
{ |
726
|
|
|
break; |
727
|
|
|
} |
728
|
|
|
$this->xh[$parser]['headers'][] = $line; |
729
|
|
|
} |
730
|
|
|
$data = implode("\r\n", $lines); |
731
|
|
|
|
732
|
|
|
|
733
|
|
|
//------------------------------------- |
734
|
|
|
// PARSE XML DATA |
735
|
|
|
//------------------------------------- |
736
|
|
|
|
737
|
|
|
if ( ! xml_parse($parser, $data, count($data))) |
738
|
|
|
{ |
739
|
|
|
$errstr = sprintf('XML error: %s at line %d', |
740
|
|
|
xml_error_string(xml_get_error_code($parser)), |
741
|
|
|
xml_get_current_line_number($parser)); |
742
|
|
|
//error_log($errstr); |
743
|
|
|
$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']); |
744
|
|
|
xml_parser_free($parser); |
745
|
|
|
return $r; |
746
|
|
|
} |
747
|
|
|
xml_parser_free($parser); |
748
|
|
|
|
749
|
|
|
// --------------------------------------- |
750
|
|
|
// Got Ourselves Some Badness, It Seems |
751
|
|
|
// --------------------------------------- |
752
|
|
|
|
753
|
|
|
if ($this->xh[$parser]['isf'] > 1) |
754
|
|
|
{ |
755
|
|
|
if ($this->debug === TRUE) |
756
|
|
|
{ |
757
|
|
|
echo "---Invalid Return---\n"; |
758
|
|
|
echo $this->xh[$parser]['isf_reason']; |
759
|
|
|
echo "---Invalid Return---\n\n"; |
760
|
|
|
} |
761
|
|
|
|
762
|
|
|
$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']); |
763
|
|
|
return $r; |
764
|
|
|
} elseif ( ! is_object($this->xh[$parser]['value'])) |
765
|
|
|
{ |
766
|
|
|
$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']); |
767
|
|
|
return $r; |
768
|
|
|
} |
769
|
|
|
|
770
|
|
|
//------------------------------------- |
771
|
|
|
// DISPLAY XML CONTENT for DEBUGGING |
772
|
|
|
//------------------------------------- |
773
|
|
|
|
774
|
|
|
if ($this->debug === TRUE) |
775
|
|
|
{ |
776
|
|
|
echo "<pre>"; |
777
|
|
|
|
778
|
|
|
if (count($this->xh[$parser]['headers'] > 0)) |
779
|
|
|
{ |
780
|
|
|
echo "---HEADERS---\n"; |
781
|
|
|
foreach ($this->xh[$parser]['headers'] as $header) |
782
|
|
|
{ |
783
|
|
|
echo "$header\n"; |
784
|
|
|
} |
785
|
|
|
echo "---END HEADERS---\n\n"; |
786
|
|
|
} |
787
|
|
|
|
788
|
|
|
echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n"; |
789
|
|
|
|
790
|
|
|
echo "---PARSED---\n"; |
791
|
|
|
var_dump($this->xh[$parser]['value']); |
|
|
|
|
792
|
|
|
echo "\n---END PARSED---</pre>"; |
793
|
|
|
} |
794
|
|
|
|
795
|
|
|
//------------------------------------- |
796
|
|
|
// SEND RESPONSE |
797
|
|
|
//------------------------------------- |
798
|
|
|
|
799
|
|
|
$v = $this->xh[$parser]['value']; |
800
|
|
|
|
801
|
|
|
if ($this->xh[$parser]['isf']) |
802
|
|
|
{ |
803
|
|
|
$errno_v = $v->me['struct']['faultCode']; |
804
|
|
|
$errstr_v = $v->me['struct']['faultString']; |
805
|
|
|
$errno = $errno_v->scalarval(); |
806
|
|
|
|
807
|
|
|
if ($errno == 0) |
808
|
|
|
{ |
809
|
|
|
// FAULT returned, errno needs to reflect that |
810
|
|
|
$errno = -1; |
811
|
|
|
} |
812
|
|
|
|
813
|
|
|
$r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval()); |
814
|
|
|
} else |
815
|
|
|
{ |
816
|
|
|
$r = new XML_RPC_Response($v); |
817
|
|
|
} |
818
|
|
|
|
819
|
|
|
$r->headers = $this->xh[$parser]['headers']; |
820
|
|
|
return $r; |
821
|
|
|
} |
822
|
|
|
|
823
|
|
|
// ------------------------------------ |
824
|
|
|
// Begin Return Message Parsing section |
825
|
|
|
// ------------------------------------ |
826
|
|
|
|
827
|
|
|
// quick explanation of components: |
828
|
|
|
// ac - used to accumulate values |
829
|
|
|
// isf - used to indicate a fault |
830
|
|
|
// lv - used to indicate "looking for a value": implements |
831
|
|
|
// the logic to allow values with no types to be strings |
832
|
|
|
// params - used to store parameters in method calls |
833
|
|
|
// method - used to store method name |
834
|
|
|
// stack - array with parent tree of the xml element, |
835
|
|
|
// used to validate the nesting of elements |
836
|
|
|
|
837
|
|
|
//------------------------------------- |
838
|
|
|
// Start Element Handler |
839
|
|
|
//------------------------------------- |
840
|
|
|
|
841
|
|
|
function open_tag($the_parser, $name, $attrs) |
|
|
|
|
842
|
|
|
{ |
843
|
|
|
// If invalid nesting, then return |
844
|
|
|
if ($this->xh[$the_parser]['isf'] > 1) { |
845
|
|
|
return; |
846
|
|
|
} |
847
|
|
|
|
848
|
|
|
// Evaluate and check for correct nesting of XML elements |
849
|
|
|
|
850
|
|
|
if (count($this->xh[$the_parser]['stack']) == 0) |
851
|
|
|
{ |
852
|
|
|
if ($name != 'METHODRESPONSE' && $name != 'METHODCALL') |
853
|
|
|
{ |
854
|
|
|
$this->xh[$the_parser]['isf'] = 2; |
855
|
|
|
$this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing'; |
856
|
|
|
return; |
857
|
|
|
} |
858
|
|
|
} else |
859
|
|
|
{ |
860
|
|
|
// not top level element: see if parent is OK |
861
|
|
|
if ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE)) |
862
|
|
|
{ |
863
|
|
|
$this->xh[$the_parser]['isf'] = 2; |
864
|
|
|
$this->xh[$the_parser]['isf_reason'] = "XML-RPC element $name cannot be child of ".$this->xh[$the_parser]['stack'][0]; |
865
|
|
|
return; |
866
|
|
|
} |
867
|
|
|
} |
868
|
|
|
|
869
|
|
|
switch ($name) |
870
|
|
|
{ |
871
|
|
|
case 'STRUCT': |
872
|
|
|
case 'ARRAY': |
873
|
|
|
// Creates array for child elements |
874
|
|
|
|
875
|
|
|
$cur_val = array('value' => array(), |
876
|
|
|
'type' => $name); |
877
|
|
|
|
878
|
|
|
array_unshift($this->xh[$the_parser]['valuestack'], $cur_val); |
879
|
|
|
break; |
880
|
|
|
case 'METHODNAME': |
881
|
|
|
case 'NAME': |
882
|
|
|
$this->xh[$the_parser]['ac'] = ''; |
883
|
|
|
break; |
884
|
|
|
case 'FAULT': |
885
|
|
|
$this->xh[$the_parser]['isf'] = 1; |
886
|
|
|
break; |
887
|
|
|
case 'PARAM': |
888
|
|
|
$this->xh[$the_parser]['value'] = NULL; |
889
|
|
|
break; |
890
|
|
|
case 'VALUE': |
891
|
|
|
$this->xh[$the_parser]['vt'] = 'value'; |
892
|
|
|
$this->xh[$the_parser]['ac'] = ''; |
893
|
|
|
$this->xh[$the_parser]['lv'] = 1; |
894
|
|
|
break; |
895
|
|
|
case 'I4': |
896
|
|
|
case 'INT': |
897
|
|
|
case 'STRING': |
898
|
|
|
case 'BOOLEAN': |
899
|
|
|
case 'DOUBLE': |
900
|
|
|
case 'DATETIME.ISO8601': |
901
|
|
|
case 'BASE64': |
902
|
|
|
if ($this->xh[$the_parser]['vt'] != 'value') |
903
|
|
|
{ |
904
|
|
|
//two data elements inside a value: an error occurred! |
905
|
|
|
$this->xh[$the_parser]['isf'] = 2; |
906
|
|
|
$this->xh[$the_parser]['isf_reason'] = "'Twas a $name element following a ".$this->xh[$the_parser]['vt']." element inside a single value"; |
907
|
|
|
return; |
908
|
|
|
} |
909
|
|
|
|
910
|
|
|
$this->xh[$the_parser]['ac'] = ''; |
911
|
|
|
break; |
912
|
|
|
case 'MEMBER': |
913
|
|
|
// Set name of <member> to nothing to prevent errors later if no <name> is found |
914
|
|
|
$this->xh[$the_parser]['valuestack'][0]['name'] = ''; |
915
|
|
|
|
916
|
|
|
// Set NULL value to check to see if value passed for this param/member |
917
|
|
|
$this->xh[$the_parser]['value'] = NULL; |
918
|
|
|
break; |
919
|
|
|
case 'DATA': |
920
|
|
|
case 'METHODCALL': |
921
|
|
|
case 'METHODRESPONSE': |
922
|
|
|
case 'PARAMS': |
923
|
|
|
// valid elements that add little to processing |
924
|
|
|
break; |
925
|
|
|
default: |
926
|
|
|
/// An Invalid Element is Found, so we have trouble |
927
|
|
|
$this->xh[$the_parser]['isf'] = 2; |
928
|
|
|
$this->xh[$the_parser]['isf_reason'] = "Invalid XML-RPC element found: $name"; |
929
|
|
|
break; |
930
|
|
|
} |
931
|
|
|
|
932
|
|
|
// Add current element name to stack, to allow validation of nesting |
933
|
|
|
array_unshift($this->xh[$the_parser]['stack'], $name); |
934
|
|
|
|
935
|
|
|
if ($name != 'VALUE') { |
936
|
|
|
$this->xh[$the_parser]['lv'] = 0; |
937
|
|
|
} |
938
|
|
|
} |
939
|
|
|
// END |
940
|
|
|
|
941
|
|
|
|
942
|
|
|
//------------------------------------- |
943
|
|
|
// End Element Handler |
944
|
|
|
//------------------------------------- |
945
|
|
|
|
946
|
|
|
function closing_tag($the_parser, $name) |
947
|
|
|
{ |
948
|
|
|
if ($this->xh[$the_parser]['isf'] > 1) { |
949
|
|
|
return; |
950
|
|
|
} |
951
|
|
|
|
952
|
|
|
// Remove current element from stack and set variable |
953
|
|
|
// NOTE: If the XML validates, then we do not have to worry about |
954
|
|
|
// the opening and closing of elements. Nesting is checked on the opening |
955
|
|
|
// tag so we be safe there as well. |
956
|
|
|
|
957
|
|
|
$curr_elem = array_shift($this->xh[$the_parser]['stack']); |
958
|
|
|
|
959
|
|
|
switch ($name) |
960
|
|
|
{ |
961
|
|
|
case 'STRUCT': |
962
|
|
|
case 'ARRAY': |
963
|
|
|
$cur_val = array_shift($this->xh[$the_parser]['valuestack']); |
964
|
|
|
$this->xh[$the_parser]['value'] = ( ! isset($cur_val['values'])) ? array() : $cur_val['values']; |
965
|
|
|
$this->xh[$the_parser]['vt'] = strtolower($name); |
966
|
|
|
break; |
967
|
|
|
case 'NAME': |
968
|
|
|
$this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac']; |
969
|
|
|
break; |
970
|
|
|
case 'BOOLEAN': |
971
|
|
|
case 'I4': |
972
|
|
|
case 'INT': |
973
|
|
|
case 'STRING': |
974
|
|
|
case 'DOUBLE': |
975
|
|
|
case 'DATETIME.ISO8601': |
976
|
|
|
case 'BASE64': |
977
|
|
|
$this->xh[$the_parser]['vt'] = strtolower($name); |
978
|
|
|
|
979
|
|
|
if ($name == 'STRING') |
980
|
|
|
{ |
981
|
|
|
$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac']; |
982
|
|
|
} |
983
|
|
|
elseif ($name == 'DATETIME.ISO8601') |
984
|
|
|
{ |
985
|
|
|
$this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime; |
986
|
|
|
$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac']; |
987
|
|
|
} |
988
|
|
|
elseif ($name == 'BASE64') |
989
|
|
|
{ |
990
|
|
|
$this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']); |
991
|
|
|
} |
992
|
|
|
elseif ($name == 'BOOLEAN') |
993
|
|
|
{ |
994
|
|
|
// Translated BOOLEAN values to TRUE AND FALSE |
995
|
|
|
if ($this->xh[$the_parser]['ac'] == '1') |
996
|
|
|
{ |
997
|
|
|
$this->xh[$the_parser]['value'] = TRUE; |
998
|
|
|
} |
999
|
|
|
else |
1000
|
|
|
{ |
1001
|
|
|
$this->xh[$the_parser]['value'] = FALSE; |
1002
|
|
|
} |
1003
|
|
|
} |
1004
|
|
View Code Duplication |
elseif ($name == 'DOUBLE') |
1005
|
|
|
{ |
1006
|
|
|
// we have a DOUBLE |
1007
|
|
|
// we must check that only 0123456789-.<space> are characters here |
1008
|
|
|
if ( ! preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])) |
1009
|
|
|
{ |
1010
|
|
|
$this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND'; |
1011
|
|
|
} |
1012
|
|
|
else |
1013
|
|
|
{ |
1014
|
|
|
$this->xh[$the_parser]['value'] = (double)$this->xh[$the_parser]['ac']; |
1015
|
|
|
} |
1016
|
|
|
} |
1017
|
|
View Code Duplication |
else |
1018
|
|
|
{ |
1019
|
|
|
// we have an I4/INT |
1020
|
|
|
// we must check that only 0123456789-<space> are characters here |
1021
|
|
|
if ( ! preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])) |
1022
|
|
|
{ |
1023
|
|
|
$this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND'; |
1024
|
|
|
} |
1025
|
|
|
else |
1026
|
|
|
{ |
1027
|
|
|
$this->xh[$the_parser]['value'] = (int)$this->xh[$the_parser]['ac']; |
1028
|
|
|
} |
1029
|
|
|
} |
1030
|
|
|
$this->xh[$the_parser]['ac'] = ''; |
1031
|
|
|
$this->xh[$the_parser]['lv'] = 3; // indicate we've found a value |
1032
|
|
|
break; |
1033
|
|
|
case 'VALUE': |
1034
|
|
|
// This if() detects if no scalar was inside <VALUE></VALUE> |
1035
|
|
View Code Duplication |
if ($this->xh[$the_parser]['vt'] == 'value') |
1036
|
|
|
{ |
1037
|
|
|
$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac']; |
1038
|
|
|
$this->xh[$the_parser]['vt'] = $this->xmlrpcString; |
1039
|
|
|
} |
1040
|
|
|
|
1041
|
|
|
// build the XML-RPC value out of the data received, and substitute it |
1042
|
|
|
$temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']); |
1043
|
|
|
|
1044
|
|
|
if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] == 'ARRAY') |
1045
|
|
|
{ |
1046
|
|
|
// Array |
1047
|
|
|
$this->xh[$the_parser]['valuestack'][0]['values'][] = $temp; |
1048
|
|
|
} else |
1049
|
|
|
{ |
1050
|
|
|
// Struct |
1051
|
|
|
$this->xh[$the_parser]['value'] = $temp; |
1052
|
|
|
} |
1053
|
|
|
break; |
1054
|
|
|
case 'MEMBER': |
1055
|
|
|
$this->xh[$the_parser]['ac'] = ''; |
1056
|
|
|
|
1057
|
|
|
// If value add to array in the stack for the last element built |
1058
|
|
|
if ($this->xh[$the_parser]['value']) |
1059
|
|
|
{ |
1060
|
|
|
$this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value']; |
1061
|
|
|
} |
1062
|
|
|
break; |
1063
|
|
|
case 'DATA': |
1064
|
|
|
$this->xh[$the_parser]['ac'] = ''; |
1065
|
|
|
break; |
1066
|
|
|
case 'PARAM': |
1067
|
|
|
if ($this->xh[$the_parser]['value']) |
1068
|
|
|
{ |
1069
|
|
|
$this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value']; |
1070
|
|
|
} |
1071
|
|
|
break; |
1072
|
|
|
case 'METHODNAME': |
1073
|
|
|
$this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']); |
1074
|
|
|
break; |
1075
|
|
|
case 'PARAMS': |
1076
|
|
|
case 'FAULT': |
1077
|
|
|
case 'METHODCALL': |
1078
|
|
|
case 'METHORESPONSE': |
1079
|
|
|
// We're all good kids with nuthin' to do |
1080
|
|
|
break; |
1081
|
|
|
default: |
1082
|
|
|
// End of an Invalid Element. Taken care of during the opening tag though |
1083
|
|
|
break; |
1084
|
|
|
} |
1085
|
|
|
} |
1086
|
|
|
|
1087
|
|
|
//------------------------------------- |
1088
|
|
|
// Parses Character Data |
1089
|
|
|
//------------------------------------- |
1090
|
|
|
|
1091
|
|
|
function character_data($the_parser, $data) |
1092
|
|
|
{ |
1093
|
|
|
if ($this->xh[$the_parser]['isf'] > 1) { |
1094
|
|
|
return; |
1095
|
|
|
} |
1096
|
|
|
// XML Fault found already |
1097
|
|
|
|
1098
|
|
|
// If a value has not been found |
1099
|
|
|
if ($this->xh[$the_parser]['lv'] != 3) |
1100
|
|
|
{ |
1101
|
|
|
if ($this->xh[$the_parser]['lv'] == 1) |
1102
|
|
|
{ |
1103
|
|
|
$this->xh[$the_parser]['lv'] = 2; // Found a value |
1104
|
|
|
} |
1105
|
|
|
|
1106
|
|
|
if ( ! @isset($this->xh[$the_parser]['ac'])) |
1107
|
|
|
{ |
1108
|
|
|
$this->xh[$the_parser]['ac'] = ''; |
1109
|
|
|
} |
1110
|
|
|
|
1111
|
|
|
$this->xh[$the_parser]['ac'] .= $data; |
1112
|
|
|
} |
1113
|
|
|
} |
1114
|
|
|
|
1115
|
|
|
|
1116
|
|
|
function addParam($par) { $this->params[] = $par; } |
1117
|
|
|
|
1118
|
|
|
function output_parameters($array = FALSE) |
1119
|
|
|
{ |
1120
|
|
|
$CI = & get_instance(); |
1121
|
|
|
|
1122
|
|
|
if ($array !== FALSE && is_array($array)) |
1123
|
|
|
{ |
1124
|
|
View Code Duplication |
while (list($key) = each($array)) |
1125
|
|
|
{ |
1126
|
|
|
if (is_array($array[$key])) |
1127
|
|
|
{ |
1128
|
|
|
$array[$key] = $this->output_parameters($array[$key]); |
1129
|
|
|
} else |
1130
|
|
|
{ |
1131
|
|
|
// 'bits' is for the MetaWeblog API image bits |
1132
|
|
|
// @todo - this needs to be made more general purpose |
1133
|
|
|
$array[$key] = ($key == 'bits' OR $this->xss_clean == FALSE) ? $array[$key] : $CI->security->xss_clean($array[$key]); |
|
|
|
|
1134
|
|
|
} |
1135
|
|
|
} |
1136
|
|
|
|
1137
|
|
|
$parameters = $array; |
1138
|
|
|
} else |
1139
|
|
|
{ |
1140
|
|
|
$parameters = array(); |
1141
|
|
|
|
1142
|
|
|
for ($i = 0; $i < count($this->params); $i++) |
|
|
|
|
1143
|
|
|
{ |
1144
|
|
|
$a_param = $this->decode_message($this->params[$i]); |
1145
|
|
|
|
1146
|
|
|
if (is_array($a_param)) |
1147
|
|
|
{ |
1148
|
|
|
$parameters[] = $this->output_parameters($a_param); |
|
|
|
|
1149
|
|
|
} else |
1150
|
|
|
{ |
1151
|
|
|
$parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param; |
1152
|
|
|
} |
1153
|
|
|
} |
1154
|
|
|
} |
1155
|
|
|
|
1156
|
|
|
return $parameters; |
1157
|
|
|
} |
1158
|
|
|
|
1159
|
|
|
|
1160
|
|
View Code Duplication |
function decode_message($param) |
1161
|
|
|
{ |
1162
|
|
|
$kind = $param->kindOf(); |
1163
|
|
|
|
1164
|
|
|
if ($kind == 'scalar') |
1165
|
|
|
{ |
1166
|
|
|
return $param->scalarval(); |
1167
|
|
|
} elseif ($kind == 'array') |
1168
|
|
|
{ |
1169
|
|
|
reset($param->me); |
1170
|
|
|
list($a, $b) = each($param->me); |
|
|
|
|
1171
|
|
|
|
1172
|
|
|
$arr = array(); |
1173
|
|
|
|
1174
|
|
|
for ($i = 0; $i < count($b); $i++) |
|
|
|
|
1175
|
|
|
{ |
1176
|
|
|
$arr[] = $this->decode_message($param->me['array'][$i]); |
1177
|
|
|
} |
1178
|
|
|
|
1179
|
|
|
return $arr; |
1180
|
|
|
} elseif ($kind == 'struct') |
1181
|
|
|
{ |
1182
|
|
|
reset($param->me['struct']); |
1183
|
|
|
|
1184
|
|
|
$arr = array(); |
1185
|
|
|
|
1186
|
|
|
while (list($key, $value) = each($param->me['struct'])) |
1187
|
|
|
{ |
1188
|
|
|
$arr[$key] = $this->decode_message($value); |
1189
|
|
|
} |
1190
|
|
|
|
1191
|
|
|
return $arr; |
1192
|
|
|
} |
1193
|
|
|
} |
1194
|
|
|
|
1195
|
|
|
} // End XML_RPC_Messages class |
1196
|
|
|
|
1197
|
|
|
|
1198
|
|
|
|
1199
|
|
|
/** |
1200
|
|
|
* XML-RPC Values class |
1201
|
|
|
* |
1202
|
|
|
* @category XML-RPC |
1203
|
|
|
* @author ExpressionEngine Dev Team |
1204
|
|
|
* @link http://codeigniter.com/user_guide/libraries/xmlrpc.html |
1205
|
|
|
*/ |
1206
|
|
|
class XML_RPC_Values extends CI_Xmlrpc |
1207
|
|
|
{ |
1208
|
|
|
var $me = array(); |
1209
|
|
|
var $mytype = 0; |
1210
|
|
|
|
1211
|
|
|
public function __construct($val = -1, $type = '') |
1212
|
|
|
{ |
1213
|
|
|
parent::__construct(); |
1214
|
|
|
|
1215
|
|
|
if ($val != -1 OR $type != '') |
1216
|
|
|
{ |
1217
|
|
|
$type = $type == '' ? 'string' : $type; |
1218
|
|
|
|
1219
|
|
|
if ($this->xmlrpcTypes[$type] == 1) |
1220
|
|
|
{ |
1221
|
|
|
$this->addScalar($val, $type); |
1222
|
|
|
} |
1223
|
|
|
elseif ($this->xmlrpcTypes[$type] == 2) |
1224
|
|
|
{ |
1225
|
|
|
$this->addArray($val); |
1226
|
|
|
} |
1227
|
|
|
elseif ($this->xmlrpcTypes[$type] == 3) |
1228
|
|
|
{ |
1229
|
|
|
$this->addStruct($val); |
1230
|
|
|
} |
1231
|
|
|
} |
1232
|
|
|
} |
1233
|
|
|
|
1234
|
|
|
/** |
1235
|
|
|
* @param integer $val |
1236
|
|
|
*/ |
1237
|
|
|
function addScalar($val, $type='string') |
1238
|
|
|
{ |
1239
|
|
|
$typeof = $this->xmlrpcTypes[$type]; |
1240
|
|
|
|
1241
|
|
|
if ($this->mytype==1) |
1242
|
|
|
{ |
1243
|
|
|
echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />'; |
1244
|
|
|
return 0; |
1245
|
|
|
} |
1246
|
|
|
|
1247
|
|
|
if ($typeof != 1) |
1248
|
|
|
{ |
1249
|
|
|
echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />'; |
1250
|
|
|
return 0; |
1251
|
|
|
} |
1252
|
|
|
|
1253
|
|
|
if ($type == $this->xmlrpcBoolean) |
1254
|
|
|
{ |
1255
|
|
|
if (strcasecmp($val, 'true') == 0 OR $val == 1 OR ($val == true && strcasecmp($val, 'false'))) |
|
|
|
|
1256
|
|
|
{ |
1257
|
|
|
$val = 1; |
1258
|
|
|
} else |
1259
|
|
|
{ |
1260
|
|
|
$val = 0; |
1261
|
|
|
} |
1262
|
|
|
} |
1263
|
|
|
|
1264
|
|
|
if ($this->mytype == 2) |
1265
|
|
|
{ |
1266
|
|
|
// adding to an array here |
1267
|
|
|
$ar = $this->me['array']; |
1268
|
|
|
$ar[] = new XML_RPC_Values($val, $type); |
1269
|
|
|
$this->me['array'] = $ar; |
1270
|
|
|
} else |
1271
|
|
|
{ |
1272
|
|
|
// a scalar, so set the value and remember we're scalar |
1273
|
|
|
$this->me[$type] = $val; |
1274
|
|
|
$this->mytype = $typeof; |
1275
|
|
|
} |
1276
|
|
|
return 1; |
1277
|
|
|
} |
1278
|
|
|
|
1279
|
|
View Code Duplication |
function addArray($vals) |
1280
|
|
|
{ |
1281
|
|
|
if ($this->mytype != 0) |
1282
|
|
|
{ |
1283
|
|
|
echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />'; |
1284
|
|
|
return 0; |
1285
|
|
|
} |
1286
|
|
|
|
1287
|
|
|
$this->mytype = $this->xmlrpcTypes['array']; |
1288
|
|
|
$this->me['array'] = $vals; |
1289
|
|
|
return 1; |
1290
|
|
|
} |
1291
|
|
|
|
1292
|
|
|
/** |
1293
|
|
|
* @param integer $vals |
1294
|
|
|
*/ |
1295
|
|
View Code Duplication |
function addStruct($vals) |
1296
|
|
|
{ |
1297
|
|
|
if ($this->mytype != 0) |
1298
|
|
|
{ |
1299
|
|
|
echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />'; |
1300
|
|
|
return 0; |
1301
|
|
|
} |
1302
|
|
|
$this->mytype = $this->xmlrpcTypes['struct']; |
1303
|
|
|
$this->me['struct'] = $vals; |
1304
|
|
|
return 1; |
1305
|
|
|
} |
1306
|
|
|
|
1307
|
|
|
function kindOf() |
1308
|
|
|
{ |
1309
|
|
|
switch ($this->mytype) |
1310
|
|
|
{ |
1311
|
|
|
case 3: |
1312
|
|
|
return 'struct'; |
1313
|
|
|
break; |
|
|
|
|
1314
|
|
|
case 2: |
1315
|
|
|
return 'array'; |
1316
|
|
|
break; |
|
|
|
|
1317
|
|
|
case 1: |
1318
|
|
|
return 'scalar'; |
1319
|
|
|
break; |
|
|
|
|
1320
|
|
|
default: |
1321
|
|
|
return 'undef'; |
1322
|
|
|
} |
1323
|
|
|
} |
1324
|
|
|
|
1325
|
|
|
function serializedata($typ, $val) |
1326
|
|
|
{ |
1327
|
|
|
$rs = ''; |
1328
|
|
|
|
1329
|
|
|
switch ($this->xmlrpcTypes[$typ]) |
1330
|
|
|
{ |
1331
|
|
|
case 3: |
1332
|
|
|
// struct |
1333
|
|
|
$rs .= "<struct>\n"; |
1334
|
|
|
reset($val); |
1335
|
|
|
while (list($key2, $val2) = each($val)) |
1336
|
|
|
{ |
1337
|
|
|
$rs .= "<member>\n<name>{$key2}</name>\n"; |
1338
|
|
|
$rs .= $this->serializeval($val2); |
1339
|
|
|
$rs .= "</member>\n"; |
1340
|
|
|
} |
1341
|
|
|
$rs .= '</struct>'; |
1342
|
|
|
break; |
1343
|
|
|
case 2: |
1344
|
|
|
// array |
1345
|
|
|
$rs .= "<array>\n<data>\n"; |
1346
|
|
|
for ($i = 0; $i < count($val); $i++) |
|
|
|
|
1347
|
|
|
{ |
1348
|
|
|
$rs .= $this->serializeval($val[$i]); |
1349
|
|
|
} |
1350
|
|
|
$rs .= "</data>\n</array>\n"; |
1351
|
|
|
break; |
1352
|
|
|
case 1: |
1353
|
|
|
// others |
1354
|
|
|
switch ($typ) |
1355
|
|
|
{ |
1356
|
|
|
case $this->xmlrpcBase64: |
1357
|
|
|
$rs .= "<{$typ}>".base64_encode((string)$val)."</{$typ}>\n"; |
1358
|
|
|
break; |
1359
|
|
|
case $this->xmlrpcBoolean: |
1360
|
|
|
$rs .= "<{$typ}>".((bool)$val ? '1' : '0')."</{$typ}>\n"; |
1361
|
|
|
break; |
1362
|
|
|
case $this->xmlrpcString: |
1363
|
|
|
$rs .= "<{$typ}>".htmlspecialchars((string)$val)."</{$typ}>\n"; |
1364
|
|
|
break; |
1365
|
|
|
default: |
1366
|
|
|
$rs .= "<{$typ}>{$val}</{$typ}>\n"; |
1367
|
|
|
break; |
1368
|
|
|
} |
1369
|
|
|
default: |
1370
|
|
|
break; |
1371
|
|
|
} |
1372
|
|
|
return $rs; |
1373
|
|
|
} |
1374
|
|
|
|
1375
|
|
|
function serialize_class() |
1376
|
|
|
{ |
1377
|
|
|
return $this->serializeval($this); |
1378
|
|
|
} |
1379
|
|
|
|
1380
|
|
|
function serializeval($o) |
1381
|
|
|
{ |
1382
|
|
|
$ar = $o->me; |
1383
|
|
|
reset($ar); |
1384
|
|
|
|
1385
|
|
|
list($typ, $val) = each($ar); |
1386
|
|
|
$rs = "<value>\n".$this->serializedata($typ, $val)."</value>\n"; |
1387
|
|
|
return $rs; |
1388
|
|
|
} |
1389
|
|
|
|
1390
|
|
|
function scalarval() |
1391
|
|
|
{ |
1392
|
|
|
reset($this->me); |
1393
|
|
|
list($a, $b) = each($this->me); |
|
|
|
|
1394
|
|
|
return $b; |
1395
|
|
|
} |
1396
|
|
|
|
1397
|
|
|
|
1398
|
|
|
//------------------------------------- |
1399
|
|
|
// Encode time in ISO-8601 form. |
1400
|
|
|
//------------------------------------- |
1401
|
|
|
|
1402
|
|
|
// Useful for sending time in XML-RPC |
1403
|
|
|
|
1404
|
|
|
function iso8601_encode($time, $utc = 0) |
1405
|
|
|
{ |
1406
|
|
|
if ($utc == 1) |
1407
|
|
|
{ |
1408
|
|
|
$t = strftime("%Y%m%dT%H:%i:%s", $time); |
1409
|
|
|
} else |
1410
|
|
|
{ |
1411
|
|
|
if (function_exists('gmstrftime')) { |
1412
|
|
|
$t = gmstrftime("%Y%m%dT%H:%i:%s", $time); |
1413
|
|
|
} else { |
1414
|
|
|
$t = strftime("%Y%m%dT%H:%i:%s", $time - date('Z')); |
1415
|
|
|
} |
1416
|
|
|
} |
1417
|
|
|
return $t; |
1418
|
|
|
} |
1419
|
|
|
|
1420
|
|
|
} |
1421
|
|
|
// END XML_RPC_Values Class |
1422
|
|
|
|
1423
|
|
|
/* End of file Xmlrpc.php */ |
1424
|
|
|
/* Location: ./system/libraries/Xmlrpc.php */ |
This check looks for the bodies of
if
statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.These
if
bodies can be removed. If you have an empty if but statements in theelse
branch, consider inverting the condition.could be turned into
This is much more concise to read.