用php实现proxy功能的示范 [已升级至v0.0.2]

发表于:2007-07-01来源:作者:点击数: 标签:
刚刚写的练手的作品。感觉还是有些实用价值的。。放出来给大家试试。 功能:通过 php 实现代理功能 适用用户:在家下载较慢。且懒得找proxy。且有高速主机,且主机有php,且主机支持socket。 使用方法: 1。把本程序传到主机上 2。通过浏览器浏览主机上的此文
刚刚写的练手的作品。感觉还是有些实用价值的。。放出来给大家试试。
功能:通过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<q3boy@sina.com> */
/* */
/***************************************/
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));
}
?>


原文转自:http://www.ltesting.net