state
: SIMPLEHTTP_STATE_NULL;
}
/**
* getMessages
*
* @return array
*/
function getMessages() {
global $instanceSimpleHTTP;
return (isset($instanceSimpleHTTP))
? $instanceSimpleHTTP->messages
: array();
}
/**
* getMessages
*
* @return string
*/
function getFilename() {
global $instanceSimpleHTTP;
return (isset($instanceSimpleHTTP))
? $instanceSimpleHTTP->filename
: "";
}
/**
* method to get data from URL -- uses timeout and user agent
*
* @param $get_url
* @param $get_referer
* @return string
*/
function getData($get_url, $get_referer = "") {
global $instanceSimpleHTTP;
// initialize if needed
if (!isset($instanceSimpleHTTP))
SimpleHTTP::initialize();
// call instance-method
return $instanceSimpleHTTP->instance_getData($get_url, $get_referer);
}
/**
* get torrent from URL. Has support for specific sites
*
* @param $durl
* @return string
*/
function getTorrent($durl) {
global $instanceSimpleHTTP;
// initialize if needed
if (!isset($instanceSimpleHTTP))
SimpleHTTP::initialize();
// call instance-method
return $instanceSimpleHTTP->instance_getTorrent($durl);
}
/**
* get nzb from URL.
*
* @param $durl
* @return string
*/
function getNzb($durl) {
global $instanceSimpleHTTP;
// initialize if needed
if (!isset($instanceSimpleHTTP))
SimpleHTTP::initialize();
// call instance-method
return $instanceSimpleHTTP->instance_getNzb($durl);
}
/**
* get size from URL.
*
* @param $durl
* @return int
*/
function getRemoteSize($durl) {
global $instanceSimpleHTTP;
// initialize if needed
if (!isset($instanceSimpleHTTP))
SimpleHTTP::initialize();
// call instance-method
return $instanceSimpleHTTP->instance_getRemoteSize($durl);
}
// =========================================================================
// ctor
// =========================================================================
/**
* do not use direct, use the factory-method !
*
* @return SimpleHTTP
*/
function SimpleHTTP() {
global $cfg;
// user-agent
$this->userAgent = $cfg['user_agent'];
// ini-settings
@ini_set("allow_url_fopen", "1");
@ini_set("user_agent", $this->userAgent);
}
// =========================================================================
// public methods
// =========================================================================
/**
* method to get data from URL -- uses timeout and user agent
*
* @param $get_url
* @param $get_referer
* @return string
*/
function instance_getData($get_url, $get_referer = "") {
global $cfg, $db;
// set fields
$this->url = $get_url;
$this->referer = $get_referer;
// (re)set state
$this->state = SIMPLEHTTP_STATE_NULL;
// (re-)set some vars
$this->cookie = "";
$this->request = "";
$this->responseBody = "";
$this->responseHeaders = array();
$this->gotResponseLine = false;
$this->status = "";
$this->errstr = "";
$this->errno = 0;
$this->socket = 0;
/**
* array of URL component parts for use in raw HTTP request
* @param array $domain
*/
$domain = parse_url($this->url);
if (
empty($domain) || // Check URL is a well-formed HTTP/HTTPS URL.
empty($domain['scheme']) || ($domain['scheme'] != 'http' && $domain['scheme'] != 'https') ||
empty($domain['host'])
) {
$this->state = SIMPLEHTTP_STATE_ERROR;
$msg = "Error fetching " . $this->url .". This is not a valid HTTP/HTTPS URL.";
array_push($this->messages, $msg);
AuditAction($cfg["constants"]["error"], $msg);
return($data="");
}
$secure = $domain['scheme'] == 'https';
if ($secure && !$this->_canTLS()) {
$this->state = SIMPLEHTTP_STATE_ERROR;
$msg = "Error fetching " . $this->url .". PHP does not have module OpenSSL, which is needed for HTTPS.";
array_push($this->messages, $msg);
AuditAction($cfg["constants"]["error"], $msg);
return($data="");
}
// get-command
if (!array_key_exists("path", $domain))
$domain["path"] = "/";
$this->getcmd = $domain["path"];
if (!array_key_exists("query", $domain))
$domain["query"] = "";
// append the query string if included:
$this->getcmd .= (!empty($domain["query"])) ? "?" . $domain["query"] : "";
// Check to see if cookie required for this domain:
$sql = "SELECT c.data AS data FROM tf_cookies AS c LEFT JOIN tf_users AS u ON ( u.uid = c.uid ) WHERE u.user_id = ".$db->qstr($cfg["user"])." AND c.host = ".$db->qstr($domain['host']);
$this->cookie = $db->GetOne($sql);
if ($db->ErrorNo() != 0) dbError($sql);
if (!array_key_exists("port", $domain))
$domain["port"] = $secure ? 443 : 80;
// Fetch the data using fsockopen():
$this->socket = @fsockopen( // connect to server, let PHP handle TLS layer for an HTTPS connection
($secure ? 'tls://' : '') . $domain["host"], $domain["port"],
$this->errno, $this->errstr, $this->timeout
);
if (!empty($this->socket)) {
// Write the outgoing HTTP request using cookie info
// Standard HTTP/1.1 request looks like:
//
// GET /url/path/example.php HTTP/1.1
// Host: example.com
// Accept: */*
// Accept-Language: en-us
// User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1) Gecko/20061010 Firefox/2.0
// Connection: Close
// Cookie: uid=12345;pass=asdfasdf;
//
//$this->request = "GET " . ($this->httpVersion=="1.1" ? $this->getcmd : $this->url ). " HTTP/" . $this->httpVersion ."\r\n";
$this->request = "GET ".$this->_fullURLEncode($this->getcmd)." HTTP/".$this->httpVersion."\r\n";
$this->request .= (!empty($this->referer)) ? "Referer: " . $this->referer . "\r\n" : "";
$this->request .= "Accept: */*\r\n";
$this->request .= "Accept-Language: en-us\r\n";
$this->request .= "User-Agent: ".$this->userAgent."\r\n";
$this->request .= "Host: " . $domain["host"] . "\r\n";
if($this->httpVersion=="1.1"){
$this->request .= "Connection: Close\r\n";
}
if(!empty($this->cookie)){
$this->request .= "Cookie: " . $this->cookie . "\r\n";
}
$this->request .= "\r\n";
// Send header packet information to server
fputs($this->socket, $this->request);
// socket-options
stream_set_timeout($this->socket, $this->timeout);
// meta-data
$info = stream_get_meta_data($this->socket);
// Get response headers:
while ((!$info['timed_out']) && ($line = @fgets($this->socket, 500000))) {
// First empty line/\r\n indicates end of response headers:
if($line == "\r\n"){
break;
}
if (!$this->gotResponseLine) {
preg_match("@HTTP/[^ ]+ (\d\d\d)@", $line, $matches);
// TODO: Use this to see if we redirected (30x) and follow the redirect:
$this->status = $matches[1];
$this->gotResponseLine = true;
continue;
}
// Get response headers:
preg_match("/^([^:]+):\s*(.*)/", trim($line), $matches);
$this->responseHeaders[strtolower($matches[1])] = $matches[2];
// meta-data
$info = stream_get_meta_data($this->socket);
}
if(
$this->httpVersion=="1.1"
&& isset($this->responseHeaders["transfer-encoding"])
&& !empty($this->responseHeaders["transfer-encoding"])
) {
/*
// NOT CURRENTLY WORKING, USE HTTP/1.0 ONLY UNTIL THIS IS FIXED!
*/
// Get body of HTTP response:
// Handle chunked encoding:
/*
length := 0
read chunk-size, chunk-extension (if any) and CRLF
while (chunk-size > 0) {
read chunk-data and CRLF
append chunk-data to entity-body
length := length + chunk-size
read chunk-size and CRLF
}
*/
// Used to count total of all chunk lengths, the content-length:
$chunkLength=0;
// Get first chunk size:
$chunkSize = hexdec(trim(fgets($this->socket)));
// 0 size chunk indicates end of content:
while ((!$info['timed_out']) && ($chunkSize > 0)) {
// Read in up to $chunkSize chars:
$line = @fgets($this->socket, $chunkSize);
// Discard crlf after current chunk:
fgets($this->socket);
// Append chunk to response body:
$this->responseBody .= $line;
// Keep track of total chunk/content length:
$chunkLength += $chunkSize;
// Read next chunk size:
$chunkSize = hexdec(trim(fgets($this->socket)));
// meta-data
$info = stream_get_meta_data($this->socket);
}
$this->responseHeaders["content-length"] = $chunkLength;
} else {
while ((!$info['timed_out']) && ($line = @fread($this->socket, 500000))) {
$this->responseBody .= $line;
// meta-data
$info = stream_get_meta_data($this->socket);
}
}
@fclose($this->socket); // Close our connection
} else {
return "Error fetching ".$this->url.". PHP Error No=".$this->errno." . PHP Error String=".$this->errstr;
}
/*
Check if we need to follow a redirect:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
Each of these HTTP response status codes indicates a redirect and the
content should be included in the Location field/header:
300 Multiple Locations
301 Moved Permanently
302 Found (has a temp location somewhere else on server)
303 See Other (should be fetched using GET, probably not relevant but won't hurt to include it)
307 Temporary Redirect
*/
if( preg_match("/^30[0-37]$/D", $this->status) > 0 ){
// Check we're not already over the max redirects limit:
if ( $this->redirectCount > $this->redirectMax ) {
$this->state = SIMPLEHTTP_STATE_ERROR;
$msg = "Error fetching " . $this->url .". The maximum number of allowed redirects ";
$msg .="(" .$this->redirectMax. ") was exceeded. Last followed URL was: " .$this->redirectUrl;
array_push($this->messages , $msg);
AuditAction($cfg["constants"]["error"], $msg);
return($data="");
} else {
$this->redirectCount++;
// Check we have a location to get redirected content:
if( isset($this->responseHeaders["location"]) && !empty($this->responseHeaders["location"]) ){
// 3 different cases for location header:
// - full URL (scheme://.../foobar) -- just go to that URL,
// - absolute URL (/foobar) -- keep everything up to host/port,
// and replace end of request,
// - relative URL (foobar) -- keep everything up to last component of path,
// and replace end of request.
$redirectLocation = $this->responseHeaders["location"];
if (preg_match('#^(ht|f)tp(s)?://#', $redirectLocation) > 0) {
// Case 1: full URL. Just use it.
$this->redirectUrl = $redirectLocation;
} else {
// Cases 2 or 3: partial URL.
// Keep scheme/user/pass/host/port of current request.
$redirectUrlBase =
$domain['scheme'].'://'.
((isset($domain['user']) || isset($domain['pass'])) ?
((isset($domain['user']) ? $domain['user'] : '').
(isset($domain['pass']) ? ':'.$domain['pass'] : '').'@') : '').
$domain['host'].
(isset($domain['port']) ? ':'.$domain['port'] : '');
if ($redirectLocation[0] == '/') {
// Case 2: absolute URL.
// Append it to current request's base.
$this->redirectUrl = $redirectUrlBase . $redirectLocation;
} else {
// Case 3: relative URL.
// Append it to current request's base + path stripped of its last component.
$domainPathAry = explode('/', $domain['path']);
array_splice($domainPathAry, -1, 1, $redirectLocation);
$domainPathNew = implode('/', $domainPathAry);
$this->redirectUrl =
$redirectUrlBase .
((isset($domainPathNew) &&
strlen($domainPathNew) > 0 &&
$domainPathNew[0] == '/') ? '' : '/') .
$domainPathNew;
}
}
} else {
$msg = "Error fetching " . $this->url .". A redirect status code (" . $this->status . ")";
$msg .= " was sent from the remote webserver, but no location header was set to obtain the redirected content from.";
AuditAction($cfg["constants"]["error"], $msg);
array_push($this->messages , $msg);
return($data="");
}
$this->instance_getData($this->redirectUrl);
}
}
// Trim any extraneous linefeed chars:
$this->responseBody = trim($this->responseBody, "\r\n");
// If a filename is associated with this content, assign it to $filename
if (isset($this->responseHeaders["content-disposition"]) && !empty($this->responseHeaders["content-disposition"])) {
// Content-disposition: attachment; filename="nameoffile":
// Don't think single quotes can be used to escape filename here, but just in case check for ' and ":
if (preg_match("/filename=(['\"])([^\\1]+)\\1/", $this->responseHeaders["content-disposition"], $matches)) {
if(isset($matches[2]) && !empty($matches[2])){
$file_name = $matches[2];
// Only accept filenames, not paths:
if (!preg_match("@/@", $file_name))
$this->filename = $file_name;
}
}
}
// state
$this->state = SIMPLEHTTP_STATE_OK;
// return content
return $this->responseBody;
}
/**
* get torrent from URL. Has support for specific sites
*
* @param $durl
* @return string
*/
function instance_getTorrent($durl) {
global $cfg;
// (re)set state
$this->state = SIMPLEHTTP_STATE_NULL;
// (re)set redir-count
$this->redirectCount = 0;
// Initialize file name:
$this->filename = "";
$domain = parse_url($durl);
// Check we have a remote URL:
if (!isset($domain["host"])) {
// Not a remote URL:
$msg = "The torrent requested for download (".$durl.") is not a remote torrent. Please enter a valid remote torrent URL such as http://example.com/example.torrent\n";
AuditAction($cfg["constants"]["error"], $msg);
array_push($this->messages , $msg);
// state
$this->state = SIMPLEHTTP_STATE_ERROR;
// return empty data:
return ($data="");
}
if (strtolower(substr($domain["path"], -8)) != ".torrent") {
/*
In these cases below, we check for torrent URLs that have to be manipulated in some
way to obtain the torrent content. These are sites that perhaps use redirection or
URL rewriting in some way.
*/
// Check known domain types
// mininova
if (strpos(strtolower($domain["host"]), "mininova") !== false) {
// Sample (http://www.mininova.org/rss.xml):
// http://www.mininova.org/tor/2254847
// FreeLinux.ISO.iso.torrent
// If received a /tor/ get the required information
if (strpos($durl, "/tor/") !== false) {
// Get the contents of the /tor/ to find the real torrent name
$data = $this->instance_getData($durl);
// Check for the tag used on mininova.org
if (preg_match("/(.[^<]+)<\/a>/i", $data, $data_preg_match)) {
// This is the real torrent filename
$this->filename = $data_preg_match[1];
}
// Change to GET torrent url
$durl = str_replace("/tor/", "/get/", $durl);
}
// Now fetch the torrent file
$data = $this->instance_getData($durl);
// demonoid
} elseif (strpos(strtolower($domain["host"]), "demonoid") !== false) {
// Sample (http://www.demonoid.com/rss/0.xml):
// http://www.demonoid.com/files/details/241739/6976998/
// ...
// If received a /details/ page url, change it to the download url
if (strpos($durl, "/details/") !== false) {
// Need to make it grab the torrent
$durl = str_replace("/details/", "/download/HTTP/", $durl);
}
// Now fetch the torrent file
$data = $this->instance_getData($durl);
// isohunt
} elseif (strpos(strtolower($domain["host"]), "isohunt") !== false) {
// Sample (http://isohunt.com/js/rss.php):
$treferer = "http://" . $domain["host"] . "/btDetails.php?id=";
// http://isohunt.com/torrent_details/7591035/
// http://isohunt.com/download/7591035/
// If the url points to the details page, change it to the download url
if (strpos($durl, "/torrent_details/") !== false) {
// Need to make it grab the torrent
$durl = str_replace("/torrent_details/", "/download/", $durl);
}
// old one, but still works:
// http://isohunt.com/btDetails.php?ihq=&id=8464972
// http://isohunt.com/download.php?mode=bt&id=8837938
// If the url points to the details page, change it to the download url
if (strpos(strtolower($durl), "/btdetails.php?") !== false) {
// Need to make it grab the torrent
$durl = str_replace("/btDetails.php?", "/download.php?", $durl) . "&mode=bt";
}
// Now fetch the torrent file
$data = $this->instance_getData($durl, $treferer);
// details.php
} elseif (strpos(strtolower($durl), "details.php?") !== false) {
// Sample (http://www.bitmetv.org/rss.php?passkey=123456):
// http://www.bitmetv.org/details.php?id=18435&hit=1
// Strip final &hit=1 if present, since it only ever returns a 302
// redirect to the same URL without the &hit=1.
$durl2 = preg_replace('/&hit=1$/', '', $durl);
$treferer = "http://" . $domain["host"] . "/details.php?id=";
$data = $this->instance_getData($durl2, $treferer);
// Sample (http://www.bitmetv.org/details.php?id=18435)
// download.php/18435/SpiderMan%20Season%204.torrent
if (preg_match("/(download.php.[^\"]+)/i", $data, $data_preg_match)) {
$torrent = substr($data_preg_match[0], 0, -1);
$turl2 = "http://" . $domain["host"] . "/" . $torrent;
$data = $this->instance_getData($turl2);
} else {
$msg = "Error: could not find link to torrent file in $durl";
AuditAction($cfg["constants"]["error"], $msg);
array_push($this->messages , $msg);
// state
$this->state = SIMPLEHTTP_STATE_ERROR;
// return empty data:
return($data="");
}
// torrentspy
} elseif (strpos(strtolower($domain["host"]), "torrentspy") !== false) {
// Sample (http://torrentspy.com/rss.asp):
// http://www.torrentspy.com/torrent/1166188/gentoo_livedvd_i686_installer_2007_0
$treferer = "http://" . $domain["host"] . "/download.asp?id=";
$data = $this->instance_getData($durl, $treferer);
// If received a /download.asp?, a /directory.asp?mode=torrentdetails
// or a /torrent/, extract real torrent link
if (
strpos($durl, "/download.asp?") !== false ||
strpos($durl, "/directory.asp?mode=torrentdetails") !== false ||
strpos($durl, "/torrent/") !== false
) {
// Check for the tag used in download details page
if (preg_match("#]*?\s+href=\"(http[^\"]+)\"#i", $data, $data_preg_match)) {
// This is the real torrent download link
$durl = $data_preg_match[1];
// Follow it
$data = $this->instance_getData($durl);
}
}
// download.asp
} elseif (strpos(strtolower($durl), "download.asp?") !== false) {
$treferer = "http://" . $domain["host"] . "/download.asp?id=";
$data = $this->instance_getData($durl, $treferer);
// default
} else {
// Fallback case for any URL not ending in .torrent and not matching the above cases:
$data = $this->instance_getData($durl);
}
} else {
$data = $this->instance_getData($durl);
}
// Make sure we have a torrent file
if (strpos($data, "d8:") === false) {
// We don't have a Torrent File... it is something else. Let the user know about it:
$msg = "Content returned from $durl does not appear to be a valid torrent.";
AuditAction($cfg["constants"]["error"], $msg);
array_push($this->messages , $msg);
// Display the first part of $data if debuglevel higher than 1:
if ($cfg["debuglevel"] > 1){
if (strlen($data) > 0){
array_push($this->messages , "Displaying first 1024 chars of output: ");
array_push($this->messages , htmlentities(substr($data, 0, 1023)), ENT_QUOTES);
} else {
array_push($this->messages , "Output from $durl was empty.");
}
} else {
array_push($this->messages , "Set debuglevel > 2 in 'Admin, Webapps' to see the content returned from $durl.");
}
$data = "";
// state
$this->state = SIMPLEHTTP_STATE_ERROR;
} else {
// If the torrent file name isn't set already, do it now:
if ((!isset($this->filename)) || (strlen($this->filename) == 0)) {
// Get the name of the torrent, and make it the filename
if (preg_match("/name([0-9][^:]):(.[^:]+)/i", $data, $data_preg_match)) {
$filelength = $data_preg_match[1];
$file_name = $data_preg_match[2];
$this->filename = substr($file_name, 0, $filelength).".torrent";
} else {
require_once('inc/classes/BDecode.php');
$btmeta = @BDecode($data);
$this->filename = ((is_array($btmeta)) && (!empty($btmeta['info'])) && (!empty($btmeta['info']['name'])))
? trim($btmeta['info']['name']).".torrent"
: "";
}
}
// state
$this->state = SIMPLEHTTP_STATE_OK;
}
return $data;
}
/**
* get nzb from URL
*
* @param $durl
* @return string
*/
function instance_getNzb($durl) {
global $cfg;
// (re)set state
$this->state = SIMPLEHTTP_STATE_NULL;
// (re)set redir-count
$this->redirectCount = 0;
// Initialize file name:
$this->filename = "";
$domain = parse_url($durl);
// Check we have a remote URL:
if (!isset($domain["host"])) {
// Not a remote URL:
$msg = "The nzb requested for download (".$durl.") is not a remote nzb. Please enter a valid remote nzb URL such as http://example.com/example.nzb\n";
AuditAction($cfg["constants"]["error"], $msg);
array_push($this->messages , $msg);
// state
$this->state = SIMPLEHTTP_STATE_ERROR;
// return empty data:
return ($data="");
}
if (strtolower(substr($domain["path"], -4)) != ".nzb") {
/*
In these cases below, we check for URLs that have to be manipulated in some
way to obtain the content. These are sites that perhaps use redirection or
URL rewriting in some way.
*/
// details.php
if (strpos(strtolower($durl), "details.php?") !== false) {
// Sample (http://www.bitmetv.org/rss.php?passkey=123456):
// http://www.bitmetv.org/details.php?id=18435&hit=1
// Strip final &hit=1 if present, since it only ever returns a 302
// redirect to the same URL without the &hit=1.
$durl2 = preg_replace('/&hit=1$/', '', $durl);
$treferer = "http://" . $domain["host"] . "/details.php?id=";
$data = $this->instance_getData($durl, $treferer);
// Sample (http://www.bitmetv.org/details.php?id=18435)
// download.php/18435/SpiderMan%20Season%204.torrent
if (preg_match("/(download.php.[^\"]+)/i", $data, $data_preg_match)) {
$tr = substr($data_preg_match[0], 0, -1);
$turl2 = "http://" . $domain["host"] . "/" . $tr;
$data = $this->instance_getData($turl2);
} else {
$msg = "Error: could not find link to nzb file in $durl";
AuditAction($cfg["constants"]["error"], $msg);
array_push($this->messages , $msg);
// state
$this->state = SIMPLEHTTP_STATE_ERROR;
// return empty data:
return($data="");
}
// download.asp
} elseif (strpos(strtolower($durl), "download.asp?") !== false) {
// Sample (TF's TorrentSpy Search):
// http://www.torrentspy.com/download.asp?id=519793
$treferer = "http://" . $domain["host"] . "/download.asp?id=";
$data = $this->instance_getData($durl, $treferer);
// default
} else {
// Fallback case for any URL not ending in .nzb and not matching the above cases:
$data = $this->instance_getData($durl);
}
} else {
$data = $this->instance_getData($durl);
}
// Make sure we have a nzb file
if (strpos($data, "nzb") === false) {
// We don't have a nzb File... it is something else. Let the user know about it:
$msg = "Content returned from $durl does not appear to be a valid nzb.";
AuditAction($cfg["constants"]["error"], $msg);
array_push($this->messages , $msg);
// Display the first part of $data if debuglevel higher than 1:
if ($cfg["debuglevel"] > 1){
if (strlen($data) > 0){
array_push($this->messages , "Displaying first 1024 chars of output: ");
array_push($this->messages , htmlentities(substr($data, 0, 1023)), ENT_QUOTES);
} else {
array_push($this->messages , "Output from $durl was empty.");
}
} else {
array_push($this->messages , "Set debuglevel > 2 in 'Admin, Webapps' to see the content returned from $durl.");
}
$data = "";
// state
$this->state = SIMPLEHTTP_STATE_ERROR;
} else {
// state
$this->state = SIMPLEHTTP_STATE_OK;
}
return $data;
}
/**
* get size from URL.
*
* @param $durl
* @return string
*/
function instance_getRemoteSize($durl) {
// set fields
$this->url = $durl;
$this->timeout = 8;
$this->status = "";
$this->errstr = "";
$this->errno = 0;
// domain
$domain = parse_url($this->url);
if (!isset($domain["port"]))
$domain["port"] = 80;
// check we have a remote URL:
if (!isset($domain["host"]))
return 0;
// check we have a remote path:
if (!isset($domain["path"]))
return 0;
// open socket
$this->socket = @fsockopen($domain["host"], $domain["port"], $this->errno, $this->errstr, $this->timeout);
if (!$this->socket)
return 0;
// send HEAD request
$this->request = "HEAD ".$domain["path"]." HTTP/1.0\r\nConnection: Close\r\n\r\n";
@fwrite($this->socket, $this->request);
// socket options
stream_set_timeout($this->socket, $this->timeout);
// meta data
$info = stream_get_meta_data($this->socket);
// read the response
$this->responseBody = "";
$ctr = 0;
while ((!$info['timed_out']) && ($ctr < 25)) {
$s = @fgets($this->socket, 4096);
$this->responseBody .= $s;
if (strcmp($s, "\r\n") == 0 || strcmp($s, "\n") == 0)
break;
// meta data
$info = stream_get_meta_data($this->socket);
// increment counter
$ctr++;
}
// close socket
@fclose($this->socket);
// try to get Content-Length in response-body
preg_match('/Content-Length:\s([0-9].+?)\s/', $this->responseBody, $matches);
return (isset($matches[1]))
? $matches[1]
: 0;
}
/**
* Check whether PHP can do TLS.
*
* @return bool
*/
function _canTLS() {
// Just check whether openssl extension is available.
if (!isset($this->canTLS))
$this->canTLS = extension_loaded('openssl');
return $this->canTLS;
}
/**
* URL-encode all fragments of an URL, not re-encoding what is already encoded.
*
* @param $url
* @return string
*/
function _fullURLEncode($url) {
# Split URL into fragments, delimiters are: '+', ':', '@', '/', '?', '=', '&' and /%[[:xdigit:]]{2}/.
$fragments = preg_split('#[+:@/?=&]+|%[[:xdigit:]]{2}#', $url, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
for ($i = count($fragments) - 1; $i >= 0; $i--) {
$fragment = $fragments[$i]; # $fragment[0] is the fragment, $fragment[1] is its starting position.
$url = substr_replace($url, rawurlencode($fragment[0]), $fragment[1], strlen($fragment[0]));
}
return $url;
}
}
?>