[ Index ]
 

Code source de GeekLog 1.4.1

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/system/pear/PEAR/ -> Remote.php (source)

   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  ?>


Généré le : Wed Nov 21 12:27:40 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics