通过php实现支持断点续传的http proxy

通过php实现支持断点续传的http proxy

练手的程序,
目前仅支持http协议,
暂不支持header重定向的处理.
有兴趣的可以看看^_^

<?php
/***************************************/
/*                                     */
/*    Php Http Proxy                   */
/*    version: 0.0.2                   */
/*    last modify: 2005.1.12           */
/*    author: q3boy<[email protected]>    */
/*                                     */
/***************************************/
set_time_limit(180);

define('PP_ERROR_CODE',1);
define('PP_ERROR_MESSAGE',2);
define('PP_ERROR_ALL',3);
define('PP_RETURN_STRING',1);
define('PP_RETURN_ARRAY',2);
define('PP_RETURN_ALL',3);

class CPhpProxy {

    var $_strUrl;
    var $_arrArgv;
    var $_strRef;
    var $_arrUrl;
    var $_resSocket;
    var $_intError;
    var $_strError;
    var $_arrDefaultArrayUrl;
    var $_arrDefaultPort;

    function CPhpProxy($strUrl = null, $arrArgv = array()) {
        $this->init();
        is_null($strUrl)?'':$this->setUrl($strUrl);
        is_null($arrArgv['refer'])?'':$this->setRef($arrArgv['refer']);
        $this->proxy($strUrl,$arrArgv);
     }
    function setError($intError,$mixArgv=null) {
        $this->_intError = $intError;
        if($intError==1001) {
            $this->_strError = "调用 $mixArgv 方法时参数传递出错, 枚举值不存在";
         }elseif($intError==1) {
            $this->_strError = "url 错误, url 格式不正确./n".$mixArgvs;
         }elseif($intError == 2) {
            $this->_strError = "url 错误, 目前尚未支持此协议./n".$mixArgvs;
         }elseif($intError == 3) {
            $this->_strError = "无法打开 ".$this->_arrUrl['host'].':'.$this->_arrUrl['port']."/n".$mixArgv[0].': '.$mixArgv[1];
         }
        
        Return false;
     }

    function getError($enumReturnType=PP_ERROR_CODE) {
        if($enumReturnType==PP_ERROR_ALL) {
            Return array(str_pad($this->_intError,5,'0',STR_PAD_LEFT),$this->_strError);
         }elseif($enumReturnType==PP_ERROR_MESSAGE) {
            Return $this->_strError;
         }elseif($enumReturnType==PP_ERROR_CODE) {
            Return $this->_intError;
         }else {
            Return false;
         }
     }

