PHP: class HTTP – A Curl Alternative – support proxy, socks4, socks4a, socks5, ssh …


PHP: class HTTP – A Curl Alternative – support proxy, socks4, socks4a, socks5, ssh …

This is pure PHP class support many feature of CURL like file upload, …

<?php

/**
 * @author Sans_Amour - WWW.TUTORIALSPOTS.COM
 * @package HTTP 
 * @version 2.0.1
 * @start 07/02/2012
 * @last 11/07/2016 
 * History:
 * 07/02/2012 start v1.0
 * 07/12/2012 v1.1
 *   using http proxy and socks4/5
 * 07/13/2012 v1.2
 *   using cookie file like CURL cookie file
 * 07/16/2012 v1.3
 *   file upload
 *   authorization basic
 * 07/18/2012 v1.4
 *   socks4a
 * 07/24/2012
 *   add cookie from additional headers
 * 08/08/2012 v1.5
 *   https connection with https proxy, socks4/4a/5
 * 03/28/2015 fix cookie_file::add
 * 03/19/2016 v1.6 ssh for http
 * 07/11/2016 v2.0 ssh for https
 * 05/15/2020 v2.0.1 change fsockopen to stream_socket_client
 */
date_default_timezone_set('Asia/Saigon');

if (!function_exists('mime_content_type'))
{
    function mime_content_type($filename)
    {
        $mime_types = array('txt' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html',
            'php' => 'text/html', 'css' => 'text/css', 'js' => 'application/javascript', 'json' =>
            'application/json', 'xml' => 'application/xml', 'swf' => 'application/x-shockwave-flash',
            'flv' => 'video/x-flv', // images
            'png' => 'image/png', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg',
            'gif' => 'image/gif', 'bmp' => 'image/bmp', 'ico' => 'image/vnd.microsoft.icon', 'tiff' =>
            'image/tiff', 'tif' => 'image/tiff', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml',
            // archives
            'zip' => 'application/zip', 'rar' => 'application/x-rar-compressed', 'exe' =>
            'application/x-msdownload', 'msi' => 'application/x-msdownload', 'cab' =>
            'application/vnd.ms-cab-compressed', // audio/video
            'mp3' => 'audio/mpeg', 'qt' => 'video/quicktime', 'mov' => 'video/quicktime', // adobe
            'pdf' => 'application/pdf', 'psd' => 'image/vnd.adobe.photoshop', 'ai' =>
            'application/postscript', 'eps' => 'application/postscript', 'ps' =>
            'application/postscript', // ms office
            'doc' => 'application/msword', 'rtf' => 'application/rtf', 'xls' =>
            'application/vnd.ms-excel', 'ppt' => 'application/vnd.ms-powerpoint', // open office
            'odt' => 'application/vnd.oasis.opendocument.text', 'ods' =>
            'application/vnd.oasis.opendocument.spreadsheet', );

        $ext = strtolower(array_pop(explode('.', $filename)));
        if (array_key_exists($ext, $mime_types))
            return $mime_types[$ext];
        elseif (function_exists('finfo_open'))
        {
            $finfo = finfo_open(FILEINFO_MIME);
            $mimetype = finfo_file($finfo, $filename);
            finfo_close($finfo);
            return $mimetype;
        } else
            return 'application/octet-stream';
    }
}

class http
{
    public $timeout = 10;
    public $referer = '';
    public $useragent = 'Mozilla/5.0 (Windows NT 6.1; rv:8.0.1) Gecko/20100101 Firefox/8.0.1';
    public $boundary = '';
    public $contenttype = 'application/x-www-form-urlencoded';
    public $length = 4096; //1024
    public $cookiefile = 'cookie.txt';
    //more header: 2 types
    public $header = array();
    public $usecookie = true;
    public $loadcookie = true;
    public $headercookie = true;
    public $connection = 'close';
    public $contentlength = 0;
    public $followlocation = false;
    public $maxredirect = 1;
    public $method = 'GET';
    public $url = '';
    public $autoreferer = true;
    public $authorization = array();

    public $proxy_type = '';
    public $proxy = '';
    public $proxy_port = '';
    public $proxy_user = '';
    public $proxy_pass = '';
    //public $returnheader = true;
    public $fp = false;

    public $_cookies = array();
    private $cf = false; //cookie_file
    private $pack = '';
    private $vars = array();
    private $files = array();
    private $content = '';
    private $var = '';
    //private $_header = array();
    public $query_time;
    public $echo=false;
    public $raw=false;
    
    /**
     * @since v2.0
     */
    public $ssh_ip = '';
    public $ssh_user = '';
    public $ssh_pass = '';
    
    public $validateHttpResponse = false;
    public $responseheaders = null;
    public $getcount = 1000;

    function __construct()
    {
        srand((double)microtime() * 1000000);
        $this->boundary = "---------------------" . substr(md5(rand(0, 32000)), 0, 10);
    }

