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