    function init() {
        $this->_strUrl = null;
        $this->_arrArgv = array();
        $this->_strRef = null;
        $this->_arrUrl = array();
        $this->_resSocket = null;
        $this->_intError = 0;
        $this->_strError = 'there is no error';
        //arrurl 默认值
        $this->_arrDefaultArrayUrl = array('protocol'=>'http','file'=>'index.htm');
        //默认端口
        $this->_arrDefaultPort =array('http'=>'80');
        Return true;
     }
    function setUrl($strUrl) {
        $strUrl = trim($strUrl);
        //正则
        $reg = "/^(([/w]+):////)?([^:|//|@]*:)?([^:|//|@]*@)?([/w|/-|/.]+)(:/d+)?(//[^/?|#]*)?(/?[^#]*)?(#.*)?$/is";
        if(!preg_match($reg,$strUrl,$arrUrl)) {
            Return $this->setError(1,$strUrl);
         }else {
            //拆解匹配数组
            list($tmp, $tmp, $arr['protocol'], $arr['user'], $arr['pass'], $arr['host'], $arr['port'], $arr['path'], $arr['query'], $arr['anchor']) = $arrUrl;
            //默认协议
            if(!$arr['protocol']) {
                $arrUrl[1] = $this->_arrDefaultArrayUrl['protocol'].'://';
             }
            //设 filename
            $arr['file'] = basename($arr['path']);
            //默认值
            foreach($this->_arrDefaultArrayUrl as $key=>$val) {
                if($arr[$key] == '') {
                    $arr[$key] = $val;
                 }
             }
            //默认端口
            if(is_null($this->_arrDefaultPort[$arr['protocol']])) {
                Return $this->setError(2,$arr['protocol']);
             }elseif(!$arr['port']) {
                $arr['port'] = $this->_arrDefaultPort[$arr['protocol']];
             }

            //设 uri
            $arr['uri']  = ($arr['path']?$arr['path']:'/') . ($arr['query']?'?'.$arr['query']:'') . ($arr['anchor']?'#'.$arr['anchor']:'');
            //设 url
            unset($arrUrl[0]);
            unset($arrUrl[2]);
            $this->_strUrl = implode('',$arrUrl);
            //设 arrurl
            $this->_arrUrl = $arr;
            Return true;
         }
     }
    function getUrl($enumReturnType = PP_RETURN_ARRAY) {
        if($enumReturnType==PP_RETURN_STRING) {
            Return $this->_strUrl;
         }elseif($enumReturnType==PP_RETURN_ARRAY) {
            Return $this->_arrUrl;
         }if($enumReturnType==PP_RETURN_ALL) {
            Return array($this->_strUrl,$this->_arrUrl);
         }else {
            Return $this->setError(1001);
         }
        
     }
    function setRefer($strRef) {
        $this->_strRef = trim($strRef);
        Return true;
     }
    function getRefer() {
        Return $this->_strRef;
     }

