Example #1
0
/**
 * Return the file in the URL by downloading it over HTTP. If a byte limit is given, it will only download that many bytes. It outputs warnings, returning NULL, on error.
 *
 * @param  URLPATH		The URL to download
 * @param  ?integer		The number of bytes to download. This is not a guarantee, it is a minimum (NULL: all bytes)
 * @range  1 max
 * @param  boolean		Whether to throw an ocPortal error, on error
 * @param  boolean		Whether to block redirects (returns NULL when found)
 * @param  string			The user-agent to identify as
 * @param  ?array			An optional array of POST parameters to send; if this is NULL, a GET request is used (NULL: none)
 * @param  ?array			An optional array of cookies to send (NULL: none)
 * @param  ?string		'accept' header value (NULL: don't pass one)
 * @param  ?string		'accept-charset' header value (NULL: don't pass one)
 * @param  ?string		'accept-language' header value (NULL: don't pass one)
 * @param  ?resource		File handle to write to (NULL: do not do that)
 * @param  ?string		The HTTP referer (NULL: none)
 * @param  ?array			A pair: authentication username and password (NULL: none)
 * @param  float			The timeout
 * @param  boolean		Whether to treat the POST parameters as a raw POST (rather than using MIME)
 * @param  ?array			Files to send. Map between field to file path (NULL: none)
 * @return ?string		The data downloaded (NULL: error)
 */
function http_download_file($url, $byte_limit = NULL, $trigger_error = true, $no_redirect = false, $ua = 'ocPortal', $post_params = NULL, $cookies = NULL, $accept = NULL, $accept_charset = NULL, $accept_language = NULL, $write_to_file = NULL, $referer = NULL, $auth = NULL, $timeout = 6.0, $is_xml = false, $files = NULL)
{
    require_code('files2');
    return _http_download_file($url, $byte_limit, $trigger_error, $no_redirect, $ua, $post_params, $cookies, $accept, $accept_charset, $accept_language, $write_to_file, $referer, $auth, $timeout, $is_xml, $files);
}
Example #2
0
/**
 * Return the file in the URL by downloading it over HTTP. If a byte limit is given, it will only download that many bytes. It outputs warnings, returning NULL, on error.
 *
 * @param  URLPATH		The URL to download
 * @param  ?integer		The number of bytes to download. This is not a guarantee, it is a minimum (NULL: all bytes)
 * @range  1 max
 * @param  boolean		Whether to throw an ocPortal error, on error
 * @param  boolean		Whether to block redirects (returns NULL when found)
 * @param  string			The user-agent to identify as
 * @param  ?array			An optional array of POST parameters to send; if this is NULL, a GET request is used (NULL: none)
 * @param  ?array			An optional array of cookies to send (NULL: none)
 * @param  ?string		'accept' header value (NULL: don't pass one)
 * @param  ?string		'accept-charset' header value (NULL: don't pass one)
 * @param  ?string		'accept-language' header value (NULL: don't pass one)
 * @param  ?resource		File handle to write to (NULL: do not do that)
 * @param  ?string		The HTTP referer (NULL: none)
 * @param  ?array			A pair: authentication username and password (NULL: none)
 * @param  float			The timeout
 * @param  boolean		Whether to treat the POST parameters as a raw POST (rather than using MIME)
 * @param  ?array			Files to send. Map between field to file path (NULL: none)
 * @return ?string		The data downloaded (NULL: error)
 */
