annotate includes/xmlrpc.inc @ 13:134d4b2e75f6

updated quicktabs and google analytics modules
author danieleb <danielebarchiesi@me.com>
date Tue, 29 Oct 2013 13:48:59 +0000
parents ff03f76ab3fe
children
rev   line source
danielebarchiesi@0 1 <?php
danielebarchiesi@0 2
danielebarchiesi@0 3 /**
danielebarchiesi@0 4 * @file
danielebarchiesi@0 5 * Drupal XML-RPC library.
danielebarchiesi@0 6 *
danielebarchiesi@0 7 * Based on the IXR - The Incutio XML-RPC Library - (c) Incutio Ltd 2002-2005
danielebarchiesi@0 8 * Version 1.7 (beta) - Simon Willison, 23rd May 2005
danielebarchiesi@0 9 * Site: http://scripts.incutio.com/xmlrpc/
danielebarchiesi@0 10 * Manual: http://scripts.incutio.com/xmlrpc/manual.php
danielebarchiesi@0 11 * This version is made available under the GNU GPL License
danielebarchiesi@0 12 */
danielebarchiesi@0 13
danielebarchiesi@0 14 /**
danielebarchiesi@0 15 * Turns a data structure into objects with 'data' and 'type' attributes.
danielebarchiesi@0 16 *
danielebarchiesi@0 17 * @param $data
danielebarchiesi@0 18 * The data structure.
danielebarchiesi@0 19 * @param $type
danielebarchiesi@0 20 * Optional type to assign to $data.
danielebarchiesi@0 21 *
danielebarchiesi@0 22 * @return object
danielebarchiesi@0 23 * An XML-RPC data object containing the input $data.
danielebarchiesi@0 24 */
danielebarchiesi@0 25 function xmlrpc_value($data, $type = FALSE) {
danielebarchiesi@0 26 $xmlrpc_value = new stdClass();
danielebarchiesi@0 27 $xmlrpc_value->data = $data;
danielebarchiesi@0 28 if (!$type) {
danielebarchiesi@0 29 $type = xmlrpc_value_calculate_type($xmlrpc_value);
danielebarchiesi@0 30 }
danielebarchiesi@0 31 $xmlrpc_value->type = $type;
danielebarchiesi@0 32 if ($type == 'struct') {
danielebarchiesi@0 33 // Turn all the values in the array into new xmlrpc_values
danielebarchiesi@0 34 foreach ($xmlrpc_value->data as $key => $value) {
danielebarchiesi@0 35 $xmlrpc_value->data[$key] = xmlrpc_value($value);
danielebarchiesi@0 36 }
danielebarchiesi@0 37 }
danielebarchiesi@0 38 if ($type == 'array') {
danielebarchiesi@0 39 for ($i = 0, $j = count($xmlrpc_value->data); $i < $j; $i++) {
danielebarchiesi@0 40 $xmlrpc_value->data[$i] = xmlrpc_value($xmlrpc_value->data[$i]);
danielebarchiesi@0 41 }
danielebarchiesi@0 42 }
danielebarchiesi@0 43 return $xmlrpc_value;
danielebarchiesi@0 44 }
danielebarchiesi@0 45
danielebarchiesi@0 46 /**
danielebarchiesi@0 47 * Maps a PHP type to an XML-RPC type.
danielebarchiesi@0 48 *
danielebarchiesi@0 49 * @param $xmlrpc_value
danielebarchiesi@0 50 * Variable whose type should be mapped.
danielebarchiesi@0 51 *
danielebarchiesi@0 52 * @return string
danielebarchiesi@0 53 * The corresponding XML-RPC type.
danielebarchiesi@0 54 *
danielebarchiesi@0 55 * @see http://www.xmlrpc.com/spec#scalars
danielebarchiesi@0 56 */
danielebarchiesi@0 57 function xmlrpc_value_calculate_type($xmlrpc_value) {
danielebarchiesi@0 58 // http://www.php.net/gettype: Never use gettype() to test for a certain type
danielebarchiesi@0 59 // [...] Instead, use the is_* functions.
danielebarchiesi@0 60 if (is_bool($xmlrpc_value->data)) {
danielebarchiesi@0 61 return 'boolean';
danielebarchiesi@0 62 }
danielebarchiesi@0 63 if (is_double($xmlrpc_value->data)) {
danielebarchiesi@0 64 return 'double';
danielebarchiesi@0 65 }
danielebarchiesi@0 66 if (is_int($xmlrpc_value->data)) {
danielebarchiesi@0 67 return 'int';
danielebarchiesi@0 68 }
danielebarchiesi@0 69 if (is_array($xmlrpc_value->data)) {
danielebarchiesi@0 70 // empty or integer-indexed arrays are 'array', string-indexed arrays 'struct'
danielebarchiesi@0 71 return empty($xmlrpc_value->data) || range(0, count($xmlrpc_value->data) - 1) === array_keys($xmlrpc_value->data) ? 'array' : 'struct';
danielebarchiesi@0 72 }
danielebarchiesi@0 73 if (is_object($xmlrpc_value->data)) {
danielebarchiesi@0 74 if (isset($xmlrpc_value->data->is_date)) {
danielebarchiesi@0 75 return 'date';
danielebarchiesi@0 76 }
danielebarchiesi@0 77 if (isset($xmlrpc_value->data->is_base64)) {
danielebarchiesi@0 78 return 'base64';
danielebarchiesi@0 79 }
danielebarchiesi@0 80 $xmlrpc_value->data = get_object_vars($xmlrpc_value->data);
danielebarchiesi@0 81 return 'struct';
danielebarchiesi@0 82 }
danielebarchiesi@0 83 // default
danielebarchiesi@0 84 return 'string';
danielebarchiesi@0 85 }
danielebarchiesi@0 86
danielebarchiesi@0 87 /**
danielebarchiesi@0 88 * Generates XML representing the given value.
danielebarchiesi@0 89 *
danielebarchiesi@0 90 * @param $xmlrpc_value
danielebarchiesi@0 91 * A value to be represented in XML.
danielebarchiesi@0 92 *
danielebarchiesi@0 93 * @return
danielebarchiesi@0 94 * XML representation of $xmlrpc_value.
danielebarchiesi@0 95 */
danielebarchiesi@0 96 function xmlrpc_value_get_xml($xmlrpc_value) {
danielebarchiesi@0 97 switch ($xmlrpc_value->type) {
danielebarchiesi@0 98 case 'boolean':
danielebarchiesi@0 99 return '<boolean>' . (($xmlrpc_value->data) ? '1' : '0') . '</boolean>';
danielebarchiesi@0 100
danielebarchiesi@0 101 case 'int':
danielebarchiesi@0 102 return '<int>' . $xmlrpc_value->data . '</int>';
danielebarchiesi@0 103
danielebarchiesi@0 104 case 'double':
danielebarchiesi@0 105 return '<double>' . $xmlrpc_value->data . '</double>';
danielebarchiesi@0 106
danielebarchiesi@0 107 case 'string':
danielebarchiesi@0 108 // Note: we don't escape apostrophes because of the many blogging clients
danielebarchiesi@0 109 // that don't support numerical entities (and XML in general) properly.
danielebarchiesi@0 110 return '<string>' . htmlspecialchars($xmlrpc_value->data) . '</string>';
danielebarchiesi@0 111
danielebarchiesi@0 112 case 'array':
danielebarchiesi@0 113 $return = '<array><data>' . "\n";
danielebarchiesi@0 114 foreach ($xmlrpc_value->data as $item) {
danielebarchiesi@0 115 $return .= ' <value>' . xmlrpc_value_get_xml($item) . "</value>\n";
danielebarchiesi@0 116 }
danielebarchiesi@0 117 $return .= '</data></array>';
danielebarchiesi@0 118 return $return;
danielebarchiesi@0 119
danielebarchiesi@0 120 case 'struct':
danielebarchiesi@0 121 $return = '<struct>' . "\n";
danielebarchiesi@0 122 foreach ($xmlrpc_value->data as $name => $value) {
danielebarchiesi@0 123 $return .= " <member><name>" . check_plain($name) . "</name><value>";
danielebarchiesi@0 124 $return .= xmlrpc_value_get_xml($value) . "</value></member>\n";
danielebarchiesi@0 125 }
danielebarchiesi@0 126 $return .= '</struct>';
danielebarchiesi@0 127 return $return;
danielebarchiesi@0 128
danielebarchiesi@0 129 case 'date':
danielebarchiesi@0 130 return xmlrpc_date_get_xml($xmlrpc_value->data);
danielebarchiesi@0 131
danielebarchiesi@0 132 case 'base64':
danielebarchiesi@0 133 return xmlrpc_base64_get_xml($xmlrpc_value->data);
danielebarchiesi@0 134 }
danielebarchiesi@0 135 return FALSE;
danielebarchiesi@0 136 }
danielebarchiesi@0 137
danielebarchiesi@0 138 /**
danielebarchiesi@0 139 * Constructs an object representing an XML-RPC message.
danielebarchiesi@0 140 *
danielebarchiesi@0 141 * @param $message
danielebarchiesi@0 142 * A string containing an XML message.
danielebarchiesi@0 143 *
danielebarchiesi@0 144 * @return object
danielebarchiesi@0 145 * An XML-RPC object containing the message.
danielebarchiesi@0 146 *
danielebarchiesi@0 147 * @see http://www.xmlrpc.com/spec
danielebarchiesi@0 148 */
danielebarchiesi@0 149 function xmlrpc_message($message) {
danielebarchiesi@0 150 $xmlrpc_message = new stdClass();
danielebarchiesi@0 151 // The stack used to keep track of the current array/struct
danielebarchiesi@0 152 $xmlrpc_message->array_structs = array();
danielebarchiesi@0 153 // The stack used to keep track of if things are structs or array
danielebarchiesi@0 154 $xmlrpc_message->array_structs_types = array();
danielebarchiesi@0 155 // A stack as well
danielebarchiesi@0 156 $xmlrpc_message->current_struct_name = array();
danielebarchiesi@0 157 $xmlrpc_message->message = $message;
danielebarchiesi@0 158 return $xmlrpc_message;
danielebarchiesi@0 159 }
danielebarchiesi@0 160
danielebarchiesi@0 161 /**
danielebarchiesi@0 162 * Parses an XML-RPC message.
danielebarchiesi@0 163 *
danielebarchiesi@0 164 * If parsing fails, the faultCode and faultString will be added to the message
danielebarchiesi@0 165 * object.
danielebarchiesi@0 166 *
danielebarchiesi@0 167 * @param $xmlrpc_message
danielebarchiesi@0 168 * An object generated by xmlrpc_message().
danielebarchiesi@0 169 *
danielebarchiesi@0 170 * @return
danielebarchiesi@0 171 * TRUE if parsing succeeded; FALSE otherwise.
danielebarchiesi@0 172 */
danielebarchiesi@0 173 function xmlrpc_message_parse($xmlrpc_message) {
danielebarchiesi@0 174 $xmlrpc_message->_parser = xml_parser_create();
danielebarchiesi@0 175 // Set XML parser to take the case of tags into account.
danielebarchiesi@0 176 xml_parser_set_option($xmlrpc_message->_parser, XML_OPTION_CASE_FOLDING, FALSE);
danielebarchiesi@0 177 // Set XML parser callback functions
danielebarchiesi@0 178 xml_set_element_handler($xmlrpc_message->_parser, 'xmlrpc_message_tag_open', 'xmlrpc_message_tag_close');
danielebarchiesi@0 179 xml_set_character_data_handler($xmlrpc_message->_parser, 'xmlrpc_message_cdata');
danielebarchiesi@0 180 xmlrpc_message_set($xmlrpc_message);
danielebarchiesi@0 181 if (!xml_parse($xmlrpc_message->_parser, $xmlrpc_message->message)) {
danielebarchiesi@0 182 return FALSE;
danielebarchiesi@0 183 }
danielebarchiesi@0 184 xml_parser_free($xmlrpc_message->_parser);
danielebarchiesi@0 185
danielebarchiesi@0 186 // Grab the error messages, if any.
danielebarchiesi@0 187 $xmlrpc_message = xmlrpc_message_get();
danielebarchiesi@0 188 if (!isset($xmlrpc_message->messagetype)) {
danielebarchiesi@0 189 return FALSE;
danielebarchiesi@0 190 }
danielebarchiesi@0 191 elseif ($xmlrpc_message->messagetype == 'fault') {
danielebarchiesi@0 192 $xmlrpc_message->fault_code = $xmlrpc_message->params[0]['faultCode'];
danielebarchiesi@0 193 $xmlrpc_message->fault_string = $xmlrpc_message->params[0]['faultString'];
danielebarchiesi@0 194 }
danielebarchiesi@0 195 return TRUE;
danielebarchiesi@0 196 }
danielebarchiesi@0 197
danielebarchiesi@0 198 /**
danielebarchiesi@0 199 * Stores a copy of the most recent XML-RPC message object temporarily.
danielebarchiesi@0 200 *
danielebarchiesi@0 201 * @param $value
danielebarchiesi@0 202 * An XML-RPC message to store, or NULL to keep the last message.
danielebarchiesi@0 203 *
danielebarchiesi@0 204 * @return object
danielebarchiesi@0 205 * The most recently stored message.
danielebarchiesi@0 206 *
danielebarchiesi@0 207 * @see xmlrpc_message_get()
danielebarchiesi@0 208 */
danielebarchiesi@0 209 function xmlrpc_message_set($value = NULL) {
danielebarchiesi@0 210 static $xmlrpc_message;
danielebarchiesi@0 211 if ($value) {
danielebarchiesi@0 212 $xmlrpc_message = $value;
danielebarchiesi@0 213 }
danielebarchiesi@0 214 return $xmlrpc_message;
danielebarchiesi@0 215 }
danielebarchiesi@0 216
danielebarchiesi@0 217 /**
danielebarchiesi@0 218 * Returns the most recently stored XML-RPC message object.
danielebarchiesi@0 219 *
danielebarchiesi@0 220 * @return object
danielebarchiesi@0 221 * The most recently stored message.
danielebarchiesi@0 222 *
danielebarchiesi@0 223 * @see xmlrpc_message_set()
danielebarchiesi@0 224 */
danielebarchiesi@0 225 function xmlrpc_message_get() {
danielebarchiesi@0 226 return xmlrpc_message_set();
danielebarchiesi@0 227 }
danielebarchiesi@0 228
danielebarchiesi@0 229 /**
danielebarchiesi@0 230 * Handles opening tags for XML parsing in xmlrpc_message_parse().
danielebarchiesi@0 231 */
danielebarchiesi@0 232 function xmlrpc_message_tag_open($parser, $tag, $attr) {
danielebarchiesi@0 233 $xmlrpc_message = xmlrpc_message_get();
danielebarchiesi@0 234 $xmlrpc_message->current_tag_contents = '';
danielebarchiesi@0 235 $xmlrpc_message->last_open = $tag;
danielebarchiesi@0 236 switch ($tag) {
danielebarchiesi@0 237 case 'methodCall':
danielebarchiesi@0 238 case 'methodResponse':
danielebarchiesi@0 239 case 'fault':
danielebarchiesi@0 240 $xmlrpc_message->messagetype = $tag;
danielebarchiesi@0 241 break;
danielebarchiesi@0 242
danielebarchiesi@0 243 // Deal with stacks of arrays and structs
danielebarchiesi@0 244 case 'data':
danielebarchiesi@0 245 $xmlrpc_message->array_structs_types[] = 'array';
danielebarchiesi@0 246 $xmlrpc_message->array_structs[] = array();
danielebarchiesi@0 247 break;
danielebarchiesi@0 248
danielebarchiesi@0 249 case 'struct':
danielebarchiesi@0 250 $xmlrpc_message->array_structs_types[] = 'struct';
danielebarchiesi@0 251 $xmlrpc_message->array_structs[] = array();
danielebarchiesi@0 252 break;
danielebarchiesi@0 253 }
danielebarchiesi@0 254 xmlrpc_message_set($xmlrpc_message);
danielebarchiesi@0 255 }
danielebarchiesi@0 256
danielebarchiesi@0 257 /**
danielebarchiesi@0 258 * Handles character data for XML parsing in xmlrpc_message_parse().
danielebarchiesi@0 259 */
danielebarchiesi@0 260 function xmlrpc_message_cdata($parser, $cdata) {
danielebarchiesi@0 261 $xmlrpc_message = xmlrpc_message_get();
danielebarchiesi@0 262 $xmlrpc_message->current_tag_contents .= $cdata;
danielebarchiesi@0 263 xmlrpc_message_set($xmlrpc_message);
danielebarchiesi@0 264 }
danielebarchiesi@0 265
danielebarchiesi@0 266 /**
danielebarchiesi@0 267 * Handles closing tags for XML parsing in xmlrpc_message_parse().
danielebarchiesi@0 268 */
danielebarchiesi@0 269 function xmlrpc_message_tag_close($parser, $tag) {
danielebarchiesi@0 270 $xmlrpc_message = xmlrpc_message_get();
danielebarchiesi@0 271 $value_flag = FALSE;
danielebarchiesi@0 272 switch ($tag) {
danielebarchiesi@0 273 case 'int':
danielebarchiesi@0 274 case 'i4':
danielebarchiesi@0 275 $value = (int)trim($xmlrpc_message->current_tag_contents);
danielebarchiesi@0 276 $value_flag = TRUE;
danielebarchiesi@0 277 break;
danielebarchiesi@0 278
danielebarchiesi@0 279 case 'double':
danielebarchiesi@0 280 $value = (double)trim($xmlrpc_message->current_tag_contents);
danielebarchiesi@0 281 $value_flag = TRUE;
danielebarchiesi@0 282 break;
danielebarchiesi@0 283
danielebarchiesi@0 284 case 'string':
danielebarchiesi@0 285 $value = $xmlrpc_message->current_tag_contents;
danielebarchiesi@0 286 $value_flag = TRUE;
danielebarchiesi@0 287 break;
danielebarchiesi@0 288
danielebarchiesi@0 289 case 'dateTime.iso8601':
danielebarchiesi@0 290 $value = xmlrpc_date(trim($xmlrpc_message->current_tag_contents));
danielebarchiesi@0 291 // $value = $iso->getTimestamp();
danielebarchiesi@0 292 $value_flag = TRUE;
danielebarchiesi@0 293 break;
danielebarchiesi@0 294
danielebarchiesi@0 295 case 'value':
danielebarchiesi@0 296 // If no type is indicated, the type is string
danielebarchiesi@0 297 // We take special care for empty values
danielebarchiesi@0 298 if (trim($xmlrpc_message->current_tag_contents) != '' || (isset($xmlrpc_message->last_open) && ($xmlrpc_message->last_open == 'value'))) {
danielebarchiesi@0 299 $value = (string) $xmlrpc_message->current_tag_contents;
danielebarchiesi@0 300 $value_flag = TRUE;
danielebarchiesi@0 301 }
danielebarchiesi@0 302 unset($xmlrpc_message->last_open);
danielebarchiesi@0 303 break;
danielebarchiesi@0 304
danielebarchiesi@0 305 case 'boolean':
danielebarchiesi@0 306 $value = (boolean)trim($xmlrpc_message->current_tag_contents);
danielebarchiesi@0 307 $value_flag = TRUE;
danielebarchiesi@0 308 break;
danielebarchiesi@0 309
danielebarchiesi@0 310 case 'base64':
danielebarchiesi@0 311 $value = base64_decode(trim($xmlrpc_message->current_tag_contents));
danielebarchiesi@0 312 $value_flag = TRUE;
danielebarchiesi@0 313 break;
danielebarchiesi@0 314
danielebarchiesi@0 315 // Deal with stacks of arrays and structs
danielebarchiesi@0 316 case 'data':
danielebarchiesi@0 317 case 'struct':
danielebarchiesi@0 318 $value = array_pop($xmlrpc_message->array_structs);
danielebarchiesi@0 319 array_pop($xmlrpc_message->array_structs_types);
danielebarchiesi@0 320 $value_flag = TRUE;
danielebarchiesi@0 321 break;
danielebarchiesi@0 322
danielebarchiesi@0 323 case 'member':
danielebarchiesi@0 324 array_pop($xmlrpc_message->current_struct_name);
danielebarchiesi@0 325 break;
danielebarchiesi@0 326
danielebarchiesi@0 327 case 'name':
danielebarchiesi@0 328 $xmlrpc_message->current_struct_name[] = trim($xmlrpc_message->current_tag_contents);
danielebarchiesi@0 329 break;
danielebarchiesi@0 330
danielebarchiesi@0 331 case 'methodName':
danielebarchiesi@0 332 $xmlrpc_message->methodname = trim($xmlrpc_message->current_tag_contents);
danielebarchiesi@0 333 break;
danielebarchiesi@0 334 }
danielebarchiesi@0 335 if ($value_flag) {
danielebarchiesi@0 336 if (count($xmlrpc_message->array_structs) > 0) {
danielebarchiesi@0 337 // Add value to struct or array
danielebarchiesi@0 338 if ($xmlrpc_message->array_structs_types[count($xmlrpc_message->array_structs_types) - 1] == 'struct') {
danielebarchiesi@0 339 // Add to struct
danielebarchiesi@0 340 $xmlrpc_message->array_structs[count($xmlrpc_message->array_structs) - 1][$xmlrpc_message->current_struct_name[count($xmlrpc_message->current_struct_name) - 1]] = $value;
danielebarchiesi@0 341 }
danielebarchiesi@0 342 else {
danielebarchiesi@0 343 // Add to array
danielebarchiesi@0 344 $xmlrpc_message->array_structs[count($xmlrpc_message->array_structs) - 1][] = $value;
danielebarchiesi@0 345 }
danielebarchiesi@0 346 }
danielebarchiesi@0 347 else {
danielebarchiesi@0 348 // Just add as a parameter
danielebarchiesi@0 349 $xmlrpc_message->params[] = $value;
danielebarchiesi@0 350 }
danielebarchiesi@0 351 }
danielebarchiesi@0 352 if (!in_array($tag, array("data", "struct", "member"))) {
danielebarchiesi@0 353 $xmlrpc_message->current_tag_contents = '';
danielebarchiesi@0 354 }
danielebarchiesi@0 355 xmlrpc_message_set($xmlrpc_message);
danielebarchiesi@0 356 }
danielebarchiesi@0 357
danielebarchiesi@0 358 /**
danielebarchiesi@0 359 * Constructs an object representing an XML-RPC request.
danielebarchiesi@0 360 *
danielebarchiesi@0 361 * @param $method
danielebarchiesi@0 362 * The name of the method to be called.
danielebarchiesi@0 363 * @param $args
danielebarchiesi@0 364 * An array of parameters to send with the method.
danielebarchiesi@0 365 *
danielebarchiesi@0 366 * @return object
danielebarchiesi@0 367 * An XML-RPC object representing the request.
danielebarchiesi@0 368 */
danielebarchiesi@0 369 function xmlrpc_request($method, $args) {
danielebarchiesi@0 370 $xmlrpc_request = new stdClass();
danielebarchiesi@0 371 $xmlrpc_request->method = $method;
danielebarchiesi@0 372 $xmlrpc_request->args = $args;
danielebarchiesi@0 373 $xmlrpc_request->xml = <<<EOD
danielebarchiesi@0 374 <?xml version="1.0"?>
danielebarchiesi@0 375 <methodCall>
danielebarchiesi@0 376 <methodName>{$xmlrpc_request->method}</methodName>
danielebarchiesi@0 377 <params>
danielebarchiesi@0 378
danielebarchiesi@0 379 EOD;
danielebarchiesi@0 380 foreach ($xmlrpc_request->args as $arg) {
danielebarchiesi@0 381 $xmlrpc_request->xml .= '<param><value>';
danielebarchiesi@0 382 $v = xmlrpc_value($arg);
danielebarchiesi@0 383 $xmlrpc_request->xml .= xmlrpc_value_get_xml($v);
danielebarchiesi@0 384 $xmlrpc_request->xml .= "</value></param>\n";
danielebarchiesi@0 385 }
danielebarchiesi@0 386 $xmlrpc_request->xml .= '</params></methodCall>';
danielebarchiesi@0 387 return $xmlrpc_request;
danielebarchiesi@0 388 }
danielebarchiesi@0 389
danielebarchiesi@0 390 /**
danielebarchiesi@0 391 * Generates, temporarily saves, and returns an XML-RPC error object.
danielebarchiesi@0 392 *
danielebarchiesi@0 393 * @param $code
danielebarchiesi@0 394 * The error code.
danielebarchiesi@0 395 * @param $message
danielebarchiesi@0 396 * The error message.
danielebarchiesi@0 397 * @param $reset
danielebarchiesi@0 398 * TRUE to empty the temporary error storage. Ignored if $code is supplied.
danielebarchiesi@0 399 *
danielebarchiesi@0 400 * @return object
danielebarchiesi@0 401 * An XML-RPC error object representing $code and $message, or the most
danielebarchiesi@0 402 * recently stored error object if omitted.
danielebarchiesi@0 403 */
danielebarchiesi@0 404 function xmlrpc_error($code = NULL, $message = NULL, $reset = FALSE) {
danielebarchiesi@0 405 static $xmlrpc_error;
danielebarchiesi@0 406 if (isset($code)) {
danielebarchiesi@0 407 $xmlrpc_error = new stdClass();
danielebarchiesi@0 408 $xmlrpc_error->is_error = TRUE;
danielebarchiesi@0 409 $xmlrpc_error->code = $code;
danielebarchiesi@0 410 $xmlrpc_error->message = $message;
danielebarchiesi@0 411 }
danielebarchiesi@0 412 elseif ($reset) {
danielebarchiesi@0 413 $xmlrpc_error = NULL;
danielebarchiesi@0 414 }
danielebarchiesi@0 415 return $xmlrpc_error;
danielebarchiesi@0 416 }
danielebarchiesi@0 417
danielebarchiesi@0 418 /**
danielebarchiesi@0 419 * Converts an XML-RPC error object into XML.
danielebarchiesi@0 420 *
danielebarchiesi@0 421 * @param $xmlrpc_error
danielebarchiesi@0 422 * The XML-RPC error object.
danielebarchiesi@0 423 *
danielebarchiesi@0 424 * @return string
danielebarchiesi@0 425 * An XML representation of the error as an XML methodResponse.
danielebarchiesi@0 426 */
danielebarchiesi@0 427 function xmlrpc_error_get_xml($xmlrpc_error) {
danielebarchiesi@0 428 return <<<EOD
danielebarchiesi@0 429 <methodResponse>
danielebarchiesi@0 430 <fault>
danielebarchiesi@0 431 <value>
danielebarchiesi@0 432 <struct>
danielebarchiesi@0 433 <member>
danielebarchiesi@0 434 <name>faultCode</name>
danielebarchiesi@0 435 <value><int>{$xmlrpc_error->code}</int></value>
danielebarchiesi@0 436 </member>
danielebarchiesi@0 437 <member>
danielebarchiesi@0 438 <name>faultString</name>
danielebarchiesi@0 439 <value><string>{$xmlrpc_error->message}</string></value>
danielebarchiesi@0 440 </member>
danielebarchiesi@0 441 </struct>
danielebarchiesi@0 442 </value>
danielebarchiesi@0 443 </fault>
danielebarchiesi@0 444 </methodResponse>
danielebarchiesi@0 445
danielebarchiesi@0 446 EOD;
danielebarchiesi@0 447 }
danielebarchiesi@0 448
danielebarchiesi@0 449 /**
danielebarchiesi@0 450 * Converts a PHP or ISO date/time to an XML-RPC object.
danielebarchiesi@0 451 *
danielebarchiesi@0 452 * @param $time
danielebarchiesi@0 453 * A PHP timestamp or an ISO date-time string.
danielebarchiesi@0 454 *
danielebarchiesi@0 455 * @return object
danielebarchiesi@0 456 * An XML-RPC time/date object.
danielebarchiesi@0 457 */
danielebarchiesi@0 458 function xmlrpc_date($time) {
danielebarchiesi@0 459 $xmlrpc_date = new stdClass();
danielebarchiesi@0 460 $xmlrpc_date->is_date = TRUE;
danielebarchiesi@0 461 // $time can be a PHP timestamp or an ISO one
danielebarchiesi@0 462 if (is_numeric($time)) {
danielebarchiesi@0 463 $xmlrpc_date->year = gmdate('Y', $time);
danielebarchiesi@0 464 $xmlrpc_date->month = gmdate('m', $time);
danielebarchiesi@0 465 $xmlrpc_date->day = gmdate('d', $time);
danielebarchiesi@0 466 $xmlrpc_date->hour = gmdate('H', $time);
danielebarchiesi@0 467 $xmlrpc_date->minute = gmdate('i', $time);
danielebarchiesi@0 468 $xmlrpc_date->second = gmdate('s', $time);
danielebarchiesi@0 469 $xmlrpc_date->iso8601 = gmdate('Ymd\TH:i:s', $time);
danielebarchiesi@0 470 }
danielebarchiesi@0 471 else {
danielebarchiesi@0 472 $xmlrpc_date->iso8601 = $time;
danielebarchiesi@0 473 $time = str_replace(array('-', ':'), '', $time);
danielebarchiesi@0 474 $xmlrpc_date->year = substr($time, 0, 4);
danielebarchiesi@0 475 $xmlrpc_date->month = substr($time, 4, 2);
danielebarchiesi@0 476 $xmlrpc_date->day = substr($time, 6, 2);
danielebarchiesi@0 477 $xmlrpc_date->hour = substr($time, 9, 2);
danielebarchiesi@0 478 $xmlrpc_date->minute = substr($time, 11, 2);
danielebarchiesi@0 479 $xmlrpc_date->second = substr($time, 13, 2);
danielebarchiesi@0 480 }
danielebarchiesi@0 481 return $xmlrpc_date;
danielebarchiesi@0 482 }
danielebarchiesi@0 483
danielebarchiesi@0 484 /**
danielebarchiesi@0 485 * Converts an XML-RPC date-time object into XML.
danielebarchiesi@0 486 *
danielebarchiesi@0 487 * @param $xmlrpc_date
danielebarchiesi@0 488 * The XML-RPC date-time object.
danielebarchiesi@0 489 *
danielebarchiesi@0 490 * @return string
danielebarchiesi@0 491 * An XML representation of the date/time as XML.
danielebarchiesi@0 492 */
danielebarchiesi@0 493 function xmlrpc_date_get_xml($xmlrpc_date) {
danielebarchiesi@0 494 return '<dateTime.iso8601>' . $xmlrpc_date->year . $xmlrpc_date->month . $xmlrpc_date->day . 'T' . $xmlrpc_date->hour . ':' . $xmlrpc_date->minute . ':' . $xmlrpc_date->second . '</dateTime.iso8601>';
danielebarchiesi@0 495 }
danielebarchiesi@0 496
danielebarchiesi@0 497 /**
danielebarchiesi@0 498 * Returns an XML-RPC base 64 object.
danielebarchiesi@0 499 *
danielebarchiesi@0 500 * @param $data
danielebarchiesi@0 501 * Base 64 data to store in returned object.
danielebarchiesi@0 502 *
danielebarchiesi@0 503 * @return object
danielebarchiesi@0 504 * An XML-RPC base 64 object.
danielebarchiesi@0 505 */
danielebarchiesi@0 506 function xmlrpc_base64($data) {
danielebarchiesi@0 507 $xmlrpc_base64 = new stdClass();
danielebarchiesi@0 508 $xmlrpc_base64->is_base64 = TRUE;
danielebarchiesi@0 509 $xmlrpc_base64->data = $data;
danielebarchiesi@0 510 return $xmlrpc_base64;
danielebarchiesi@0 511 }
danielebarchiesi@0 512
danielebarchiesi@0 513 /**
danielebarchiesi@0 514 * Converts an XML-RPC base 64 object into XML.
danielebarchiesi@0 515 *
danielebarchiesi@0 516 * @param $xmlrpc_base64
danielebarchiesi@0 517 * The XML-RPC base 64 object.
danielebarchiesi@0 518 *
danielebarchiesi@0 519 * @return string
danielebarchiesi@0 520 * An XML representation of the base 64 data as XML.
danielebarchiesi@0 521 */
danielebarchiesi@0 522 function xmlrpc_base64_get_xml($xmlrpc_base64) {
danielebarchiesi@0 523 return '<base64>' . base64_encode($xmlrpc_base64->data) . '</base64>';
danielebarchiesi@0 524 }
danielebarchiesi@0 525
danielebarchiesi@0 526 /**
danielebarchiesi@0 527 * Performs one or more XML-RPC requests.
danielebarchiesi@0 528 *
danielebarchiesi@0 529 * @param $url
danielebarchiesi@0 530 * An absolute URL of the XML-RPC endpoint, e.g.,
danielebarchiesi@0 531 * http://example.com/xmlrpc.php
danielebarchiesi@0 532 * @param $args
danielebarchiesi@0 533 * An associative array whose keys are the methods to call and whose values
danielebarchiesi@0 534 * are the arguments to pass to the respective method. If multiple methods
danielebarchiesi@0 535 * are specified, a system.multicall is performed.
danielebarchiesi@0 536 * @param $options
danielebarchiesi@0 537 * (optional) An array of options to pass along to drupal_http_request().
danielebarchiesi@0 538 *
danielebarchiesi@0 539 * @return
danielebarchiesi@0 540 * A single response (single request) or an array of responses (multicall
danielebarchiesi@0 541 * request). Each response is the return value of the method, just as if it
danielebarchiesi@0 542 * has been a local function call, on success, or FALSE on failure. If FALSE
danielebarchiesi@0 543 * is returned, see xmlrpc_errno() and xmlrpc_error_msg() to get more
danielebarchiesi@0 544 * information.
danielebarchiesi@0 545 */
danielebarchiesi@0 546 function _xmlrpc($url, $args, $options = array()) {
danielebarchiesi@0 547 xmlrpc_clear_error();
danielebarchiesi@0 548 if (count($args) > 1) {
danielebarchiesi@0 549 $multicall_args = array();
danielebarchiesi@0 550 foreach ($args as $method => $call) {
danielebarchiesi@0 551 $multicall_args[] = array('methodName' => $method, 'params' => $call);
danielebarchiesi@0 552 }
danielebarchiesi@0 553 $method = 'system.multicall';
danielebarchiesi@0 554 $args = array($multicall_args);
danielebarchiesi@0 555 }
danielebarchiesi@0 556 else {
danielebarchiesi@0 557 $method = key($args);
danielebarchiesi@0 558 $args = $args[$method];
danielebarchiesi@0 559 }
danielebarchiesi@0 560 $xmlrpc_request = xmlrpc_request($method, $args);
danielebarchiesi@0 561 // Required options which will replace any that are passed in.
danielebarchiesi@0 562 $options['method'] = 'POST';
danielebarchiesi@0 563 $options['headers']['Content-Type'] = 'text/xml';
danielebarchiesi@0 564 $options['data'] = $xmlrpc_request->xml;
danielebarchiesi@0 565 $result = drupal_http_request($url, $options);
danielebarchiesi@0 566 if ($result->code != 200) {
danielebarchiesi@0 567 xmlrpc_error($result->code, $result->error);
danielebarchiesi@0 568 return FALSE;
danielebarchiesi@0 569 }
danielebarchiesi@0 570 $message = xmlrpc_message($result->data);
danielebarchiesi@0 571 // Now parse what we've got back
danielebarchiesi@0 572 if (!xmlrpc_message_parse($message)) {
danielebarchiesi@0 573 // XML error
danielebarchiesi@0 574 xmlrpc_error(-32700, t('Parse error. Not well formed'));
danielebarchiesi@0 575 return FALSE;
danielebarchiesi@0 576 }
danielebarchiesi@0 577 // Is the message a fault?
danielebarchiesi@0 578 if ($message->messagetype == 'fault') {
danielebarchiesi@0 579 xmlrpc_error($message->fault_code, $message->fault_string);
danielebarchiesi@0 580 return FALSE;
danielebarchiesi@0 581 }
danielebarchiesi@0 582 // We now know that the message is well-formed and a non-fault result.
danielebarchiesi@0 583 if ($method == 'system.multicall') {
danielebarchiesi@0 584 // Return per-method results or error objects.
danielebarchiesi@0 585 $return = array();
danielebarchiesi@0 586 foreach ($message->params[0] as $result) {
danielebarchiesi@0 587 if (array_keys($result) == array(0)) {
danielebarchiesi@0 588 $return[] = $result[0];
danielebarchiesi@0 589 }
danielebarchiesi@0 590 else {
danielebarchiesi@0 591 $return[] = xmlrpc_error($result['faultCode'], $result['faultString']);
danielebarchiesi@0 592 }
danielebarchiesi@0 593 }
danielebarchiesi@0 594 }
danielebarchiesi@0 595 else {
danielebarchiesi@0 596 $return = $message->params[0];
danielebarchiesi@0 597 }
danielebarchiesi@0 598 return $return;
danielebarchiesi@0 599 }
danielebarchiesi@0 600
danielebarchiesi@0 601 /**
danielebarchiesi@0 602 * Returns the last XML-RPC client error number.
danielebarchiesi@0 603 */
danielebarchiesi@0 604 function xmlrpc_errno() {
danielebarchiesi@0 605 $error = xmlrpc_error();
danielebarchiesi@0 606 return ($error != NULL ? $error->code : NULL);
danielebarchiesi@0 607 }
danielebarchiesi@0 608
danielebarchiesi@0 609 /**
danielebarchiesi@0 610 * Returns the last XML-RPC client error message.
danielebarchiesi@0 611 */
danielebarchiesi@0 612 function xmlrpc_error_msg() {
danielebarchiesi@0 613 $error = xmlrpc_error();
danielebarchiesi@0 614 return ($error != NULL ? $error->message : NULL);
danielebarchiesi@0 615 }
danielebarchiesi@0 616
danielebarchiesi@0 617 /**
danielebarchiesi@0 618 * Clears any previously-saved errors.
danielebarchiesi@0 619 *
danielebarchiesi@0 620 * @see xmlrpc_error()
danielebarchiesi@0 621 */
danielebarchiesi@0 622 function xmlrpc_clear_error() {
danielebarchiesi@0 623 xmlrpc_error(NULL, NULL, TRUE);
danielebarchiesi@0 624 }