    function getProxyUrl() {
        global $_SERVER;
        list($strProcotol) = explode('/',strtolower(trim($_SERVER['SERVER_PROTOCOL'])));
        $str = $strProcotol.'://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].
                 '?u='.urlencode($this->getUrl(PP_RETURN_STRING)).
                 ($this->getRefer()?('&r='.urlencode($this->getRefer())):'');
        Return $str;
     }
    function openSocket() {
        $arr = $this->getUrl();
        $this->_resSocket = @fsockopen($arr['host'],$arr['port'],$intError, $strError, 30);
        if(!$this->_resSocket) {
            $this->_resSocket = null;
            Return $this->setError(3,array($intError, $strError));
         }else {
            Return true;
         }
     }
    function getRequest() {
        Return $this->{ 'get'.ucfirst($this->_arrUrl['protocol']).'Request' }();
     }
    function sendRequest() {
        Return fwrite($this->_resSocket,$this->getRequest());
     }
    function flushResponse() {
        Return $this->{ 'flush'.ucfirst($this->_arrUrl['protocol']).'Response' }();
     }
    function getHttpRequest() {
        $arr = $this->getUrl();
        $arrRequest = getallheaders();
        $arrRequest['Host'] = $arr['host'];
        $strRequest  = "GET ".$arr['uri']." HTTP/1.1/r/n";
        foreach($arrRequest as $key=>$val) {
            $strRequest .="$key: $val/r/n";
         }
        $strRequest .="/r/n";
        Return $strRequest;
     }
    function flushHttpResponse() {
        $bolHeader=true;
        while (!feof($this->_resSocket)) {
            $str = fgets($this->_resSocket, 4096);
            if($bolHeader) {
                @header($str);
             }else {
                echo($str);
             }
            if($bolHeader && $str=="/r/n") {
                $bolHeader=false;
                @header("Content-type: application/gzip");
                @header('Content-Disposition: attachment; filename="'.$this->_arrUrl['file'].'"');
             }
         }
        Return true;
     }
    function close() {
        fclose($this->_resSocket);
        $this->_resSocket = null;
        Return true;
     }
    function proxy($strUrl = null,$arrArgv = array()) {
        if(!is_null($this->getUrl(PP_RETURN_STRING)) && $this->openSocket() && $this->sendRequest() && $this->flushResponse()) {
            echo(123);
            $this->close();
         }else {
            Return false;
         }
     }
}
if(sizeof($_GET)) {
    $strGetArrayName = '_GET';
}elseif(sizeof($HTTP_GET_VARS)) {
    $strGetArrayName = 'HTTP_GET_VARS';
}else {
    die('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html">
<title>PhpProxy</title>
<style type="text/css">
<!--body,td { font-family: verdana; font-size: 12px; }th,input { font-family: verdana; }-->
</style>
</head>
<body>
<form name="form1" method="get" action="'.$_SERVER['PHP_SELF'].'">
    <table width="500" border="1" align="center" cellpadding="5" cellspacing="1">
        <tr>
            <th colspan="2">PhpProxy</th>
        </tr>
        <tr>
            <td width="39" nowrap>URL:</td>
            <td width="432"><input name="u" type="text" id="u" size="60"></td>
        </tr>
        <tr>
            <td nowrap>REFERER:</td>
            <td><input name="r" type="text" id="r" size="60"></td>
        </tr>
        <tr>
            <td colspan="2" align="center"><input name="act" value="make" type="hidden">
                <input type="submit" value="Get Proxy Url">
                <input type="reset"  value="Reset"></td>
        </tr>
    </table>
</form>
</body>
</html>');
}
$strUrl = trim(${ $strGetArrayName }['u']);
if($strUrl=='') {
    die('请输入 url 地址.');
}
//get referer
$strRefTmp = trim(${ $strGetArrayName }['r']);
//初始化 proxy 类
$objProxy = new CPhpProxy();
//设置 url 和 refer
$objProxy->setUrl($strUrl);
$objProxy->setRefer($strRef);
//错误输出
if($objProxy->getError()) {
    die($objProxy->getError(PP_ERROR_MESSAGE));
}

//echo url for download
if(${ $strGetArrayName }['act']=='make') {
    die("<center><h4><a href='".$objProxy->getProxyUrl()."'>点击此处通过 PhpProxy 下载文件</a></h2></center>");
}
//取文件
$objProxy->proxy();
//错误处理
if($objProxy->getError()) {
    die($objProxy->getError(PP_ERROR_MESSAGE));
}
?>

<?php
/***************************************/
/*                                     */
/*    Php Http Proxy                   */
/*    version: 0.0.2                   */
/*    last modify: 2005.1.12           */
/*    author: q3boy<[email protected]>    */
/*                                     */
/***************************************/
set_time_limit(180);

define('PP_ERROR_CODE',1);
define('PP_ERROR_MESSAGE',2);
define('PP_ERROR_ALL',3);
define('PP_RETURN_STRING',1);
define('PP_RETURN_ARRAY',2);
define('PP_RETURN_ALL',3);

class CPhpProxy {

    var $_strUrl;
    var $_arrArgv;
    var $_strRef;
    var $_arrUrl;
    var $_resSocket;
    var $_intError;
    var $_strError;
    var $_arrDefaultArrayUrl;
    var $_arrDefaultPort;

    function CPhpProxy($strUrl = null, $arrArgv = array()) {
        $this->init();
        is_null($strUrl)?'':$this->setUrl($strUrl);
        is_null($arrArgv['refer'])?'':$this->setRef($arrArgv['refer']);
        $this->proxy($strUrl,$arrArgv);
     }
    function setError($intError,$mixArgv=null) {
        $this->_intError = $intError;
        if($intError==1001) {
            $this->_strError = "调用 $mixArgv 方法时参数传递出错, 枚举值不存在";
         }elseif($intError==1) {
            $this->_strError = "url 错误, url 格式不正确./n".$mixArgvs;
         }elseif($intError == 2) {
            $this->_strError = "url 错误, 目前尚未支持此协议./n".$mixArgvs;
         }elseif($intError == 3) {
            $this->_strError = "无法打开 ".$this->_arrUrl['host'].':'.$this->_arrUrl['port']."/n".$mixArgv[0].': '.$mixArgv[1];
         }
        
        Return false;
     }

    function getError($enumReturnType=PP_ERROR_CODE) {
        if($enumReturnType==PP_ERROR_ALL) {
            Return array(str_pad($this->_intError,5,'0',STR_PAD_LEFT),$this->_strError);
         }elseif($enumReturnType==PP_ERROR_MESSAGE) {
            Return $this->_strError;
         }elseif($enumReturnType==PP_ERROR_CODE) {
            Return $this->_intError;
         }else {
            Return false;
         }
     }

    function init() {
        $this->_strUrl = null;
        $this->_arrArgv = array();
        $this->_strRef = null;
        $this->_arrUrl = array();
        $this->_resSocket = null;
        $this->_intError = 0;
        $this->_strError = 'there is no error';
        //arrurl 默认值
        $this->_arrDefaultArrayUrl = array('protocol'=>'http','file'=>'index.htm');
        //默认端口
        $this->_arrDefaultPort =array('http'=>'80');
        Return true;
     }
    function setUrl($strUrl) {
        $strUrl = trim($strUrl);
        //正则
        $reg = "/^(([/w]+):////)?([^:|//|@]*:)?([^:|//|@]*@)?([/w|/-|/.]+)(:/d+)?(//[^/?|#]*)?(/?[^#]*)?(#.*)?$/is";
        if(!preg_match($reg,$strUrl,$arrUrl)) {
            Return $this->setError(1,$strUrl);
         }else {
            //拆解匹配数组
            list($tmp, $tmp, $arr['protocol'], $arr['user'], $arr['pass'], $arr['host'], $arr['port'], $arr['path'], $arr['query'], $arr['anchor']) = $arrUrl;
            //默认协议
            if(!$arr['protocol']) {
                $arrUrl[1] = $this->_arrDefaultArrayUrl['protocol'].'://';
             }
            //设 filename
            $arr['file'] = basename($arr['path']);
            //默认值
            foreach($this->_arrDefaultArrayUrl as $key=>$val) {
                if($arr[$key] == '') {
                    $arr[$key] = $val;
                 }
             }
            //默认端口
            if(is_null($this->_arrDefaultPort[$arr['protocol']])) {
                Return $this->setError(2,$arr['protocol']);
             }elseif(!$arr['port']) {
                $arr['port'] = $this->_arrDefaultPort[$arr['protocol']];
             }

            //设 uri
            $arr['uri']  = ($arr['path']?$arr['path']:'/') . ($arr['query']?'?'.$arr['query']:'') . ($arr['anchor']?'#'.$arr['anchor']:'');
            //设 url
            unset($arrUrl[0]);
            unset($arrUrl[2]);
            $this->_strUrl = implode('',$arrUrl);
            //设 arrurl
            $this->_arrUrl = $arr;
            Return true;
         }
     }
    function getUrl($enumReturnType = PP_RETURN_ARRAY) {
        if($enumReturnType==PP_RETURN_STRING) {
            Return $this->_strUrl;
         }elseif($enumReturnType==PP_RETURN_ARRAY) {
            Return $this->_arrUrl;
         }if($enumReturnType==PP_RETURN_ALL) {
            Return array($this->_strUrl,$this->_arrUrl);
         }else {
            Return $this->setError(1001);
         }
        
     }
    function setRefer($strRef) {
        $this->_strRef = trim($strRef);
        Return true;
     }
    function getRefer() {
        Return $this->_strRef;
     }

    function getProxyUrl() {
        global $_SERVER;
        list($strProcotol) = explode('/',strtolower(trim($_SERVER['SERVER_PROTOCOL'])));
        $str = $strProcotol.'://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].
                 '?u='.urlencode($this->getUrl(PP_RETURN_STRING)).
                 ($this->getRefer()?('&r='.urlencode($this->getRefer())):'');
        Return $str;
     }
    function openSocket() {
        $arr = $this->getUrl();
        $this->_resSocket = @fsockopen($arr['host'],$arr['port'],$intError, $strError, 30);
        if(!$this->_resSocket) {
            $this->_resSocket = null;
            Return $this->setError(3,array($intError, $strError));
         }else {
            Return true;
         }
     }
    function getRequest() {
        Return $this->{ 'get'.ucfirst($this->_arrUrl['protocol']).'Request' }();
     }
    function sendRequest() {
        Return fwrite($this->_resSocket,$this->getRequest());
     }
    function flushResponse() {
        Return $this->{ 'flush'.ucfirst($this->_arrUrl['protocol']).'Response' }();
     }
    function getHttpRequest() {
        $arr = $this->getUrl();
        $arrRequest = getallheaders();
        $arrRequest['Host'] = $arr['host'];
        $strRequest  = "GET ".$arr['uri']." HTTP/1.1/r/n";
        foreach($arrRequest as $key=>$val) {
            $strRequest .="$key: $val/r/n";
         }
        $strRequest .="/r/n";
        Return $strRequest;
     }
    function flushHttpResponse() {
        $bolHeader=true;
        while (!feof($this->_resSocket)) {
            $str = fgets($this->_resSocket, 4096);
            if($bolHeader) {
                @header($str);
             }else {
                echo($str);
             }
            if($bolHeader && $str=="/r/n") {
                $bolHeader=false;
                @header("Content-type: application/gzip");
                @header('Content-Disposition: attachment; filename="'.$this->_arrUrl['file'].'"');
             }
         }
        Return true;
     }
    function close() {
        fclose($this->_resSocket);
        $this->_resSocket = null;
        Return true;
     }
    function proxy($strUrl = null,$arrArgv = array()) {
        if(!is_null($this->getUrl(PP_RETURN_STRING)) && $this->openSocket() && $this->sendRequest() && $this->flushResponse()) {
            echo(123);
            $this->close();
         }else {
            Return false;
         }
     }
}
if(sizeof($_GET)) {
    $strGetArrayName = '_GET';
}elseif(sizeof($HTTP_GET_VARS)) {
    $strGetArrayName = 'HTTP_GET_VARS';
}else {
    die('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html">
<title>PhpProxy</title>
<style type="text/css">
<!--body,td { font-family: verdana; font-size: 12px; }th,input { font-family: verdana; }-->
</style>
</head>
<body>
<form name="form1" method="get" action="'.$_SERVER['PHP_SELF'].'">
    <table width="500" border="1" align="center" cellpadding="5" cellspacing="1">
        <tr>
            <th colspan="2">PhpProxy</th>
        </tr>
        <tr>
            <td width="39" nowrap>URL:</td>
            <td width="432"><input name="u" type="text" id="u" size="60"></td>
        </tr>
        <tr>
            <td nowrap>REFERER:</td>
            <td><input name="r" type="text" id="r" size="60"></td>
        </tr>
        <tr>
            <td colspan="2" align="center"><input name="act" value="make" type="hidden">
                <input type="submit" value="Get Proxy Url">
                <input type="reset"  value="Reset"></td>
        </tr>
    </table>
</form>
</body>
</html>');
}
$strUrl = trim(${ $strGetArrayName }['u']);
if($strUrl=='') {
    die('请输入 url 地址.');
}
//get referer
$strRefTmp = trim(${ $strGetArrayName }['r']);
//初始化 proxy 类
$objProxy = new CPhpProxy();
//设置 url 和 refer
$objProxy->setUrl($strUrl);
$objProxy->setRefer($strRef);
//错误输出
if($objProxy->getError()) {
    die($objProxy->getError(PP_ERROR_MESSAGE));
}

//echo url for download
if(${ $strGetArrayName }['act']=='make') {
    die("<center><h4><a href='".$objProxy->getProxyUrl()."'>点击此处通过 PhpProxy 下载文件</a></h2></center>");
}
//取文件
$objProxy->proxy();
//错误处理
if($objProxy->getError()) {
    die($objProxy->getError(PP_ERROR_MESSAGE));
}
?>

你可能感兴趣的:(PHP,server,function,header,null,url)