[ Index ] |
|
Code source de GeekLog 1.4.1 |
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-2006 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.20 2006/03/02 03:09:31 pajoye 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-2006 The PHP Group 36 * @license http://www.php.net/license/3_0.txt PHP License 3.0 37 * @version Release: 1.4.11 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 @unlink($cacheidfile); 239 return false; 240 } 241 fwrite($fp, serialize($contents)); 242 fclose($fp); 243 return true; 244 } 245 246 /** 247 * Efficiently Download a file through HTTP. Returns downloaded file as a string in-memory 248 * This is best used for small files 249 * 250 * If an HTTP proxy has been configured (http_proxy PEAR_Config 251 * setting), the proxy will be used. 252 * 253 * @param string $url the URL to download 254 * @param string $save_dir directory to save file in 255 * @param false|string|array $lastmodified header values to check against for caching 256 * use false to return the header values from this download 257 * @param false|array $accept Accept headers to send 258 * @return string|array Returns the contents of the downloaded file or a PEAR 259 * error on failure. If the error is caused by 260 * socket-related errors, the error object will 261 * have the fsockopen error code available through 262 * getCode(). If caching is requested, then return the header 263 * values. 264 * 265 * @access public 266 */ 267 function downloadHttp($url, $lastmodified = null, $accept = false) 268 { 269 $info = parse_url($url); 270 if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) { 271 return PEAR::raiseError('Cannot download non-http URL "' . $url . '"'); 272 } 273 if (!isset($info['host'])) { 274 return PEAR::raiseError('Cannot download from non-URL "' . $url . '"'); 275 } else { 276 $host = $info['host']; 277 if (!array_key_exists('port', $info)) { 278 $info['port'] = null; 279 } 280 if (!array_key_exists('path', $info)) { 281 $info['path'] = null; 282 } 283 $port = $info['port']; 284 $path = $info['path']; 285 } 286 $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; 287 if ($this->config->get('http_proxy')&& 288 $proxy = parse_url($this->config->get('http_proxy'))) { 289 $proxy_host = @$proxy['host']; 290 if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { 291 $proxy_host = 'ssl://' . $proxy_host; 292 } 293 $proxy_port = @$proxy['port']; 294 $proxy_user = @$proxy['user']; 295 $proxy_pass = @$proxy['pass']; 296 297 if ($proxy_port == '') { 298 $proxy_port = 8080; 299 } 300 } 301 if (empty($port)) { 302 if (isset($info['scheme']) && $info['scheme'] == 'https') { 303 $port = 443; 304 } else { 305 $port = 80; 306 } 307 } 308 If (isset($proxy['host'])) { 309 $request = "GET $url HTTP/1.1\r\n"; 310 } else { 311 $request = "GET $path HTTP/1.1\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 .= "Host: $host:$port\r\n" . $ifmodifiedsince . 326 "User-Agent: PEAR/1.4.11/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 .= "Connection: close\r\n"; 341 $request .= "\r\n"; 342 if ($proxy_host != '') { 343 $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, 15); 344 if (!$fp) { 345 return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", 346 -9276); 347 } 348 } else { 349 if (isset($info['scheme']) && $info['scheme'] == 'https') { 350 $host = 'ssl://' . $host; 351 } 352 $fp = @fsockopen($host, $port, $errno, $errstr); 353 if (!$fp) { 354 return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno); 355 } 356 } 357 fwrite($fp, $request); 358 $headers = array(); 359 while (trim($line = fgets($fp, 1024))) { 360 if (preg_match('/^([^:]+):\s+(.*)\s*$/', $line, $matches)) { 361 $headers[strtolower($matches[1])] = trim($matches[2]); 362 } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { 363 if ($matches[1] == 304 && ($lastmodified || ($lastmodified === false))) { 364 return false; 365 } 366 if ($matches[1] != 200) { 367 return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)", (int) $matches[1]); 368 } 369 } 370 } 371 if (isset($headers['content-length'])) { 372 $length = $headers['content-length']; 373 } else { 374 $length = -1; 375 } 376 $data = ''; 377 while ($chunk = @fread($fp, 8192)) { 378 $data .= $chunk; 379 } 380 fclose($fp); 381 if ($lastmodified === false || $lastmodified) { 382 if (isset($headers['etag'])) { 383 $lastmodified = array('ETag' => $headers['etag']); 384 } 385 if (isset($headers['last-modified'])) { 386 if (is_array($lastmodified)) { 387 $lastmodified['Last-Modified'] = $headers['last-modified']; 388 } else { 389 $lastmodified = $headers['last-modified']; 390 } 391 } 392 return array($data, $lastmodified, $headers); 393 } 394 return $data; 395 } 396 } 397 ?>
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 |
![]() |