    /**
     * @since v1.1
     */
    public function proxy($proxy, $user = '', $type = 'http')
    {
        $valid_types = array('http', 'socks4', 'socks4a', 'socks5');
        if (in_array($type, $valid_types))
        {
            $this->proxy_type = $type;

            if (preg_match("/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\:(\d{1,5}))?/", $proxy, $m))
            {

                $this->proxy = $m[1];
                $this->proxy_port = $m[3] ? $m[3] : '80';
                if ($user && strpos($user, ':') !== false)
                {
                    $user = explode(":", $user);
                    $this->proxy_user = $user[0];
                    $this->proxy_pass = $user[1];
                }
            } else
                $this->proxy_type = '';
        } else
            $this->proxy_type = '';
    }
    /**
     * @since v2.0
     */
    public function ssh($ssh_ip, $user = '')
    {
            $this->ssh_ip = $ssh_ip;

            if ($user && strpos($user, ':') !== false)
            {
                $user = explode(":", $user);
                $this->ssh_user = $user[0];
                $this->ssh_pass = $user[1];
            }
    }
    /**
     * @since v1.0
     */
    public function get($url, $ret = 1)
    {
        $return = $this->exec('GET', $url, '', $ret);
        $this->clear();
        if($this->echo) echo $return;
        return $return;
    }

    /**
     * @since v1.0
     */
    public function post($url, $var = null, $ret = 1)
    {
        $return = $this->exec('POST', $url, $var, $ret);
        $this->clear();
        if($this->echo) echo $return;
        return $return;
    }

    /**
     * @since v1.0
     */
    public function parseHeaders($headers)
    {
        $h = array();
        if (!$this->cf)
            $this->loadCookie();
        foreach ($headers as $header)
        {
            if (strpos($header, ': ') !== false)
            {
                $h2 = explode(': ', $header, 2);
                if ($h2[0] != "Set-Cookie")
                    $h[$h2[0]] = $h2[1];
                else
                {
                    //var_dump($h2);
                    if ($this->usecookie)
                    {
                        if (!isset($h["Set-Cookie"]))
                            $h["Set-Cookie"] = array();
                        $_c = cookie::grab($header, $this->url);
                        //var_dump($_c);
                        if (!cookie_file::exists($h["Set-Cookie"], $_c))
                            $h["Set-Cookie"][] = $_c;

                        if (!cookie_file::exists($this->_cookies, $_c))
                            $this->_cookies[] = $_c;
                        //var_dump($this->cf->cookies);
                        $this->cf->add($_c, $this->url);
                        //var_dump($this->cf->cookies);
                    }
                }
            }
        }
        //var_dump($headers);
        return $h;
    }

    /**
     * @since v1.0
     */
    public function saveCookie()
    {
        if (!$this->cf)
            $this->loadCookie();
        //var_dump($this->cf->lines);
        //var_dump($this->_cookies);
        $this->cf->write_file($this->url);

        $this->_cookies = array();
        $this->cf->cookies = array();
    }

    /**
     * @since v1.0
     */
    public function loadCookie()
    {
        $this->cf = new cookie_file($this->cookiefile);
        $cd = $this->cf->domain($this->url, false);
        //var_dump($cd);die();
        if ($cd)
            $this->_cookies = $cd;
    }

    /**
     * @since v1.0
     */
    private function content($array)
    {
        if($this->raw) return $array;
        if (is_string($array))
        {
            if (strpos($array, 'Content-Disposition: form-data') !== false)
                return $array;
            parse_str($array, $vars);
            $array = $vars;
        }
        $this->detect_file_upload($array);
        if (count($this->files))
        {
            $this->contenttype = "multipart/form-data; boundary={$this->boundary}"; //,

            // attach post vars

            $data = self::form_data($this->vars, $this->boundary);
            $data .= "--{$this->boundary}\r\n";
            // and attach the file
            foreach ($this->files as $index => $file)
            {
                $content_file = join("", file($file));
                $content_type = mime_content_type($file);
                $data .= "Content-Disposition: form-data; name=\"" . urldecode($index) . "\"; filename=\"" .
                    basename($file) . "\"
Content-Type: $content_type

$content_file
--{$this->boundary}";

            }
            $data .= "--\r\n\r\n";
            return $data;
        } else
            return http_build_query($this->vars);
    }

    /**
     * @since v1.2
     */
    public static function form_data($vars, $boundary)
    {
        $data = '';
        foreach ($vars as $index => $value)
        {
            $data .= "--{$boundary}\r\n";
            $data .= "Content-Disposition: form-data; name=\"" . urldecode($index) . "\"\r\n";
            $data .= "\r\n" . $value . "\r\n";
            $data .= "--{$boundary}\r\n";
        }
        return $data;
    }

