[ Index ] |
|
Code source de GeekLog 1.4.1 |
1 <?php 2 /** 3 * PEAR_Remote 4 * 5 * PHP versions 4 and 5 6 * 7 * LICENSE: This source file is subject to version 3.0 of the PHP license 8 * that is available through the world-wide-web at the following URI: 9 * http://www.php.net/license/3_0.txt. If you did not receive a copy of 10 * the PHP License and are unable to obtain it through the web, please 11 * send a note to license@php.net so we can mail you a copy immediately. 12 * 13 * @category pear 14 * @package PEAR 15 * @author Stig Bakken <ssb@php.net> 16 * @author Greg Beaver <cellog@php.net> 17 * @copyright 1997-2006 The PHP Group 18 * @license http://www.php.net/license/3_0.txt PHP License 3.0 19 * @version CVS: $Id: Remote.php,v 1.76 2006/03/02 18:14:13 cellog Exp $ 20 * @link http://pear.php.net/package/PEAR 21 * @since File available since Release 0.1 22 */ 23 24 /** 25 * needed for PEAR_Error 26 */ 27 require_once 'PEAR.php'; 28 require_once 'PEAR/Config.php'; 29 30 /** 31 * This is a class for doing remote operations against the central 32 * PEAR database. 33 * 34 * @nodep XML_RPC_Value 35 * @nodep XML_RPC_Message 36 * @nodep XML_RPC_Client 37 * @category pear 38 * @package PEAR 39 * @author Stig Bakken <ssb@php.net> 40 * @author Greg Beaver <cellog@php.net> 41 * @copyright 1997-2006 The PHP Group 42 * @license http://www.php.net/license/3_0.txt PHP License 3.0 43 * @version Release: 1.4.11 44 * @link http://pear.php.net/package/PEAR 45 * @since Class available since Release 0.1 46 */ 47 class PEAR_Remote extends PEAR 48 { 49 // {{{ properties 50 51 var $config = null; 52 var $cache = null; 53 /** 54 * @var PEAR_Registry 55 * @access private 56 */ 57 var $_registry; 58 59 // }}} 60 61 // {{{ PEAR_Remote(config_object) 62 63 function PEAR_Remote(&$config) 64 { 65 $this->PEAR(); 66 $this->config = &$config; 67 $this->_registry = &$this->config->getRegistry(); 68 } 69 70 // }}} 71 // {{{ setRegistry() 72 73 function setRegistry(&$reg) 74 { 75 $this->_registry = &$reg; 76 } 77 // }}} 78 // {{{ getCache() 79 80 81 function getCache($args) 82 { 83 $id = md5(serialize($args)); 84 $cachedir = $this->config->get('cache_dir'); 85 $filename = $cachedir . DIRECTORY_SEPARATOR . 'xmlrpc_cache_' . $id; 86 if (!file_exists($filename)) { 87 return null; 88 } 89 90 $fp = fopen($filename, 'rb'); 91 if (!$fp) { 92 return null; 93 } 94 if (function_exists('file_get_contents')) { 95 fclose($fp); 96 $content = file_get_contents($filename); 97 } else { 98 $content = fread($fp, filesize($filename)); 99 fclose($fp); 100 } 101 $result = array( 102 'age' => time() - filemtime($filename), 103 'lastChange' => filemtime($filename), 104 'content' => unserialize($content), 105 ); 106 return $result; 107 } 108 109 // }}} 110 111 // {{{ saveCache() 112 113 function saveCache($args, $data) 114 { 115 $id = md5(serialize($args)); 116 $cachedir = $this->config->get('cache_dir'); 117 if (!file_exists($cachedir)) { 118 System::mkdir(array('-p', $cachedir)); 119 } 120 $filename = $cachedir.'/xmlrpc_cache_'.$id; 121 122 $fp = @fopen($filename, "wb"); 123 if ($fp) { 124 fwrite($fp, serialize($data)); 125 fclose($fp); 126 } 127 } 128 129 // }}} 130 131 // {{{ clearCache() 132 133 function clearCache($method, $args) 134 { 135 array_unshift($args, $method); 136 array_unshift($args, $this->config->get('default_channel')); // cache by channel 137 $id = md5(serialize($args)); 138 $cachedir = $this->config->get('cache_dir'); 139 $filename = $cachedir.'/xmlrpc_cache_'.$id; 140 if (file_exists($filename)) { 141 @unlink($filename); 142 } 143 } 144 145 // }}} 146 // {{{ call(method, [args...]) 147 148 function call($method) 149 { 150 $_args = $args = func_get_args(); 151 152 $server_channel = $this->config->get('default_channel'); 153 $channel = $this->_registry->getChannel($server_channel); 154 if (!PEAR::isError($channel)) { 155 $mirror = $this->config->get('preferred_mirror'); 156 if ($channel->getMirror($mirror)) { 157 if ($channel->supports('xmlrpc', $method, $mirror)) { 158 $server_channel = $server_host = $mirror; // use the preferred mirror 159 $server_port = $channel->getPort($mirror); 160 } elseif (!$channel->supports('xmlrpc', $method)) { 161 return $this->raiseError("Channel $server_channel does not " . 162 "support xml-rpc method $method"); 163 } 164 } 165 if (!isset($server_host)) { 166 if (!$channel->supports('xmlrpc', $method)) { 167 return $this->raiseError("Channel $server_channel does not support " . 168 "xml-rpc method $method"); 169 } else { 170 $server_host = $server_channel; 171 $server_port = $channel->getPort(); 172 } 173 } 174 } else { 175 return $this->raiseError("Unknown channel '$server_channel'"); 176 } 177 178 array_unshift($_args, $server_channel); // cache by channel 179 $this->cache = $this->getCache($_args); 180 $cachettl = $this->config->get('cache_ttl'); 181 // If cache is newer than $cachettl seconds, we use the cache! 182 if ($this->cache !== null && $this->cache['age'] < $cachettl) { 183 return $this->cache['content']; 184 } 185 if (extension_loaded("xmlrpc")) { 186 $result = call_user_func_array(array(&$this, 'call_epi'), $args); 187 if (!PEAR::isError($result)) { 188 $this->saveCache($_args, $result); 189 } 190 return $result; 191 } elseif (!@include_once 'XML/RPC.php') { 192 return $this->raiseError("For this remote PEAR operation you need to load the xmlrpc extension or install XML_RPC"); 193 } 194 195 array_shift($args); 196 $username = $this->config->get('username'); 197 $password = $this->config->get('password'); 198 $eargs = array(); 199 foreach($args as $arg) { 200 $eargs[] = $this->_encode($arg); 201 } 202 $f = new XML_RPC_Message($method, $eargs); 203 if ($this->cache !== null) { 204 $maxAge = '?maxAge='.$this->cache['lastChange']; 205 } else { 206 $maxAge = ''; 207 } 208 $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; 209 if ($proxy = parse_url($this->config->get('http_proxy'))) { 210 $proxy_host = @$proxy['host']; 211 if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { 212 $proxy_host = 'https://' . $proxy_host; 213 } 214 $proxy_port = @$proxy['port']; 215 $proxy_user = @urldecode(@$proxy['user']); 216 $proxy_pass = @urldecode(@$proxy['pass']); 217 } 218 $shost = $server_host; 219 if ($channel->getSSL()) { 220 $shost = "https://$shost"; 221 } 222 $c = new XML_RPC_Client('/' . $channel->getPath('xmlrpc') 223 . $maxAge, $shost, $server_port, $proxy_host, $proxy_port, 224 $proxy_user, $proxy_pass); 225 if ($username && $password) { 226 $c->setCredentials($username, $password); 227 } 228 if ($this->config->get('verbose') >= 3) { 229 $c->setDebug(1); 230 } 231 $r = $c->send($f); 232 if (!$r) { 233 return $this->raiseError("XML_RPC send failed"); 234 } 235 $v = $r->value(); 236 if ($e = $r->faultCode()) { 237 if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) { 238 return $this->cache['content']; 239 } 240 return $this->raiseError($r->faultString(), $e); 241 } 242 243 $result = XML_RPC_decode($v); 244 $this->saveCache($_args, $result); 245 return $result; 246 } 247 248 // }}} 249 250 // {{{ call_epi(method, [args...]) 251 252 function call_epi($method) 253 { 254 do { 255 if (extension_loaded("xmlrpc")) { 256 break; 257 } 258 if (OS_WINDOWS) { 259 $ext = 'dll'; 260 } elseif (PHP_OS == 'HP-UX') { 261 $ext = 'sl'; 262 } elseif (PHP_OS == 'AIX') { 263 $ext = 'a'; 264 } else { 265 $ext = 'so'; 266 } 267 $ext = OS_WINDOWS ? 'dll' : 'so'; 268 @dl("xmlrpc-epi.$ext"); 269 if (extension_loaded("xmlrpc")) { 270 break; 271 } 272 @dl("xmlrpc.$ext"); 273 if (extension_loaded("xmlrpc")) { 274 break; 275 } 276 return $this->raiseError("unable to load xmlrpc extension"); 277 } while (false); 278 $server_channel = $this->config->get('default_channel'); 279 $channel = $this->_registry->getChannel($server_channel); 280 if (!PEAR::isError($channel)) { 281 $mirror = $this->config->get('preferred_mirror'); 282 if ($channel->getMirror($mirror)) { 283 if ($channel->supports('xmlrpc', $method, $mirror)) { 284 $server_channel = $server_host = $mirror; // use the preferred mirror 285 $server_port = $channel->getPort($mirror); 286 } elseif (!$channel->supports('xmlrpc', $method)) { 287 return $this->raiseError("Channel $server_channel does not " . 288 "support xml-rpc method $method"); 289 } 290 } 291 if (!isset($server_host)) { 292 if (!$channel->supports('xmlrpc', $method)) { 293 return $this->raiseError("Channel $server_channel does not support " . 294 "xml-rpc method $method"); 295 } else { 296 $server_host = $server_channel; 297 $server_port = $channel->getPort(); 298 } 299 } 300 } else { 301 return $this->raiseError("Unknown channel '$server_channel'"); 302 } 303 $params = func_get_args(); 304 array_shift($params); 305 $method = str_replace("_", ".", $method); 306 $request = xmlrpc_encode_request($method, $params); 307 if ($http_proxy = $this->config->get('http_proxy')) { 308 $proxy = parse_url($http_proxy); 309 $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; 310 $proxy_host = @$proxy['host']; 311 if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { 312 $proxy_host = 'ssl://' . $proxy_host; 313 } 314 $proxy_port = @$proxy['port']; 315 $proxy_user = @urldecode(@$proxy['user']); 316 $proxy_pass = @urldecode(@$proxy['pass']); 317 $fp = @fsockopen($proxy_host, $proxy_port); 318 $use_proxy = true; 319 if ($channel->getSSL()) { 320 $server_host = "https://$server_host"; 321 } 322 } else { 323 $use_proxy = false; 324 $ssl = $channel->getSSL(); 325 $fp = @fsockopen(($ssl ? 'ssl://' : '') . $server_host, $server_port); 326 if (!$fp) { 327 $server_host = "$ssl$server_host"; // for error-reporting 328 } 329 } 330 if (!$fp && $http_proxy) { 331 return $this->raiseError("PEAR_Remote::call: fsockopen(`$proxy_host', $proxy_port) failed"); 332 } elseif (!$fp) { 333 return $this->raiseError("PEAR_Remote::call: fsockopen(`$server_host', $server_port) failed"); 334 } 335 $len = strlen($request); 336 $req_headers = "Host: $server_host:$server_port\r\n" . 337 "Content-type: text/xml\r\n" . 338 "Content-length: $len\r\n"; 339 $username = $this->config->get('username'); 340 $password = $this->config->get('password'); 341 if ($username && $password) { 342 $req_headers .= "Cookie: PEAR_USER=$username; PEAR_PW=$password\r\n"; 343 $tmp = base64_encode("$username:$password"); 344 $req_headers .= "Authorization: Basic $tmp\r\n"; 345 } 346 if ($this->cache !== null) { 347 $maxAge = '?maxAge='.$this->cache['lastChange']; 348 } else { 349 $maxAge = ''; 350 } 351 352 if ($use_proxy && $proxy_host != '' && $proxy_user != '') { 353 $req_headers .= 'Proxy-Authorization: Basic ' 354 .base64_encode($proxy_user.':'.$proxy_pass) 355 ."\r\n"; 356 } 357 358 if ($this->config->get('verbose') > 3) { 359 print "XMLRPC REQUEST HEADERS:\n"; 360 var_dump($req_headers); 361 print "XMLRPC REQUEST BODY:\n"; 362 var_dump($request); 363 } 364 365 if ($use_proxy && $proxy_host != '') { 366 $post_string = "POST http://".$server_host; 367 if ($proxy_port > '') { 368 $post_string .= ':'.$server_port; 369 } 370 } else { 371 $post_string = "POST "; 372 } 373 374 $path = '/' . $channel->getPath('xmlrpc'); 375 fwrite($fp, ($post_string . $path . "$maxAge HTTP/1.0\r\n$req_headers\r\n$request")); 376 $response = ''; 377 $line1 = fgets($fp, 2048); 378 if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) { 379 return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server"); 380 } 381 switch ($matches[1]) { 382 case "200": // OK 383 break; 384 case "304": // Not Modified 385 return $this->cache['content']; 386 case "401": // Unauthorized 387 if ($username && $password) { 388 return $this->raiseError("PEAR_Remote ($server_host:$server_port) " . 389 ": authorization failed", 401); 390 } else { 391 return $this->raiseError("PEAR_Remote ($server_host:$server_port) " . 392 ": authorization required, please log in first", 401); 393 } 394 default: 395 return $this->raiseError("PEAR_Remote ($server_host:$server_port) : " . 396 "unexpected HTTP response", (int)$matches[1], null, null, 397 "$matches[1] $matches[2]"); 398 } 399 while (trim(fgets($fp, 2048)) != ''); // skip rest of headers 400 while ($chunk = fread($fp, 10240)) { 401 $response .= $chunk; 402 } 403 fclose($fp); 404 if ($this->config->get('verbose') > 3) { 405 print "XMLRPC RESPONSE:\n"; 406 var_dump($response); 407 } 408 $ret = xmlrpc_decode($response); 409 if (is_array($ret) && isset($ret['__PEAR_TYPE__'])) { 410 if ($ret['__PEAR_TYPE__'] == 'error') { 411 if (isset($ret['__PEAR_CLASS__'])) { 412 $class = $ret['__PEAR_CLASS__']; 413 } else { 414 $class = "PEAR_Error"; 415 } 416 if ($ret['code'] === '') $ret['code'] = null; 417 if ($ret['message'] === '') $ret['message'] = null; 418 if ($ret['userinfo'] === '') $ret['userinfo'] = null; 419 if (strtolower($class) == 'db_error') { 420 $ret = $this->raiseError(PEAR::errorMessage($ret['code']), 421 $ret['code'], null, null, 422 $ret['userinfo']); 423 } else { 424 $ret = $this->raiseError($ret['message'], $ret['code'], 425 null, null, $ret['userinfo']); 426 } 427 } 428 } elseif (is_array($ret) && sizeof($ret) == 1 && isset($ret[0]) 429 && is_array($ret[0]) && 430 !empty($ret[0]['faultString']) && 431 !empty($ret[0]['faultCode'])) { 432 extract($ret[0]); 433 $faultString = "XML-RPC Server Fault: " . 434 str_replace("\n", " ", $faultString); 435 return $this->raiseError($faultString, $faultCode); 436 } elseif (is_array($ret) && sizeof($ret) == 2 && !empty($ret['faultString']) && 437 !empty($ret['faultCode'])) { 438 extract($ret); 439 $faultString = "XML-RPC Server Fault: " . 440 str_replace("\n", " ", $faultString); 441 return $this->raiseError($faultString, $faultCode); 442 } 443 return $ret; 444 } 445 446 // }}} 447 448 // {{{ _encode 449 450 // a slightly extended version of XML_RPC_encode 451 function _encode($php_val) 452 { 453 global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double; 454 global $XML_RPC_String, $XML_RPC_Array, $XML_RPC_Struct; 455 456 $type = gettype($php_val); 457 $xmlrpcval = new XML_RPC_Value; 458 459 switch($type) { 460 case "array": 461 reset($php_val); 462 $firstkey = key($php_val); 463 end($php_val); 464 $lastkey = key($php_val); 465 reset($php_val); 466 if ($firstkey === 0 && is_int($lastkey) && 467 ($lastkey + 1) == count($php_val)) { 468 $is_continuous = true; 469 reset($php_val); 470 $size = count($php_val); 471 for ($expect = 0; $expect < $size; $expect++, next($php_val)) { 472 if (key($php_val) !== $expect) { 473 $is_continuous = false; 474 break; 475 } 476 } 477 if ($is_continuous) { 478 reset($php_val); 479 $arr = array(); 480 while (list($k, $v) = each($php_val)) { 481 $arr[$k] = $this->_encode($v); 482 } 483 $xmlrpcval->addArray($arr); 484 break; 485 } 486 } 487 // fall though if not numerical and continuous 488 case "object": 489 $arr = array(); 490 while (list($k, $v) = each($php_val)) { 491 $arr[$k] = $this->_encode($v); 492 } 493 $xmlrpcval->addStruct($arr); 494 break; 495 case "integer": 496 $xmlrpcval->addScalar($php_val, $XML_RPC_Int); 497 break; 498 case "double": 499 $xmlrpcval->addScalar($php_val, $XML_RPC_Double); 500 break; 501 case "string": 502 case "NULL": 503 $xmlrpcval->addScalar($php_val, $XML_RPC_String); 504 break; 505 case "boolean": 506 $xmlrpcval->addScalar($php_val, $XML_RPC_Boolean); 507 break; 508 case "unknown type": 509 default: 510 return null; 511 } 512 return $xmlrpcval; 513 } 514 515 // }}} 516 517 } 518 519 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Wed Nov 21 12:27:40 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |