home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / tmp / PEAR-1.7.1 / PEAR / Remote.php < prev    next >
Encoding:
PHP Script  |  2008-02-15  |  17.8 KB  |  499 lines

  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-2008 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.80 2008/01/03 20:26:36 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-2008 The PHP Group
  42.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  43.  * @version    Release: 1.7.1
  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.         fclose($fp);
  95.         $content = file_get_contents($filename);
  96.         $result   = array(
  97.             'age'        => time() - filemtime($filename),
  98.             'lastChange' => filemtime($filename),
  99.             'content'    => unserialize($content),
  100.             );
  101.         return $result;
  102.     }
  103.  
  104.     // }}}
  105.  
  106.     // {{{ saveCache()
  107.  
  108.     function saveCache($args, $data)
  109.     {
  110.         $id       = md5(serialize($args));
  111.         $cachedir = $this->config->get('cache_dir');
  112.         if (!file_exists($cachedir)) {
  113.             System::mkdir(array('-p', $cachedir));
  114.         }
  115.         $filename = $cachedir.'/xmlrpc_cache_'.$id;
  116.  
  117.         $fp = @fopen($filename, "wb");
  118.         if ($fp) {
  119.             fwrite($fp, serialize($data));
  120.             fclose($fp);
  121.         }
  122.     }
  123.  
  124.     // }}}
  125.  
  126.     // {{{ clearCache()
  127.  
  128.     function clearCache($method, $args)
  129.     {
  130.         array_unshift($args, $method);
  131.         array_unshift($args, $this->config->get('default_channel')); // cache by channel
  132.         $id       = md5(serialize($args));
  133.         $cachedir = $this->config->get('cache_dir');
  134.         $filename = $cachedir.'/xmlrpc_cache_'.$id;
  135.         if (file_exists($filename)) {
  136.             @unlink($filename);
  137.         }
  138.     }
  139.  
  140.     // }}}
  141.     // {{{ call(method, [args...])
  142.  
  143.     function call($method)
  144.     {
  145.         $_args = $args = func_get_args();
  146.  
  147.         $server_channel = $this->config->get('default_channel');
  148.         $channel = $this->_registry->getChannel($server_channel);
  149.         if (!PEAR::isError($channel)) {
  150.             $mirror = $this->config->get('preferred_mirror');
  151.             if ($channel->getMirror($mirror)) {
  152.                 if ($channel->supports('xmlrpc', $method, $mirror)) {
  153.                     $server_channel = $server_host = $mirror; // use the preferred mirror
  154.                     $server_port = $channel->getPort($mirror);
  155.                 } elseif (!$channel->supports('xmlrpc', $method)) {
  156.                     return $this->raiseError("Channel $server_channel does not " .
  157.                         "support xml-rpc method $method");
  158.                 }
  159.             }
  160.             if (!isset($server_host)) {
  161.                 if (!$channel->supports('xmlrpc', $method)) {
  162.                     return $this->raiseError("Channel $server_channel does not support " .
  163.                         "xml-rpc method $method");
  164.                 } else {
  165.                     $server_host = $server_channel;
  166.                     $server_port = $channel->getPort();
  167.                 }
  168.             }
  169.         } else {
  170.             return $this->raiseError("Unknown channel '$server_channel'");
  171.         }
  172.  
  173.         array_unshift($_args, $server_channel); // cache by channel
  174.         $this->cache = $this->getCache($_args);
  175.         $cachettl = $this->config->get('cache_ttl');
  176.         // If cache is newer than $cachettl seconds, we use the cache!
  177.         if ($this->cache !== null && $this->cache['age'] < $cachettl) {
  178.             return $this->cache['content'];
  179.         }
  180.         $fp = false;
  181.         if (extension_loaded("xmlrpc")) {
  182.             $result = call_user_func_array(array(&$this, 'call_epi'), $args);
  183.             if (!PEAR::isError($result)) {
  184.                 $this->saveCache($_args, $result);
  185.             }
  186.             return $result;
  187.         } elseif (!($fp = fopen('XML/RPC.php', 'r', true))) {
  188.             return $this->raiseError("For this remote PEAR operation you need to load the xmlrpc extension or install XML_RPC");
  189.         }
  190.         include_once 'XML/RPC.php';
  191.         if ($fp) {
  192.             fclose($fp);
  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 = isset($proxy['host']) ? $proxy['host'] : null;
  211.             if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {
  212.                 $proxy_host = 'https://' . $proxy_host;
  213.             }
  214.             $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080;
  215.             $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null;
  216.             $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
  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.         if (!extension_loaded("xmlrpc")) {
  255.             return $this->raiseError("xmlrpc extension is not loaded");
  256.         }
  257.         $server_channel = $this->config->get('default_channel');
  258.         $channel = $this->_registry->getChannel($server_channel);
  259.         if (!PEAR::isError($channel)) {
  260.             $mirror = $this->config->get('preferred_mirror');
  261.             if ($channel->getMirror($mirror)) {
  262.                 if ($channel->supports('xmlrpc', $method, $mirror)) {
  263.                     $server_channel = $server_host = $mirror; // use the preferred mirror
  264.                     $server_port = $channel->getPort($mirror);
  265.                 } elseif (!$channel->supports('xmlrpc', $method)) {
  266.                     return $this->raiseError("Channel $server_channel does not " .
  267.                         "support xml-rpc method $method");
  268.                 }
  269.             }
  270.             if (!isset($server_host)) {
  271.                 if (!$channel->supports('xmlrpc', $method)) {
  272.                     return $this->raiseError("Channel $server_channel does not support " .
  273.                         "xml-rpc method $method");
  274.                 } else {
  275.                     $server_host = $server_channel;
  276.                     $server_port = $channel->getPort();
  277.                 }
  278.             }
  279.         } else {
  280.             return $this->raiseError("Unknown channel '$server_channel'");
  281.         }
  282.         $params = func_get_args();
  283.         array_shift($params);
  284.         $method = str_replace("_", ".", $method);
  285.         $request = xmlrpc_encode_request($method, $params);
  286.         if ($http_proxy = $this->config->get('http_proxy')) {
  287.             $proxy = parse_url($http_proxy);
  288.             $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
  289.             $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
  290.             if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {
  291.                 $proxy_host = 'https://' . $proxy_host;
  292.             }
  293.             $proxy_port = isset($proxy['port']) ? $proxy['port'] : null;
  294.             $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null;
  295.             $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
  296.             $fp = @fsockopen($proxy_host, $proxy_port);
  297.             $use_proxy = true;
  298.             if ($channel->getSSL()) {
  299.                 $server_host = "https://$server_host";
  300.             }
  301.         } else {
  302.             $use_proxy = false;
  303.             $ssl = $channel->getSSL();
  304.             $fp = @fsockopen(($ssl ? 'ssl://' : '') . $server_host, $server_port);
  305.             if (!$fp) {
  306.                 $server_host = "$ssl$server_host"; // for error-reporting
  307.             }
  308.         }
  309.         if (!$fp && $http_proxy) {
  310.             return $this->raiseError("PEAR_Remote::call: fsockopen(`$proxy_host', $proxy_port) failed");
  311.         } elseif (!$fp) {
  312.             return $this->raiseError("PEAR_Remote::call: fsockopen(`$server_host', $server_port) failed");
  313.         }
  314.         $len = strlen($request);
  315.         $req_headers = "Host: $server_host:$server_port\r\n" .
  316.              "Content-type: text/xml\r\n" .
  317.              "Content-length: $len\r\n";
  318.         $username = $this->config->get('username');
  319.         $password = $this->config->get('password');
  320.         if ($username && $password) {
  321.             $req_headers .= "Cookie: PEAR_USER=$username; PEAR_PW=$password\r\n";
  322.             $tmp = base64_encode("$username:$password");
  323.             $req_headers .= "Authorization: Basic $tmp\r\n";
  324.         }
  325.         if ($this->cache !== null) {
  326.             $maxAge = '?maxAge='.$this->cache['lastChange'];
  327.         } else {
  328.             $maxAge = '';
  329.         }
  330.  
  331.         if ($use_proxy && $proxy_host != '' && $proxy_user != '') {
  332.             $req_headers .= 'Proxy-Authorization: Basic '
  333.                 .base64_encode($proxy_user.':'.$proxy_pass)
  334.                 ."\r\n";
  335.         }
  336.  
  337.         if ($this->config->get('verbose') > 3) {
  338.             print "XMLRPC REQUEST HEADERS:\n";
  339.             var_dump($req_headers);
  340.             print "XMLRPC REQUEST BODY:\n";
  341.             var_dump($request);
  342.         }
  343.  
  344.         if ($use_proxy && $proxy_host != '') {
  345.             $post_string = "POST http://".$server_host;
  346.             if ($proxy_port > '') {
  347.                 $post_string .= ':'.$server_port;
  348.             }
  349.         } else {
  350.             $post_string = "POST ";
  351.         }
  352.  
  353.         $path = '/' . $channel->getPath('xmlrpc');
  354.         fwrite($fp, ($post_string . $path . "$maxAge HTTP/1.0\r\n$req_headers\r\n$request"));
  355.         $response = '';
  356.         $line1 = fgets($fp, 2048);
  357.         if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) {
  358.             return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server");
  359.         }
  360.         switch ($matches[1]) {
  361.             case "200": // OK
  362.                 break;
  363.             case "304": // Not Modified
  364.                 return $this->cache['content'];
  365.             case "401": // Unauthorized
  366.                 if ($username && $password) {
  367.                     return $this->raiseError("PEAR_Remote ($server_host:$server_port) " .
  368.                         ": authorization failed", 401);
  369.                 } else {
  370.                     return $this->raiseError("PEAR_Remote ($server_host:$server_port) " .
  371.                         ": authorization required, please log in first", 401);
  372.                 }
  373.             default:
  374.                 return $this->raiseError("PEAR_Remote ($server_host:$server_port) : " .
  375.                     "unexpected HTTP response", (int)$matches[1], null, null,
  376.                     "$matches[1] $matches[2]");
  377.         }
  378.         while (trim(fgets($fp, 2048)) != ''); // skip rest of headers
  379.         while ($chunk = fread($fp, 10240)) {
  380.             $response .= $chunk;
  381.         }
  382.         fclose($fp);
  383.         if ($this->config->get('verbose') > 3) {
  384.             print "XMLRPC RESPONSE:\n";
  385.             var_dump($response);
  386.         }
  387.         $ret = xmlrpc_decode($response);
  388.         if (is_array($ret) && isset($ret['__PEAR_TYPE__'])) {
  389.             if ($ret['__PEAR_TYPE__'] == 'error') {
  390.                 if (isset($ret['__PEAR_CLASS__'])) {
  391.                     $class = $ret['__PEAR_CLASS__'];
  392.                 } else {
  393.                     $class = "PEAR_Error";
  394.                 }
  395.                 if ($ret['code']     === '') $ret['code']     = null;
  396.                 if ($ret['message']  === '') $ret['message']  = null;
  397.                 if ($ret['userinfo'] === '') $ret['userinfo'] = null;
  398.                 if (strtolower($class) == 'db_error') {
  399.                     $ret = $this->raiseError(PEAR::errorMessage($ret['code']),
  400.                                              $ret['code'], null, null,
  401.                                              $ret['userinfo']);
  402.                 } else {
  403.                     $ret = $this->raiseError($ret['message'], $ret['code'],
  404.                                              null, null, $ret['userinfo']);
  405.                 }
  406.             }
  407.         } elseif (is_array($ret) && sizeof($ret) == 1 && isset($ret[0])
  408.                   && is_array($ret[0]) &&
  409.                   !empty($ret[0]['faultString']) &&
  410.                   !empty($ret[0]['faultCode'])) {
  411.             extract($ret[0]);
  412.             $faultString = "XML-RPC Server Fault: " .
  413.                  str_replace("\n", " ", $faultString);
  414.             return $this->raiseError($faultString, $faultCode);
  415.         } elseif (is_array($ret) && sizeof($ret) == 2 && !empty($ret['faultString']) &&
  416.               !empty($ret['faultCode'])) {
  417.             extract($ret);
  418.             $faultString = "XML-RPC Server Fault: " .
  419.                  str_replace("\n", " ", $faultString);
  420.             return $this->raiseError($faultString, $faultCode);
  421.         }
  422.         return $ret;
  423.     }
  424.  
  425.     // }}}
  426.  
  427.     // {{{ _encode
  428.  
  429.     // a slightly extended version of XML_RPC_encode
  430.     function _encode($php_val)
  431.     {
  432.         global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double;
  433.         global $XML_RPC_String, $XML_RPC_Array, $XML_RPC_Struct;
  434.  
  435.         $type = gettype($php_val);
  436.         $xmlrpcval = new XML_RPC_Value;
  437.  
  438.         switch($type) {
  439.             case "array":
  440.                 reset($php_val);
  441.                 $firstkey = key($php_val);
  442.                 end($php_val);
  443.                 $lastkey = key($php_val);
  444.                 reset($php_val);
  445.                 if ($firstkey === 0 && is_int($lastkey) &&
  446.                     ($lastkey + 1) == count($php_val)) {
  447.                     $is_continuous = true;
  448.                     reset($php_val);
  449.                     $size = count($php_val);
  450.                     for ($expect = 0; $expect < $size; $expect++, next($php_val)) {
  451.                         if (key($php_val) !== $expect) {
  452.                             $is_continuous = false;
  453.                             break;
  454.                         }
  455.                     }
  456.                     if ($is_continuous) {
  457.                         reset($php_val);
  458.                         $arr = array();
  459.                         while (list($k, $v) = each($php_val)) {
  460.                             $arr[$k] = $this->_encode($v);
  461.                         }
  462.                         $xmlrpcval->addArray($arr);
  463.                         break;
  464.                     }
  465.                 }
  466.                 // fall though if not numerical and continuous
  467.             case "object":
  468.                 $arr = array();
  469.                 while (list($k, $v) = each($php_val)) {
  470.                     $arr[$k] = $this->_encode($v);
  471.                 }
  472.                 $xmlrpcval->addStruct($arr);
  473.                 break;
  474.             case "integer":
  475.                 $xmlrpcval->addScalar($php_val, $XML_RPC_Int);
  476.                 break;
  477.             case "double":
  478.                 $xmlrpcval->addScalar($php_val, $XML_RPC_Double);
  479.                 break;
  480.             case "string":
  481.             case "NULL":
  482.                 $xmlrpcval->addScalar($php_val, $XML_RPC_String);
  483.                 break;
  484.             case "boolean":
  485.                 $xmlrpcval->addScalar($php_val, $XML_RPC_Boolean);
  486.                 break;
  487.             case "unknown type":
  488.             default:
  489.                 return null;
  490.         }
  491.         return $xmlrpcval;
  492.     }
  493.  
  494.     // }}}
  495.  
  496. }
  497.  
  498. ?>
  499.