00001 <?php
00002
00003
00023 function xmlrpc_value($data, $type = FALSE) {
00024 $xmlrpc_value = new stdClass();
00025 $xmlrpc_value->data = $data;
00026 if (!$type) {
00027 $type = xmlrpc_value_calculate_type($xmlrpc_value);
00028 }
00029 $xmlrpc_value->type = $type;
00030 if ($type == 'struct') {
00031
00032 foreach ($xmlrpc_value->data as $key => $value) {
00033 $xmlrpc_value->data[$key] = xmlrpc_value($value);
00034 }
00035 }
00036 if ($type == 'array') {
00037 for ($i = 0, $j = count($xmlrpc_value->data); $i < $j; $i++) {
00038 $xmlrpc_value->data[$i] = xmlrpc_value($xmlrpc_value->data[$i]);
00039 }
00040 }
00041 return $xmlrpc_value;
00042 }
00043
00054 function xmlrpc_value_calculate_type(&$xmlrpc_value) {
00055
00056 if (is_bool($xmlrpc_value->data)) {
00057 return 'boolean';
00058 }
00059 if (is_double($xmlrpc_value->data)) {
00060 return 'double';
00061 }
00062 if (is_int($xmlrpc_value->data)) {
00063 return 'int';
00064 }
00065 if (is_array($xmlrpc_value->data)) {
00066
00067 return empty($xmlrpc_value->data) || range(0, count($xmlrpc_value->data) - 1) === array_keys($xmlrpc_value->data) ? 'array' : 'struct';
00068 }
00069 if (is_object($xmlrpc_value->data)) {
00070 if ($xmlrpc_value->data->is_date) {
00071 return 'date';
00072 }
00073 if ($xmlrpc_value->data->is_base64) {
00074 return 'base64';
00075 }
00076 $xmlrpc_value->data = get_object_vars($xmlrpc_value->data);
00077 return 'struct';
00078 }
00079
00080 return 'string';
00081 }
00082
00090 function xmlrpc_value_get_xml($xmlrpc_value) {
00091 switch ($xmlrpc_value->type) {
00092 case 'boolean':
00093 return '<boolean>' . (($xmlrpc_value->data) ? '1' : '0') . '</boolean>';
00094 break;
00095 case 'int':
00096 return '<int>' . $xmlrpc_value->data . '</int>';
00097 break;
00098 case 'double':
00099 return '<double>' . $xmlrpc_value->data . '</double>';
00100 break;
00101 case 'string':
00102
00103
00104 return '<string>' . htmlspecialchars($xmlrpc_value->data) . '</string>';
00105 break;
00106 case 'array':
00107 $return = '<array><data>' . "\n";
00108 foreach ($xmlrpc_value->data as $item) {
00109 $return .= ' <value>' . xmlrpc_value_get_xml($item) . "</value>\n";
00110 }
00111 $return .= '</data></array>';
00112 return $return;
00113 break;
00114 case 'struct':
00115 $return = '<struct>' . "\n";
00116 foreach ($xmlrpc_value->data as $name => $value) {
00117 $return .= " <member><name>" . check_plain($name) . "</name><value>";
00118 $return .= xmlrpc_value_get_xml($value) . "</value></member>\n";
00119 }
00120 $return .= '</struct>';
00121 return $return;
00122 break;
00123 case 'date':
00124 return xmlrpc_date_get_xml($xmlrpc_value->data);
00125 break;
00126 case 'base64':
00127 return xmlrpc_base64_get_xml($xmlrpc_value->data);
00128 break;
00129 }
00130 return FALSE;
00131 }
00132
00141 function xmlrpc_message($message) {
00142 $xmlrpc_message = new stdClass();
00143 $xmlrpc_message->array_structs = array();
00144 $xmlrpc_message->array_structs_types = array();
00145 $xmlrpc_message->current_struct_name = array();
00146 $xmlrpc_message->message = $message;
00147 return $xmlrpc_message;
00148 }
00149
00159 function xmlrpc_message_parse(&$xmlrpc_message) {
00160
00161 $xmlrpc_message->message = preg_replace('/<\?xml(.*)?\?' . '>/', '', $xmlrpc_message->message);
00162 if (trim($xmlrpc_message->message) == '') {
00163 return FALSE;
00164 }
00165 $xmlrpc_message->_parser = xml_parser_create();
00166
00167 xml_parser_set_option($xmlrpc_message->_parser, XML_OPTION_CASE_FOLDING, FALSE);
00168
00169 xml_set_element_handler($xmlrpc_message->_parser, 'xmlrpc_message_tag_open', 'xmlrpc_message_tag_close');
00170 xml_set_character_data_handler($xmlrpc_message->_parser, 'xmlrpc_message_cdata');
00171 xmlrpc_message_set($xmlrpc_message);
00172 if (!xml_parse($xmlrpc_message->_parser, $xmlrpc_message->message)) {
00173 return FALSE;
00174 }
00175 xml_parser_free($xmlrpc_message->_parser);
00176
00177 $xmlrpc_message = xmlrpc_message_get();
00178 if ($xmlrpc_message->messagetype == 'fault') {
00179 $xmlrpc_message->fault_code = $xmlrpc_message->params[0]['faultCode'];
00180 $xmlrpc_message->fault_string = $xmlrpc_message->params[0]['faultString'];
00181 }
00182 return TRUE;
00183 }
00184
00193 function xmlrpc_message_set($value = NULL) {
00194 static $xmlrpc_message;
00195 if ($value) {
00196 $xmlrpc_message = $value;
00197 }
00198 return $xmlrpc_message;
00199 }
00200
00201 function xmlrpc_message_get() {
00202 return xmlrpc_message_set();
00203 }
00204
00205 function xmlrpc_message_tag_open($parser, $tag, $attr) {
00206 $xmlrpc_message = xmlrpc_message_get();
00207 $xmlrpc_message->current_tag_contents = '';
00208 $xmlrpc_message->last_open = $tag;
00209 switch ($tag) {
00210 case 'methodCall':
00211 case 'methodResponse':
00212 case 'fault':
00213 $xmlrpc_message->messagetype = $tag;
00214 break;
00215
00216 case 'data':
00217 $xmlrpc_message->array_structs_types[] = 'array';
00218 $xmlrpc_message->array_structs[] = array();
00219 break;
00220 case 'struct':
00221 $xmlrpc_message->array_structs_types[] = 'struct';
00222 $xmlrpc_message->array_structs[] = array();
00223 break;
00224 }
00225 xmlrpc_message_set($xmlrpc_message);
00226 }
00227
00228 function xmlrpc_message_cdata($parser, $cdata) {
00229 $xmlrpc_message = xmlrpc_message_get();
00230 $xmlrpc_message->current_tag_contents .= $cdata;
00231 xmlrpc_message_set($xmlrpc_message);
00232 }
00233
00234 function xmlrpc_message_tag_close($parser, $tag) {
00235 $xmlrpc_message = xmlrpc_message_get();
00236 $value_flag = FALSE;
00237 switch ($tag) {
00238 case 'int':
00239 case 'i4':
00240 $value = (int)trim($xmlrpc_message->current_tag_contents);
00241 $value_flag = TRUE;
00242 break;
00243 case 'double':
00244 $value = (double)trim($xmlrpc_message->current_tag_contents);
00245 $value_flag = TRUE;
00246 break;
00247 case 'string':
00248 $value = $xmlrpc_message->current_tag_contents;
00249 $value_flag = TRUE;
00250 break;
00251 case 'dateTime.iso8601':
00252 $value = xmlrpc_date(trim($xmlrpc_message->current_tag_contents));
00253
00254 $value_flag = TRUE;
00255 break;
00256 case 'value':
00257
00258
00259 if (trim($xmlrpc_message->current_tag_contents) != '' || (isset($xmlrpc_message->last_open) && ($xmlrpc_message->last_open == 'value'))) {
00260 $value = (string)$xmlrpc_message->current_tag_contents;
00261 $value_flag = TRUE;
00262 }
00263 unset($xmlrpc_message->last_open);
00264 break;
00265 case 'boolean':
00266 $value = (boolean)trim($xmlrpc_message->current_tag_contents);
00267 $value_flag = TRUE;
00268 break;
00269 case 'base64':
00270 $value = base64_decode(trim($xmlrpc_message->current_tag_contents));
00271 $value_flag = TRUE;
00272 break;
00273
00274 case 'data':
00275 case 'struct':
00276 $value = array_pop($xmlrpc_message->array_structs );
00277 array_pop($xmlrpc_message->array_structs_types);
00278 $value_flag = TRUE;
00279 break;
00280 case 'member':
00281 array_pop($xmlrpc_message->current_struct_name);
00282 break;
00283 case 'name':
00284 $xmlrpc_message->current_struct_name[] = trim($xmlrpc_message->current_tag_contents);
00285 break;
00286 case 'methodName':
00287 $xmlrpc_message->methodname = trim($xmlrpc_message->current_tag_contents);
00288 break;
00289 }
00290 if ($value_flag) {
00291 if (count($xmlrpc_message->array_structs ) > 0) {
00292
00293 if ($xmlrpc_message->array_structs_types[count($xmlrpc_message->array_structs_types)-1] == 'struct') {
00294
00295 $xmlrpc_message->array_structs [count($xmlrpc_message->array_structs )-1][$xmlrpc_message->current_struct_name[count($xmlrpc_message->current_struct_name)-1]] = $value;
00296 }
00297 else {
00298
00299 $xmlrpc_message->array_structs [count($xmlrpc_message->array_structs )-1][] = $value;
00300 }
00301 }
00302 else {
00303
00304 $xmlrpc_message->params[] = $value;
00305 }
00306 }
00307 if (!in_array($tag, array("data", "struct", "member"))) {
00308 $xmlrpc_message->current_tag_contents = '';
00309 }
00310 xmlrpc_message_set($xmlrpc_message);
00311 }
00312
00323 function xmlrpc_request($method, $args) {
00324 $xmlrpc_request = new stdClass();
00325 $xmlrpc_request->method = $method;
00326 $xmlrpc_request->args = $args;
00327 $xmlrpc_request->xml = <<<EOD
00328 <?xml version="1.0"?>
00329 <methodCall>
00330 <methodName>{$xmlrpc_request->method}</methodName>
00331 <params>
00332
00333 EOD;
00334 foreach ($xmlrpc_request->args as $arg) {
00335 $xmlrpc_request->xml .= '<param><value>';
00336 $v = xmlrpc_value($arg);
00337 $xmlrpc_request->xml .= xmlrpc_value_get_xml($v);
00338 $xmlrpc_request->xml .= "</value></param>\n";
00339 }
00340 $xmlrpc_request->xml .= '</params></methodCall>';
00341 return $xmlrpc_request;
00342 }
00343
00344
00345 function xmlrpc_error($code = NULL, $message = NULL) {
00346 static $xmlrpc_error;
00347 if (isset($code)) {
00348 $xmlrpc_error = new stdClass();
00349 $xmlrpc_error->is_error = TRUE;
00350 $xmlrpc_error->code = $code;
00351 $xmlrpc_error->message = $message;
00352 module_invoke('system', 'check_http_request');
00353 }
00354 return $xmlrpc_error;
00355 }
00356
00357 function xmlrpc_error_get_xml($xmlrpc_error) {
00358 return <<<EOD
00359 <methodResponse>
00360 <fault>
00361 <value>
00362 <struct>
00363 <member>
00364 <name>faultCode</name>
00365 <value><int>{$xmlrpc_error->code}</int></value>
00366 </member>
00367 <member>
00368 <name>faultString</name>
00369 <value><string>{$xmlrpc_error->message}</string></value>
00370 </member>
00371 </struct>
00372 </value>
00373 </fault>
00374 </methodResponse>
00375
00376 EOD;
00377 }
00378
00379 function xmlrpc_date($time) {
00380 $xmlrpc_date = new stdClass();
00381 $xmlrpc_date->is_date = TRUE;
00382
00383 if (is_numeric($time)) {
00384 $xmlrpc_date->year = date('Y', $time);
00385 $xmlrpc_date->month = date('m', $time);
00386 $xmlrpc_date->day = date('d', $time);
00387 $xmlrpc_date->hour = date('H', $time);
00388 $xmlrpc_date->minute = date('i', $time);
00389 $xmlrpc_date->second = date('s', $time);
00390 $xmlrpc_date->iso8601 = date('Ymd\TH:i:s', $time);
00391 }
00392 else {
00393 $xmlrpc_date->iso8601 = $time;
00394 $time = str_replace(array('-', ':'), '', $time);
00395 $xmlrpc_date->year = substr($time, 0, 4);
00396 $xmlrpc_date->month = substr($time, 4, 2);
00397 $xmlrpc_date->day = substr($time, 6, 2);
00398 $xmlrpc_date->hour = substr($time, 9, 2);
00399 $xmlrpc_date->minute = substr($time, 11, 2);
00400 $xmlrpc_date->second = substr($time, 13, 2);
00401 }
00402 return $xmlrpc_date;
00403 }
00404
00405 function xmlrpc_date_get_xml($xmlrpc_date) {
00406 return '<dateTime.iso8601>' . $xmlrpc_date->year . $xmlrpc_date->month . $xmlrpc_date->day . 'T' . $xmlrpc_date->hour . ':' . $xmlrpc_date->minute . ':' . $xmlrpc_date->second . '</dateTime.iso8601>';
00407 }
00408
00409 function xmlrpc_base64($data) {
00410 $xmlrpc_base64 = new stdClass();
00411 $xmlrpc_base64->is_base64 = TRUE;
00412 $xmlrpc_base64->data = $data;
00413 return $xmlrpc_base64;
00414 }
00415
00416 function xmlrpc_base64_get_xml($xmlrpc_base64) {
00417 return '<base64>' . base64_encode($xmlrpc_base64->data) . '</base64>';
00418 }
00419
00427 function _xmlrpc() {
00428 $args = func_get_args();
00429 $url = array_shift($args);
00430 if (is_array($args[0])) {
00431 $method = 'system.multicall';
00432 $multicall_args = array();
00433 foreach ($args[0] as $call) {
00434 $multicall_args[] = array('methodName' => array_shift($call), 'params' => $call);
00435 }
00436 $args = array($multicall_args);
00437 }
00438 else {
00439 $method = array_shift($args);
00440 }
00441 $xmlrpc_request = xmlrpc_request($method, $args);
00442 $result = drupal_http_request($url, array("Content-Type" => "text/xml"), 'POST', $xmlrpc_request->xml);
00443 if ($result->code != 200) {
00444 xmlrpc_error($result->code, $result->error);
00445 return FALSE;
00446 }
00447 $message = xmlrpc_message($result->data);
00448
00449 if (!xmlrpc_message_parse($message)) {
00450
00451 xmlrpc_error(-32700, t('Parse error. Not well formed'));
00452 return FALSE;
00453 }
00454
00455 if ($message->messagetype == 'fault') {
00456 xmlrpc_error($message->fault_code, $message->fault_string);
00457 return FALSE;
00458 }
00459
00460 return $message->params[0];
00461 }
00462
00466 function xmlrpc_errno() {
00467 $error = xmlrpc_error();
00468 return ($error != NULL ? $error->code : NULL);
00469 }
00470
00474 function xmlrpc_error_msg() {
00475 $error = xmlrpc_error();
00476 return ($error != NULL ? $error->message : NULL);
00477 }