PEAR_Downloader::downloadHttp PHP Method

downloadHttp() public method

'setup' called at the very beginning, parameter is a UI object that should be used for all output 'message' the parameter is a string with an informational message 'saveas' may be used to save with a different file name, the parameter is the filename that is about to be used. If a 'saveas' callback returns a non-empty string, that file name will be used as the filename instead. Note that $save_dir will not be affected by this, only the basename of the file. 'start' download is starting, parameter is number of bytes that are expected, or -1 if unknown 'bytesread' parameter is the number of bytes read so far 'done' download is complete, parameter is the total number of bytes read 'connfailed' if the TCP/SSL connection fails, this callback is called with array(host,port,errno,errmsg) 'writefailed' if writing to disk fails, this callback is called with array(destfile,errmsg) If an HTTP proxy has been configured (http_proxy PEAR_Config setting), the proxy will be used.
public downloadHttp ( string $url, object &$ui, string $save_dir = '.', mixed $callback = null, false | string | array $lastmodified = null, false | array $accept = false, false | string $channel = false ) : string | array
$url string the URL to download
$ui object PEAR_Frontend_* instance
$save_dir string directory to save file in
$callback mixed function/method to call for status updates
$lastmodified false | string | array header values to check against for caching use false to return the header values from this download
$accept false | array Accept headers to send
$channel false | string Channel to use for retrieving authentication
return string | array Returns the full path of the downloaded file or a PEAR error on failure. If the error is caused by socket-related errors, the error object will have the fsockopen error code available through getCode(). If caching is requested, then return the header values.
    function downloadHttp($url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null, $accept = false, $channel = false)
    {
        static $redirect = 0;
        // always reset , so we are clean case of error
        $wasredirect = $redirect;
        $redirect = 0;
        if ($callback) {
            call_user_func($callback, 'setup', array(&$ui));
        }
        $info = parse_url($url);
        if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
            return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
        }
        if (!isset($info['host'])) {
            return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
        }
        $host = isset($info['host']) ? $info['host'] : null;
        $port = isset($info['port']) ? $info['port'] : null;
        $path = isset($info['path']) ? $info['path'] : null;
        if (isset($this)) {
            $config =& $this->config;
        } else {
            $config =& PEAR_Config::singleton();
        }
        $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
        if ($config->get('http_proxy') && ($proxy = parse_url($config->get('http_proxy')))) {
            $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
            if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {
                $proxy_host = 'ssl://' . $proxy_host;
            }
            $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080;
            $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null;
            $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
            if ($callback) {
                call_user_func($callback, 'message', "Using HTTP proxy {$host}:{$port}");
            }
        }
        if (empty($port)) {
            $port = isset($info['scheme']) && $info['scheme'] == 'https' ? 443 : 80;
        }
        $scheme = isset($info['scheme']) && $info['scheme'] == 'https' ? 'https' : 'http';
        if ($proxy_host != '') {
            $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr);
            if (!$fp) {
                if ($callback) {
                    call_user_func($callback, 'connfailed', array($proxy_host, $proxy_port, $errno, $errstr));
                }
                return PEAR::raiseError("Connection to `{$proxy_host}:{$proxy_port}' failed: {$errstr}", $errno);
            }
            if ($lastmodified === false || $lastmodified) {
                $request = "GET {$url} HTTP/1.1\r\n";
                $request .= "Host: {$host}\r\n";
            } else {
                $request = "GET {$url} HTTP/1.0\r\n";
                $request .= "Host: {$host}\r\n";
            }
        } else {
            $network_host = $host;
            if (isset($info['scheme']) && $info['scheme'] == 'https') {
                $network_host = 'ssl://' . $host;
            }
            $fp = @fsockopen($network_host, $port, $errno, $errstr);
            if (!$fp) {
                if ($callback) {
                    call_user_func($callback, 'connfailed', array($host, $port, $errno, $errstr));
                }
                return PEAR::raiseError("Connection to `{$host}:{$port}' failed: {$errstr}", $errno);
            }
            if ($lastmodified === false || $lastmodified) {
                $request = "GET {$path} HTTP/1.1\r\n";
                $request .= "Host: {$host}\r\n";
            } else {
                $request = "GET {$path} HTTP/1.0\r\n";
                $request .= "Host: {$host}\r\n";
            }
        }
        $ifmodifiedsince = '';
        if (is_array($lastmodified)) {
            if (isset($lastmodified['Last-Modified'])) {
                $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
            }
            if (isset($lastmodified['ETag'])) {
                $ifmodifiedsince .= "If-None-Match: {$lastmodified['ETag']}\r\n";
            }
        } else {
            $ifmodifiedsince = $lastmodified ? "If-Modified-Since: {$lastmodified}\r\n" : '';
        }
        $request .= $ifmodifiedsince . "User-Agent: PEAR/1.9.1/PHP/" . PHP_VERSION . "\r\n";
        if (isset($this)) {
            // only pass in authentication for non-static calls
            $username = $config->get('username', null, $channel);
            $password = $config->get('password', null, $channel);
            if ($username && $password) {
                $tmp = base64_encode("{$username}:{$password}");
                $request .= "Authorization: Basic {$tmp}\r\n";
            }
        }
        if ($proxy_host != '' && $proxy_user != '') {
            $request .= 'Proxy-Authorization: Basic ' . base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
        }
        if ($accept) {
            $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
        }
        $request .= "Connection: close\r\n";
        $request .= "\r\n";
        fwrite($fp, $request);
        $headers = array();
        $reply = 0;
        while (trim($line = fgets($fp, 1024))) {
            if (preg_match('/^([^:]+):\\s+(.*)\\s*\\z/', $line, $matches)) {
                $headers[strtolower($matches[1])] = trim($matches[2]);
            } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
                $reply = (int) $matches[1];
                if ($reply == 304 && ($lastmodified || $lastmodified === false)) {
                    return false;
                }
                if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
                    return PEAR::raiseError("File {$scheme}://{$host}:{$port}{$path} not valid (received: {$line})");
                }
            }
        }
        if ($reply != 200) {
            if (!isset($headers['location'])) {
                return PEAR::raiseError("File {$scheme}://{$host}:{$port}{$path} not valid (redirected but no location)");
            }
            if ($wasredirect > 4) {
                return PEAR::raiseError("File {$scheme}://{$host}:{$port}{$path} not valid (redirection looped more than 5 times)");
            }
            $redirect = $wasredirect + 1;
            return $this->downloadHttp($headers['location'], $ui, $save_dir, $callback, $lastmodified, $accept);
        }
        if (isset($headers['content-disposition']) && preg_match('/\\sfilename=\\"([^;]*\\S)\\"\\s*(;|\\z)/', $headers['content-disposition'], $matches)) {
            $save_as = basename($matches[1]);
        } else {
            $save_as = basename($url);
        }
        if ($callback) {
            $tmp = call_user_func($callback, 'saveas', $save_as);
            if ($tmp) {
                $save_as = $tmp;
            }
        }
        $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as;
        if (is_link($dest_file)) {
            return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $dest_file . ' as it is symlinked to ' . readlink($dest_file) . ' - Possible symlink attack');
        }
        if (!($wp = @fopen($dest_file, 'wb'))) {
            fclose($fp);
            if ($callback) {
                call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg));
            }
            return PEAR::raiseError("could not open {$dest_file} for writing");
        }
        $length = isset($headers['content-length']) ? $headers['content-length'] : -1;
        $bytes = 0;
        if ($callback) {
            call_user_func($callback, 'start', array(basename($dest_file), $length));
        }
        while ($data = fread($fp, 1024)) {
            $bytes += strlen($data);
            if ($callback) {
                call_user_func($callback, 'bytesread', $bytes);
            }
            if (!@fwrite($wp, $data)) {
                fclose($fp);
                if ($callback) {
                    call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg));
                }
                return PEAR::raiseError("{$dest_file}: write failed ({$php_errormsg})");
            }
        }
        fclose($fp);
        fclose($wp);
        if ($callback) {
            call_user_func($callback, 'done', $bytes);
        }
        if ($lastmodified === false || $lastmodified) {
            if (isset($headers['etag'])) {
                $lastmodified = array('ETag' => $headers['etag']);
            }
            if (isset($headers['last-modified'])) {
                if (is_array($lastmodified)) {
                    $lastmodified['Last-Modified'] = $headers['last-modified'];
                } else {
                    $lastmodified = $headers['last-modified'];
                }
            }
            return array($dest_file, $lastmodified, $headers);
        }
        return $dest_file;
    }