    /**
     * @since v1.0
     */
    private function detect_file_upload($array)
    {
        if (!is_array($array))
            return false;
        foreach ($array as $key => $var)
        {
            if (substr($var, 0, 1) == '@')
                $this->files[$key] = substr($var, 1);
            else
                $this->vars[$key] = $var;
        }
    }

    /**
     * @since v1.1
     */
    private function pack($t, $content)
    {
        return implode("\r\n", $t) . "\r\n\r\n" . $content;
    }

    /**
     * @since v1.5
     */
    public function parse($url, &$host, &$port, &$uri, &$sslhost)
    {
        $url2 = parse_url($url);
        $host = $url2['host'];
        $port = isset($url2['port']) ? $url2['port'] : ($url2['scheme'] == 'https' ? 443 : ($url2['scheme'] ==
            'ftp' ? 21 : 80));
        $uri = $url2['path'] == '' ? '/' : $url2['path'];
        if (isset($url2["query"]))
            $uri .= '?' . $url2["query"];

        if ($port == 443)
            $sslhost = "ssl://" . $host;
        elseif ($port == 21)
            $sslhost = "ftp://" . $host;
        else
            $sslhost = $host;
    }

    /**
     * @since v1.5
     */
    public function socket($host, $port, &$errno, &$errstr, $timeout)
    {
        //var_dump($host, $port, $errno, $errstr, $timeout);
        //die('2');
        
        $contextOptions = array('ssl' => array(
            //'cafile' => openssl_get_cert_locations()['default_cert_file'],
            'verify_peer' => false,
             
            'verify_peer_name'  => false,
            'allow_self_signed' => true            
        ));
     
        $streamContext = stream_context_create($contextOptions);
        $this->fp = stream_socket_client($host.':'.$port, $errno, $errstr, $timeout,
            STREAM_CLIENT_CONNECT, $streamContext);
        
        //$this->fp = @fsockopen($host, $port, $errno, $errstr, $timeout);
    }
    
    /**
     * @since v2.0
     */
    public function sshsocket($host, $port)
    {
        $connection = ssh2_connect($this->ssh_ip, 22);
        
        if(!$connection) return false;
        
        if(!ssh2_auth_password($connection, $this->ssh_user, $this->ssh_pass)) return false;
        
        //var_dump($this->ssh_ip, $this->ssh_user, $this->ssh_pass,$host, $port); 
        //$ip = gethostbyname($host)
        $this->fp = ssh2_tunnel($connection, $host, $port);
    }

    /**
     * @since v1.5
     */
    public function send($cmd)
    {
        return fwrite($this->fp, $cmd);
    }

