登录 白背景
<?php
// session_start();
date_default_timezone_set("Asia/Shanghai");
class MouseHole{
    public $default_host = 'https://www.google.com';
    
    public $param_name = 'url';
    public $param_special = 'site';
    public $param_static = 'static_res';
    
    public $white_list = [
            'url','site'
        ];

    public $gbk_site = [
        'www.mitbbs.com'
        ];
    
    //特殊站点替换无效链接
    public $cdn_list = [
        'www.archiveofourown.org'=>[
            '//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js'=>'//cdn.bootcss.com/jquery/1.9.0/jquery.min.js',
            '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js'=>'//cdn.bootcss.com/jqueryui/1.10.0/jquery-ui.min.js'
        ]
    ];
    
    public $content_type = [
        'png'=>'image/png',
        'gif'=>'image/gif',
        'webp'=>'image/webp',
        'jpg'=>'image/jpeg',
        'ico'=>'image/x-icon',
        
        'css'=>'text/css',
        'json'=>'application/json',
        'js'=>'application/javascript',
        'woff'=>'font/woff',
        ];
    
    function __construct(){
        $this->HTTP_ACCEPT_LANGUAGE = empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])?'':$_SERVER['HTTP_ACCEPT_LANGUAGE'];
        $this->HTTP_USER_AGENT = empty($_SERVER['HTTP_USER_AGENT'])?'':$_SERVER['HTTP_USER_AGENT'];
        
        $this->get = $_GET;
        $this->post = $_POST;
        
        $this->self_name = $_SERVER['PHP_SELF'];
    }
    
    //主进程
    function execute(){
        if(empty($this->get) && empty($this->post)){
            //主页
            return $this->index();
        }else if(!empty($this->get[$this->param_special])){
            //测试
            return $this->catchRes();
        }else if(!empty($this->get[$this->param_static])){
            //静态文件
            return $this->staticSource();
        }else if(!empty($this->get['self_code'])){
            //源码
            show_source(__FILE__);
        }else{
            //解析页面
            return $this->genHtml();
        }
    }
    
    //error
    function showError($errorMessage, $data = []){
        echo 'errorMessage:' . $errorMessage . "<br />errorData:";
        print_r($data);
        exit;
    }

    //简易主页
    function index(){
        $ret = '';
        //展示常用网站
        $showList = array(
            );
        $showList2 = [
            ];
            
        foreach($showList as $item){
            $ret .= sprintf("<a href='?%s=%s'>%s</a><br><br>",
                $this->param_name, $item, $item);
        }
        foreach($showList2 as $item){
            $ret .= sprintf("<a href='%s'>%s</a><br><br>",
                $item, $item);
        }
        $ret .= sprintf("<form action='%s'><input name='%s' type='search' value='%s' /> <input type='submit' value='打开'></form>",
            $this->self_name, $this->param_name, $this->default_host);
        
        $ret .= "<a href='?self_code=1'>查看源代码</a><br><br>";
        
        return $ret;
    }
    
    //验证host正确性
    function checkRequest(){
        /*
        - check:get post 中至少有一个有host
        - 获得url
        */
        
        $url = '';
        if(!empty($this->get[$this->param_name])){
            $url = $this->get[$this->param_name];
        }else if(!empty($this->post[$this->param_name])){
            $url = $this->post[$this->param_name];
        }
        $url = urldecode($url);
        
        //检查url
        if(preg_match("/^(https?:\/\/)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)+(:\d+)?(\/.*)?$/", $url)){
            if(!preg_match("/^https?:\/\//", $url)){
                $url = 'https://' . $url;
            }
        }else{
            $this->showError('url不合法', array($url));
        }
        
        $paramStr = '';
        //拼接额外get参数
        foreach($this->get as $k => $v){
            if(in_array($k,$this->white_list)){
                continue;
            }
            $paramStr .= '&' . $k . '=' . urlencode($v);
        }
        if(strpos($url, '?') > 0){
            $url .= $paramStr;
        }else{
            $url .= '?' . substr($paramStr,1);
        }
        
        preg_match_all("/^(https?:\/\/)([a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)+(:\d+)?)/", $url, $res);
        $this->requestProtocol = $res[1][0];
        $this->requestSite = $res[2][0];

        if(isset($this->cdn_list[$this->requestSite])){
            $this->IS_site_special = true;
        }else{
            $this->IS_site_special = false;
        }
        return $url;
    }
    
    function getSite(){
        return $this->requestProtocol . $this->requestSite;
    }
    
    //修复静态文件链接
    function staticUrl(&$html){
        $arr_find = array();
        $arr_replace = array();
        
        preg_match_all('/<script.*?src="([^"]+)".*?><\/script>/', $html, $scriptList);
        preg_match_all('/<link.*?href="([^"]+)".*?>/', $html, $scriptList2);
        foreach(array_merge($scriptList[1], $scriptList2[1]) as $k => $scriptUrl){
            /*
            2. 非本站完整链接,特殊站点,替换
            3. 本站完整链接,过洞
            4. 本站相对路径链接,补充过洞
            */
            
            $scriptUrl = trim($scriptUrl);
            //是否为完整链接
            if(preg_match("/^(https?|\/\/)/", $scriptUrl)){
                //检查静态文件的域名是否跟网站一致
                //如果一致,依然不能跳过
                if(strpos($scriptUrl, $this->getSite()) === 0){
                    //与站点一致,取路径部分,待替换
                    $scriptUrl = substr($scriptUrl, strlen($this->getSite()));
                }else{
                    //是否有cdn地址
                    if($this->IS_site_special && isset($this->cdn_list[$this->requestSite][$scriptUrl])){
                        //替换
                        $arr_find[] = $scriptUrl;
                        $arr_replace[] = $this->cdn_list[$this->requestSite][$scriptUrl];
                    }
                    continue;
                }
            }
            if($scriptUrl == '/'){
                continue;
            }
            if(preg_match("/^\/\?/", $scriptUrl)){
                continue;
            }
            //替换
            $arr_find[] = $scriptUrl;
            $arr_replace[] = $this->self_name . '?' . $this->param_static . '=' . urlencode($this->getSite() . $scriptUrl);
        }
        // var_dump($arr_find,$arr_replace);
        // exit();
        $html = str_replace($arr_find, $arr_replace, $html);
    }
    
    //获取html页面
    function genHtml(){
        //检查链接
        $this->requestUrl = $this->checkRequest();
        //设置编码
        if(in_array($this->requestSite, $this->gbk_site)){
            header('Content-Type:text/html;charset=GBK');
        }else{
            header('Content-Type:text/html;charset=UTF-8');
        }
        //请求html
        $html = $this->holeGet($this->requestUrl, $this->post);
        
        //修复script link标签地址
        $this->staticUrl($html);
        
        //拼接footjs用于修复页面中的links form表单
        return $html . $this->footJs();
    }
    
    //debug
    function catchRes(){
        // $this->IS_site_special = true;
        $html = file_get_contents($this->get[$this->param_special]);
        //$this->staticUrl($html);
        return $html;
    }
    
    //输出静态文件
    function staticSource(){
        $url = strtolower($this->get[$this->param_static]);
        
        $mReg = implode('|', array_keys($this->content_type));
        
        $matchStr = "/\.(".$mReg.")/";
        
        preg_match_all($matchStr, $url, $res);
        //var_dump($res);exit;
        header("Content-Type: " . $this->content_type[$res[1][0]]);
        header('Cache-Control:max-age=315360000');
        
        return file_get_contents($this->get[$this->param_static]);
    }
    
    function holeGet($url, $post_data=array())
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, false);
        $header = array(
            'Accept-Language: ' . $this->HTTP_ACCEPT_LANGUAGE,
            'User-agent: ' . $this->HTTP_USER_AGENT,
            
        ); //设置一个你的浏览器agent的header
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_USERAGENT, $this->HTTP_USER_AGENT);
        //跟随302跳转
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        if(!empty($post_data)){
            //设置post方式提交
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
        }
        $res = curl_exec($ch);
        // $rescode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return $res;
    }
    
    function footJs(){
        $site = $this->getSite();
        return
<<<EOF
        
<script>
//https://www.baidu.com:80
//window.onload = function(){
var Req_Site = "$site";
var Main_Site = window.location.protocol + '//' + window.location.host;
var Main_Url = window.location.href.match(/[^?]*/)[0];
Main_Url = Main_Site + '$this->self_name';
var i,o;
var Req_Url,Str_Param;
var Reg_Path = /^(https?:)?\/\/[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)+(\/.*)/;
var Reg_Param = /(\?|&)([^&\?=]+=[^&\?=]+)/g;
var Reg_Filename = /\/[^\?]*/;

//console.log(document.links);

//将a链接中省略域名的链接修复
for(i = 0; i < document.links.length; i++){
    //console.log('scan url:' + document.links[i].href);
    //排除空链接
    if(document.links[i].href.match(/^javascript:/i)){
        //console.log('empty');
        continue;
    }
    //排除非当前站的链接(针对google还有导航站)
    if(document.links[i].href.search(Req_Site) == -1 && document.links[i].href.search(Main_Site) == -1){
        //console.log('not main');
        continue;
    }
    //获取路径部分
    Req_Path = document.links[i].href.match(Reg_Path)[3];
    //console.log('i='+i,Req_Path);
    
    //拆分路径中的路径和参数
    Req_Filename = Req_Path.match(Reg_Filename)[0];
    Req_Param = Req_Path.match(Reg_Param);
    Str_Param = '';
    if(Req_Param != null){
        for(o=0;o<Req_Param.length;o++){
            if(Req_Param[o].substr(1,3)=='url')continue;
            Str_Param += '&' + Req_Param[o].substr(1);
        }
    }
    //console.log(Req_Path, Str_Param);
    
    //链接路径部分和域名部分
    Req_Url = encodeURIComponent(Req_Site + Req_Filename);
    //console.log('Req_Url:' + Req_Url);
    //拼接上本页面链接
    document.links[i].href = Main_Url +'?url=' + Req_Url + '&' + Str_Param.substr(1);
}

//将图片链接修复
for(i = 0; i < document.images.length; i++){
    console.log('scan url:' + document.images[i].src);
    //排除空链接
    if(document.images[i].src.match(/^#/i)){
        //console.log('empty');
        continue;
    }
    //排除非当前站的链接
    if(document.images[i].src.search(Req_Site) == -1 && document.images[i].src.search(Main_Site) == -1){
        //console.log('not main');
        continue;
    }
    //获取路径部分
    Req_Path = document.images[i].src.match(Reg_Path)[3];
    //console.log('i='+i,Req_Path);
    
    //拼接上本页面链接
    document.images[i].src = Main_Url +'?static_res=' + Req_Site + Req_Path;
    if (document.images[i].srcset != '') {
        document.images[i].srcset = '';
    }
}

for(i = 0; i < document.forms.length; i++){
    //排除跳转到其他站的表单
    if(document.forms[i].action.search(Req_Site) == -1 && document.forms[i].action.search(Main_Site) == -1){
        continue;
    }
    Req_Path = document.forms[i].action.match(Reg_Path)[3];
    Req_Url = encodeURIComponent(Req_Site + Req_Path);
    document.forms[i].action = Main_Url +'?url=' + Req_Url;
    document.forms[i].innerHTML += '<input type="hidden" name="url" value="' + Req_Url + '" />';
}
console.log('url:','$this->requestUrl');
//};
</script>
EOF;
    }
}
//echo json_encode($_SERVER);exit;
$obj = new MouseHole();
echo $obj->execute();
// var_dump($obj);
exit;