<?php
set_time_limit
(600);
/*********************************
PHP Web Proxy sample code
*********************************/


/**************
Display Proxy Welcome Page when no URL Supplied !
*/
if(!isset($_GET['vk_fryprox_url']) || !$_GET['vk_fryprox_url']) {
    
//display an adress bar
    
echo '<html><head><title>Durron.net Web Proxy</title></head><body><div align="center"><img src="durron.png" alt="Durron.net Web Proxy"><br /><br /><form action="index.php">Saisissez une adresse : <input size="40" type="text" value="http://" name="vk_fryprox_url" /></form></div></body></html>';
    exit(
0);
}
else {
    
$_GET['vk_fryprox_url'] = stripslashes($_GET['vk_fryprox_url']);
}

/****************
We Need to extract peculiar data from provided URL
*/
$hostmatches = array();
preg_match('/^(https?\:\/\/)?(?<host>[^\/\?]+)\/?.*/i'$_GET['vk_fryprox_url'], $hostmatches);
$host $hostmatches['host'];
$basematches = array();
preg_match('/^(https?\:\/\/)?([^\/\?]+)\/?([^\/\?]+\/)*/i'$_GET['vk_fryprox_url'], $basematches);
if(
$basematches[0]{strlen($basematches[0])-1} != '/'$basematches[0] .= '/';
$basedir $basematches[0];
$protomatches = array();
preg_match('/^(https?\:\/\/)?/i'$_GET['vk_fryprox_url'], $protomatches);
$proto $protomatches[0] ? $protomatches[0] : 'http://';
$url_filematches = array();
preg_match('/^(https?\:\/\/)?([^\/\?]+)\/?([^\/\?]+\/)*(?<filename>[^\/\?]+)/i'$_GET['vk_fryprox_url'], $url_filematches);
$url_filename = (strpos($url_filematches['filename'], '%') === TRUE) ? $url_filematches['filename'] : rawurldecode($url_filematches['filename']);
// You'll get 3 important data
// $host = hostname (ie : www.google.com)
// $basedir = URL basedir without file for relative URI
// $proto = Protocol Used (http|https)
// $url_filename = hypothetic filename of the url

/**************
The last query could let you with some GET params added to the URI
*/
$urltmp $_GET['vk_fryprox_url'];
unset(
$_GET['vk_fryprox_url']);
$url_get_data build_raw_post_data($_GET);
$_GET['vk_fryprox_url'] = strlen($url_get_data) ? (strpos($urltmp'?') === TRUE $urltmp.'&'.$url_get_data $urltmp.'?'.$url_get_data) : $urltmp;
//Get params are serialized and added to the URL

//DEBUG :
//echo $_GET['vk_fryprox_url'];

/*******************
Perl Compatible RegExp for HTML/CSS, and some JS get caught too but results are Randomly bad...
*/
$patterns = array();
$replacements = array();

 
//URI
$patterns[] = '/(?<=href\=\"(?!javascript\:))[^\"]*(?=\")|(?<=href\=\'(?!javascript\:))[^\']*(?=\')|(?<=\ href\=(?!javascript\:))[^\'\"][^\ \>]*(?=[\ \>])/ie';
$replacements[] = "build_proxy_html_href('$0')";

 
//Image and script
$patterns[] = '/(?<=src\=\")[^\"]*(?=\")|(?<=src\=\')[^\']*(?=\')|(?<=\ src\=)[^\'\"][^\ \>]*(?=[\ \>])/ie';
$replacements[] = "build_proxy_html_href('$0')";

 
//CSS
$patterns[] = '/(?<=url\(\")[^\"]*(?=\"\))|(?<=url\(\')[^\']*(?=\'\))|(?<=\ url\()[^\'\"][^\ \)]*(?=[\ \)])/ie';
$replacements[] = "build_proxy_html_href('$0')";

//Repair get Forms
$patterns[] = '/\<form\ *(((?<=action\=\")[^\"]*(?=\")|(?<=action\=\')[^\']*(?=\')|(?<=a\ ction\=)[^\'\"][^\ \>]*(?=[\ \>]))|[^\>])*\>/iem';
$replacements[] = "\"$0\".\"\n\".'<input type=\"hidden\" name=\"vk_fryprox_url\" value=\"'.build_proxy_html_href('$2', true).'\" />'";

 
//Forms
$patterns[] = '/(?<=action\=\")[^\"]*(?=\")|(?<=action\=\')[^\']*(?=\')|(?<=\ action\=)[^\'\"][^\ \>]*(?=[\ \>])/ie';
$replacements[] = "build_proxy_html_href('$0')";

//for some js ... mostly don't work
$patterns[] = '/domain=[a-z0-9\.\-]+/i';
$replacements[] = 'domain=www.freyad.net';

 
//for some swf ... mostly don't work
$patterns[] = '/(?<=\"|\ |\=|\'|\()[a-z\/0-9\_][^\"\'\<\>\ ]+\.swf[^\'\"\>\ ]*/ie';
$replacements[] = "build_proxy_html_href('$0')";
 
 
//for deezer ... mostly don't work
$patterns[] = '/\(\\ ?\"HOST\"\ ?\,\ ?\"([^\"])*\"\)/ie';
$replacements[] = "'(\"HOST\", \"'.build_proxy_html_href('$1').'\")'";

//for google IMG ... mostly don't work
$patterns[] = '/(?<=[^\=]\")https?\:\/\/[^\"\ ]*(?=\")/ie';
$replacements[] = "build_proxy_html_href('$0')";

$patterns[] = '/(?<=[^\=]\')https?\:\/\/[^\'\ ]*(?=\')/ie';
$replacements[] = "build_proxy_html_href('$0')";

/************
Compute a found URL to get a full FQDN URL and even a 'rerouted/rewrited'-URL
Usefull to convert Links and Headers Hosts Data
*/
function build_proxy_html_href($href$returl false) {
    global 
$basedir$host$proto;
    
//DEBUG :
    //echo $href;
    //return $href;
    
if(preg_match('/^https?\:\/\/([^\/]+)/i'$href)) {
    
//url
        
$href $href;
    }
    else if(
$href{0} == '/') {
        
//absolute
        
$href $proto.$host.$href;
    }
    else {
        
//path, need basedir
        
$href $basedir.$href;
    }
    
//DEBUG :
    //echo ' - '.urlencode(html_entity_decode($href)).'<br />';
    
if($returl)
        return 
html_entity_decode($href);
    else
        return 
$_SERVER['PHP_SELF'].'?vk_fryprox_url='.rawurlencode(html_entity_decode($href));
}

/****************
Simple RegExp replace runned against the body of the page content to rewrite URL data
*/
function build_raw_html_output($body) {
    
//Add Modification to Body Here
    
global $patterns$replacements;
    
    
//DEBUG :
    //$rmatches = array();
    //preg_match($patterns[3], $body, $rmatches);
    //$body .= print_r($rmatches, 1);
    
    
return preg_replace($patterns$replacements$body);
}

/*************
Sub-function of build_raw_post_data to handle 'array' params 
*/
function build_raw_post_data_array($data_array$pkey) {
    
$ret "";
    if(
is_array($data_array)) {
        foreach(
$data_array as $k => $v) {
            if(
is_array($v)) {
                
$ret .= build_raw_post_data_array($v$pkey.'['.$k.']');
            }
            else {
                
$ret .= $pkey.'['.$k.']'.'='.rawurlencode($v).'&';
            }
        }

    }
    return 
$ret;

}
/*************
Build raw post data Entry point to serialize initially $_POST but work for $_GET also, used for re-injecting into HTTP Query
*/
function build_raw_post_data($post_array) {
    
$ret "";
    if(
is_array($post_array)) {
        foreach(
$post_array as $k => $v) {
            if(
is_array($v)) {
                
$ret .= build_raw_post_data_array($v$k);
            }
            else {
                
$ret .= $k."=".rawurlencode($v)."&";
            }
        }    
    }
    return 
$ret;
}

/************************
Mostly the same function as build raw post data, but for cookies...
*/
function build_raw_cookie($cookie_array) {
    
$ret "";
    if(
is_array($cookie_array)) {
        foreach(
$cookie_array as $k => $v) {
            if(
is_array($v)) {
                
$ret .= build_raw_post_data_array($v$k);
            } else {
                
$ret .= rawurlencode($k)."=".rawurlencode($v)."; ";
            }
        }
    }
    return 
$ret;
}

/****************************
TODO : Handle $_FILES save/forward data !
*/


/***************************
*    Init Query : Everything happens HERE !
* Use Curl Object to make HTTP request and get Result Headers and Content
* Throw the contents against differents filters to get them usable by client Browser
****************************/

//Init Curl object with the URL we'll use...
$curl_request curl_init();
curl_setopt($curl_requestCURLOPT_URL$_GET['vk_fryprox_url']);

//which method are we going to use ?
switch($_SERVER['REQUEST_METHOD']) {

    case 
'POST' :
    
$post_data build_raw_post_data($_POST);
    
curl_setopt($curl_requestCURLOPT_POST1);
    
curl_setopt($curl_requestCURLOPT_POSTFIELDS$post_data);
    break;
    
    case 
'GET' :
    default :
    
curl_setopt($curl_requestCURLOPT_HTTPGET1);
    break;
}

//forward headers from client...

$header[] = "Accept: ".$_SERVER["HTTP_ACCEPT"];
$header[] = "Accept-Charset: ".$_SERVER["HTTP_ACCEPT_CHARSET"];
$header[] = "Accept-Encoding: gzip";
$header[] = "Referer: ".rawurldecode(preg_replace('/^(.*)\?vk\_fryprox\_url\=/i'''$_SERVER['HTTP_REFERER']));
$header[] = "Accept-Language: ".$_SERVER["HTTP_ACCEPT_LANGUAGE"];
$header[] = "User-Agent: ".$_SERVER["HTTP_USER_AGENT"];
$header[] = "Cookie: ".build_raw_cookie($_COOKIE);

//set some option to the Curl object (especially Headers, content-transfer, timeout...)

curl_setopt($curl_requestCURLOPT_HEADER1);
curl_setopt($curl_requestCURLOPT_HTTPHEADER$header);
curl_setopt($curl_requestCURLOPT_TIMEOUT595);
curl_setopt($curl_requestCURLOPT_RETURNTRANSFER1);
curl_setopt($curl_requestCURLOPT_ENCODING"gzip");
curl_setopt($curl_requestCURLOPT_INTERFACE"87.98.253.64");


//launch our query !
$response curl_exec($curl_request);     
//get errors ...
$curl_errno 0;
if (
$curl_errno curl_errno($curl_request)) {
    
//what to do with errors...
    
switch($curl_errno) {
        case 
CURLE_URL_MALFORMAT :
        case 
CURLE_COULDNT_RESOLVE_HOST :
            
header("Location: ".$_SERVER['PHP_SELF'].'?vk_fryprox_url='.rawurlencode("http://www.google.com/search?q=".rawurlencode($_GET['vk_fryprox_url'])));
        break;
        default :
            print 
curl_error($curl_request);
        break;
    }
}
else {
    
//No Errors ! We can Continue !!
    
    /*********************************
    Here we can act to make the Proxy Transparent for the Browser, but it needs some tuning !
    */
    
    //Explode Body from Headers
    
do {
        
$headers substr($response0strpos($response"\r\n\r\n"));
        
$response substr($responsestrpos($response"\r\n\r\n")+4);
    }
    while(
preg_match('/^HTTP.*100.*Continue/i'$headers));
    
    
//we've got the Body and each Lines of Headers
    
    
$body $response;
    
$headers explode("\r\n"$headers);
    
    
//DEBUG :
    //header("Content-Type: text/plain");
    //echo $response;
    //print_r($headers);

    //Modify Header to comply with Proxy
    
foreach($headers as $v) {
        
//look for cookie header
        
if(preg_match('/^Set\-Cookie\ ?\:/i'$v)) {
            
//we have a cookie header let change his domain and PATH !
            
$v preg_replace('/domain\ ?\=\ ?([^\ \;]+)/i''domain='.$_SERVER['HTTP_HOST'].';'$v);
            
$v preg_replace('/path\ ?\=\ ?([^\ \;]+)/i''path=/'$v);
        }
        
        
//look for content type header
        
if(preg_match('/^Content-Type\ ?\:/i'$v)) {
            
//juste save content-type for later use...
            
$content_matches = array();
            
preg_match('/^Content-Type\ ?\:\ ?(?<type>[^\ \;]+)\ ?\;?\ ?(charset\=(?<charset>[^\ \;]+))?/i'$v$content_matches);
            
$content_type $content_matches['type'];
            
$content_charset $content_matches['charset'];
        }

        
//do I proxy the compressed output ?
        
if(preg_match('/^Content-Encoding\ ?\:\ ?gzip/i'$v)) {
            
$gzip_output 1;
        }
        
        
//do I proxy Content-disposition ?
        
if(preg_match('/^Content-Disposition\ ?\:/i'$v)) {
            
$content_disposition 1;
        }

        
//look for content Transfer-Encoding Header
        
if(preg_match('/^Transfer-Encoding\ ?\:/i'$v)) {
            
$v preg_replace('/^Transfer-Encoding\ ?\:\ ?[^\ \;]+/i',''$v);
        }
        
        
//look for location header
        
$matches = array();
        if(
preg_match('/^Location\ ?\:\ ?(?<href>[^\ ]*)/i'$v$matches)) {
            
//we have a location header let's re-route it !
            
$v "Location: ".build_proxy_html_href($matches['href']);
        }
        
// Throw Header to Browser
        
header($vtrue);
    }

    
//no Content-disposition put it yourself !
    
if(!isset($content_disposition) || !$content_disposition) {
        
header("Content-Disposition: inline; filename=\"".$url_filename."\""true);
    }

    
//Modify Body to comply with Proxy, (depending on Content-type)
    
switch($content_type) {
        case 
'text/html' :
        case 
'text/css' :
        case 
'application/x-javascript' :
            
//DEBUG :
            //echo "Modified Body <BR />";
            
$body build_raw_html_output($body);
        default :
            
//DEBUG :
            //echo "Content-Type: ".$content_type." Charset :".$content_charset;
            //If the server returned a compressed Body We need to compress it to for the Client !
            
if(isset($gzip_output) && $gzip_output$body gzencode($body);
            echo 
$body;
        break;
    }
        
}

//finish the Curl Request by closing it ...
curl_close($curl_request);

//DEBUG :
//echo "DONE !";

?>