Location: PHPKode > projects > ZZ/OSS Installer > zic-1.1.0dev1/installer/lib/ZZOSS_File/Download.php
<?php 
//
// +----------------------------------------------------------------------+
// | PHP Version 4                                                        |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group                                |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license,       |
// | that is bundled with this package in the file LICENSE, and is        |
// | available through the world-wide-web at the following url:           |
// | http://www.php.net/license/3_0.txt.                                  |
// | If you did not receive a copy of the PHP license and are unable to   |
// | obtain it through the world-wide-web, please send a note to          |
// | hide@address.com so we can mail you a copy immediately.               |
// +----------------------------------------------------------------------+
    
    /**
    @version $Id: Download.php,v 1.1 2004/01/28 11:39:51 ordnas Exp $
    @copyright Copyright &copy; 2001-2004 ZZ/OSS GbR, http://www.zzoss.com
    @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
    */

/**
* Helper methods for several occasions.
*/
class ZZOSS_FileDownload
{
    var $src;
    var $dest_dir;
    var $save_as;
    var $log;
    var $proxy = array();
    var $callback = NULL;
    
    function setCallback($callback)
    {
        if(is_array($callback)){
            $this->callback = $callback;
        } else {
            PEAR::raiseError('Callback parameters need to be passed in an array');
        }
    }
    
    function setProxy($host, $port, $user, $pass)
    {
        $this->proxy['host'] = $host;
        $this->proxy['port'] = $port;
        $this->proxy['user'] = $user;
        $this->proxy['pass'] = $pass;
    }
    
    function download($src, $dest, $replace = true)
    {
        $this->src = $src;
        
		if($replace && is_file($dest)) {
			@unlink($dest);
		}

        if(!is_dir($dest)){
            $this->save_as = basename($dest);
            $this->dest_dir = dirname($dest);
        } else {
            $this->save_as = basename($src);
            $this->dest_dir = $dest;
        }

        if(is_null($this->callback)){
            $this->callback = array(&$this, '_downloadCallback');
        }
        
		$result = $this->downloadHttp($this->src, $this->dest_dir, $this->callback);
        // WORKAROUND, did not understand how to define
        // the full file path in PEAR's method, so we
        // copy the saved file to the defined location,
        // but only if the differ
        //echo "$dest != $result";
		if(is_object($result)) {
			// TODO: trigger error since we got a pear error object
			return PEAR::raiseError("Unable to get file $src");
		}/* elseif(!is_dir($dest) && $dest != $result){
            copy($result, $dest);
            unlink($result);
        }*/
        return $result;
    }

    function getLog()
    {
        return $this->log;
    }
    
    /**
    * Taken and modified from PEAR_Common.
    */
    function _downloadCallback($msg, $params = null)
    {
        switch ($msg) {
            case 'done':
                $this->log .= '...done: ' . number_format($params, 0, '', ',') . ' bytes'."\n";
                break;
            case 'bytesread':
                static $bytes;
                if (empty($bytes)) {
                    $bytes = 0;
                }
                if (!($bytes % 10240)) {
                    $this->log .= '.';
                }
                $bytes += $params;
                break;
            case 'start':
                $this->log .= "Starting to download {$params[0]} (".number_format($params[1], 0, '', ',')." bytes)"."\n";
                break;
        }
    }
    
     /**
     * Taken and modified from PEAR_Common.
     *
     * 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:
     *
     *  'message'     the parameter is a string with an informational message
     *  '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  $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
     */
    function downloadHttp($url, $save_dir = '.', $callback = null)
    {
        if ($callback) {
            call_user_func($callback, 'setup');
        }
        if (preg_match('!^http://([^/:?#]*)(:(\d+))?(/.*)!', $url, $matches)) {
            list(,$host,,$port,$path) = $matches;
        }

        $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
        if (count($this->proxy)) {
            $proxy_host = @$this->proxy['host'];
            $proxy_port = @$this->proxy['port'];
            $proxy_user = @$this->proxy['user'];
            $proxy_pass = @$this->proxy['pass'];

            if ($proxy_port == '') {
                $proxy_port = 8080;
            }
            if ($callback) {
                call_user_func($callback, 'message', "Using HTTP proxy $host:$port");
            }
        }
        if (empty($port)) {
            $port = 80;
        }
        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);
            }
            $request = "GET $url HTTP/1.0\r\n";
        } else {
            $fp = @fsockopen($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);
            }
            $request = "GET $path HTTP/1.0\r\n";
        }
        $request .= "Host: $host:$port\r\n".
            "User-Agent: PHP/".PHP_VERSION."\r\n";
        if ($proxy_host != '' && $proxy_user != '') {
            $request .= 'Proxy-Authorization: Basic ' .
                base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
        }
        $request .= "\r\n";
        fwrite($fp, $request);
        $headers = array();
        while (trim($line = fgets($fp, 1024))) {
            if (preg_match('/^([^:]+):\s+(.*)\s*$/', $line, $matches)) {
                $headers[strtolower($matches[1])] = trim($matches[2]);
            } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
                if ($matches[1] != 200) {
                    return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)");
                }
            }
        }
        if (isset($headers['content-disposition']) &&
            preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|$)/', $headers['content-disposition'], $matches)) {
            $save_as = basename($matches[1]);
        } else {
            $save_as = basename($url);
        }
        if (strlen($this->save_as)) {
            $save_as = $this->save_as;
        }
        $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as;
        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");
        }
        if (isset($headers['content-length'])) {
            $length = $headers['content-length'];
        } else {
            $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);
        }
        return $dest_file;
    }

}
?>
Return current item: ZZ/OSS Installer