【www.gdgbn.com--安卓教程】

try{
    $tor = new TorHttp("127.0.0.1", 9050);
    $data = array("username" => "liujun");
    $headers = array("Cookie" => "php教程id=123456; xx=v");
    echo $tor->get("http://host.com/testsocks.php", $headers);
    $tor->newId("123456");
}catch(Exception $e){
    if($e->getCode() == 9999){
        $tor->newId("123456");
    }
    echo $e->getMessage() . "n";
}
*/

class Tool_TorHttp
{
    /**
     * Tor提供的socks服务器
     *
     * @var      */
    private $_host;

    /**
     * socks服务的连接
     *
     * @var
     */
    private $_sock;

    /**
     * 构造函数
     *
     * @param $host socks服务器地址
     * @param $port
     */
    public function __construct($host = "127.0.0.1", $port = 9050)
    {
        $this->_host = $host;
        @ $this->_sock = fsockopen($host, $port, $errorCode, $error, 5);

        if($errorCode){
           throw new Exception("不能连接代理服务器");
        }

        //建立应用层的连接
        fwrite($this->_sock, pack("C3", 5, 1, 0));
        $resp = fread($this->_sock, 1024);
        $resp = unpack("Cversion/Cmethod", $resp);
        if($resp["version"] != 5 || $resp["method"] != 0){
            $this->_sock = null;
            throw new Exception("代理服务器不可用或者需要连接密码");
        }
    }

    /**
     * 连接目标主机
     *
     * @param $host
     * @param $port
     */
    private function _connect($host, $port)
    {
        //ip和域名描述的服务器用不同的报文格式
        $lip = ip2long($host);
        if(empty($lip)){
            $pack = pack("C5", 5, 1, 0, 3, strlen($host)) . $host . pack("n", intval($port));
        }else{
            $pack = pack("C4Nn", 5, 1, 0, 1, $lip, $port);
        }
        fwrite($this->_sock, $pack);
        $resp = "";
        $counter = 0;
        while(true){
            if(feof($this->_sock)){
                break;
            }
            $resp .= fread($this->_sock, 1024);
            if(!empty($resp) || $counter == 50){
                break;
            }
            $counter += 1;
        }

        $resp = unpack("Cversion/Crep", $resp);
        if(($resp["version"] != 5) || ($resp["rep"] != 0)){
            throw new Exception("请求的服务[$host:$port]暂时不可用,或者Tor不能到达,如果反复发生,请尝试重启Tor", 9999);
        }
    }

    /**
     * 发起一次http的get请求
     *
     * @param $url
     * @return
     */
    public function get($url, $headers = array())
    {
        $ua = parse_url($url);
        if(empty($ua["port"])){
            $ua["port"] = 80;
        }

        $this->_connect($ua["host"], $ua["port"]);

        $requestUri = $ua["path"];

        if(!empty($ua["query"])){
                $requestUri .= "?" . $ua["query"];
        }

        $headers["Host"] = $ua["host"];
        if(!isset($headers["User-Agent"])){
            $headers["User-Agent"] = "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10 GTB5";
        }
        $headers["Connection"] = "close";

        fwrite($this->_sock, "GET {$requestUri} HTTP/1.1n");
        foreach ($headers as $key => $val){
            fwrite($this->_sock, "{$key}: {$val}n");
        }
        fwrite($this->_sock, "n");

        $resp = "";
        while(!feof($this->_sock)){
            $resp .= fread($this->_sock, 1024);
        }
        return $resp;
    }

    /**
     * 发起一次http的post请求
     *
     * @param $url
     * @param $data
     * @param $headers
     * @return
     */
    public function post($url, $data, $headers = array())
    {
        $ua = parse_url($url);

        if(empty($ua["port"])){
            $ua["port"] = 80;
        }

        $this->_connect($ua["host"], $ua["port"]);

        if(isset($ua["path"]) && !empty($ua["path"])){
            $requestUri = $ua["path"];
        }else{
            $requestUri = "/";
        }

        if(!empty($ua["query"])){
            $requestUri .= "?" . $ua["query"];
        }

        if(!isset($headers["User-Agent"])){
            $headers["User-Agent"] = "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10 GTB5";
        }
        $headers["Connection"] = "close";

        $data = $this->_parseData($data);

        fwrite($this->_sock, "POST {$requestUri} HTTP/1.1n");
        fwrite($this->_sock, "Host: {$ua["host"]}n");
        fwrite($this->_sock, "Content-Type: application/x-www-form-urlencodedn");
        fwrite($this->_sock, "Content-Length: " . strlen($data) . "n");
        foreach ($headers as $key => $val){
            fwrite($this->_sock, "{$key}: {$val}n");
        }
        fwrite($this->_sock, "n");
        fwrite($this->_sock, $data . "n");

        $resp = "";
        while(!feof($this->_sock)){
            $resp .= fread($this->_sock, 1024);
        }
        return $resp;
    }

    /**
     * 更新Tor的身份
     *
     * @param $password
     * @param $port
     * @return
     */
    public function newId($password = "", $port = 9051)
    {
        if(!empty($password) && $password[0] != """){
            $password = """ . $password . """;
        }

        //创建到tor控终端的连接
        @ $sock = fsockopen($this->_host, $port, $errorCode, $error, 5);
        if($errorCode){
           throw new Exception("不能连接代理服务器控制端,请检查端口号");
        }

        fwrite($sock, "AUTHENTICATE {$password}n");
        $resp = fread($sock, 1024);
        if(!preg_match("/^250/", $resp)){
            throw new Exception("Tor控制认证失败,请确认密码正确");
        }

        fwrite($sock, "SIGNAL NEWNYMn");
        $resp = fread($sock, 1024);
        if(!preg_match("/^250/", $resp)){
            throw new Exception("更新身份失败,请重试");
        }
        return true;
    }

    private function _parseData($data)
    {
        if(empty($data) || !is_array($data)){
                return $data;
        }
        $encoded = "";
        while (list($k, $v) = each($data)) {
            $encoded .= $k . "=" . $v . "&";
        }
        return substr($encoded, 0, -1);
    }

    public function  __destruct()
    {
        fclose($this->_sock);
        $this->_sock = null;
    }
}

本文来源:http://www.gdgbn.com/shoujikaifa/24528/