[2] | 1 | <?php |
---|
| 2 | // by Edd Dumbill (C) 1999-2001 |
---|
| 3 | // <edd@usefulinc.com> |
---|
| 4 | // xmlrpc.inc,v 1.18 2001/07/06 18:23:57 edmundd |
---|
| 5 | |
---|
| 6 | // License is granted to use or modify this software ("XML-RPC for PHP") |
---|
| 7 | // for commercial or non-commercial use provided the copyright of the author |
---|
| 8 | // is preserved in any distributed or derivative work. |
---|
| 9 | |
---|
| 10 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR |
---|
| 11 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
---|
| 12 | // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
---|
| 13 | // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
---|
| 14 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
---|
| 15 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
---|
| 16 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
---|
| 17 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
---|
| 18 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
---|
| 19 | // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
| 20 | |
---|
| 21 | |
---|
| 22 | if (!function_exists('xml_parser_create')) |
---|
| 23 | { |
---|
| 24 | // Win 32 fix. From: "Leo West" <lwest@imaginet.fr> |
---|
| 25 | if($WINDIR) |
---|
| 26 | { |
---|
| 27 | dl('php3_xml.dll'); |
---|
| 28 | } |
---|
| 29 | else |
---|
| 30 | { |
---|
| 31 | dl('xml.so'); |
---|
| 32 | } |
---|
| 33 | } |
---|
| 34 | |
---|
| 35 | define('xmlrpcI4','i4'); |
---|
| 36 | define('xmlrpcInt','int'); |
---|
| 37 | define('xmlrpcBoolean','boolean'); |
---|
| 38 | define('xmlrpcDouble','double'); |
---|
| 39 | define('xmlrpcString','string'); |
---|
| 40 | define('xmlrpcDateTime','dateTime.iso8601'); |
---|
| 41 | define('xmlrpcBase64','base64'); |
---|
| 42 | define('xmlrpcArray','array'); |
---|
| 43 | define('xmlrpcStruct','struct'); |
---|
| 44 | |
---|
| 45 | $GLOBALS['xmlrpcTypes'] = array( |
---|
| 46 | xmlrpcI4 => 1, |
---|
| 47 | xmlrpcInt => 1, |
---|
| 48 | xmlrpcBoolean => 1, |
---|
| 49 | xmlrpcString => 1, |
---|
| 50 | xmlrpcDouble => 1, |
---|
| 51 | xmlrpcDateTime => 1, |
---|
| 52 | xmlrpcBase64 => 1, |
---|
| 53 | xmlrpcArray => 2, |
---|
| 54 | xmlrpcStruct => 3 |
---|
| 55 | ); |
---|
| 56 | |
---|
| 57 | $GLOBALS['xmlEntities']=array( |
---|
| 58 | 'amp' => '&', |
---|
| 59 | 'quot' => '"', |
---|
| 60 | 'lt' => '<', |
---|
| 61 | 'gt' => '>', |
---|
| 62 | 'apos' => "'" |
---|
| 63 | ); |
---|
| 64 | |
---|
| 65 | $GLOBALS['xmlrpcerr']['unknown_method'] = 1; |
---|
| 66 | $GLOBALS['xmlrpcstr']['unknown_method'] = 'Unknown method'; |
---|
| 67 | $GLOBALS['xmlrpcerr']['invalid_return'] = 2; |
---|
| 68 | $GLOBALS['xmlrpcstr']['invalid_return'] = 'Invalid return payload: enabling debugging to examine incoming payload'; |
---|
| 69 | $GLOBALS['xmlrpcerr']['incorrect_params'] = 3; |
---|
| 70 | $GLOBALS['xmlrpcstr']['incorrect_params'] = 'Incorrect parameters passed to method'; |
---|
| 71 | $GLOBALS['xmlrpcerr']['introspect_unknown'] = 4; |
---|
| 72 | $GLOBALS['xmlrpcstr']['introspect_unknown'] = "Can't introspect: method unknown"; |
---|
| 73 | $GLOBALS['xmlrpcerr']['http_error'] = 5; |
---|
| 74 | $GLOBALS['xmlrpcstr']['http_error'] = "Didn't receive 200 OK from remote server."; |
---|
| 75 | $GLOBALS['xmlrpcerr']['no_data'] = 6; |
---|
| 76 | $GLOBALS['xmlrpcstr']['no_data'] = 'No data received from server.'; |
---|
| 77 | $GLOBALS['xmlrpcerr']['no_ssl'] = 7; |
---|
| 78 | $GLOBALS['xmlrpcstr']['no_ssl'] = 'No SSL support compiled in.'; |
---|
| 79 | $GLOBALS['xmlrpcerr']['curl_fail'] = 8; |
---|
| 80 | $GLOBALS['xmlrpcstr']['curl_fail'] = 'CURL error'; |
---|
| 81 | $GLOBALS['xmlrpcerr']['no_access'] = 9; |
---|
| 82 | $GLOBALS['xmlrpcstr']['no_access'] = 'Access denied'; |
---|
| 83 | $GLOBALS['xmlrpcerr']['not_existent'] = 10; |
---|
| 84 | $GLOBALS['xmlrpcstr']['not_existent'] = 'Entry does not (longer) exist!'; |
---|
| 85 | |
---|
| 86 | $GLOBALS['xmlrpc_defencoding'] = 'UTF-8'; |
---|
| 87 | |
---|
| 88 | $GLOBALS['xmlrpcName'] = 'XML-RPC for PHP'; |
---|
| 89 | $GLOBALS['xmlrpcVersion'] = '1.0b9'; |
---|
| 90 | |
---|
| 91 | // let user errors start at 800 |
---|
| 92 | $GLOBALS['xmlrpcerruser'] = 800; |
---|
| 93 | // let XML parse errors start at 100 |
---|
| 94 | $GLOBALS['xmlrpcerrxml'] = 100; |
---|
| 95 | |
---|
| 96 | // formulate backslashes for escaping regexp |
---|
| 97 | $GLOBALS['xmlrpc_backslash'] = chr(92) . chr(92); |
---|
| 98 | |
---|
| 99 | /*! |
---|
| 100 | @function xmlrpcfault |
---|
| 101 | @abstract Error reporting for XML-RPC |
---|
| 102 | @discussion Author: jengo <br> |
---|
| 103 | Returns XML-RPC fault and stops this execution of the application. <br> |
---|
| 104 | Syntax: void xmlrpcfault(string) <br> |
---|
| 105 | Example1: xmlrpcfault('Session could not be verifed'); <br> |
---|
| 106 | @param $string Error message to be returned. |
---|
| 107 | */ |
---|
| 108 | function xmlrpcfault($string) |
---|
| 109 | { |
---|
| 110 | $r = CreateObject('phpgwapi.xmlrpcresp', |
---|
| 111 | CreateObject('phpgwapi.xmlrpcval'), |
---|
| 112 | $GLOBALS['xmlrpcerr']['unknown_method'], |
---|
| 113 | $string |
---|
| 114 | ); |
---|
| 115 | $payload = '<?xml version="1.0"?>' . "\n" . $r->serialize(); |
---|
| 116 | Header('Content-type: text/xml'); |
---|
| 117 | Header('Content-length: ' . strlen($payload)); |
---|
| 118 | print $payload; |
---|
| 119 | $GLOBALS['phpgw']->common->phpgw_exit(False); |
---|
| 120 | } |
---|
| 121 | |
---|
| 122 | // used to store state during parsing |
---|
| 123 | // quick explanation of components: |
---|
| 124 | // st - used to build up a string for evaluation |
---|
| 125 | // ac - used to accumulate values |
---|
| 126 | // qt - used to decide if quotes are needed for evaluation |
---|
| 127 | // cm - used to denote struct or array (comma needed) |
---|
| 128 | // isf - used to indicate a fault |
---|
| 129 | // lv - used to indicate "looking for a value": implements |
---|
| 130 | // the logic to allow values with no types to be strings |
---|
| 131 | // params - used to store parameters in method calls |
---|
| 132 | // method - used to store method name |
---|
| 133 | |
---|
| 134 | $GLOBALS['_xh']=array(); |
---|
| 135 | |
---|
| 136 | function xmlrpc_entity_decode($string) |
---|
| 137 | { |
---|
| 138 | $top = split('&', $string); |
---|
| 139 | $op = ''; |
---|
| 140 | $i = 0; |
---|
| 141 | while($i<sizeof($top)) |
---|
| 142 | { |
---|
| 143 | if (ereg("^([#a-zA-Z0-9]+);", $top[$i], $regs)) |
---|
| 144 | { |
---|
| 145 | $op .= ereg_replace("^[#a-zA-Z0-9]+;", |
---|
| 146 | xmlrpc_lookup_entity($regs[1]), $top[$i]); |
---|
| 147 | } |
---|
| 148 | else |
---|
| 149 | { |
---|
| 150 | if ($i == 0) |
---|
| 151 | { |
---|
| 152 | $op = $top[$i]; |
---|
| 153 | } |
---|
| 154 | else |
---|
| 155 | { |
---|
| 156 | $op .= '&' . $top[$i]; |
---|
| 157 | } |
---|
| 158 | } |
---|
| 159 | $i++; |
---|
| 160 | } |
---|
| 161 | return $op; |
---|
| 162 | } |
---|
| 163 | |
---|
| 164 | function xmlrpc_lookup_entity($ent) |
---|
| 165 | { |
---|
| 166 | if (isset($GLOBALS['xmlEntities'][strtolower($ent)])) |
---|
| 167 | { |
---|
| 168 | return $GLOBALS['xmlEntities'][strtolower($ent)]; |
---|
| 169 | } |
---|
| 170 | if (ereg("^#([0-9]+)$", $ent, $regs)) |
---|
| 171 | { |
---|
| 172 | return chr($regs[1]); |
---|
| 173 | } |
---|
| 174 | return '?'; |
---|
| 175 | } |
---|
| 176 | |
---|
| 177 | function xmlrpc_se($parser, $name, $attrs) |
---|
| 178 | { |
---|
| 179 | switch($name) |
---|
| 180 | { |
---|
| 181 | case 'STRUCT': |
---|
| 182 | case 'ARRAY': |
---|
| 183 | $GLOBALS['_xh'][$parser]['st'] .= 'array('; |
---|
| 184 | $GLOBALS['_xh'][$parser]['cm']++; |
---|
| 185 | // this last line turns quoting off |
---|
| 186 | // this means if we get an empty array we'll |
---|
| 187 | // simply get a bit of whitespace in the eval |
---|
| 188 | $GLOBALS['_xh'][$parser]['qt']=0; |
---|
| 189 | break; |
---|
| 190 | case 'NAME': |
---|
| 191 | $GLOBALS['_xh'][$parser]['st'] .= "'"; |
---|
| 192 | $GLOBALS['_xh'][$parser]['ac'] = ''; |
---|
| 193 | break; |
---|
| 194 | case 'FAULT': |
---|
| 195 | $GLOBALS['_xh'][$parser]['isf'] = 1; |
---|
| 196 | break; |
---|
| 197 | case 'PARAM': |
---|
| 198 | $GLOBALS['_xh'][$parser]['st'] = ''; |
---|
| 199 | break; |
---|
| 200 | case 'VALUE': |
---|
| 201 | $GLOBALS['_xh'][$parser]['st'] .= " CreateObject('phpgwapi.xmlrpcval',"; |
---|
| 202 | $GLOBALS['_xh'][$parser]['vt'] = xmlrpcString; |
---|
| 203 | $GLOBALS['_xh'][$parser]['ac'] = ''; |
---|
| 204 | $GLOBALS['_xh'][$parser]['qt'] = 0; |
---|
| 205 | $GLOBALS['_xh'][$parser]['lv'] = 1; |
---|
| 206 | // look for a value: if this is still 1 by the |
---|
| 207 | // time we reach the first data segment then the type is string |
---|
| 208 | // by implication and we need to add in a quote |
---|
| 209 | break; |
---|
| 210 | case 'I4': |
---|
| 211 | case 'INT': |
---|
| 212 | case 'STRING': |
---|
| 213 | case 'BOOLEAN': |
---|
| 214 | case 'DOUBLE': |
---|
| 215 | case 'DATETIME.ISO8601': |
---|
| 216 | case 'BASE64': |
---|
| 217 | $GLOBALS['_xh'][$parser]['ac']=''; // reset the accumulator |
---|
| 218 | |
---|
| 219 | if ($name=='DATETIME.ISO8601' || $name=='STRING') |
---|
| 220 | { |
---|
| 221 | $GLOBALS['_xh'][$parser]['qt']=1; |
---|
| 222 | if ($name=='DATETIME.ISO8601') |
---|
| 223 | { |
---|
| 224 | $GLOBALS['_xh'][$parser]['vt']=xmlrpcDateTime; |
---|
| 225 | } |
---|
| 226 | } |
---|
| 227 | elseif($name=='BASE64') |
---|
| 228 | { |
---|
| 229 | $GLOBALS['_xh'][$parser]['qt']=2; |
---|
| 230 | } |
---|
| 231 | else |
---|
| 232 | { |
---|
| 233 | // No quoting is required here -- but |
---|
| 234 | // at the end of the element we must check |
---|
| 235 | // for data format errors. |
---|
| 236 | $GLOBALS['_xh'][$parser]['qt']=0; |
---|
| 237 | } |
---|
| 238 | break; |
---|
| 239 | case 'MEMBER': |
---|
| 240 | $GLOBALS['_xh'][$parser]['ac']=''; |
---|
| 241 | break; |
---|
| 242 | default: |
---|
| 243 | break; |
---|
| 244 | } |
---|
| 245 | |
---|
| 246 | if ($name!='VALUE') |
---|
| 247 | { |
---|
| 248 | $GLOBALS['_xh'][$parser]['lv']=0; |
---|
| 249 | } |
---|
| 250 | } |
---|
| 251 | |
---|
| 252 | function xmlrpc_ee($parser, $name) |
---|
| 253 | { |
---|
| 254 | switch($name) |
---|
| 255 | { |
---|
| 256 | case 'STRUCT': |
---|
| 257 | case 'ARRAY': |
---|
| 258 | if ($GLOBALS['_xh'][$parser]['cm'] && substr($GLOBALS['_xh'][$parser]['st'], -1) ==',') |
---|
| 259 | { |
---|
| 260 | $GLOBALS['_xh'][$parser]['st']=substr($GLOBALS['_xh'][$parser]['st'],0,-1); |
---|
| 261 | } |
---|
| 262 | $GLOBALS['_xh'][$parser]['st'].=')'; |
---|
| 263 | $GLOBALS['_xh'][$parser]['vt']=strtolower($name); |
---|
| 264 | $GLOBALS['_xh'][$parser]['cm']--; |
---|
| 265 | break; |
---|
| 266 | case 'NAME': |
---|
| 267 | $GLOBALS['_xh'][$parser]['st'].= $GLOBALS['_xh'][$parser]['ac'] . "' => "; |
---|
| 268 | break; |
---|
| 269 | case 'BOOLEAN': |
---|
| 270 | // special case here: we translate boolean 1 or 0 into PHP |
---|
| 271 | // constants true or false |
---|
| 272 | if ($GLOBALS['_xh'][$parser]['ac']=='1') |
---|
| 273 | { |
---|
| 274 | $GLOBALS['_xh'][$parser]['ac']='True'; |
---|
| 275 | } |
---|
| 276 | else |
---|
| 277 | { |
---|
| 278 | $GLOBALS['_xh'][$parser]['ac']='false'; |
---|
| 279 | } |
---|
| 280 | $GLOBALS['_xh'][$parser]['vt']=strtolower($name); |
---|
| 281 | // Drop through intentionally. |
---|
| 282 | case 'I4': |
---|
| 283 | case 'INT': |
---|
| 284 | case 'STRING': |
---|
| 285 | case 'DOUBLE': |
---|
| 286 | case 'DATETIME.ISO8601': |
---|
| 287 | case 'BASE64': |
---|
| 288 | if ($GLOBALS['_xh'][$parser]['qt']==1) |
---|
| 289 | { |
---|
| 290 | // we use double quotes rather than single so backslashification works OK |
---|
| 291 | $GLOBALS['_xh'][$parser]['st'].='"'. $GLOBALS['_xh'][$parser]['ac'] . '"'; |
---|
| 292 | } |
---|
| 293 | elseif ($GLOBALS['_xh'][$parser]['qt']==2) |
---|
| 294 | { |
---|
| 295 | $GLOBALS['_xh'][$parser]['st'].="base64_decode('". $GLOBALS['_xh'][$parser]['ac'] . "')"; |
---|
| 296 | } |
---|
| 297 | elseif ($name=='BOOLEAN') |
---|
| 298 | { |
---|
| 299 | $GLOBALS['_xh'][$parser]['st'].=$GLOBALS['_xh'][$parser]['ac']; |
---|
| 300 | } |
---|
| 301 | else |
---|
| 302 | { |
---|
| 303 | // we have an I4, INT or a DOUBLE |
---|
| 304 | // we must check that only 0123456789-.<space> are characters here |
---|
| 305 | if (!ereg("^\-?[0123456789 \t\.]+$", $GLOBALS['_xh'][$parser]['ac'])) |
---|
| 306 | { |
---|
| 307 | // TODO: find a better way of throwing an error |
---|
| 308 | // than this! |
---|
| 309 | error_log('XML-RPC: non numeric value received in INT or DOUBLE'); |
---|
| 310 | $GLOBALS['_xh'][$parser]['st'].='ERROR_NON_NUMERIC_FOUND'; |
---|
| 311 | } |
---|
| 312 | else |
---|
| 313 | { |
---|
| 314 | // it's ok, add it on |
---|
| 315 | $GLOBALS['_xh'][$parser]['st'].=$GLOBALS['_xh'][$parser]['ac']; |
---|
| 316 | } |
---|
| 317 | } |
---|
| 318 | $GLOBALS['_xh'][$parser]['ac']=""; $GLOBALS['_xh'][$parser]['qt']=0; |
---|
| 319 | $GLOBALS['_xh'][$parser]['lv']=3; // indicate we've found a value |
---|
| 320 | break; |
---|
| 321 | case 'VALUE': |
---|
| 322 | // deal with a string value |
---|
| 323 | if (strlen($GLOBALS['_xh'][$parser]['ac'])>0 && |
---|
| 324 | $GLOBALS['_xh'][$parser]['vt']==xmlrpcString) |
---|
| 325 | { |
---|
| 326 | $GLOBALS['_xh'][$parser]['st'].='"'. $GLOBALS['_xh'][$parser]['ac'] . '"'; |
---|
| 327 | } |
---|
| 328 | // This if() detects if no scalar was inside <VALUE></VALUE> |
---|
| 329 | // and pads an empty "". |
---|
| 330 | if($GLOBALS['_xh'][$parser]['st'][strlen($GLOBALS['_xh'][$parser]['st'])-1] == '(') |
---|
| 331 | { |
---|
| 332 | $GLOBALS['_xh'][$parser]['st'].= '""'; |
---|
| 333 | } |
---|
| 334 | $GLOBALS['_xh'][$parser]['st'].=", '" . $GLOBALS['_xh'][$parser]['vt'] . "')"; |
---|
| 335 | if ($GLOBALS['_xh'][$parser]['cm']) |
---|
| 336 | { |
---|
| 337 | $GLOBALS['_xh'][$parser]['st'].=","; |
---|
| 338 | } |
---|
| 339 | break; |
---|
| 340 | case 'MEMBER': |
---|
| 341 | $GLOBALS['_xh'][$parser]['ac']=""; |
---|
| 342 | $GLOBALS['_xh'][$parser]['qt']=0; |
---|
| 343 | break; |
---|
| 344 | case 'DATA': |
---|
| 345 | $GLOBALS['_xh'][$parser]['ac']=""; |
---|
| 346 | $GLOBALS['_xh'][$parser]['qt']=0; |
---|
| 347 | break; |
---|
| 348 | case 'PARAM': |
---|
| 349 | $GLOBALS['_xh'][$parser]['params'][]=$GLOBALS['_xh'][$parser]['st']; |
---|
| 350 | break; |
---|
| 351 | case 'METHODNAME': |
---|
| 352 | $GLOBALS['_xh'][$parser]['method']=ereg_replace("^[\n\r\t ]+", "", $GLOBALS['_xh'][$parser]['ac']); |
---|
| 353 | break; |
---|
| 354 | case 'BOOLEAN': |
---|
| 355 | // special case here: we translate boolean 1 or 0 into PHP |
---|
| 356 | // constants true or false |
---|
| 357 | if ($GLOBALS['_xh'][$parser]['ac']=='1') |
---|
| 358 | { |
---|
| 359 | $GLOBALS['_xh'][$parser]['ac']='True'; |
---|
| 360 | } |
---|
| 361 | else |
---|
| 362 | { |
---|
| 363 | $GLOBALS['_xh'][$parser]['ac']='false'; |
---|
| 364 | } |
---|
| 365 | $GLOBALS['_xh'][$parser]['vt']=strtolower($name); |
---|
| 366 | break; |
---|
| 367 | default: |
---|
| 368 | break; |
---|
| 369 | } |
---|
| 370 | // if it's a valid type name, set the type |
---|
| 371 | if (isset($GLOBALS['xmlrpcTypes'][strtolower($name)])) |
---|
| 372 | { |
---|
| 373 | $GLOBALS['_xh'][$parser]['vt']=strtolower($name); |
---|
| 374 | } |
---|
| 375 | } |
---|
| 376 | |
---|
| 377 | function xmlrpc_cd($parser, $data) |
---|
| 378 | { |
---|
| 379 | //if (ereg("^[\n\r \t]+$", $data)) return; |
---|
| 380 | // print "adding [${data}]\n"; |
---|
| 381 | |
---|
| 382 | if ($GLOBALS['_xh'][$parser]['lv']!=3) |
---|
| 383 | { |
---|
| 384 | // "lookforvalue==3" means that we've found an entire value |
---|
| 385 | // and should discard any further character data |
---|
| 386 | if ($GLOBALS['_xh'][$parser]['lv']==1) |
---|
| 387 | { |
---|
| 388 | // if we've found text and we're just in a <value> then |
---|
| 389 | // turn quoting on, as this will be a string |
---|
| 390 | $GLOBALS['_xh'][$parser]['qt']=1; |
---|
| 391 | // and say we've found a value |
---|
| 392 | $GLOBALS['_xh'][$parser]['lv']=2; |
---|
| 393 | } |
---|
| 394 | $GLOBALS['_xh'][$parser]['ac'].=str_replace('$', '\$', |
---|
| 395 | str_replace('"', '\"', |
---|
| 396 | str_replace(chr(92),$GLOBALS['xmlrpc_backslash'], $data))); |
---|
| 397 | } |
---|
| 398 | } |
---|
| 399 | |
---|
| 400 | function xmlrpc_dh($parser, $data) |
---|
| 401 | { |
---|
| 402 | if (substr($data, 0, 1) == '&' && substr($data, -1, 1) == ';') |
---|
| 403 | { |
---|
| 404 | if ($GLOBALS['_xh'][$parser]['lv']==1) |
---|
| 405 | { |
---|
| 406 | $GLOBALS['_xh'][$parser]['qt']=1; |
---|
| 407 | $GLOBALS['_xh'][$parser]['lv']=2; |
---|
| 408 | } |
---|
| 409 | $GLOBALS['_xh'][$parser]['ac'].=str_replace('$', '\$', |
---|
| 410 | str_replace('"', '\"', |
---|
| 411 | str_replace(chr(92),$GLOBALS['xmlrpc_backslash'], $data))); |
---|
| 412 | } |
---|
| 413 | } |
---|
| 414 | |
---|
| 415 | // date helpers |
---|
| 416 | function iso8601_encode($timet, $utc=0) |
---|
| 417 | { |
---|
| 418 | // return an ISO8601 encoded string |
---|
| 419 | // really, timezones ought to be supported |
---|
| 420 | // but the XML-RPC spec says: |
---|
| 421 | // |
---|
| 422 | // "Don't assume a timezone. It should be specified by the server in its |
---|
| 423 | // documentation what assumptions it makes about timezones." |
---|
| 424 | // |
---|
| 425 | // these routines always assume localtime unless |
---|
| 426 | // $utc is set to 1, in which case UTC is assumed |
---|
| 427 | // and an adjustment for locale is made when encoding |
---|
| 428 | if (!$utc) |
---|
| 429 | { |
---|
| 430 | $t=strftime("%Y%m%dT%H:%M:%S", $timet); |
---|
| 431 | } |
---|
| 432 | else |
---|
| 433 | { |
---|
| 434 | if (function_exists("gmstrftime")) |
---|
| 435 | { |
---|
| 436 | // gmstrftime doesn't exist in some versions |
---|
| 437 | // of PHP |
---|
| 438 | $t=gmstrftime("%Y%m%dT%H:%M:%S", $timet); |
---|
| 439 | } |
---|
| 440 | else |
---|
| 441 | { |
---|
| 442 | $t=strftime("%Y%m%dT%H:%M:%S", $timet-date("Z")); |
---|
| 443 | } |
---|
| 444 | } |
---|
| 445 | return $t; |
---|
| 446 | } |
---|
| 447 | |
---|
| 448 | function iso8601_decode($idate, $utc=0) |
---|
| 449 | { |
---|
| 450 | // return a timet in the localtime, or UTC |
---|
| 451 | $t=0; |
---|
| 452 | if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})",$idate, $regs)) |
---|
| 453 | { |
---|
| 454 | if ($utc) |
---|
| 455 | { |
---|
| 456 | $t=gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); |
---|
| 457 | } |
---|
| 458 | else |
---|
| 459 | { |
---|
| 460 | $t=mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); |
---|
| 461 | } |
---|
| 462 | } |
---|
| 463 | return $t; |
---|
| 464 | } |
---|
| 465 | |
---|
| 466 | /**************************************************************** |
---|
| 467 | * xmlrpc_decode takes a message in PHP xmlrpc object format and * |
---|
| 468 | * tranlates it into native PHP types. * |
---|
| 469 | * * |
---|
| 470 | * author: Dan Libby (dan@libby.com) * |
---|
| 471 | ****************************************************************/ |
---|
| 472 | function phpgw_xmlrpc_decode($xmlrpc_val) |
---|
| 473 | { |
---|
| 474 | $kind = @$xmlrpc_val->kindOf(); |
---|
| 475 | |
---|
| 476 | if($kind == "scalar") |
---|
| 477 | { |
---|
| 478 | return $xmlrpc_val->scalarval(); |
---|
| 479 | } |
---|
| 480 | elseif($kind == "array") |
---|
| 481 | { |
---|
| 482 | $size = $xmlrpc_val->arraysize(); |
---|
| 483 | $arr = array(); |
---|
| 484 | |
---|
| 485 | for($i = 0; $i < $size; $i++) |
---|
| 486 | { |
---|
| 487 | $arr[]=phpgw_xmlrpc_decode($xmlrpc_val->arraymem($i)); |
---|
| 488 | } |
---|
| 489 | return $arr; |
---|
| 490 | } |
---|
| 491 | elseif($kind == "struct") |
---|
| 492 | { |
---|
| 493 | $xmlrpc_val->structreset(); |
---|
| 494 | $arr = array(); |
---|
| 495 | |
---|
| 496 | while(list($key,$value)=$xmlrpc_val->structeach()) |
---|
| 497 | { |
---|
| 498 | $arr[$key] = phpgw_xmlrpc_decode($value); |
---|
| 499 | } |
---|
| 500 | return $arr; |
---|
| 501 | } |
---|
| 502 | } |
---|
| 503 | |
---|
| 504 | /**************************************************************** |
---|
| 505 | * xmlrpc_encode takes native php types and encodes them into * |
---|
| 506 | * xmlrpc PHP object format. * |
---|
| 507 | * BUG: All sequential arrays are turned into structs. I don't * |
---|
| 508 | * know of a good way to determine if an array is sequential * |
---|
| 509 | * only. * |
---|
| 510 | * * |
---|
| 511 | * feature creep -- could support more types via optional type * |
---|
| 512 | * argument. * |
---|
| 513 | * * |
---|
| 514 | * author: Dan Libby (dan@libby.com) * |
---|
| 515 | ****************************************************************/ |
---|
| 516 | function phpgw_xmlrpc_encode($php_val) |
---|
| 517 | { |
---|
| 518 | $type = gettype($php_val); |
---|
| 519 | $xmlrpc_val = CreateObject('phpgwapi.xmlrpcval'); |
---|
| 520 | |
---|
| 521 | switch($type) |
---|
| 522 | { |
---|
| 523 | case "array": |
---|
| 524 | case "object": |
---|
| 525 | $arr = array(); |
---|
| 526 | while (list($k,$v) = each($php_val)) |
---|
| 527 | { |
---|
| 528 | $arr[$k] = phpgw_xmlrpc_encode($v); |
---|
| 529 | } |
---|
| 530 | $xmlrpc_val->addStruct($arr); |
---|
| 531 | break; |
---|
| 532 | case "integer": |
---|
| 533 | $xmlrpc_val->addScalar($php_val, xmlrpcInt); |
---|
| 534 | break; |
---|
| 535 | case "double": |
---|
| 536 | $xmlrpc_val->addScalar($php_val, xmlrpcDouble); |
---|
| 537 | break; |
---|
| 538 | case "string": |
---|
| 539 | $xmlrpc_val->addScalar($php_val, xmlrpcString); |
---|
| 540 | break; |
---|
| 541 | // <G_Giunta_2001-02-29> |
---|
| 542 | // Add support for encoding/decoding of booleans, since they are supported in PHP |
---|
| 543 | case "boolean": |
---|
| 544 | $xmlrpc_val->addScalar($php_val, xmlrpcBoolean); |
---|
| 545 | break; |
---|
| 546 | // </G_Giunta_2001-02-29> |
---|
| 547 | case "unknown type": |
---|
| 548 | default: |
---|
| 549 | $xmlrpc_val = false; |
---|
| 550 | break; |
---|
| 551 | } |
---|
| 552 | return $xmlrpc_val; |
---|
| 553 | } |
---|
| 554 | |
---|
| 555 | // listMethods: either a string, or nothing |
---|
| 556 | $GLOBALS['_xmlrpcs_listMethods_sig'] = array(array(xmlrpcArray, xmlrpcString), array(xmlrpcArray)); |
---|
| 557 | $GLOBALS['_xmlrpcs_listMethods_doc'] = 'This method lists all the methods that the XML-RPC server knows how to dispatch'; |
---|
| 558 | function _xmlrpcs_listMethods($server, $m) |
---|
| 559 | { |
---|
| 560 | $v = CreateObject('phpgwapi.xmlrpcval'); |
---|
| 561 | $dmap = $server->dmap; |
---|
| 562 | $outAr = array(); |
---|
| 563 | for(reset($dmap); list($key, $val) = each($dmap); ) |
---|
| 564 | { |
---|
| 565 | $outAr[] = CreateObject('phpgwapi.xmlrpcval',$key, 'string'); |
---|
| 566 | } |
---|
| 567 | $dmap = $GLOBALS['_xmlrpcs_dmap']; |
---|
| 568 | for(reset($dmap); list($key, $val) = each($dmap); ) |
---|
| 569 | { |
---|
| 570 | $outAr[] = CreateObject('phpgwapi.xmlrpcval',$key, 'string'); |
---|
| 571 | } |
---|
| 572 | $v->addArray($outAr); |
---|
| 573 | return CreateObject('phpgwapi.xmlrpcresp',$v); |
---|
| 574 | } |
---|
| 575 | |
---|
| 576 | $GLOBALS['_xmlrpcs_methodSignature_sig']=array(array(xmlrpcArray, xmlrpcString)); |
---|
| 577 | $GLOBALS['_xmlrpcs_methodSignature_doc']='Returns an array of known signatures (an array of arrays) for the method name passed. If no signatures are known, returns a none-array (test for type != array to detect missing signature)'; |
---|
| 578 | function _xmlrpcs_methodSignature($server, $m) |
---|
| 579 | { |
---|
| 580 | $methName = $m->getParam(0); |
---|
| 581 | $methName = $methName->scalarval(); |
---|
| 582 | if (ereg("^system\.", $methName)) |
---|
| 583 | { |
---|
| 584 | $dmap = $GLOBALS['_xmlrpcs_dmap']; |
---|
| 585 | $sysCall = 1; |
---|
| 586 | } |
---|
| 587 | else |
---|
| 588 | { |
---|
| 589 | $dmap = $server->dmap; |
---|
| 590 | $sysCall = 0; |
---|
| 591 | } |
---|
| 592 | // print "<!-- ${methName} -->\n"; |
---|
| 593 | if (isset($dmap[$methName])) |
---|
| 594 | { |
---|
| 595 | if ($dmap[$methName]['signature']) |
---|
| 596 | { |
---|
| 597 | $sigs = array(); |
---|
| 598 | $thesigs=$dmap[$methName]['signature']; |
---|
| 599 | for($i=0; $i<sizeof($thesigs); $i++) |
---|
| 600 | { |
---|
| 601 | $cursig = array(); |
---|
| 602 | $inSig = $thesigs[$i]; |
---|
| 603 | for($j=0; $j<sizeof($inSig); $j++) |
---|
| 604 | { |
---|
| 605 | $cursig[] = CreateObject('phpgwapi.xmlrpcval',$inSig[$j], 'string'); |
---|
| 606 | } |
---|
| 607 | $sigs[] = CreateObject('phpgwapi.xmlrpcval',$cursig, 'array'); |
---|
| 608 | } |
---|
| 609 | $r = CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',$sigs, 'array')); |
---|
| 610 | } |
---|
| 611 | else |
---|
| 612 | { |
---|
| 613 | $r = CreateObject('phpgwapi.xmlrpcresp', CreateObject('phpgwapi.xmlrpcval','undef', 'string')); |
---|
| 614 | } |
---|
| 615 | } |
---|
| 616 | else |
---|
| 617 | { |
---|
| 618 | $r = CreateObject('phpgwapi.xmlrpcresp',0,$GLOBALS['xmlrpcerr']['introspect_unknown'],$GLOBALS['xmlrpcstr']['introspect_unknown']); |
---|
| 619 | } |
---|
| 620 | return $r; |
---|
| 621 | } |
---|
| 622 | |
---|
| 623 | $GLOBALS['_xmlrpcs_methodHelp_sig'] = array(array(xmlrpcString, xmlrpcString)); |
---|
| 624 | $GLOBALS['_xmlrpcs_methodHelp_doc'] = 'Returns help text if defined for the method passed, otherwise returns an empty string'; |
---|
| 625 | function _xmlrpcs_methodHelp($server, $m) |
---|
| 626 | { |
---|
| 627 | $methName = $m->getParam(0); |
---|
| 628 | $methName = $methName->scalarval(); |
---|
| 629 | if (ereg("^system\.", $methName)) |
---|
| 630 | { |
---|
| 631 | $dmap = $GLOBALS['_xmlrpcs_dmap']; |
---|
| 632 | $sysCall=1; |
---|
| 633 | } |
---|
| 634 | else |
---|
| 635 | { |
---|
| 636 | $dmap = $server->dmap; |
---|
| 637 | $sysCall=0; |
---|
| 638 | } |
---|
| 639 | // print "<!-- ${methName} -->\n"; |
---|
| 640 | if (isset($dmap[$methName])) |
---|
| 641 | { |
---|
| 642 | if ($dmap[$methName]['docstring']) |
---|
| 643 | { |
---|
| 644 | $r = CreateObject('phpgwapi.xmlrpcresp', CreateObject('phpgwapi.xmlrpcval',$dmap[$methName]['docstring']),'string'); |
---|
| 645 | } |
---|
| 646 | else |
---|
| 647 | { |
---|
| 648 | $r = CreateObject('phpgwapi.xmlrpcresp', CreateObject('phpgwapi.xmlrpcval'), 'string'); |
---|
| 649 | } |
---|
| 650 | } |
---|
| 651 | else |
---|
| 652 | { |
---|
| 653 | $r = CreateObject('phpgwapi.xmlrpcresp',0,$GLOBALS['xmlrpcerr']['introspect_unknown'],$GLOBALS['xmlrpcstr']['introspect_unknown']); |
---|
| 654 | } |
---|
| 655 | return $r; |
---|
| 656 | } |
---|
| 657 | |
---|
| 658 | /* |
---|
| 659 | $GLOBALS['_xmlrpcs_listApps_sig'] = array(array(xmlrpcStruct,xmlrpcString)); |
---|
| 660 | $GLOBALS['_xmlrpcs_listApps_doc'] = 'Returns a list of installed phpgw apps'; |
---|
| 661 | function _xmlrpcs_listApps($server,$m) |
---|
| 662 | { |
---|
| 663 | $m->getParam(0); |
---|
| 664 | $GLOBALS['phpgw']->db->query("SELECT * FROM phpgw_applications WHERE app_enabled<3",__LINE__,__FILE__); |
---|
| 665 | if($GLOBALS['phpgw']->db->num_rows()) |
---|
| 666 | { |
---|
| 667 | while ($GLOBALS['phpgw']->db->next_record()) |
---|
| 668 | { |
---|
| 669 | $name = $GLOBALS['phpgw']->db->f('app_name'); |
---|
| 670 | $title = $GLOBALS['phpgw']->db->f('app_title'); |
---|
| 671 | $status = $GLOBALS['phpgw']->db->f('app_enabled'); |
---|
| 672 | $version= $GLOBALS['phpgw']->db->f('app_version'); |
---|
| 673 | $apps[$name] = CreateObject('phpgwapi.xmlrpcval', |
---|
| 674 | array( |
---|
| 675 | 'title' => CreateObject('phpgwapi.xmlrpcval',$title,'string'), |
---|
| 676 | 'name' => CreateObject('phpgwapi.xmlrpcval',$name,'string'), |
---|
| 677 | 'status' => CreateObject('phpgwapi.xmlrpcval',$status,'string'), |
---|
| 678 | 'version'=> CreateObject('phpgwapi.xmlrpcval',$version,'string') |
---|
| 679 | ), |
---|
| 680 | 'struct' |
---|
| 681 | ); |
---|
| 682 | } |
---|
| 683 | } |
---|
| 684 | return CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',$apps, 'struct')); |
---|
| 685 | } |
---|
| 686 | */ |
---|
| 687 | |
---|
| 688 | $GLOBALS['_xmlrpcs_login_sig'] = array(array(xmlrpcStruct,xmlrpcStruct)); |
---|
| 689 | $GLOBALS['_xmlrpcs_login_doc'] = 'phpGroupWare client or server login via XML-RPC'; |
---|
| 690 | function _xmlrpcs_login($server,$m) |
---|
| 691 | { |
---|
| 692 | $rdata = $m->getParam(0); |
---|
| 693 | $data = $rdata->scalarval(); |
---|
| 694 | |
---|
| 695 | if($data['server_name']) |
---|
| 696 | { |
---|
| 697 | $server_name = $data['server_name']->scalarval(); |
---|
| 698 | } |
---|
| 699 | if($data['domain']) |
---|
| 700 | { |
---|
| 701 | $domain = $data['domain']->scalarval(); |
---|
| 702 | } |
---|
| 703 | $username = $data['username']->scalarval(); |
---|
| 704 | $password = $data['password']->scalarval(); |
---|
| 705 | |
---|
| 706 | if($server_name) |
---|
| 707 | { |
---|
| 708 | list($sessionid,$kp3) = $GLOBALS['phpgw']->session->create_server($username.'@'.$server_name,$password,"text"); |
---|
| 709 | } |
---|
| 710 | else |
---|
| 711 | { |
---|
| 712 | if($domain) |
---|
| 713 | { |
---|
| 714 | $user = $username.'@'.$domain; |
---|
| 715 | } |
---|
| 716 | else |
---|
| 717 | { |
---|
| 718 | $user = $username; |
---|
| 719 | } |
---|
| 720 | $sessionid = $GLOBALS['phpgw']->session->create($user,$password,"text"); |
---|
| 721 | $kp3 = $GLOBALS['phpgw']->session->kp3; |
---|
| 722 | $domain = $GLOBALS['phpgw']->session->account_domain; |
---|
| 723 | } |
---|
| 724 | |
---|
| 725 | if($sessionid && $kp3) |
---|
| 726 | { |
---|
| 727 | $rtrn['domain'] = CreateObject('phpgwapi.xmlrpcval',$domain,'string'); |
---|
| 728 | $rtrn['sessionid'] = CreateObject('phpgwapi.xmlrpcval',$sessionid,'string'); |
---|
| 729 | $rtrn['kp3'] = CreateObject('phpgwapi.xmlrpcval',$kp3,'string'); |
---|
| 730 | } |
---|
| 731 | else |
---|
| 732 | { |
---|
| 733 | $rtrn['GOAWAY'] = CreateObject('phpgwapi.xmlrpcval','XOXO','string'); |
---|
| 734 | } |
---|
| 735 | return CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',$rtrn,'struct')); |
---|
| 736 | } |
---|
| 737 | |
---|
| 738 | $GLOBALS['_xmlrpcs_phpgw_api_version_sig'] = array(array(xmlrpcString,xmlrpcString)); |
---|
| 739 | $GLOBALS['_xmlrpcs_phpgw_api_version_doc'] = 'Returns the phpGroupWare API version'; |
---|
| 740 | function _xmlrpcs_phpgw_api_version($server,$m) |
---|
| 741 | { |
---|
| 742 | $version = $GLOBALS['phpgw_info']['server']['versions']['phpgwapi']; |
---|
| 743 | |
---|
| 744 | return CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',$version,'string')); |
---|
| 745 | } |
---|
| 746 | |
---|
| 747 | |
---|
| 748 | $GLOBALS['_xmlrpcs_logout_sig'] = array(array(xmlrpcStruct,xmlrpcStruct)); |
---|
| 749 | $GLOBALS['_xmlrpcs_logout_doc'] = 'phpGroupWare client or server logout via XML-RPC'; |
---|
| 750 | function _xmlrpcs_logout($server,$m) |
---|
| 751 | { |
---|
| 752 | $rdata = $m->getParam(0); |
---|
| 753 | $data = $rdata->scalarval(); |
---|
| 754 | |
---|
| 755 | $sessionid = $data['sessionid']->scalarval(); |
---|
| 756 | $kp3 = $data['kp3']->scalarval(); |
---|
| 757 | |
---|
| 758 | $later = $GLOBALS['phpgw']->session->destroy($sessionid,$kp3); |
---|
| 759 | |
---|
| 760 | if ($later) |
---|
| 761 | { |
---|
| 762 | $rtrn['GOODBYE'] = CreateObject('phpgwapi.xmlrpcval','XOXO','string'); |
---|
| 763 | } |
---|
| 764 | else |
---|
| 765 | { |
---|
| 766 | /* This never happens, yet */ |
---|
| 767 | $rtrn['OOPS'] = CreateObject('phpgwapi.xmlrpcval','WHAT?','string'); |
---|
| 768 | } |
---|
| 769 | return CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',$rtrn,'struct')); |
---|
| 770 | } |
---|
| 771 | |
---|
| 772 | $GLOBALS['_xmlrpcs_dmap'] = array( |
---|
| 773 | 'system.listMethods' => array( |
---|
| 774 | 'function' => '_xmlrpcs_listMethods', |
---|
| 775 | 'signature' => $GLOBALS['_xmlrpcs_listMethods_sig'], |
---|
| 776 | 'docstring' => $GLOBALS['_xmlrpcs_listMethods_doc'] |
---|
| 777 | ), |
---|
| 778 | 'system.methodHelp' => array( |
---|
| 779 | 'function' => '_xmlrpcs_methodHelp', |
---|
| 780 | 'signature' => $GLOBALS['_xmlrpcs_methodHelp_sig'], |
---|
| 781 | 'docstring' => $GLOBALS['_xmlrpcs_methodHelp_doc'] |
---|
| 782 | ), |
---|
| 783 | 'system.methodSignature' => array( |
---|
| 784 | 'function' => '_xmlrpcs_methodSignature', |
---|
| 785 | 'signature' => $GLOBALS['_xmlrpcs_methodSignature_sig'], |
---|
| 786 | 'docstring' => $GLOBALS['_xmlrpcs_methodSignature_doc'] |
---|
| 787 | ), |
---|
| 788 | /* |
---|
| 789 | 'system.listApps' => array( |
---|
| 790 | 'function' => '_xmlrpcs_listApps', |
---|
| 791 | 'signature' => $GLOBALS['_xmlrpcs_listApps_sig'], |
---|
| 792 | 'docstring' => $GLOBALS['_xmlrpcs_listApps_doc'] |
---|
| 793 | ), |
---|
| 794 | */ |
---|
| 795 | 'system.login' => array( |
---|
| 796 | 'function' => '_xmlrpcs_login', |
---|
| 797 | 'signature' => $GLOBALS['_xmlrpcs_login_sig'], |
---|
| 798 | 'docstring' => $GLOBALS['_xmlrpcs_login_doc'] |
---|
| 799 | ), |
---|
| 800 | 'system.logout' => array( |
---|
| 801 | 'function' => '_xmlrpcs_logout', |
---|
| 802 | 'signature' => $GLOBALS['_xmlrpcs_logout_sig'], |
---|
| 803 | 'docstring' => $GLOBALS['_xmlrpcs_logout_doc'] |
---|
| 804 | ), |
---|
| 805 | 'system.phpgw_api_version' => array( |
---|
| 806 | 'function' => '_xmlrpcs_phpgw_api_version', |
---|
| 807 | 'signature' => $GLOBALS['_xmlrpcs_phpgw_api_version_sig'], |
---|
| 808 | 'docstring' => $GLOBALS['_xmlrpcs_phpgw_api_version_doc'] |
---|
| 809 | ) |
---|
| 810 | ); |
---|
| 811 | |
---|
| 812 | $GLOBALS['_xmlrpc_debuginfo'] = ''; |
---|
| 813 | function xmlrpc_debugmsg($m) |
---|
| 814 | { |
---|
| 815 | $GLOBALS['_xmlrpc_debuginfo'] .= $m . "\n"; |
---|
| 816 | } |
---|
| 817 | ?> |
---|