当前位置:首页> PHP教程> PHP代码
关键字
文章内容
用php实现proxy功能的示范
 
 
修改时间:[2012/03/26 20:47]    阅读次数:[708]    发表者:[起缘]
 
刚刚写的练手的作品。感觉还是有些实用价值的。。放出来给大家试试。
功能:通过php实现代理功能
适用用户:在家下载较慢。且懒得找proxy。且有高速主机,且主机有php,且主机支持socket。
使用方法:
1。把本程序传到主机上
2。通过浏览器浏览主机上的此文件
3。在url中填入欲下载的文件地址(如果有必要,可以填入referer)
4。点击get proxy url
5。新打开的页面中的链接即为通过proxy下载的链接

注意:
1。支持多线程下载,断点续传
2。仅支持http协议
3。不支持服务器端header重定向
4。不支持http auth
5。下载较大的文件时,可以修改程序中set_time_limit的值,以减少断线的现象(默认为180,即3分钟)

PHP代码:

<?php
/***************************************/
/*                                     */
/*    Php Http Proxy                   */
/*    version: 0.0.2                   */
/*    last modify: 2005.1.12           */
/*    author: q3boy<>    */
/*                                     */
/***************************************/
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));
}
?>