function _http_download_file($url, $byte_limit = NULL, $trigger_error = true, $no_redirect = false, $ua = 'ocPortal', $post_params = NULL, $cookies = NULL, $accept = NULL, $accept_charset = NULL, $accept_language = NULL, $write_to_file = NULL, $referer = NULL, $auth = NULL, $timeout = 6.0, $is_xml = false, $files = NULL)
{
    $url = str_replace(' ', '%20', $url);
    // Prevent DOS loop attack
    if (ocp_srv('HTTP_USER_AGENT') == $ua) {
        $ua = 'ocP-recurse';
    }
    if (ocp_srv('HTTP_USER_AGENT') == 'ocP-recurse') {
        return NULL;
    }
    require_code('urls');
    if (url_is_local($url)) {
        $url = get_custom_base_url() . '/' . $url;
    }
    if (strpos($url, '/') !== false && strrpos($url, '/') < 7) {
        $url .= '/';
    }
    global $DOWNLOAD_LEVEL;
    $DOWNLOAD_LEVEL++;
    global $HTTP_DOWNLOAD_MIME_TYPE;
    $HTTP_DOWNLOAD_MIME_TYPE = NULL;
    global $HTTP_CHARSET;
    $HTTP_CHARSET = NULL;
    global $HTTP_DOWNLOAD_SIZE;
    $HTTP_DOWNLOAD_SIZE = 0;
    global $HTTP_DOWNLOAD_URL;
    $HTTP_DOWNLOAD_URL = $url;
    global $HTTP_MESSAGE;
    $HTTP_MESSAGE = NULL;
    global $HTTP_MESSAGE_B;
    $HTTP_MESSAGE_B = NULL;
    global $HTTP_NEW_COOKIES;
    if ($DOWNLOAD_LEVEL == 0) {
        $HTTP_NEW_COOKIES = array();
    }
    global $HTTP_FILENAME;
    $HTTP_FILENAME = NULL;
    if ($DOWNLOAD_LEVEL == 8) {
        return '';
    }
    //critical_error('FILE_DOS',$url); // Prevent possible DOS attack
    $url_parts = @parse_url($url);
    if ($url_parts === false || !isset($url_parts['host'])) {
        if ($trigger_error) {
            warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_BAD_URL', escape_html($url)));
        } else {
            $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_BAD_URL', escape_html($url));
        }
        $DOWNLOAD_LEVEL--;
        $HTTP_MESSAGE = 'malconstructed-URL';
        return NULL;
    }
    if (!array_key_exists('scheme', $url_parts)) {
        $url_parts['scheme'] = 'http';
    }
    $use_curl = $url_parts['scheme'] != 'http' && function_exists('curl_version') || function_exists('get_value') && get_value('prefer_curl') === '1';
    // Prep cookies and post data
    if (!is_null($post_params)) {
        if ($is_xml) {
            $_postdetails_params = $post_params[0];
        } else {
            $_postdetails_params = '';
            //$url_parts['scheme'].'://'.$url_parts['host'].$url2.'?';
            $first = true;
            if (array_keys($post_params) == array('_')) {
                $_postdetails_params = $post_params['_'];
            } else {
                foreach ($post_params as $param_key => $param_value) {
                    if ($use_curl) {
                        if (substr($param_value, 0, 1) == '@') {
                            $param_value = ' @' . substr($param_value, 1);
                        }
                    }
                    $_postdetails_params .= array_key_exists('query', $url_parts) || !$first ? '&' . $param_key . '=' . rawurlencode($param_value) : $param_key . '=' . rawurlencode($param_value);
                    $first = false;
                }
            }
        }
    } else {
        $_postdetails_params = '';
    }
    if (!is_null($cookies) && count($cookies) != 0) {
        $_cookies = '';
        $done_one_cookie = false;
        foreach ($cookies as $key => $val) {
            if ($done_one_cookie) {
                $_cookies .= '; ';
            }
            if (is_array($val)) {
                foreach ($val as $key2 => $val2) {
                    if (!is_string($key2)) {
                        $key2 = strval($key2);
                    }
                    if ($done_one_cookie) {
                        $_cookies .= '; ';
                    }
                    $_cookies .= $key . '[' . $key2 . ']=' . rawurlencode($val2);
                    $done_one_cookie = true;
                }
            } else {
                $_cookies .= $key . '=' . rawurlencode($val);
            }
            $done_one_cookie = true;
        }
    }
    if ($use_curl) {
        if (!is_null($files)) {
            if (is_null($post_params)) {
                $post_params = array();
            }
            foreach ($files as $upload_field => $file_path) {
                $post_params[$upload_field] = '@' . $file_path;
            }
        }
        // CURL
        if (function_exists('curl_version')) {
            if (function_exists('curl_init')) {
                if (function_exists('curl_setopt')) {
                    if (function_exists('curl_exec')) {
                        if (function_exists('curl_error')) {
                            if (function_exists('curl_close')) {
                                if (function_exists('curl_getinfo')) {
                                    if ($url_parts['scheme'] == 'https' || $url_parts['scheme'] == 'http') {
                                        $curl_version = curl_version();
                                        if (is_string($curl_version) && strpos($curl_version, 'OpenSSL') !== false || is_array($curl_version) && array_key_exists('ssl_version', $curl_version)) {
                                            $ch = curl_init($url);
                                            if (!is_null($post_params)) {
                                                curl_setopt($ch, CURLOPT_POST, true);
                                                if (is_null($files)) {
                                                    curl_setopt($ch, CURLOPT_POSTFIELDS, $_postdetails_params);
                                                } else {
                                                    @curl_setopt($ch, CURLOPT_POSTFIELDS, $post_params);
                                                    // PHP5.5 gives a deprecation warning
                                                }
                                            }
                                            if (!is_null($cookies) && count($cookies) != 0) {
                                                curl_setopt($ch, CURLOPT_COOKIE, $_cookies);
                                            }
                                            $crt_path = get_file_base() . '/data/curl-ca-bundle.crt';
                                            if (ini_get('curl.cainfo') == '') {
                                                curl_setopt($ch, CURLOPT_CAINFO, $crt_path);
                                                curl_setopt($ch, CURLOPT_CAPATH, $crt_path);
                                            }
                                            //curl_setopt($ch,CURLOPT_SSLVERSION,6);
                                            curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'TLSv1');
                                            //if (!$no_redirect) @curl_setopt($ch,CURLOPT_FOLLOWLOCATION,true); // May fail with safe mode, meaning we can't follow Location headers. But we can do better ourselves anyway and protect against file:// exploits.
                                            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, intval($timeout));
                                            curl_setopt($ch, CURLOPT_TIMEOUT, intval($timeout));
                                            curl_setopt($ch, CURLOPT_USERAGENT, $ua);
                                            $headers = array();
                                            if ($is_xml) {
                                                $headers[] = 'Content-Type: application/xml';
                                            }
                                            if (!is_null($accept)) {
                                                $headers[] = 'Accept: ' . rawurlencode($accept);
                                            }
                                            if (!is_null($accept_charset)) {
                                                $headers[] = 'Accept-Charset: ' . rawurlencode($accept_charset);
                                            }
                                            if (!is_null($accept_language)) {
                                                $headers[] = 'Accept-Language: ' . rawurlencode($accept_language);
                                            }
                                            if (is_null($files)) {
                                                // Breaks file uploads for some reason
                                                curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
                                            }
                                            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                                            curl_setopt($ch, CURLOPT_HEADER, true);
                                            if (!is_null($auth)) {
                                                curl_setopt($ch, CURLOPT_USERPWD, implode(':', $auth));
                                            }
                                            if (!is_null($referer)) {
                                                curl_setopt($ch, CURLOPT_REFERER, $referer);
                                            }
                                            $proxy = get_value('proxy', NULL, true);
                                            if ($proxy == '') {
                                                $proxy = NULL;
                                            }
                                            if (!is_null($proxy) && $url_parts['host'] != 'localhost' && $url_parts['host'] != '127.0.0.1') {
                                                $port = get_value('proxy_port', NULL, true);
                                                if (is_null($port)) {
                                                    $port = '8080';
                                                }
                                                curl_setopt($ch, CURLOPT_PROXY, $proxy . ':' . $port);
                                                $proxy_user = get_value('proxy_user', NULL, true);
                                                if (!is_null($proxy_user)) {
                                                    $proxy_password = get_value('proxy_password', NULL, true);
                                                    curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_user . ':' . $proxy_password);
                                                }
                                            }
                                            if (!is_null($byte_limit)) {
                                                curl_setopt($ch, CURLOPT_RANGE, '0-' . strval($byte_limit == 0 ? 0 : $byte_limit - 1));
                                            }
                                            $line = curl_exec($ch);
                                            if ($line === false) {
                                                $error = curl_error($ch);
                                                curl_close($ch);
                                            } else {
                                                if (substr($line, 0, 25) == "HTTP/1.1 100 Continue\r\n\r\n") {
                                                    $line = substr($line, 25);
                                                }
                                                if (substr($line, 0, 25) == "HTTP/1.0 100 Continue\r\n\r\n") {
                                                    $line = substr($line, 25);
                                                }
                                                $HTTP_DOWNLOAD_MIME_TYPE = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
                                                $HTTP_DOWNLOAD_SIZE = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
                                                $HTTP_DOWNLOAD_URL = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
                                                $HTTP_MESSAGE = strval(curl_getinfo($ch, CURLINFO_HTTP_CODE));
                                                if ($HTTP_MESSAGE == '206') {
                                                    $HTTP_MESSAGE = '200';
                                                }
                                                // We don't care about partial-content return code, as ocP implementation gets ranges differently and we check '200' as a return result
                                                if (strpos($HTTP_DOWNLOAD_MIME_TYPE, ';') !== false) {
                                                    $HTTP_CHARSET = substr($HTTP_DOWNLOAD_MIME_TYPE, 8 + strpos($HTTP_DOWNLOAD_MIME_TYPE, 'charset='));
                                                    $HTTP_DOWNLOAD_MIME_TYPE = substr($HTTP_DOWNLOAD_MIME_TYPE, 0, strpos($HTTP_DOWNLOAD_MIME_TYPE, ';'));
                                                }
                                                curl_close($ch);
                                                if (substr($line, 0, strlen('HTTP/1.0 200 Connection Established')) == 'HTTP/1.0 200 Connection Established') {
                                                    $line = substr($line, strpos($line, "\r\n\r\n") + 4);
                                                }
                                                $pos = strpos($line, "\r\n\r\n");
                                                if (substr($line, 0, strlen('HTTP/1.1 100 ')) == 'HTTP/1.1 100 ' || substr($line, 0, strlen('HTTP/1.0 100 ')) == 'HTTP/1.0 100 ') {
                                                    $pos = strpos($line, "\r\n\r\n", $pos + 4);
                                                }
                                                if ($pos === false) {
                                                    $pos = strlen($line);
                                                } else {
                                                    $pos += 4;
                                                }
                                                $lines = explode("\r\n", substr($line, 0, $pos));
                                                foreach ($lines as $lno => $_line) {
                                                    $_line .= "\r\n";
                                                    $matches = array();
                                                    if (preg_match('#^Content-Disposition: [^;]*;\\s*filename="([^"]*)"#i', $_line, $matches) != 0) {
                                                        $HTTP_FILENAME = $matches[1];
                                                    }
                                                    if (preg_match("#^Set-Cookie: ([^\r\n=]*)=([^\r\n]*)\r\n#i", $_line, $matches) != 0) {
                                                        $HTTP_NEW_COOKIES[trim(rawurldecode($matches[1]))] = trim($matches[2]);
                                                    }
                                                    if (preg_match("#^Location: (.*)\r\n#i", $_line, $matches) != 0) {
                                                        if (is_null($HTTP_FILENAME)) {
                                                            $HTTP_FILENAME = basename($matches[1]);
                                                        }
                                                        if (strpos($matches[1], '://') === false) {
                                                            $matches[1] = qualify_url($matches[1], $url);
                                                        }
                                                        if ($matches[1] != $url) {
                                                            $bak = $HTTP_FILENAME;
                                                            $text = $no_redirect ? mixed() : _http_download_file($matches[1], $byte_limit, $trigger_error, false, $ua, NULL, $cookies, $accept, $accept_charset, $accept_language, $write_to_file);
                                                            if (is_null($HTTP_FILENAME)) {
                                                                $HTTP_FILENAME = $bak;
                                                            }
                                                            $DOWNLOAD_LEVEL--;
                                                            return _detect_character_encoding($text);
                                                        }
                                                    }
                                                }
                                                $DOWNLOAD_LEVEL--;
                                                $ret = _detect_character_encoding(substr($line, $pos));
                                                if (!is_null($write_to_file)) {
                                                    fwrite($write_to_file, $ret);
                                                    $ret = '';
                                                }
                                                return $ret;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    $errno = 0;
    $errstr = '';
    if ($url_parts['scheme'] == 'http') {
        if (!array_key_exists('host', $url_parts)) {
            $url_parts['host'] = '127.0.0.1';
        }
        $connect_to = $url_parts['host'];
        $base_url_parsed = parse_url(get_base_url());
        if (!array_key_exists('host', $base_url_parsed)) {
            $base_url_parsed['host'] = '127.0.0.1';
        }
        if ($base_url_parsed['host'] == $connect_to && function_exists('get_option') && get_option('ip_forwarding') == '1') {
            $connect_to = '127.0.0.1';
            // Localhost can fail due to IP6
        } elseif (preg_match('#(\\s|,|^)gethostbyname(\\s|$|,)#i', @ini_get('disable_functions')) == 0) {
            $connect_to = gethostbyname($connect_to);
        }
        // for DNS cacheing
        $proxy = function_exists('get_value') ? get_value('proxy', NULL, true) : NULL;
        if ($proxy == '') {
            $proxy = NULL;
        }
        if (!is_null($proxy) && $connect_to != 'localhost' && $connect_to != '127.0.0.1') {
            $proxy_port = get_value('proxy_port', NULL, true);
            if (is_null($proxy_port)) {
                $proxy_port = '8080';
            }
            $mysock = @fsockopen($proxy, intval($proxy_port), $errno, $errstr, $timeout);
        } else {
            $mysock = @fsockopen($connect_to, array_key_exists('port', $url_parts) ? $url_parts['port'] : 80, $errno, $errstr, $timeout);
        }
        if (is_null($mysock)) {
            $mysock = false;
        }
        // For Quercus #4549
    } else {
        $mysock = false;
    }
    if ($mysock !== false) {
        if (function_exists('stream_set_timeout')) {
            if (@stream_set_timeout($mysock, intval($timeout)) === false) {
                $mysock = false;
            }
        } elseif (function_exists('socket_set_timeout')) {
            if (@socket_set_timeout($mysock, intval($timeout)) === false) {
                $mysock = false;
            }
        }
    }
    if ($mysock !== false) {
        $url2 = array_key_exists('path', $url_parts) ? $url_parts['path'] : '/';
        if (array_key_exists('query', $url_parts)) {
            $url2 .= '?' . $url_parts['query'];
        }
        if (!is_null($proxy) && $connect_to != 'localhost' && $connect_to != '127.0.0.1') {
            $out = '';
            $out .= (is_null($post_params) ? $byte_limit === 0 ? 'HEAD ' : 'GET ' : 'POST ') . str_replace("\r", '', str_replace(chr(10), '', $url)) . " HTTP/1.1\r\n";
            $proxy_user = get_value('proxy_user', NULL, true);
            if (!is_null($proxy_user)) {
                $proxy_password = get_value('proxy_password', NULL, true);
                $out .= 'Proxy-Authorization: Basic ' . base64_encode($proxy_user . ':' . $proxy_password) . "\r\n";
            }
        } else {
            $out = (is_null($post_params) ? $byte_limit === 0 ? 'HEAD ' : 'GET ' : 'POST ') . str_replace("\r", '', str_replace(chr(10), '', $url2)) . " HTTP/1.1\r\n";
        }
        $out .= "Host: " . $url_parts['host'] . "\r\n";
        if (!is_null($cookies) && count($cookies) != 0) {
            $out .= 'Cookie: ' . $_cookies . "\r\n";
        }
        $out .= "User-Agent: " . rawurlencode($ua) . "\r\n";
        if (!is_null($auth)) {
            $out .= "Authorization: Basic " . base64_encode(implode(':', $auth)) . "==\r\n";
        }
        if (!is_null($accept)) {
            $out .= "Accept: " . rawurlencode($accept) . "\r\n";
        } else {
            $out .= "Accept: */*\r\n";
            // There's a mod_security rule that checks for this
        }
        if (!is_null($accept_charset)) {
            $out .= "Accept-Charset: " . rawurlencode($accept_charset) . "\r\n";
        }
        if (!is_null($accept_language)) {
            $out .= "Accept-Language: " . rawurlencode($accept_language) . "\r\n";
        }
        if (!is_null($referer)) {
            $out .= "Referer: " . rawurlencode($referer) . "\r\n";
        }
        if ($_postdetails_params != '') {
            if ($is_xml) {
                $out .= "Content-Type: application/xml\r\n";
                $out .= 'Content-length: ' . strval(strlen($_postdetails_params)) . "\r\n";
                $out .= "\r\n" . $_postdetails_params . "\r\n\r\n";
            } else {
                if (is_null($files)) {
                    $out .= 'Content-type: application/x-www-form-urlencoded; charset=' . get_charset() . "\r\n";
                    $out .= 'Content-length: ' . strval(strlen($_postdetails_params)) . "\r\n";
                    $out .= "\r\n" . $_postdetails_params . "\r\n\r\n";
                } else {
                    $divider = uniqid('', true);
                    $out2 = '';
                    $out .= 'Content-type: multipart/form-data; boundary="--ocp' . $divider . '"; charset=' . get_charset() . "\r\n";
                    foreach ($post_params as $key => $val) {
                        $out2 .= '----ocp' . $divider . "\r\n";
                        $out2 .= 'Content-Disposition: form-data; name="' . urlencode($key) . '"' . "\r\n\r\n";
                        $out2 .= $val . "\r\n";
                    }
                    if (!is_null($files)) {
                        foreach ($files as $upload_field => $file_path) {
                            $out2 .= '----ocp' . $divider . "\r\n";
                            $out2 .= 'Content-Disposition: form-data; name="' . urlencode($upload_field) . '"; filename="' . urlencode(basename($file_path)) . '"' . "\r\n";
                            $out2 .= 'Content-Type: application/octet-stream' . "\r\n\r\n";
                            $out2 .= file_get_contents($file_path) . "\r\n";
                        }
                    }
                    $out2 .= '----ocp' . $divider . "--\r\n";
                    $out .= 'Content-length: ' . strval(strlen($out2)) . "\r\n";
                    $out .= "\r\n" . $out2;
                }
            }
        }
        $out .= "Connection: Close\r\n\r\n";
        @fwrite($mysock, $out);
        $data_started = false;
        $input = '';
        $input_len = 0;
        $first_fail_time = mixed();
        $chunked = false;
        $buffer_unprocessed = '';
        while ($chunked || !@feof($mysock)) {
            $line = @fread($mysock, $chunked && strlen($buffer_unprocessed) > 10 ? 10 : 1024);
            if ($line === false) {
                if (!$chunked || $buffer_unprocessed == '') {
                    break;
                }
                $line = '';
            }
            if ($line == '') {
                if (!is_null($first_fail_time)) {
                    if ($first_fail_time < time() - 5) {
                        break;
                    }
                } else {
                    $first_fail_time = time();
                }
            } else {
                $first_fail_time = NULL;
            }
            if ($data_started) {
                $line = $buffer_unprocessed . $line;
                $buffer_unprocessed = '';
                if ($chunked) {
                    $matches = array();
                    if (preg_match('#^(\\r\\n)?([a-f\\d]+) *(;[^\\r\\n]*)?\\r\\n(.*)$#is', $line, $matches) != 0) {
                        $amount_wanted = hexdec($matches[2]);
                        if (strlen($matches[4]) < $amount_wanted) {
                            $buffer_unprocessed = $line;
                            continue;
                        }
                        $buffer_unprocessed = substr($matches[4], $amount_wanted);
                        // May be some more extra read
                        $line = substr($matches[4], 0, $amount_wanted);
                        if ($line == '') {
                            break;
                        }
                    } else {
                        // Should not happen :S
                    }
                }
                if (is_null($write_to_file)) {
                    $input .= $line;
                } else {
                    fwrite($write_to_file, $line);
                }
                $input_len += strlen($line);
                if (!is_null($byte_limit) && $input_len >= $byte_limit) {
                    $input = substr($input, 0, $byte_limit);
                    break;
                }
            } elseif ($line != '') {
                $old_line = $line;
                $lines = explode("\r\n", $line);
                $tally = 0;
                foreach ($lines as $lno => $line) {
                    $line .= "\r\n";
                    $tally += strlen($line);
                    $matches = array();
                    if (preg_match("#Transfer-Encoding: chunked\r\n#i", $line, $matches) != 0) {
                        $chunked = true;
                    }
                    if (preg_match("#Content-Disposition: [^\r\n]*filename=\"([^;\r\n]*)\"\r\n#i", $line, $matches) != 0) {
                        $HTTP_FILENAME = $matches[1];
                    }
                    if (preg_match("#^Set-Cookie: ([^\r\n=]*)=([^\r\n]*)\r\n#i", $line, $matches) != 0) {
                        $HTTP_NEW_COOKIES[trim(rawurldecode($matches[1]))] = trim($matches[2]);
                    }
                    if (preg_match("#^Content-Length: ([^;\r\n]*)\r\n#i", $line, $matches) != 0) {
                        $HTTP_DOWNLOAD_SIZE = intval($matches[1]);
                    }
                    if (preg_match("#^Content-Type: ([^;\r\n]*)(;[^\r\n]*)?\r\n#i", $line, $matches) != 0) {
                        $HTTP_DOWNLOAD_MIME_TYPE = $matches[1];
                        if (array_key_exists(2, $matches)) {
                            $_ct_more = explode(';', str_replace(' ', '', trim($matches[2])));
                            foreach ($_ct_more as $ct_more) {
                                $ct_bits = explode('=', $ct_more, 2);
                                if (count($ct_bits) == 2 && strtolower($ct_bits[0]) == 'charset') {
                                    $HTTP_CHARSET = trim($ct_bits[1]);
                                }
                            }
                        }
                    }
                    if (preg_match("#^Refresh: (\\d*);(.*)\r\n#i", $line, $matches) != 0) {
                        if (is_null($HTTP_FILENAME)) {
                            $HTTP_FILENAME = basename($matches[1]);
                        }
                        @fclose($mysock);
                        if (strpos($matches[1], '://') === false) {
                            $matches[1] = qualify_url($matches[1], $url);
                        }
                        $bak = $HTTP_FILENAME;
                        $text = $no_redirect ? mixed() : _http_download_file($matches[2], $byte_limit, $trigger_error, false, $ua, NULL, $cookies, $accept, $accept_charset, $accept_language, $write_to_file);
                        if (is_null($HTTP_FILENAME)) {
                            $HTTP_FILENAME = $bak;
                        }
                        $DOWNLOAD_LEVEL--;
                        return _detect_character_encoding($text);
                    }
                    if (preg_match("#^Location: (.*)\r\n#i", $line, $matches) != 0) {
                        if (is_null($HTTP_FILENAME)) {
                            $HTTP_FILENAME = basename($matches[1]);
                        }
                        @fclose($mysock);
                        if (strpos($matches[1], '://') === false) {
                            $matches[1] = qualify_url($matches[1], $url);
                        }
                        if ($matches[1] != $url) {
                            $bak = $HTTP_FILENAME;
                            $text = $no_redirect ? mixed() : _http_download_file($matches[1], $byte_limit, $trigger_error, false, $ua, NULL, $cookies, $accept, $accept_charset, $accept_language, $write_to_file);
                            if (is_null($HTTP_FILENAME)) {
                                $HTTP_FILENAME = $bak;
                            }
                            $DOWNLOAD_LEVEL--;
                            return _detect_character_encoding($text);
                        }
                    }
                    if (preg_match("#HTTP/(\\d*\\.\\d*) (\\d*) #", $line, $matches) != 0) {
                        // 200 = Ok
                        // 301/302 = Redirected: Not good, we should not be here
                        // 401 = Unauthorized
                        // 403 = Forbidden
                        // 404 = Not found
                        // 500 = Internal server error
                        $HTTP_MESSAGE = $matches[2];
                        switch ($matches[2]) {
                            case '302':
                            case '301':
                                // We'll expect a location header
                                break;
                            case '200':
                                // Good
                                break;
                            case '401':
                                if ($trigger_error) {
                                    warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED', escape_html($url)));
                                } else {
                                    $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED', escape_html($url));
                                }
                                @fclose($mysock);
                                $HTTP_DOWNLOAD_MIME_TYPE = 'security';
                                $DOWNLOAD_LEVEL--;
                                return NULL;
                            case '403':
                                if ($trigger_error) {
                                    warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED', escape_html($url)));
                                } else {
                                    $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED', escape_html($url));
                                }
                                @fclose($mysock);
                                $HTTP_DOWNLOAD_MIME_TYPE = 'security';
                                $DOWNLOAD_LEVEL--;
                                return NULL;
                            case '404':
                                if ($trigger_error) {
                                    warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_NOT_FOUND', escape_html($url)));
                                }
                                @fclose($mysock);
                                $DOWNLOAD_LEVEL--;
                                return NULL;
                            case '500':
                                if ($trigger_error) {
                                    warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_SERVER_ERROR', escape_html($url)));
                                }
                                @fclose($mysock);
                                $DOWNLOAD_LEVEL--;
                                return NULL;
                            default:
                                if ($trigger_error) {
                                    warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNKNOWN', escape_html($url)));
                                }
                        }
                    }
                    if ($line == "\r\n") {
                        $data_started = true;
                        $buffer_unprocessed = substr($old_line, $tally);
                        if ($buffer_unprocessed === false) {
                            $buffer_unprocessed = '';
                        }
                        break;
                    }
                }
            }
        }
        // Process any non-chunked extra buffer (chunked would have been handled in main loop)
        if (!$chunked) {
            if ($buffer_unprocessed != '') {
                if (is_null($write_to_file)) {
                    $input .= $buffer_unprocessed;
                } else {
                    fwrite($write_to_file, $buffer_unprocessed);
                }
                $input_len += strlen($buffer_unprocessed);
                if (!is_null($byte_limit) && $input_len >= $byte_limit) {
                    $input = substr($input, 0, $byte_limit);
                }
            }
        }
        @fclose($mysock);
        if (!$data_started) {
            if ($byte_limit === 0) {
                return '';
            }
            if ($trigger_error) {
                warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_NO_SERVER', escape_html($url)));
            } else {
                $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_NO_SERVER', escape_html($url));
            }
            $DOWNLOAD_LEVEL--;
            $HTTP_MESSAGE = 'no-data';
            return NULL;
        }
        $size_expected = $HTTP_DOWNLOAD_SIZE;
        if (!is_null($byte_limit)) {
            if ($byte_limit < $HTTP_DOWNLOAD_SIZE) {
                $size_expected = $byte_limit;
            }
        }
        if ($input_len < $size_expected) {
            if ($trigger_error) {
                warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_CUT_SHORT', escape_html($url), escape_html(integer_format($size_expected)), escape_html(integer_format($input_len))));
            } else {
                $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_CUT_SHORT', escape_html($url), escape_html(integer_format($size_expected)), escape_html(integer_format($input_len)));
            }
            $DOWNLOAD_LEVEL--;
            $HTTP_MESSAGE = 'short-data';
            return _detect_character_encoding($input);
        }
        $DOWNLOAD_LEVEL--;
        return _detect_character_encoding($input);
    } else {
        if ($errno != 110 && ($errno != 10060 || @ini_get('default_socket_timeout') == '1') && is_null($post_params)) {
            // Perhaps fsockopen is restricted... try fread/file_get_contents
            @ini_set('allow_url_fopen', '1');
            $timeout_before = @ini_get('default_socket_timeout');
            @ini_set('default_socket_timeout', strval(intval($timeout)));
            if (is_null($byte_limit) && is_null($write_to_file)) {
                $read_file = @file_get_contents($url);
            } else {
                $_read_file = @fopen($url, 'rb');
                if ($_read_file !== false) {
                    $read_file = '';
                    while (!feof($_read_file) && (is_null($byte_limit) || strlen($read_file) < $byte_limit)) {
                        $line = fread($_read_file, 1024);
                        if (is_null($write_to_file)) {
                            $read_file .= $line;
                        } else {
                            fwrite($write_to_file, $line);
                        }
                    }
                    fclose($_read_file);
                } else {
                    $read_file = false;
                }
            }
            @ini_set('allow_url_fopen', '0');
            @ini_set('default_socket_timeout', $timeout_before);
            if ($read_file !== false) {
                $DOWNLOAD_LEVEL--;
                return _detect_character_encoding($read_file);
            }
            $errstr = $php_errormsg;
        }
        if ($trigger_error) {
            if ($errstr == '') {
                $errstr = strval($errno);
            }
            $error = do_lang_tempcode('_HTTP_DOWNLOAD_NO_SERVER', escape_html($url), escape_html($errstr));
            warn_exit($error);
        } else {
            $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_NO_SERVER', escape_html($url));
        }
        $DOWNLOAD_LEVEL--;
        $HTTP_MESSAGE = 'could not connect to host (' . $errstr . ')';
        return NULL;
    }
}