/**
* Fetches content of file from Internet (using proxy if defined). Uses cURL extension if present.
* @param string $url file url
+ * @param array $headers http headers, null if none
+ * @param array $postdata array means use POST request with given parameters
+ * @param bool $fullresponse return headers, responses, etc in a similar way snoopy does
+ * @param int $timeout connection timeout
* @return mixed false if request failed or content of the file as string if ok.
*/
-function download_file_content($url) {
+function download_file_content($url, $headers=null, $postdata=null, $fullresponse=false, $timeout=20) {
global $CFG;
- if (!extension_loaded('curl')) {
+ if (!extension_loaded('curl') or ($ch = curl_init($url)) === false) {
require_once($CFG->libdir.'/snoopy/Snoopy.class.inc');
$snoopy = new Snoopy();
- $snoopy->proxy_host = $CFG->proxyhost;
- $snoopy->proxy_port = $CFG->proxyport;
+ $snoopy->read_timeout = $timeout;
+ $snoopy->proxy_host = $CFG->proxyhost;
+ $snoopy->proxy_port = $CFG->proxyport;
if (!empty($CFG->proxyuser) and !empty($CFG->proxypassword)) {
// this will probably fail, but let's try it anyway
$snoopy->proxy_user = $CFG->proxyuser;
$snoopy->proxy_password = $CFG->proxypassword;
}
- if ($snoopy->fetch($url)) {
- if (strpos($snoopy->response_code, '200') === false) {
+ if (is_array($headers) ) {
+ $client->rawheaders = $headers;
+ }
+
+ if (is_array($postdata)) {
+ $fetch = @$snoopy->fetch($url, $postdata); // use more specific debug code bellow
+ } else {
+ $fetch = @$snoopy->fetch($url); // use more specific debug code bellow
+ }
+
+ if ($fetch) {
+ if ($fullresponse) {
+ //fix header line endings
+ foreach ($snoopy->headers as $key=>$unused) {
+ $snoopy->headers[$key] = trim($snoopy->headers[$key]);
+ }
+ $response = new object();
+ $response->status = $snoopy->status;
+ $response->headers = $snoopy->headers;
+ $response->response_code = trim($snoopy->response_code);
+ $response->results = $snoopy->results;
+ $response->error = $snoopy->error;
+ return $response;
+
+ } else if ($snoopy->status != 200) {
debugging("Snoopy request for \"$url\" failed, http response code: ".$snoopy->response_code, DEBUG_ALL);
return false;
+
} else {
return $snoopy->results;
}
} else {
- debugging("Snoopy request for \"$url\" failed with: ".$snoopy->error, DEBUG_ALL);
- return false;
+ if ($fullresponse) {
+ $response = new object();
+ $response->status = $snoopy->status;
+ $response->headers = array();
+ $response->response_code = $snoopy->response_code;
+ $response->results = '';
+ $response->error = $snoopy->error;
+ return $response;
+ } else {
+ debugging("Snoopy request for \"$url\" failed with: ".$snoopy->error, DEBUG_ALL);
+ return false;
+ }
+ }
+ }
+
+ // set extra headers, trim all newlines for extra security
+ if (is_array($headers) ) {
+ $headers2 = array();
+ foreach ($headers as $key => $value) {
+ $value = str_replace("\n", '', $value);
+ $value = str_replace("\r", '', $value);
+ $headers2[] = "$key: $value";
}
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers2);
+ }
+
+ // use POST if requested
+ if (is_array($postdata)) {
+ foreach ($postdata as $k=>$v) {
+ $postdata[$k] = urlencode($k).'='.urlencode($v);
+ }
+ $postdata = implode('&', $postdata);
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
}
- $ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_HEADER, true);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
+ if (!ini_get('open_basedir') and !ini_get('safe_mode')) {
+ // TODO: add version check for '7.10.5'
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
+ }
+
if (!empty($CFG->proxyhost)) {
// SOCKS supported in PHP5 only
if (!empty($CFG->proxytype) and ($CFG->proxytype == 'SOCKS5')) {
}
}
- // don't CONNECT for non-https connections
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, false);
if (empty($CFG->proxyport)) {
}
}
}
+
$result = curl_exec($ch);
+ // detect encoding problems
+ if ((curl_errno($ch) == 23 or curl_errno($ch) == 61) and defined('CURLOPT_ENCODING')) {
+ curl_setopt($ch, CURLOPT_ENCODING, 'none');
+ $result = curl_exec($ch);
+ }
+
if (curl_errno($ch)) {
- debugging("CURL request for \"$url\" failed with: ".curl_error($ch), DEBUG_ALL);
- $result = false;
+ $error = curl_error($ch);
+ $error_no = curl_errno($ch);
+ curl_close($ch);
+
+ if ($fullresponse) {
+ $response = new object();
+ if ($error_no == 28) {
+ $response->status = '-100'; // mimic snoopy
+ } else {
+ $response->status = '0';
+ }
+ $response->headers = array();
+ $response->response_code = $error;
+ $response->results = '';
+ $response->error = $error;
+ return $response;
+ } else {
+ debugging("CURL request for \"$url\" failed with: $error ($error_no)", DEBUG_ALL);
+ return false;
+ }
} else {
- $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- if ($code != 200) {
- $codes = array(
- 100=>'Continue',
- 101=>'Switching Protocols',
- 200=>'OK',
- 201=>'Created',
- 202=>'Accepted',
- 203=>'Non-Authoritative Information',
- 204=>'No Content',
- 205=>'Reset Content',
- 206=>'Partial Content',
- 300=>'Multiple Choices',
- 301=>'Moved Permanently',
- 302=>'Moved Temporarily',
- 303=>'See Other',
- 304=>'Not Modified',
- 305=>'Use Proxy',
- 306=>'(Unused)',
- 307=>'Temporary Redirect',
- 400=>'Bad Request',
- 401=>'Unauthorized',
- 402=>'Payment Required',
- 403=>'Forbidden',
- 404=>'Not Found',
- 405=>'Method Not Allowed',
- 406=>'Not Acceptable',
- 407=>'Proxy Authentication Required',
- 408=>'Request Timeout',
- 409=>'Conflict',
- 410=>'Gone',
- 411=>'Length Required',
- 412=>'Precondition Failed',
- 413=>'Request Entity Too Large',
- 414=>'Request-URI Too Long',
- 415=>'Unsupported Media Type',
- 416=>'Requested Range Not Satisfiable',
- 417=>'Expectation Failed',
- 500=>'Internal Server Error',
- 501=>'Not Implemented',
- 502=>'Bad Gateway',
- 503=>'Service Unavailable',
- 504=>'Gateway Timeout',
- 505=>'HTTP Version Not Supported');
-
- debugging("CURL request for \"$url\" failed, http response code: ".$code.' '.$codes[$code], DEBUG_ALL);
- $result = false;
+ $info = curl_getinfo($ch);
+ curl_close($ch);
+ // strip redirect headers and constrct headers array and body
+ $result = explode("\r\n\r\n", $result, $info['redirect_count'] + 2);
+ $results = array_pop($result);
+ $headers = array_pop($result);
+ $headers = explode("\r\n", trim($headers));
+
+ $response = new object();;
+ $response->status = (string)$info['http_code'];
+ $response->headers = $headers;
+ $response->response_code = $headers[0];
+ $response->results = $results;
+ $response->error = '';
+
+ if ($fullresponse) {
+ return $response;
+ } else if ($info['http_code'] != 200) {
+ debugging("CURL request for \"$url\" failed, http response code: $response_code", DEBUG_ALL);
+ return false;
+ } else {
+ return $response->results;
}
}
-
- curl_close($ch);
- return $result;
}
/**