[ Index ] |
|
Code source de Drupal 5.3 |
1 <?php 2 // $Id: xmlrpc.inc,v 1.38.2.1 2007/04/19 02:05:15 drumm Exp $ 3 4 /* 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 // First remove the XML declaration 160 $xmlrpc_message->message = preg_replace('/<\?xml(.*)?\?'.'>/', '', $xmlrpc_message->message); 161 if (trim($xmlrpc_message->message) == '') { 162 return FALSE; 163 } 164 $xmlrpc_message->_parser = xml_parser_create(); 165 // Set XML parser to take the case of tags into account 166 xml_parser_set_option($xmlrpc_message->_parser, XML_OPTION_CASE_FOLDING, FALSE); 167 // Set XML parser callback functions 168 /* Do not set object. $xmlrpc_message does not have member functions any more 169 xml_set_object($xmlrpc_message->_parser, $xmlrpc_message); */ 170 xml_set_element_handler($xmlrpc_message->_parser, 'xmlrpc_message_tag_open', 'xmlrpc_message_tag_close'); 171 xml_set_character_data_handler($xmlrpc_message->_parser, 'xmlrpc_message_cdata'); 172 xmlrpc_message_set($xmlrpc_message); 173 if (!xml_parse($xmlrpc_message->_parser, $xmlrpc_message->message)) { 174 return FALSE; 175 } 176 xml_parser_free($xmlrpc_message->_parser); 177 // Grab the error messages, if any 178 $xmlrpc_message = xmlrpc_message_get(); 179 if ($xmlrpc_message->messagetype == 'fault') { 180 $xmlrpc_message->fault_code = $xmlrpc_message->params[0]['faultCode']; 181 $xmlrpc_message->fault_string = $xmlrpc_message->params[0]['faultString']; 182 } 183 return TRUE; 184 } 185 186 /** 187 * Store a copy of the $xmlrpc_message object temporarily. 188 * 189 * @param $value 190 * Object 191 * @return 192 * The most recently stored $xmlrpc_message 193 */ 194 function xmlrpc_message_set($value = NULL) { 195 static $xmlrpc_message; 196 if ($value) { 197 $xmlrpc_message = $value; 198 } 199 return $xmlrpc_message; 200 } 201 202 function xmlrpc_message_get() { 203 return xmlrpc_message_set(); 204 } 205 206 function xmlrpc_message_tag_open($parser, $tag, $attr) { 207 $xmlrpc_message = xmlrpc_message_get(); 208 $xmlrpc_message->current_tag_contents = ''; 209 $xmlrpc_message->last_open = $tag; 210 switch($tag) { 211 case 'methodCall': 212 case 'methodResponse': 213 case 'fault': 214 $xmlrpc_message->messagetype = $tag; 215 break; 216 // Deal with stacks of arrays and structs 217 case 'data': 218 $xmlrpc_message->array_structs_types[] = 'array'; 219 $xmlrpc_message->array_structs[] = array(); 220 break; 221 case 'struct': 222 $xmlrpc_message->array_structs_types[] = 'struct'; 223 $xmlrpc_message->array_structs[] = array(); 224 break; 225 } 226 xmlrpc_message_set($xmlrpc_message); 227 } 228 229 function xmlrpc_message_cdata($parser, $cdata) { 230 $xmlrpc_message = xmlrpc_message_get(); 231 $xmlrpc_message->current_tag_contents .= $cdata; 232 xmlrpc_message_set($xmlrpc_message); 233 } 234 235 function xmlrpc_message_tag_close($parser, $tag) { 236 $xmlrpc_message = xmlrpc_message_get(); 237 $value_flag = FALSE; 238 switch($tag) { 239 case 'int': 240 case 'i4': 241 $value = (int)trim($xmlrpc_message->current_tag_contents); 242 $value_flag = TRUE; 243 break; 244 case 'double': 245 $value = (double)trim($xmlrpc_message->current_tag_contents); 246 $value_flag = TRUE; 247 break; 248 case 'string': 249 $value = $xmlrpc_message->current_tag_contents; 250 $value_flag = TRUE; 251 break; 252 case 'dateTime.iso8601': 253 $value = xmlrpc_date(trim($xmlrpc_message->current_tag_contents)); 254 // $value = $iso->getTimestamp(); 255 $value_flag = TRUE; 256 break; 257 case 'value': 258 // If no type is indicated, the type is string 259 // We take special care for empty values 260 if (trim($xmlrpc_message->current_tag_contents) != '' || $xmlrpc_message->last_open == 'value') { 261 $value = (string)$xmlrpc_message->current_tag_contents; 262 $value_flag = TRUE; 263 } 264 unset($xmlrpc_message->last_open); 265 break; 266 case 'boolean': 267 $value = (boolean)trim($xmlrpc_message->current_tag_contents); 268 $value_flag = TRUE; 269 break; 270 case 'base64': 271 $value = base64_decode(trim($xmlrpc_message->current_tag_contents)); 272 $value_flag = TRUE; 273 break; 274 // Deal with stacks of arrays and structs 275 case 'data': 276 case 'struct': 277 $value = array_pop($xmlrpc_message->array_structs ); 278 array_pop($xmlrpc_message->array_structs_types); 279 $value_flag = TRUE; 280 break; 281 case 'member': 282 array_pop($xmlrpc_message->current_struct_name); 283 break; 284 case 'name': 285 $xmlrpc_message->current_struct_name[] = trim($xmlrpc_message->current_tag_contents); 286 break; 287 case 'methodName': 288 $xmlrpc_message->methodname = trim($xmlrpc_message->current_tag_contents); 289 break; 290 } 291 if ($value_flag) { 292 if (count($xmlrpc_message->array_structs ) > 0) { 293 // Add value to struct or array 294 if ($xmlrpc_message->array_structs_types[count($xmlrpc_message->array_structs_types)-1] == 'struct') { 295 // Add to struct 296 $xmlrpc_message->array_structs [count($xmlrpc_message->array_structs )-1][$xmlrpc_message->current_struct_name[count($xmlrpc_message->current_struct_name)-1]] = $value; 297 } 298 else { 299 // Add to array 300 $xmlrpc_message->array_structs [count($xmlrpc_message->array_structs )-1][] = $value; 301 } 302 } 303 else { 304 // Just add as a parameter 305 $xmlrpc_message->params[] = $value; 306 } 307 } 308 if (!in_array($tag, array("data", "struct", "member"))) { 309 $xmlrpc_message->current_tag_contents = ''; 310 } 311 xmlrpc_message_set($xmlrpc_message); 312 } 313 314 /** 315 * Construct an object representing an XML-RPC request 316 * 317 * @param $method 318 * The name of the method to be called 319 * @param $args 320 * An array of parameters to send with the method. 321 * @return 322 * Object 323 */ 324 function xmlrpc_request($method, $args) { 325 $xmlrpc_request = new stdClass(); 326 $xmlrpc_request->method = $method; 327 $xmlrpc_request->args = $args; 328 $xmlrpc_request->xml = <<<EOD 329 <?xml version="1.0"?> 330 <methodCall> 331 <methodName>{$xmlrpc_request->method}</methodName> 332 <params> 333 334 EOD; 335 foreach ($xmlrpc_request->args as $arg) { 336 $xmlrpc_request->xml .= '<param><value>'; 337 $v = xmlrpc_value($arg); 338 $xmlrpc_request->xml .= xmlrpc_value_get_xml($v); 339 $xmlrpc_request->xml .= "</value></param>\n"; 340 } 341 $xmlrpc_request->xml .= '</params></methodCall>'; 342 return $xmlrpc_request; 343 } 344 345 346 function xmlrpc_error($code = NULL, $message = NULL) { 347 static $xmlrpc_error; 348 if (isset($code)) { 349 $xmlrpc_error = new stdClass(); 350 $xmlrpc_error->is_error = TRUE; 351 $xmlrpc_error->code = $code; 352 $xmlrpc_error->message = $message; 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 = date('Y', $time); 385 $xmlrpc_date->month = date('m', $time); 386 $xmlrpc_date->day = date('d', $time); 387 $xmlrpc_date->hour = date('H', $time); 388 $xmlrpc_date->minute = date('i', $time); 389 $xmlrpc_date->second = date('s', $time); 390 $xmlrpc_date->iso8601 = date('Ymd\TH:i:s'); 391 } 392 else { 393 $xmlrpc_date->year = substr($time, 0, 4); 394 $xmlrpc_date->month = substr($time, 4, 2); 395 $xmlrpc_date->day = substr($time, 6, 2); 396 $xmlrpc_date->hour = substr($time, 9, 2); 397 $xmlrpc_date->minute = substr($time, 12, 2); 398 $xmlrpc_date->second = substr($time, 15, 2); 399 $xmlrpc_date->iso8601 = $time; 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 if (is_array($args[0])) { 430 $method = 'system.multicall'; 431 $multicall_args = array(); 432 foreach ($args[0] as $call) { 433 $multicall_args[] = array('methodName' => array_shift($call),'params' => $call); 434 } 435 $args = array($multicall_args); 436 } 437 else { 438 $method = array_shift($args); 439 } 440 $xmlrpc_request = xmlrpc_request($method, $args); 441 $result = drupal_http_request($url, array("Content-Type" => "text/xml"), 'POST', $xmlrpc_request->xml); 442 if ($result->code != 200) { 443 xmlrpc_error($result->code, $result->error); 444 return FALSE; 445 } 446 $message = xmlrpc_message($result->data); 447 // Now parse what we've got back 448 if (!xmlrpc_message_parse($message)) { 449 // XML error 450 xmlrpc_error(-32700, t('Parse error. Not well formed')); 451 return FALSE; 452 } 453 // Is the message a fault? 454 if ($message->messagetype == 'fault') { 455 xmlrpc_error($message->fault_code, $message->fault_string); 456 return FALSE; 457 } 458 // Message must be OK 459 return $message->params[0]; 460 } 461 462 /** 463 * Returns the last XML-RPC client error number 464 */ 465 function xmlrpc_errno() { 466 $error = xmlrpc_error(); 467 return $error->code; 468 } 469 470 /** 471 * Returns the last XML-RPC client error message 472 */ 473 function xmlrpc_error_msg() { 474 $error = xmlrpc_error(); 475 return $error->message; 476 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Fri Nov 30 16:20:15 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |