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 / REST.php < prev    next >
Encoding:
PHP Script  |  2008-02-15  |  14.6 KB  |  399 lines

  1. <?php
  2. /**
  3.  * PEAR_REST
  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     Greg Beaver <cellog@php.net>
  16.  * @copyright  1997-2008 The PHP Group
  17.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  18.  * @version    CVS: $Id: REST.php,v 1.29 2008/01/31 23:42:04 timj Exp $
  19.  * @link       http://pear.php.net/package/PEAR
  20.  * @since      File available since Release 1.4.0a1
  21.  */
  22.  
  23. /**
  24.  * For downloading xml files
  25.  */
  26. require_once 'PEAR.php';
  27. require_once 'PEAR/XMLParser.php';
  28.  
  29. /**
  30.  * Intelligently retrieve data, following hyperlinks if necessary, and re-directing
  31.  * as well
  32.  * @category   pear
  33.  * @package    PEAR
  34.  * @author     Greg Beaver <cellog@php.net>
  35.  * @copyright  1997-2008 The PHP Group
  36.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  37.  * @version    Release: 1.7.1
  38.  * @link       http://pear.php.net/package/PEAR
  39.  * @since      Class available since Release 1.4.0a1
  40.  */
  41. class PEAR_REST
  42. {
  43.     var $config;
  44.     var $_options;
  45.     function PEAR_REST(&$config, $options = array())
  46.     {
  47.         $this->config = &$config;
  48.         $this->_options = $options;
  49.     }
  50.  
  51.     /**
  52.      * Retrieve REST data, but always retrieve the local cache if it is available.
  53.      *
  54.      * This is useful for elements that should never change, such as information on a particular
  55.      * release
  56.      * @param string full URL to this resource
  57.      * @param array|false contents of the accept-encoding header
  58.      * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
  59.      *                    parsed using PEAR_XMLParser
  60.      * @return string|array
  61.      */
  62.     function retrieveCacheFirst($url, $accept = false, $forcestring = false)
  63.     {
  64.         $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
  65.             md5($url) . 'rest.cachefile';
  66.         if (file_exists($cachefile)) {
  67.             return unserialize(implode('', file($cachefile)));
  68.         }
  69.         return $this->retrieveData($url, $accept, $forcestring);
  70.     }
  71.  
  72.     /**
  73.      * Retrieve a remote REST resource
  74.      * @param string full URL to this resource
  75.      * @param array|false contents of the accept-encoding header
  76.      * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
  77.      *                    parsed using PEAR_XMLParser
  78.      * @return string|array
  79.      */
  80.     function retrieveData($url, $accept = false, $forcestring = false)
  81.     {
  82.         $cacheId = $this->getCacheId($url);
  83.         if ($ret = $this->useLocalCache($url, $cacheId)) {
  84.             return $ret;
  85.         }
  86.         if (!isset($this->_options['offline'])) {
  87.             $trieddownload = true;
  88.             $file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept);
  89.         } else {
  90.             $trieddownload = false;
  91.             $file = false;
  92.         }
  93.         if (PEAR::isError($file)) {
  94.             if ($file->getCode() == -9276) {
  95.                 $trieddownload = false;
  96.                 $file = false; // use local copy if available on socket connect error
  97.             } else {
  98.                 return $file;
  99.             }
  100.         }
  101.         if (!$file) {
  102.             $ret = $this->getCache($url);
  103.             if (!PEAR::isError($ret) && $trieddownload) {
  104.                 // reset the age of the cache if the server says it was unmodified
  105.                 $this->saveCache($url, $ret, null, true, $cacheId);
  106.             }
  107.             return $ret;
  108.         }
  109.         if (is_array($file)) {
  110.             $headers = $file[2];
  111.             $lastmodified = $file[1];
  112.             $content = $file[0];
  113.         } else {
  114.             $content = $file;
  115.             $lastmodified = false;
  116.             $headers = array();
  117.         }
  118.         if ($forcestring) {
  119.             $this->saveCache($url, $content, $lastmodified, false, $cacheId);
  120.             return $content;
  121.         }
  122.         if (isset($headers['content-type'])) {
  123.             switch ($headers['content-type']) {
  124.                 case 'text/xml' :
  125.                 case 'application/xml' :
  126.                     $parser = new PEAR_XMLParser;
  127.                     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  128.                     $err = $parser->parse($content);
  129.                     PEAR::popErrorHandling();
  130.                     if (PEAR::isError($err)) {
  131.                         return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' .
  132.                             $err->getMessage());
  133.                     }
  134.                     $content = $parser->getData();
  135.                 case 'text/html' :
  136.                 default :
  137.                     // use it as a string
  138.             }
  139.         } else {
  140.             // assume XML
  141.             $parser = new PEAR_XMLParser;
  142.             $parser->parse($content);
  143.             $content = $parser->getData();
  144.         }
  145.         $this->saveCache($url, $content, $lastmodified, false, $cacheId);
  146.         return $content;
  147.     }
  148.  
  149.     function useLocalCache($url, $cacheid = null)
  150.     {
  151.         if ($cacheid === null) {
  152.             $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
  153.                 md5($url) . 'rest.cacheid';
  154.             if (file_exists($cacheidfile)) {
  155.                 $cacheid = unserialize(implode('', file($cacheidfile)));
  156.             } else {
  157.                 return false;
  158.             }
  159.         }
  160.         $cachettl = $this->config->get('cache_ttl');
  161.         // If cache is newer than $cachettl seconds, we use the cache!
  162.         if (time() - $cacheid['age'] < $cachettl) {
  163.             return $this->getCache($url);
  164.         }
  165.         return false;
  166.     }
  167.  
  168.     function getCacheId($url)
  169.     {
  170.         $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
  171.             md5($url) . 'rest.cacheid';
  172.         if (file_exists($cacheidfile)) {
  173.             $ret = unserialize(implode('', file($cacheidfile)));
  174.             return $ret;
  175.         } else {
  176.             return false;
  177.         }
  178.     }
  179.  
  180.     function getCache($url)
  181.     {
  182.         $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
  183.             md5($url) . 'rest.cachefile';
  184.         if (file_exists($cachefile)) {
  185.             return unserialize(implode('', file($cachefile)));
  186.         } else {
  187.             return PEAR::raiseError('No cached content available for "' . $url . '"');
  188.         }
  189.     }
  190.  
  191.     /**
  192.      * @param string full URL to REST resource
  193.      * @param string original contents of the REST resource
  194.      * @param array  HTTP Last-Modified and ETag headers
  195.      * @param bool   if true, then the cache id file should be regenerated to
  196.      *               trigger a new time-to-live value
  197.      */
  198.     function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null)
  199.     {
  200.         $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
  201.             md5($url) . 'rest.cacheid';
  202.         $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
  203.             md5($url) . 'rest.cachefile';
  204.         if ($cacheid === null && $nochange) {
  205.             $cacheid = unserialize(implode('', file($cacheidfile)));
  206.         }
  207.  
  208.         $fp = @fopen($cacheidfile, 'wb');
  209.         if (!$fp) {
  210.             $cache_dir = $this->config->get('cache_dir');
  211.             if (!is_dir($cache_dir)) {
  212.                 System::mkdir(array('-p', $cache_dir));
  213.                 $fp = @fopen($cacheidfile, 'wb');
  214.                 if (!$fp) {
  215.                     return false;
  216.                 }
  217.             } else {
  218.                 return false;
  219.             }
  220.         }
  221.  
  222.         if ($nochange) {
  223.             fwrite($fp, serialize(array(
  224.                 'age'        => time(),
  225.                 'lastChange' => $cacheid['lastChange'],
  226.                 )));
  227.             fclose($fp);
  228.             return true;
  229.         } else {
  230.             fwrite($fp, serialize(array(
  231.                 'age'        => time(),
  232.                 'lastChange' => $lastmodified,
  233.                 )));
  234.         }
  235.         fclose($fp);
  236.         $fp = @fopen($cachefile, 'wb');
  237.         if (!$fp) {
  238.             if (file_exists($cacheidfile)) {
  239.                 @unlink($cacheidfile);
  240.             }
  241.             return false;
  242.         }
  243.         fwrite($fp, serialize($contents));
  244.         fclose($fp);
  245.         return true;
  246.     }
  247.  
  248.     /**
  249.      * Efficiently Download a file through HTTP.  Returns downloaded file as a string in-memory
  250.      * This is best used for small files
  251.      *
  252.      * If an HTTP proxy has been configured (http_proxy PEAR_Config
  253.      * setting), the proxy will be used.
  254.      *
  255.      * @param string  $url       the URL to download
  256.      * @param string  $save_dir  directory to save file in
  257.      * @param false|string|array $lastmodified header values to check against for caching
  258.      *                           use false to return the header values from this download
  259.      * @param false|array $accept Accept headers to send
  260.      * @return string|array  Returns the contents of the downloaded file or a PEAR
  261.      *                       error on failure.  If the error is caused by
  262.      *                       socket-related errors, the error object will
  263.      *                       have the fsockopen error code available through
  264.      *                       getCode().  If caching is requested, then return the header
  265.      *                       values.
  266.      *
  267.      * @access public
  268.      */
  269.     function downloadHttp($url, $lastmodified = null, $accept = false)
  270.     {
  271.         $info = parse_url($url);
  272.         if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
  273.             return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
  274.         }
  275.         if (!isset($info['host'])) {
  276.             return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
  277.         } else {
  278.             $host = $info['host'];
  279.             if (!array_key_exists('port', $info)) {
  280.                 $info['port'] = null;
  281.             }
  282.             if (!array_key_exists('path', $info)) {
  283.                 $info['path'] = null;
  284.             }
  285.             $port = $info['port'];
  286.             $path = $info['path'];
  287.         }
  288.         $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
  289.         if ($this->config->get('http_proxy')&&
  290.               $proxy = parse_url($this->config->get('http_proxy'))) {
  291.             $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
  292.             if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {
  293.                 $proxy_host = 'ssl://' . $proxy_host;
  294.             }
  295.             $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080;
  296.             $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null;
  297.             $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
  298.         }
  299.         if (empty($port)) {
  300.             if (isset($info['scheme']) && $info['scheme'] == 'https') {
  301.                 $port = 443;
  302.             } else {
  303.                 $port = 80;
  304.             }
  305.         }
  306.         If (isset($proxy['host'])) {
  307.             $request = "GET $url HTTP/1.1\r\n";
  308.             $request .= 'Host: ' . $proxy['host'] . ":$port\r\n";
  309.         } else {
  310.             $request = "GET $path HTTP/1.1\r\n";
  311.             $request .= "Host: $host:$port\r\n";
  312.         }
  313.  
  314.         $ifmodifiedsince = '';
  315.         if (is_array($lastmodified)) {
  316.             if (isset($lastmodified['Last-Modified'])) {
  317.                 $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
  318.             }
  319.             if (isset($lastmodified['ETag'])) {
  320.                 $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
  321.             }
  322.         } else {
  323.             $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
  324.         }
  325.         $request .= $ifmodifiedsince .
  326.             "User-Agent: PEAR/1.7.1/PHP/" . PHP_VERSION . "\r\n";
  327.         $username = $this->config->get('username');
  328.         $password = $this->config->get('password');
  329.         if ($username && $password) {
  330.             $tmp = base64_encode("$username:$password");
  331.             $request .= "Authorization: Basic $tmp\r\n";
  332.         }
  333.         if ($proxy_host != '' && $proxy_user != '') {
  334.             $request .= 'Proxy-Authorization: Basic ' .
  335.                 base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
  336.         }
  337.         if ($accept) {
  338.             $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
  339.         }
  340.         $request .= "Accept-Encoding:\r\n";
  341.         $request .= "Connection: close\r\n";
  342.         $request .= "\r\n";
  343.         if ($proxy_host != '') {
  344.             $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, 15);
  345.             if (!$fp) {
  346.                 return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr",
  347.                     -9276);
  348.             }
  349.         } else {
  350.             if (isset($info['scheme']) && $info['scheme'] == 'https') {
  351.                 $host = 'ssl://' . $host;
  352.             }
  353.             $fp = @fsockopen($host, $port, $errno, $errstr);
  354.             if (!$fp) {
  355.                 return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
  356.             }
  357.         }
  358.         fwrite($fp, $request);
  359.         $headers = array();
  360.         while (trim($line = fgets($fp, 1024))) {
  361.             if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
  362.                 $headers[strtolower($matches[1])] = trim($matches[2]);
  363.             } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
  364.                 if ($matches[1] == 304 && ($lastmodified || ($lastmodified === false))) {
  365.                     return false;
  366.                 }
  367.                 if ($matches[1] != 200) {
  368.                     return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)", (int) $matches[1]);
  369.                 }
  370.             }
  371.         }
  372.         if (isset($headers['content-length'])) {
  373.             $length = $headers['content-length'];
  374.         } else {
  375.             $length = -1;
  376.         }
  377.         $data = '';
  378.         while ($chunk = @fread($fp, 8192)) {
  379.             $data .= $chunk;
  380.         }
  381.         fclose($fp);
  382.         if ($lastmodified === false || $lastmodified) {
  383.             if (isset($headers['etag'])) {
  384.                 $lastmodified = array('ETag' => $headers['etag']);
  385.             }
  386.             if (isset($headers['last-modified'])) {
  387.                 if (is_array($lastmodified)) {
  388.                     $lastmodified['Last-Modified'] = $headers['last-modified'];
  389.                 } else {
  390.                     $lastmodified = $headers['last-modified'];
  391.                 }
  392.             }
  393.             return array($data, $lastmodified, $headers);
  394.         }
  395.         return $data;
  396.     }
  397. }
  398. ?>
  399.