    /**
     * @since v1.0
     * ret = 0: not return transfer
     * ret = 1: return body                                             default
     * ret = 2: return array header
     * ret = 3: return array header parsed
     * ret = 4: return full response
     * ret = 5: return array (array header, body)
     */
    public function exec($method = 'POST', $url, $content = null, $ret = 1)
    {
        if (empty($content) && $method == 'POST')
            return false;
        
        $_bm = microtime(1);
        
        $this->method = $method;
        $this->url = $url;
        $this->var = $content;

        $this->parse($url, $host, $port, $uri, $sslhost);

        $content = $this->content($content);

        if ($this->usecookie && ($this->loadcookie || ($this->cf && !$this->loadcookie)))
            $this->loadCookie();
            //$this->headercookie = true;
        
        if ($this->ssh_ip && $port == '443'){
            
            $connection = ssh2_connect($this->ssh_ip, 22);
        
            if(!$connection) return false;
            
            if(!ssh2_auth_password($connection, $this->ssh_user, $this->ssh_pass)) return false;
            
            $cmd = "curl --include".
                " -H ".('\'Host: ' . $host . ($port == 80 ? '' : ":$port"))."'".
                " -H "."'User-Agent: {$this->useragent}'";
                
            if ($this->contenttype)
                $cmd .=  ' -H \'Content-Type: ' . $this->contenttype."'";
            if ($this->referer)
                $cmd .=  " -H 'Referer: {$this->referer}'";    
                
            if (count($this->authorization) == 2)
                $cmd .= " -H 'Authorization: Basic " . base64_encode("{$this->authorization[0]}:{$this->authorization[1]}")."'";
    
            if ($this->method == 'POST')
                $cmd .= ' -H \'Content-Length: ' . ($this->contentlength <> 0 ? $this->contentlength : strlen($content))."'";
            $cmd .= ' -H \'Connection: ' . $this->connection."'";    
            
            if (count($this->header))
            {
                if (isset($this->header[0]))
                    $this->header = $this->parseHeaders($this->header);
                foreach ($this->header as $k => $h)
                {
                    if (!is_array($h))
                        $cmd .= " -H '$k: $h'";                
                }
            }
                
            $cmd .=   " -X ".$this->method." --cookie-jar ".$this->cookiefile.
                " --cookie ".$this->cookiefile." ".($content!=null?"-d '".str_replace("'","\'",$content)."'":"")." ".$this->url;
            
            $x = ssh2_exec($connection,$cmd);

            stream_set_blocking($x, true);
             
            $rsp = $this->content = stream_get_contents($x);
            
            //return $this->content;
 
            //return false;
        }else{   
        
            $t = array();
            $t[] = $method . ' ' . $uri . ' HTTP/1.1';
            //$t[] = 'Host: ' . $sslhost;
            //$t[] = 'Host: ' . $host . ($port == 443 ? ':443' : '');
            $t[] = 'Host: ' . $host . ($port == 80 ? '' : ":$port");
            if ($this->contenttype)
                $t[] = 'Content-Type: ' . $this->contenttype;
            if ($this->referer)
                $t[] = "Referer: {$this->referer}";
            $t[] = "User-Agent: {$this->useragent}";
            if (count($this->authorization) == 2)
                $t[] = "Authorization: Basic " . base64_encode("{$this->authorization[0]}:{$this->authorization[1]}");
    
            if ($this->method == 'POST')
                $t[] = 'Content-Length: ' . ($this->contentlength <> 0 ? $this->contentlength : strlen($content));
            $t[] = 'Connection: ' . $this->connection;
    
            if (count($this->header))
            {
                if (isset($this->header[0]))
                    $this->header = $this->parseHeaders($this->header);
                foreach ($this->header as $k => $h)
                {
                    if (!is_array($h))
                        $t[] = "$k: $h";                
                }
            }
    
            if (count($this->_cookies) && ($this->loadcookie || (!$this->loadcookie && $this->cf)) &&
                $this->headercookie)
                $t[] = cookie_file::toString($this->_cookies);
            $t = array_unique($t);
     
            $this->pack = $this->pack($t, $content);
            //  var_dump($this->pack);die();
            //var_dump($this->proxy_type,$this->proxy_type);die();
            
            if (!$this->proxy_type)
            {
                if($this->ssh_ip){
                    //$this->sshsocket($sslhost, $port);
                    $this->sshsocket($host, $port);
                }else
                    $this->socket($sslhost, $port, $errno, $errstr, $this->timeout);
                //var_dump($this->fp,$sslhost, $port, $errno, $errstr, $this->timeout);die();
                if (!$this->fp || !(get_resource_type($this->fp) == 'stream'))
                    return false;
                    
                //if ($this->ssh_ip && $port == '443')                    
                //    self::_ssl_encrypt();    
                //if ($port == '443')                    
                //    self::_ssl_encrypt();     
                    
                if (!$this->send($this->pack))
                {
                    fclose($this->fp);
                    return false;
                }
                 
                if ($this->ssh_ip)  {
                    stream_set_blocking($this->fp, true);
                }  
                              
                
            } else
            {
                $this->socket($this->proxy, $this->proxy_port, $errno, $errstr, $this->timeout);
                if (!$this->fp || !(get_resource_type($this->fp) == 'stream'))
                    return false;
                if ($this->proxy_type == 'http')
                {
                    if ($this->proxy_user && $this->proxy_pass)
                        $t[] = "Proxy-Authorization: basic " . base64_encode($this->proxy_user . ":" . $this->
                            proxy_pass);
                    $url = 'http' . ($port == 443 ? 's' : '') . '://' . $host . $uri;
                    $t[0] = $method . " " . $url . " HTTP/1.0";
                    $this->pack = $this->pack($t, $content);
                    //var_dump($this->pack);
                    if ($port == '443')
                    {
                        /*
                        The practical way to handle https destination+http proxy is:
    
                        connect http(not encrypted) connection to the proxy server.
                        send CONNECT request to start ssl tunneling.
                        change the connection to encrypted mode.
                        send normal proxy request (GET or POST).
                        */
                        
                        
                        $t3 = $t;
                        $t3[0] = 'CONNECT ' . $host . ':' . $port . ' HTTP/1.0';
    
                        $_pack = $this->pack($t3, '');
                        //HTTP/1.0 200 Connection established
                        //HTTP/1.0 200 OK
                        /*var_dump($_pack);
                        
                        $_pack = "CONNECT httpbin.org:443 HTTP/1.0
Host: httpbin.org:443
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:8.0.1) Gecko/20100101 Firefox/8.0.1
Connection: close

";*/
                        
                        if (!$this->send($_pack))
                        {
                            fclose($this->fp);//var_dump('1');
                            return false;
                        }
                        //var_dump(fgets($this->fp, $this->length));die();
                        $q = fgets($this->fp, $this->length);
                        if (strpos($q, '200 Connection established') === false &&
                            strpos($q, '200 OK') === false)
                        {
                            fclose($this->fp);
                            return false;
                        }
                        //var_dump('1');
                        self::_ssl_encrypt();
                    }
                    if (!$this->send($this->pack))
                    {
                        fclose($this->fp);
                        return false;
                    }
                } elseif ($this->proxy_type == 'socks4')
                {
                    //http://www.openssh.org/txt/socks4.protocol
                    $ip = gethostbyname($host);
                    if (preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $ip, $matches))
                        $int = pack('C4', $matches[1], $matches[2], $matches[3], $matches[4]);
                    else
                    {
                        fclose($this->fp);
                        return false;
                    }
                    $request = pack('C2', 0x04, 0x01) . pack('n', $port) . $int . ($this->proxy_user ? $this->
                        proxy_user : '0') . pack('C', 0x00);
                    fwrite($this->fp, $request);
                    $resp = fread($this->fp, 9);
                    if (strlen($resp) != 8)
                    {
                        fclose($this->fp);
                        return false;
                    }
                    $answer = unpack('Cvn/Ccd', substr($resp, 0, 2));
                    //var_dump($answer);
                    if ($answer['vn'] != 0x00 && $answer['vn'] != 0x04)
                    {
                        fclose($this->fp);
                        return false;
                    }
                    if ($answer['cd'] != 0x5A)
                    {
                        fclose($this->fp);
                        return false;
                    }
                    if ($port == '443')
                        self::_ssl_encrypt();
    
                    if (!$this->send($this->pack))
                    {
                        fclose($this->fp);
                        return false;
                    }
                } elseif ($this->proxy_type == 'socks4a')
                {
                    //http://ballastsec.blogspot.com/2012/06/php-socks4a-interface.html
                    //http://www.openssh.org/txt/socks4a.protocol
                    $ip = rand(1, 255);
                    $int = pack('C4', 0, 0, 0, $ip);
    
                    $request = pack('C2', 0x04, 0x01) . pack('n', $port) . $int . ($this->proxy_user ? $this->
                        proxy_user : '0') . pack('C', 0x00) . $host . pack('C', 0x00);
                    $this->send($request);
                    $resp = fread($this->fp, 9);
                    if (strlen($resp) != 8)
                    {
                        fclose($this->fp);
                        return false;
                    }
                    $answer = unpack('Cvn/Ccd', substr($resp, 0, 2));
    
                    if ($answer['vn'] != 0x00 && $answer['vn'] != 0x04)
                    {
                        fclose($this->fp);
                        return false;
                    }
                    if ($answer['cd'] != 0x5A)
                    {
                        fclose($this->fp);
                        return false;
                    }
                    if ($port == '443')                
                        self::_ssl_encrypt();
                                        
                    if (!$this->send($this->pack))
                    {
                        fclose($this->fp);
                        return false;
                    }
                } elseif ($this->proxy_type == 'socks5')
                {
                    if ($this->proxy_user && $this->proxy_pass)
                        $request = pack('C4', 0x05, 0x02, 0x00, 0x02);
                    else
                        $request = pack('C3', 0x05, 0x01, 0x00);
                    $this->send($request);
    
                    $resp = fread($this->fp, 3);
                    $answer = @unpack('Cver/Cmethod', $resp);
    
                    if (!$answer)
                        return false;
                    if ($answer['method'] == 0x02)
                    {
                        $request = pack('C', 0x01) . pack('C', strlen($this->proxy_user)) . $this->proxy_user .
                            pack('C', strlen($this->proxy_pass)) . $this->proxy_pass;
                        fwrite($this->fp, $request);
                        $resp = fread($this->fp, 3);
                        $answer = unpack('Cvn/Cresult', $resp);
                        if ($answer['vn'] != 0x01 && $answer['result'] != 0x00)
                        {
                            fclose($this->fp);
                            return false;
                        }
                    }
                    if ($answer['method'] == 0x00)
                    {
                        $ip = gethostbyname($host);
                        if (preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $ip, $matches))
    
                            $int = pack('C4', $matches[1], $matches[2], $matches[3], $matches[4]);
                        else
                        {
                            fclose($this->fp);
                            return false;
                        }
    
                        $request = pack('C4', 0x05, 0x01, 0x00, 0x01) . $int . pack('n', $port); // pack("C2", 0x00, 0x00);
                        $this->send($request);
    
                        $resp = fread($this->fp, 11);
                        $answer = @unpack('Cver/CREP', substr($resp, 0, 2));
    
                        if (!$answer)
                            return false;
                        if ($answer['REP'] != 0x00)
                        {
                            fclose($this->fp);
                            return false;
                        }
                        if ($port == '443')                    
                            self::_ssl_encrypt();
                        
                        if (!$this->send($this->pack))
                        {
                            fclose($this->fp);
                            return false;
                        }
                    } else
                        return false;
                }
            }
    