Usage Example

示例#1
0
 /**
  * Download a file through HTTP.  Considers suggested file name in
  * Content-disposition: header and can run a callback function for
  * different events.  The callback will be called with two
  * parameters: the callback type, and parameters.  The implemented
  * callback types are:
  *
  *  'setup'       called at the very beginning, parameter is a UI object
  *                that should be used for all output
  *  'message'     the parameter is a string with an informational message
  *  'saveas'      may be used to save with a different file name, the
  *                parameter is the filename that is about to be used.
  *                If a 'saveas' callback returns a non-empty string,
  *                that file name will be used as the filename instead.
  *                Note that $save_dir will not be affected by this, only
  *                the basename of the file.
  *  'start'       download is starting, parameter is number of bytes
  *                that are expected, or -1 if unknown
  *  'bytesread'   parameter is the number of bytes read so far
  *  'done'        download is complete, parameter is the total number
  *                of bytes read
  *  'connfailed'  if the TCP connection fails, this callback is called
  *                with array(host,port,errno,errmsg)
  *  'writefailed' if writing to disk fails, this callback is called
  *                with array(destfile,errmsg)
  *
  * If an HTTP proxy has been configured (http_proxy PEAR_Config
  * setting), the proxy will be used.
  *
  * @param string  $url       the URL to download
  * @param object  $ui        PEAR_Frontend_* instance
  * @param object  $config    PEAR_Config instance
  * @param string  $save_dir  (optional) directory to save file in
  * @param mixed   $callback  (optional) function/method to call for status
  *                           updates
  *
  * @return string  Returns the full path of the downloaded file or a PEAR
  *                 error on failure.  If the error is caused by
  *                 socket-related errors, the error object will
  *                 have the fsockopen error code available through
  *                 getCode().
  *
  * @access public
  * @deprecated in favor of PEAR_Downloader::downloadHttp()
  */
 function downloadHttp($url, &$ui, $save_dir = '.', $callback = null)
 {
     if (!class_exists('PEAR_Downloader')) {
         require_once 'PEAR/Downloader.php';
     }
     return PEAR_Downloader::downloadHttp($url, $ui, $save_dir, $callback);
 }
All Usage Examples Of PEAR_Downloader::downloadHttp