";
* // ----------------------------------------------------------------------------
*
*
* // Example POST request:
* // ----------------------------------------------------------------------------
* $keyword = "blitzaffe code"; // search Google for this keyword
* $values = array(
* "hl"=>"en",
* "q"=>"%22".urlencode($keyword)."%22",
* "btnG"=>"Search",
* "meta"=>""
* );
* // Note: This example is just to demonstrate the POST equivalent of the GET
* // example above; running this script will return a 501 Not Implemented, as
* // Google does not support POST requests.
* if (!$http->post("http://www.google.com/search",$http->make_query_string($values))) {
* echo "HTTP request error: #{$http->result_code}: {$http->result_text}";
* return false;
* }
* echo "HTTP response headers:
";
* var_dump($http->response_headers);
* echo "
";
*
* echo "Page content:
";
* echo $http->response;
* echo "
";
* // ----------------------------------------------------------------------------
*
*
* LICENSE
*
* This script is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This script is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with this script; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// define user agent ID's
define("UA_EXPLORER",0);
define("UA_MOZILLA",1);
define("UA_FIREFOX",2);
define("UA_OPERA",3);
// define progress message severity levels
define('HRP_DEBUG',0);
define('HRP_INFO',1);
define('HRP_ERROR',2);
if (!defined("CURL_PATH")) define("CURL_PATH","/usr/bin/curl");
// if the CURL extension is not loaded, but the CURL Emulation Library is found, try
// to load it
if (!extension_loaded("curl") && !defined('HTTPR_NO_REDECLARE_CURL') ) {
foreach (array(dirname(__FILE__)."/",dirname(__FILE__)."/libcurlemu/") as $k=>$libcurlemupath) {
$libcurlemuinc = $libcurlemupath.'libcurlexternal.inc.php';
if (is_readable($libcurlemuinc)) require_once($libcurlemuinc);
}
}
class HTTPRetriever {
// Constructor
function HTTPRetriever() {
// default HTTP headers to send with all requests
$this->headers = array(
"Referer"=>"",
"User-Agent"=>"HTTPRetriever/1.0",
"Connection"=>"close"
);
// HTTP version (has no effect if using CURL)
$this->version = "1.1";
// Normally, CURL is only used for HTTPS requests; setting this to
// TRUE will force CURL for HTTP requests as well. Not recommended.
$this->force_curl = false;
// If you don't want to use CURL at all, set this to TRUE.
$this->disable_curl = false;
// If HTTPS request return an error message about SSL certificates in
// $this->error and you don't care about security, set this to TRUE
$this->insecure_ssl = false;
// Set the maximum time to wait for a connection
$this->connect_timeout = 15;
// Set the maximum time to allow a transfer to run, or 0 to disable.
$this->max_time = 0;
// Set the maximum time for a socket read/write operation, or 0 to disable.
$this->stream_timeout = 0;
// If you're making an HTTPS request to a host whose SSL certificate
// doesn't match its domain name, AND YOU FULLY UNDERSTAND THE
// SECURITY IMPLICATIONS OF IGNORING THIS PROBLEM, set this to TRUE.
$this->ignore_ssl_hostname = false;
// If TRUE, the get() and post() methods will close the connection
// and return immediately after receiving the HTTP result code
$this->result_close = false;
// If set to a positive integer value, retrieved pages will be cached
// for this number of seconds. Any subsequent calls within the cache
// period will return the cached page, without contacting the remote
// server.
$this->caching = false;
// If $this->caching is enabled, this specifies the folder under which
// cached pages are saved.
$this->cache_path = '/tmp/';
// Set these to perform basic HTTP authentication
$this->auth_username = '';
$this->auth_password = '';
// Optionally set this to a valid callback method to have HTTPRetriever
// provide progress messages. Your callback must accept 2 parameters:
// an integer representing the severity (0=debug, 1=information, 2=error),
// and a string representing the progress message
$this->progress_callback = null;
// Optionally set this to a valid callback method to have HTTPRetriever
// provide bytes-transferred messages. Your callbcak must accept 2
// parameters: an integer representing the number of bytes transferred,
// and an integer representing the total number of bytes expected (or
// -1 if unknown).
$this->transfer_callback = null;
// Set this to TRUE if you HTTPRetriever to transparently follow HTTP
// redirects (code 301, 302, 303, and 307). Optionally set this to a
// numeric value to limit the maximum number of redirects to the specified
// value. (Redirection loops are detected automatically.)
// Note that non-GET/HEAD requests will NOT be redirected except on code
// 303, as per HTTP standards.
$this->follow_redirects = false;
}
// Send an HTTP GET request to $url; if $ipaddress is specified, the
// connection will be made to the selected IP instead of resolving the
// hostname in $url.
//
// If $cookies is set, it should be an array in one of two formats.
//
// Either: $cookies[ 'cookiename' ] = array (
// '/path/'=>array(
// 'expires'=>time(),
// 'domain'=>'yourdomain.com',
// 'value'=>'cookievalue'
// )
// );
//
// Or, a more simplified format:
// $cookies[ 'cookiename' ] = 'value';
//
// The former format will automatically check to make sure that the path, domain,
// and expiration values match the HTTP request, and will only send the cookie if
// they do match. The latter will force the cookie to be set for the HTTP request
// unconditionally.
//
function get($url,$ipaddress = false,$cookies = false) {
$this->method = "GET";
$this->post_data = "";
$this->connect_ip = $ipaddress;
return $this->_execute_request($url,$cookies);
}
// Send an HTTP POST request to $url containing the POST data $data. See ::get()
// for a description of the remaining arguments.
function post($url,$data="",$ipaddress = false,$cookies = false) {
$this->method = "POST";
$this->post_data = $data;
$this->connect_ip = $ipaddress;
return $this->_execute_request($url,$cookies);
}
// Send an HTTP HEAD request to $url. See ::get() for a description of the arguments.
function head($url,$ipaddress = false,$cookies = false) {
$this->method = "HEAD";
$this->post_data = "";
$this->connect_ip = $ipaddress;
return $this->_execute_request($url,$cookies);
}
// send an alternate (non-GET/POST) HTTP request to $url
function custom($method,$url,$data="",$ipaddress = false,$cookies = false) {
$this->method = $method;
$this->post_data = $data;
$this->connect_ip = $ipaddress;
return $this->_execute_request($url,$cookies);
}
function array_to_query($arrayname,$arraycontents) {
$output = "";
foreach ($arraycontents as $key=>$value) {
if (is_array($value)) {
$output .= $this->array_to_query(sprintf('%s[%s]',$arrayname,urlencode($key)),$value);
} else {
$output .= sprintf('%s[%s]=%s&',$arrayname,urlencode($key),urlencode($value));
}
}
return $output;
}
// builds a query string from the associative array array $data;
// returns a string that can be passed to $this->post()
function make_query_string($data) {
$output = "";
if (is_array($data)) {
foreach ($data as $name=>$value) {
if (is_array($value)) {
$output .= $this->array_to_query(urlencode($name),$value);
} elseif (is_scalar($value)) {
$output .= urlencode($name)."=".urlencode($value)."&";
} else {
$output .= urlencode($name)."=".urlencode(serialize($value)).'&';
}
}
}
return substr($output,0,strlen($output)-1);
}
// this is pretty limited... but really, if you're going to spoof you UA, you'll probably
// want to use a Windows OS for the spoof anyway
//
// if you want to set the user agent to a custom string, just assign your string to
// $this->headers["User-Agent"] directly
function set_user_agent($agenttype,$agentversion,$windowsversion) {
$useragents = array(
"Mozilla/4.0 (compatible; MSIE %agent%; Windows NT %os%)", // IE
"Mozilla/5.0 (Windows; U; Windows NT %os%; en-US; rv:%agent%) Gecko/20040514", // Moz
"Mozilla/5.0 (Windows; U; Windows NT %os%; en-US; rv:1.7) Gecko/20040803 Firefox/%agent%", // FFox
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT %os%) Opera %agent% [en]", // Opera
);
$agent = $useragents[$agenttype];
$this->headers["User-Agent"] = str_replace(array("%agent%","%os%"),array($agentversion,$windowsversion),$agent);
}
// this isn't presently used as it's now handled inline by the request parser
function remove_chunkiness() {
$remaining = $this->response;
$this->response = "";
while ($remaining) {
$hexlen = strpos($remaining,"\r");
$chunksize = substr($remaining,0,$hexlen);
$argstart = strpos($chunksize,';');
if ($argstart!==false) $chunksize = substr($chunksize,0,$argstart);
$chunksize = (int) @hexdec($chunksize);
$this->response .= substr($remaining,$hexlen+2,$chunksize);
$remaining = substr($remaining,$hexlen+2+$chunksize+2);
if (!$chunksize) {
// either we're done, or something's borked... exit
$this->response .= $remaining;
return;
}
}
}
// (internal) store a page in the cache
function _cache_store($token) {
$values = array(
"stats"=>$this->stats,
"result_code"=>$this->result_code,
"result_text"=>$this->result_text,
"version"=>$this->version,
"response"=>$this->response,
"response_headers"=>$this->response_headers,
"response_cookies"=>$this->response_cookies,
"raw_response"=>$this->raw_response,
);
$values = serialize($values);
$filename = $this->cache_path.$token.'.tmp';
$fp = @fopen($filename,"w");
if (!$fp) {
$this->progress(HRP_DEBUG,"Unable to create cache file");
return false;
}
fwrite($fp,$values);
fclose($fp);
$this->progress(HRP_DEBUG,"HTTP response stored to cache");
}
// (internal) fetch a page from the cache
function _cache_fetch($token) {
$this->cache_hit = false;
$this->progress(HRP_DEBUG,"Checking for cached page value");
$filename = $this->cache_path.$token.'.tmp';
if (!file_exists($filename)) {
$this->progress(HRP_DEBUG,"Page not available in cache");
return false;
}
if (time()-filemtime($filename)>$this->caching) {
$this->progress(HRP_DEBUG,"Page in cache is expired");
@unlink($filename);
return false;
}
if ($values = file_get_contents($filename)) {
$values = unserialize($values);
if (!$values) {
$this->progress(HRP_DEBUG,"Invalid cache contents");
return false;
}
$this->stats = $values["stats"];
$this->result_code = $values["result_code"];
$this->result_text = $values["result_text"];
$this->version = $values["version"];
$this->response = $values["response"];
$this->response_headers = $values["response_headers"];
$this->response_cookies = $values["response_cookies"];
$this->raw_response = $values["raw_response"];
$this->progress(HRP_DEBUG,"Page loaded from cache");
$this->cache_hit = true;
return true;
} else {
$this->progress(HRP_DEBUG,"Error reading cache file");
return false;
}
}
function parent_path($path) {
if (substr($path,0,1)=='/') $path = substr($path,1);
if (substr($path,-1)=='/') $path = substr($path,0,strlen($path)-1);
$path = explode('/',$path);
array_pop($path);
return count($path) ? ('/' . implode('/',$path)) : '';
}
// $cookies should be an array in one of two formats.
//
// Either: $cookies[ 'cookiename' ] = array (
// '/path/'=>array(
// 'expires'=>time(),
// 'domain'=>'yourdomain.com',
// 'value'=>'cookievalue'
// )
// );
//
// Or, a more simplified format:
// $cookies[ 'cookiename' ] = 'value';
//
// The former format will automatically check to make sure that the path, domain,
// and expiration values match the HTTP request, and will only send the cookie if
// they do match. The latter will force the cookie to be set for the HTTP request
// unconditionally.
//
function response_to_request_cookies($cookies,$urlinfo) {
// check for simplified cookie format (name=value)
$cookiekeys = array_keys($cookies);
if (!count($cookiekeys)) return;
$testkey = array_pop($cookiekeys);
if (!is_array($cookies[ $testkey ])) {
foreach ($cookies as $k=>$v) $this->request_cookies[$k] = $v;
return;
}
// must not be simplified format, so parse as complex format:
foreach ($cookies as $name=>$paths) {
foreach ($paths as $path=>$values) {
// make sure the cookie isn't expired
if ( isset($values['expires']) && ($values['expires']