            if ($ret > 0)
            {
                $rsp = '';
                $ec = 0; $ccc = 0;
                //var_dump($this->fp);
                
                stream_set_timeout($this->fp,$this->timeout);
                
                while ((!feof($this->fp)) && (($ccc++)<$this->getcount))
                {
                    $rsp .= fgets($this->fp, $this->length);
                    //if ($ec++ == 0 && $fget == "\r\n") // && $this->length == 4096
                    //    $rsp .= '';
                    //else
                    //$rsp .= $fget;
                }
                //var_dump($rsp);
                //die();
            }
            fclose($this->fp);
            
            $this->content = $rsp;
        }
        
        $this->query_time = microtime(1)-$_bm;
        
        if ($this->autoreferer)
            $this->referer = $url;
        
        if ($this->usecookie)
        {
            $res = $this->parseHttpResponse($rsp, $ret);
            $this->saveCookie();
        }
        if ($ret == 4)
        {
            return $rsp;
        }
        if ($ret > 0)
        {
            return $this->usecookie ? $res : $this->parseHttpResponse($rsp, $ret);
        }
    }
    
    /**
     * @since v.15
     */
    private function _ssl_encrypt(){
        if (!in_array('ssl', stream_get_transports()))
            die('not support ssl');
        //var_dump(stream_get_transports());die();
        //stream_set_blocking($this->fp, true);
        $modes = array(
            //STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
            //STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT,
            //STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT,
            STREAM_CRYPTO_METHOD_TLS_CLIENT, 
            STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
            STREAM_CRYPTO_METHOD_SSLv23_CLIENT, 
            STREAM_CRYPTO_METHOD_SSLv2_CLIENT
        );

        $success = false;
        foreach ($modes as $mode)
        {
            $success = @stream_socket_enable_crypto($this->fp, true, $mode);
            if ($success)
                break;
            //else stream_socket_enable_crypto($this->fp, false);
        }  //var_dump($success);
        //stream_set_blocking($this->fp, false);
    }

    /**
     * @since v1.2
     */
    public function clear()
    {
        $this->pack = '';
        $this->content = '';
        $this->vars = array();
        $this->files = array();
    }

    /**
     * @since v1.0
     */
    public function parseHttpResponse($content = null, $ret = 1)
    {
        if (empty($content))
        {
            return false;
        }

        $nl = "\r\n";
        //$content = trim($content);
        $content = ltrim($content);
        $hunks = explode($nl . $nl, $content, 2);
        
        //var_dump($hunks);
         
        if (!is_array($hunks))
            return false;
        if (count($hunks) < 2)
            $body = '';
        else
            $body = end($hunks);

        $header = reset($hunks);
         
        $this->responseheaders = $headers = explode($nl, $header);
         
        unset($hunks);
        unset($header);

        if ($this->validateHttpResponse && !self::validateHttpResponse($headers))
        {
            return false;
        }

        if ($this->followlocation && $this->maxredirect > 0)
        {
            $_headers = $this->parseHeaders($headers);

            if (isset($_headers["Location"]))
            {
                $newobject = $this->_clone();
                $newobject->maxredirect = $newobject->maxredirect - 1;
                //if ($this->autoreferer)
                //    $newobject->referer = $this->url;
                $newobject->autoreferer = false;
                $newobject->referer = '';

                $newobject->loadcookie = false;
                $newobject->url = $_headers['Location'];
                $newobject->clear();
                // var_dump($newobject,$ret);die();

                return $newobject->exec($this->method, $_headers['Location'], $this->var, $ret);
            }
        }
 
        if ($ret == 2)
            return $headers;
        if ($ret == 3)
            return $this->parseHeaders($headers);
        //var_dump($headers,$ret,$body);die();
        if ($ret == 1 || $ret == 5)
        {
            //$this->parseHeaders($headers);
            //var_dump($headers);die();                                                              
            if (in_array('Transfer-Coding: chunked', $headers) || in_array('Transfer-Encoding: chunked',
                $headers))
                $body = trim(self::unchunkHttpResponse($body));
            else
                $body = trim($body);
            
            return $ret==1?$body:array($headers, $body);
        }
        
    }

    /**
     * @since v1.0
     */
    public static function validateHttpResponse($headers = null)
    {
        if (!is_array($headers) or count($headers) < 1)
        {
            return false;
        }
        if (strpos(trim(strtolower($headers[0])), "200") !== false || strpos(trim(strtolower($headers[0])),
            "100") !== false || strpos(trim(strtolower($headers[0])), "301") !== false || strpos(trim
            (strtolower($headers[0])), "302") !== false)
            return true;
            
        return false;
    }

    /**
     * @since v1.0
     */
    public static function unchunkHttpResponse2($result)
    {
        return preg_replace('/([0-9A-F]+)\r\n(.*)/sie', '($cnt=@base_convert("\1", 16, 10))
               ?substr(($str=@strtr(\'\2\', array(\'\"\'=>\'"\', \'\\\\0\'=>"\x00"))), 0, $cnt).http::unchunkHttpResponse(substr($str, $cnt+2))
               :""', $result);
    }

    public static function unchunkHttpResponse($data)
    { //die();
        $fp = 0;
        $outData = "";
        while ($fp < strlen($data))
        {
            $rawnum = substr($data, $fp, strpos(substr($data, $fp), "\r\n") + 2);
            $num = hexdec(trim($rawnum));
            $fp += strlen($rawnum);
            $chunk = substr($data, $fp, $num);
            $outData .= $chunk;
            $fp += strlen($chunk);
        }
        return $outData;
    }

    /**
     * @since v1.1
     */
    private function _clone()
    {
        return $this;
    }
}


class cookie_file
{
    public $cookies = array();
    public $filename = 'c.txt';
    public $f = false;
    public $content = '';
    private $head = '# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This file was generated by sa_http_class! Edit at your own risk.
';
    public $lines = array();

    function __construct($filename = '')
    {
        if ($filename != '')
            $this->filename = $filename;
        if(!file_exists($this->filename)){
            $_f = fopen($this->filename, 'w');
            fclose($_f);
        }
        $this->f = fopen($this->filename, 'r+');
        if(!$this->f) return false;
        $this->read();

        if ($this->content != '')
            $this->parselines();
        else
        {
            $this->write_new_file();
            $this->content = $this->head;
            $this->lines = explode("\r\n", $this->head);
        }
    }

    public function write_new_file()
    {
        file_put_contents($this->filename, $this->head);
    }

    public function write_file($url)
    {
        $cookie_domains = $this->domain($url, false);
        //var_dump($cookie_domains);
        if ($cookie_domains)
        {
            foreach ($cookie_domains as $k => $c)
            {
                if ($c->expired())
                    unset($this->lines[$k]);
                else
                    $this->lines[$k] = $c->toString();
            }
            file_put_contents($this->filename, implode("\r\n", $this->lines) . "\r\n");
            $this->__construct($this->filename);
        }
    }

    public function add($cookie, $url = false) //cookie $cookie
    {
        if(!($cookie instanceof cookie)) return;
        if ($url === false)
            $url = 'http://' . ltrim($cookie->domain, '.') . $cookie->path;
        //first select all cookie of domain
        $cookie_domains = $this->domain($url, false);

        if ($cookie_domains && count($cookie_domains) > 0)
        {
            //check douplicate name of cookie
            foreach ($cookie_domains as $k => $c)
            {
                if ($c->name == $cookie->name)
                {
                    //update
                    $sd = $this->cookies[$k]->domain;
                    $this->cookies[$k] = $cookie; // = $cookie_domains[$k] = $c
                    $this->cookies[$k]->domain = $sd;
                    $this->lines[$k] = $cookie->toString();
                    $updated = true;
                    break;
                }
            }
            if (!isset($updated))
            {
                //insert new
                $new_key = count($this->lines);
                $this->cookies[$new_key] = $cookie;
                $this->lines[$new_key] = $cookie->toString();
                unset($updated);
            }
        } else
        {
            $new_key = count($this->lines);
            $this->cookies[$new_key] = $cookie;
            $this->lines[$new_key] = $cookie->toString();
        }
    }

    public function parselines()
    {
        //$lines = explode("\r\n", $this->content);
        $lines = preg_split("/(\r)?\n/", $this->content);
        //var_dump($lines);
        if (count($lines) > 0)
        {
            foreach ($lines as $k => $line)
            {
                $line = trim($line);
                if (substr($line, 0, 1) != '#' && $line <> '')
                {
                    $c = self::parseline($line);
                    if ($c)
                        $this->cookies[$k] = $c;
                }
                $this->lines[$k] = $line;
            }
        }
    }

    public function read($bytes = 1024)
    {
        while (!feof($this->f))
            $this->content .= fgets($this->f, $bytes);
        $this->content = trim($this->content);
    }

    function __destruct()
    {
        if ($this->f !== false)
            @fclose($this->f);
    }

    public static function parseline($line)
    {
        //echo $line;
        $cookie = new cookie;

        $line2 = explode("\t", $line);
        if (!isset($line2[0]) || !isset($line2[6]))
            return false;
        $cookie->setvalue($line2[5], $line2[6]);
        $cookie->expires = $line2[4];
        $cookie->path = $line2[2];
        $cookie->domain = $line2[0];
        $cookie->secure = $line2[3] == 'TRUE';
        //check expires
        //if (!$cookie->expired())
        return $cookie;
        //return false;
    }

    public function domain($url, $tostring = true)
    {
        $url2 = parse_url($url);
        $domain = $url2['host'];
        $port = isset($url2['port']) ? $url2['port'] : ($url2['scheme'] == 'https' ? 443 : 80);
        $path = isset($url2['path']) ? $url2['path'] : '/';
        //var_dump($this->cookies);
        if (count($this->cookies) > 0)
        {
            $ret = array();
            foreach ($this->cookies as $k => $c)
            {
                if ($port == 443 && $c->secure)
                    continue;

                if ($c->path != '/')
                {
                    $pl = strlen($c->path);
                    if (substr($path, 0, $pl) != $c->path)
                        continue;
                }

                if ($c->allowsub())
                {
                    //$pl = strlen($domain);
                    $pl = strlen($c->domain);
                    //if (substr($c->domain, -$pl) == $domain) {
                    //var_dump($domain,$c->domain);
                    if ((substr($domain, -$pl) == $c->domain) || ($domain == substr($c->domain, 1)))
                        $ok = true;
                } elseif ($domain == $c->domain)
                    $ok = true;

                if (isset($ok))
                {
                    $ret[$k] = $c;
                    unset($ok);
                }
            }
            return $tostring ? self::toString($ret) : $ret;
        }
        return false;
    }

    public static function toString($domain_cookies, $prefix = true)
    {
        if (($count = count($domain_cookies)) == 0)
            return '';
        $ret = $prefix ? 'Cookie: ' : '';
        foreach ($domain_cookies as $k => $c)
            $ret .= $c->name . "=" . $c->value . ($count - 1 == $k ? "" : "; ");
        return rtrim($ret, '; ');
    }

    public static function toArray($domain_cookies)
    {
        $ret = array();
        if (count($domain_cookies) > 0)
        {
            foreach ($domain_cookies as $c)
                $ret[$c->name] = $c->value;
        }
        return $ret;
    }

    public static function exists(&$cookies, $new)
    {
        foreach ($cookies as $k => $c)
        {
            if ($c->name == $new->name)
            {
                $cookies[$k]->value = $new->value;
                return true;
            }
        }
        return false;
    }
}

class cookie
{
    private $vars = array("name" => '', "value" => '', "expires" => 0, "path" => '/', "domain" =>
        '', "secure" => false, "httponly" => false, );

    private function notnamevalue($val)
    {
        $keys = array_slice($this->vars, 2);
        return array_key_exists($val, $keys);
    }

    function setvalue($name, $value = '')
    {
        $name2 = strtolower($name);
        if ($this->notnamevalue($name2))
            $this->vars[$name2] = $value;
        elseif ($this->name == '')
        {
            $this->name = $name;
            $this->value = $value;
        }
    }

    function __set($name, $value = '')
    {
        $name = strtolower($name);
        if (array_key_exists($name, $this->vars))
            $this->vars[$name] = $value;
    }

    function __get($name)
    {
        $name = strtolower($name);
        if (array_key_exists($name, $this->vars))
            return ($name == 'path' && $this->vars[$name] == '') ? '/' : $this->vars[$name];
        else
            return false;
    }

    public function allowsub()
    {
        if ($this->vars['domain'])
            return substr($this->vars['domain'], 0, 1) == '.';
        else
            trigger_error('domain not exists');
    }

    public function toString()
    {
        return $this->domain . "\t" . ($this->allowsub() ? 'TRUE' : 'FALSE') . "\t" . $this->path .
            "\t" . ($this->secure ? 'TRUE' : 'FALSE') . "\t" . $this->expires . "\t" . $this->name . "\t" .
            $this->value; //."\r\n";
    }

    public function expired()
    {
        return $this->expires < time() && $this->expires != 0;
    }

    public static function grab($line, $url = '')
    {
        if (preg_match('/^Set-Cookie: /i', $line))
        {
            $line = preg_replace('/^Set-Cookie: /i', '', trim($line));

            if (strpos($line, ';') !== false)
            {
                $line = preg_split("/;[ ]*/", $line);

                $cookie = new cookie;
                foreach ($line as $k => $l)
                {
                    if (strpos($l, '=') !== false)
                    {
                        $l2 = explode("=", $l, 2);
                        //$l2[0] = strtolower($l2[0]);
                        $cookie->setvalue($l2[0], strtolower($l2[0]) == 'expires' ? strtotime($l2[1]) : $l2[1]);
                    } elseif ($l != '')
                        $cookie->$l = true;
                }
                //var_dump($cookie);die();
                if ($cookie->domain == '')
                {
                    if ($url == '')
                        return false;
                    $cookie->domain = parse_url($url, PHP_URL_HOST);
                }
                //var_dump($cookie);
                return ($cookie);
            } elseif (strpos($line, '=') !== false)
            {
                $l2 = explode("=", $line, 2);
                $cookie = new cookie;
                $cookie->name = $l2[0];
                $cookie->value = $l2[1]; 
            }
        }
        return false;
    }
}

Read more: Some examples of using class HTTP

Leave a Reply