| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: xmlrpc.inc,v 1.47.2.6 2010/06/02 12:22:02 goba Exp $ 3 4 /** 5 * @file 6 * Drupal XML-RPC library. Based on the IXR - The Incutio XML-RPC Library - (c) Incutio Ltd 2002-2005 7 * Version 1.7 (beta) - Simon Willison, 23rd May 2005 8 * Site: http://scripts.incutio.com/xmlrpc/ 9 * Manual: http://scripts.incutio.com/xmlrpc/manual.php 10 * This version is made available under the GNU GPL License 11 */ 12 13 /** 14 * Recursively turn a data structure into objects with 'data' and 'type' attributes. 15 * 16 * @param $data 17 * The data structure. 18 * @param $type 19 * Optional type assign to $data. 20 * @return 21 * Object. 22 */ 23 function xmlrpc_value($data, $type = FALSE) { 24 $xmlrpc_value = new stdClass(); 25 $xmlrpc_value->data = $data; 26 if (!$type) { 27 $type = xmlrpc_value_calculate_type($xmlrpc_value); 28 } 29 $xmlrpc_value->type = $type; 30 if ($type == 'struct') { 31 // Turn all the values in the array into new xmlrpc_values 32 foreach ($xmlrpc_value->data as $key => $value) { 33 $xmlrpc_value->data[$key] = xmlrpc_value($value); 34 } 35 } 36 if ($type == 'array') { 37 for ($i = 0, $j = count($xmlrpc_value->data); $i < $j; $i++) { 38 $xmlrpc_value->data[$i] = xmlrpc_value($xmlrpc_value->data[$i]); 39 } 40 } 41 return $xmlrpc_value; 42 } 43 44 /** 45 * Map PHP type to XML-RPC type. 46 * 47 * @param $xmlrpc_value 48 * Variable whose type should be mapped. 49 * @return 50 * XML-RPC type as string. 51 * @see 52 * http://www.xmlrpc.com/spec#scalars 53 */ 54 function xmlrpc_value_calculate_type(&$xmlrpc_value) { 55 // http://www.php.net/gettype: Never use gettype() to test for a certain type [...] Instead, use the is_* functions. 56 if (is_bool($xmlrpc_value->data)) { 57 return 'boolean'; 58 } 59 if (is_double($xmlrpc_value->data)) { 60 return 'double'; 61 } 62 if (is_int($xmlrpc_value->data)) { 63 return 'int'; 64 } 65 if (is_array($xmlrpc_value->data)) { 66 // empty or integer-indexed arrays are 'array', string-indexed arrays 'struct' 67 return empty($xmlrpc_value->data) || range(0, count($xmlrpc_value->data) - 1) === array_keys($xmlrpc_value->data) ? 'array' : 'struct'; 68 } 69 if (is_object($xmlrpc_value->data)) { 70 if ($xmlrpc_value->data->is_date) { 71 return 'date'; 72 } 73 if ($xmlrpc_value->data->is_base64) { 74 return 'base64'; 75 } 76 $xmlrpc_value->data = get_object_vars($xmlrpc_value->data); 77 return 'struct'; 78 } 79 // default 80 return 'string'; 81 } 82 83 /** 84 * Generate XML representing the given value. 85 * 86 * @param $xmlrpc_value 87 * @return 88 * XML representation of value. 89 */ 90 function xmlrpc_value_get_xml($xmlrpc_value) { 91 switch ($xmlrpc_value->type) { 92 case 'boolean': 93 return '<boolean>'. (($xmlrpc_value->data) ? '1' : '0') .'</boolean>'; 94 break; 95 case 'int': 96 return '<int>'. $xmlrpc_value->data .'</int>'; 97 break; 98 case 'double': 99 return '<double>'. $xmlrpc_value->data .'</double>'; 100 break; 101 case 'string': 102 // Note: we don't escape apostrophes because of the many blogging clients 103 // that don't support numerical entities (and XML in general) properly. 104 return '<string>'. htmlspecialchars($xmlrpc_value->data) .'</string>'; 105 break; 106 case 'array': 107 $return = '<array><data>'."\n"; 108 foreach ($xmlrpc_value->data as $item) { 109 $return .= ' <value>'. xmlrpc_value_get_xml($item) ."</value>\n"; 110 } 111 $return .= '</data></array>'; 112 return $return; 113 break; 114 case 'struct': 115 $return = '<struct>'."\n"; 116 foreach ($xmlrpc_value->data as $name => $value) { 117 $return .= " <member><name>". check_plain($name) ."</name><value>"; 118 $return .= xmlrpc_value_get_xml($value) ."</value></member>\n"; 119 } 120 $return .= '</struct>'; 121 return $return; 122 break; 123 case 'date': 124 return xmlrpc_date_get_xml($xmlrpc_value->data); 125 break; 126 case 'base64': 127 return xmlrpc_base64_get_xml($xmlrpc_value->data); 128 break; 129 } 130 return FALSE; 131 } 132 133 /** 134 * Construct an object representing an XML-RPC message. 135 * 136 * @param $message 137 * String containing XML as defined at http://www.xmlrpc.com/spec 138 * @return 139 * Object 140 */ 141 function xmlrpc_message($message) { 142 $xmlrpc_message = new stdClass(); 143 $xmlrpc_message->array_structs = array(); // The stack used to keep track of the current array/struct 144 $xmlrpc_message->array_structs_types = array(); // The stack used to keep track of if things are structs or array 145 $xmlrpc_message->current_struct_name = array(); // A stack as well 146 $xmlrpc_message->message = $message; 147 return $xmlrpc_message; 148 } 149 150 /** 151 * Parse an XML-RPC message. If parsing fails, the faultCode and faultString 152 * will be added to the message object. 153 * 154 * @param $xmlrpc_message 155 * Object generated by xmlrpc_message() 156 * @return 157 * TRUE if parsing succeeded; FALSE otherwise 158 */ 159 function xmlrpc_message_parse(&$xmlrpc_message) { 160 $xmlrpc_message->_parser = xml_parser_create(); 161 // Set XML parser to take the case of tags into account. 162 xml_parser_set_option($xmlrpc_message->_parser, XML_OPTION_CASE_FOLDING, FALSE); 163 // Set XML parser callback functions 164 xml_set_element_handler($xmlrpc_message->_parser, 'xmlrpc_message_tag_open', 'xmlrpc_message_tag_close'); 165 xml_set_character_data_handler($xmlrpc_message->_parser, 'xmlrpc_message_cdata'); 166 xmlrpc_message_set($xmlrpc_message); 167 if (!xml_parse($xmlrpc_message->_parser, $xmlrpc_message->message)) { 168 return FALSE; 169 } 170 xml_parser_free($xmlrpc_message->_parser); 171 // Grab the error messages, if any 172 $xmlrpc_message = xmlrpc_message_get(); 173 if (!isset($xmlrpc_message->messagetype)) { 174 return FALSE; 175 } 176 elseif ($xmlrpc_message->messagetype == 'fault') { 177 $xmlrpc_message->fault_code = $xmlrpc_message->params[0]['faultCode']; 178 $xmlrpc_message->fault_string = $xmlrpc_message->params[0]['faultString']; 179 } 180 return TRUE; 181 } 182 183 /** 184 * Store a copy of the $xmlrpc_message object temporarily. 185 * 186 * @param $value 187 * Object 188 * @return 189 * The most recently stored $xmlrpc_message 190 */ 191 function xmlrpc_message_set($value = NULL) { 192 static $xmlrpc_message; 193 if ($value) { 194 $xmlrpc_message = $value; 195 } 196 return $xmlrpc_message; 197 } 198 199 function xmlrpc_message_get() { 200 return xmlrpc_message_set(); 201 } 202 203 function xmlrpc_message_tag_open($parser, $tag, $attr) { 204 $xmlrpc_message = xmlrpc_message_get(); 205 $xmlrpc_message->current_tag_contents = ''; 206 $xmlrpc_message->last_open = $tag; 207 switch ($tag) { 208 case 'methodCall': 209 case 'methodResponse': 210 case 'fault': 211 $xmlrpc_message->messagetype = $tag; 212 break; 213 // Deal with stacks of arrays and structs 214 case 'data': 215 $xmlrpc_message->array_structs_types[] = 'array'; 216 $xmlrpc_message->array_structs[] = array(); 217 break; 218 case 'struct': 219 $xmlrpc_message->array_structs_types[] = 'struct'; 220 $xmlrpc_message->array_structs[] = array(); 221 break; 222 } 223 xmlrpc_message_set($xmlrpc_message); 224 } 225 226 function xmlrpc_message_cdata($parser, $cdata) { 227 $xmlrpc_message = xmlrpc_message_get(); 228 $xmlrpc_message->current_tag_contents .= $cdata; 229 xmlrpc_message_set($xmlrpc_message); 230 } 231 232 function xmlrpc_message_tag_close($parser, $tag) { 233 $xmlrpc_message = xmlrpc_message_get(); 234 $value_flag = FALSE; 235 switch ($tag) { 236 case 'int': 237 case 'i4': 238 $value = (int)trim($xmlrpc_message->current_tag_contents); 239 $value_flag = TRUE; 240 break; 241 case 'double': 242 $value = (double)trim($xmlrpc_message->current_tag_contents); 243 $value_flag = TRUE; 244 break; 245 case 'string': 246 $value = $xmlrpc_message->current_tag_contents; 247 $value_flag = TRUE; 248 break; 249 case 'dateTime.iso8601': 250 $value = xmlrpc_date(trim($xmlrpc_message->current_tag_contents)); 251 // $value = $iso->getTimestamp(); 252 $value_flag = TRUE; 253 break; 254 case 'value': 255 // If no type is indicated, the type is string 256 // We take special care for empty values 257 if (trim($xmlrpc_message->current_tag_contents) != '' || (isset($xmlrpc_message->last_open) && ($xmlrpc_message->last_open == 'value'))) { 258 $value = (string)$xmlrpc_message->current_tag_contents; 259 $value_flag = TRUE; 260 } 261 unset($xmlrpc_message->last_open); 262 break; 263 case 'boolean': 264 $value = (boolean)trim($xmlrpc_message->current_tag_contents); 265 $value_flag = TRUE; 266 break; 267 case 'base64': 268 $value = base64_decode(trim($xmlrpc_message->current_tag_contents)); 269 $value_flag = TRUE; 270 break; 271 // Deal with stacks of arrays and structs 272 case 'data': 273 case 'struct': 274 $value = array_pop($xmlrpc_message->array_structs ); 275 array_pop($xmlrpc_message->array_structs_types); 276 $value_flag = TRUE; 277 break; 278 case 'member': 279 array_pop($xmlrpc_message->current_struct_name); 280 break; 281 case 'name': 282 $xmlrpc_message->current_struct_name[] = trim($xmlrpc_message->current_tag_contents); 283 break; 284 case 'methodName': 285 $xmlrpc_message->methodname = trim($xmlrpc_message->current_tag_contents); 286 break; 287 } 288 if ($value_flag) { 289 if (count($xmlrpc_message->array_structs ) > 0) { 290 // Add value to struct or array 291 if ($xmlrpc_message->array_structs_types[count($xmlrpc_message->array_structs_types)-1] == 'struct') { 292 // Add to struct 293 $xmlrpc_message->array_structs [count($xmlrpc_message->array_structs )-1][$xmlrpc_message->current_struct_name[count($xmlrpc_message->current_struct_name)-1]] = $value; 294 } 295 else { 296 // Add to array 297 $xmlrpc_message->array_structs [count($xmlrpc_message->array_structs )-1][] = $value; 298 } 299 } 300 else { 301 // Just add as a parameter 302 $xmlrpc_message->params[] = $value; 303 } 304 } 305 if (!in_array($tag, array("data", "struct", "member"))) { 306 $xmlrpc_message->current_tag_contents = ''; 307 } 308 xmlrpc_message_set($xmlrpc_message); 309 } 310 311 /** 312 * Construct an object representing an XML-RPC request 313 * 314 * @param $method 315 * The name of the method to be called 316 * @param $args 317 * An array of parameters to send with the method. 318 * @return 319 * Object 320 */ 321 function xmlrpc_request($method, $args) { 322 $xmlrpc_request = new stdClass(); 323 $xmlrpc_request->method = $method; 324 $xmlrpc_request->args = $args; 325 $xmlrpc_request->xml = <<<EOD 326 <?xml version="1.0"?> 327 <methodCall> 328 <methodName>{$xmlrpc_request->method}</methodName> 329 <params> 330 331 EOD; 332 foreach ($xmlrpc_request->args as $arg) { 333 $xmlrpc_request->xml .= '<param><value>'; 334 $v = xmlrpc_value($arg); 335 $xmlrpc_request->xml .= xmlrpc_value_get_xml($v); 336 $xmlrpc_request->xml .= "</value></param>\n"; 337 } 338 $xmlrpc_request->xml .= '</params></methodCall>'; 339 return $xmlrpc_request; 340 } 341 342 343 function xmlrpc_error($code = NULL, $message = NULL, $reset = FALSE) { 344 static $xmlrpc_error; 345 if (isset($code)) { 346 $xmlrpc_error = new stdClass(); 347 $xmlrpc_error->is_error = TRUE; 348 $xmlrpc_error->code = $code; 349 $xmlrpc_error->message = $message; 350 } 351 elseif ($reset) { 352 $xmlrpc_error = NULL; 353 } 354 return $xmlrpc_error; 355 } 356 357 function xmlrpc_error_get_xml($xmlrpc_error) { 358 return <<<EOD 359 <methodResponse> 360 <fault> 361 <value> 362 <struct> 363 <member> 364 <name>faultCode</name> 365 <value><int>{$xmlrpc_error->code}</int></value> 366 </member> 367 <member> 368 <name>faultString</name> 369 <value><string>{$xmlrpc_error->message}</string></value> 370 </member> 371 </struct> 372 </value> 373 </fault> 374 </methodResponse> 375 376 EOD; 377 } 378 379 function xmlrpc_date($time) { 380 $xmlrpc_date = new stdClass(); 381 $xmlrpc_date->is_date = TRUE; 382 // $time can be a PHP timestamp or an ISO one 383 if (is_numeric($time)) { 384 $xmlrpc_date->year = gmdate('Y', $time); 385 $xmlrpc_date->month = gmdate('m', $time); 386 $xmlrpc_date->day = gmdate('d', $time); 387 $xmlrpc_date->hour = gmdate('H', $time); 388 $xmlrpc_date->minute = gmdate('i', $time); 389 $xmlrpc_date->second = gmdate('s', $time); 390 $xmlrpc_date->iso8601 = gmdate('Ymd\TH:i:s', $time); 391 } 392 else { 393 $xmlrpc_date->iso8601 = $time; 394 $time = str_replace(array('-', ':'), '', $time); 395 $xmlrpc_date->year = substr($time, 0, 4); 396 $xmlrpc_date->month = substr($time, 4, 2); 397 $xmlrpc_date->day = substr($time, 6, 2); 398 $xmlrpc_date->hour = substr($time, 9, 2); 399 $xmlrpc_date->minute = substr($time, 11, 2); 400 $xmlrpc_date->second = substr($time, 13, 2); 401 } 402 return $xmlrpc_date; 403 } 404 405 function xmlrpc_date_get_xml($xmlrpc_date) { 406 return '<dateTime.iso8601>'. $xmlrpc_date->year . $xmlrpc_date->month . $xmlrpc_date->day .'T'. $xmlrpc_date->hour .':'. $xmlrpc_date->minute .':'. $xmlrpc_date->second .'</dateTime.iso8601>'; 407 } 408 409 function xmlrpc_base64($data) { 410 $xmlrpc_base64 = new stdClass(); 411 $xmlrpc_base64->is_base64 = TRUE; 412 $xmlrpc_base64->data = $data; 413 return $xmlrpc_base64; 414 } 415 416 function xmlrpc_base64_get_xml($xmlrpc_base64) { 417 return '<base64>'. base64_encode($xmlrpc_base64->data) .'</base64>'; 418 } 419 420 /** 421 * Execute an XML remote procedural call. This is private function; call xmlrpc() 422 * in common.inc instead of this function. 423 * 424 * @return 425 * A $xmlrpc_message object if the call succeeded; FALSE if the call failed 426 */ 427 function _xmlrpc() { 428 $args = func_get_args(); 429 $url = array_shift($args); 430 xmlrpc_clear_error(); 431 if (is_array($args[0])) { 432 $method = 'system.multicall'; 433 $multicall_args = array(); 434 foreach ($args[0] as $call) { 435 $multicall_args[] = array('methodName' => array_shift($call), 'params' => $call); 436 } 437 $args = array($multicall_args); 438 } 439 else { 440 $method = array_shift($args); 441 } 442 $xmlrpc_request = xmlrpc_request($method, $args); 443 $result = drupal_http_request($url, array("Content-Type" => "text/xml"), 'POST', $xmlrpc_request->xml); 444 if ($result->code != 200) { 445 xmlrpc_error($result->code, $result->error); 446 return FALSE; 447 } 448 $message = xmlrpc_message($result->data); 449 // Now parse what we've got back 450 if (!xmlrpc_message_parse($message)) { 451 // XML error 452 xmlrpc_error(-32700, t('Parse error. Not well formed')); 453 return FALSE; 454 } 455 // Is the message a fault? 456 if ($message->messagetype == 'fault') { 457 xmlrpc_error($message->fault_code, $message->fault_string); 458 return FALSE; 459 } 460 // Message must be OK 461 return $message->params[0]; 462 } 463 464 /** 465 * Returns the last XML-RPC client error number 466 */ 467 function xmlrpc_errno() { 468 $error = xmlrpc_error(); 469 return ($error != NULL ? $error->code : NULL); 470 } 471 472 /** 473 * Returns the last XML-RPC client error message 474 */ 475 function xmlrpc_error_msg() { 476 $error = xmlrpc_error(); 477 return ($error != NULL ? $error->message : NULL); 478 } 479 480 /** 481 * Clears any previous error. 482 */ 483 function xmlrpc_clear_error() { 484 xmlrpc_error(NULL, NULL, TRUE); 485 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |