<?php

class HTTPSocket
{
    var $version = '3.0.4';
    var $method = 'GET';
    var $remote_host;
    var $remote_port;
    var $remote_uname;
    var $remote_passwd;
    var $result;
    var $result_header;
    var $result_body;
    var $result_status_code;
    var $lastTransferSpeed;
    var $bind_host;
    var $error = array();
    var $warn = array();
    var $query_cache = array();
    var $doFollowLocationHeader = TRUE;
    var $redirectURL;
    var $max_redirects = 5;
    var $ssl_setting_message = 'DirectAdmin appears to be using SSL. Change your script to connect to ssl://';
    var $extra_headers = array();
    var $proxy = false;
    var $proxy_headers = array();
    function connect($host, $port = '')
    {
        if (!is_numeric($port)) {
            $port = 80;
        }
        $this->remote_host = $host;
        $this->remote_port = $port;
    }
    function bind($ip = '')
    {
        if ($ip == '') {
            $ip = $_SERVER['SERVER_ADDR'];
        }
        $this->bind_host = $ip;
    }
    function set_method($method = 'GET')
    {
        $this->method = strtoupper($method);
    }
    function set_login($uname = '', $passwd = '')
    {
        if (strlen($uname) > 0) {
            $this->remote_uname = $uname;
        }
        if (strlen($passwd) > 0) {
            $this->remote_passwd = $passwd;
        }
    }
    private function stream_chunk($ch, $data)
    {
        echo $data;
        return strlen($data);
    }
    private function stream_header($ch, $data)
    {
        if (!preg_match('/^HTTP/i', $data)) {
            header($data);
        }
        return strlen($data);
    }
    function query($request, $content = '', $doSpeedCheck = 0)
    {
        $this->error = $this->warn = array();
        $this->result_status_code = NULL;
        $is_ssl = FALSE;
        if (preg_match('!^http://!i', $request) || preg_match('!^https://!i', $request)) {
            $location = parse_url($request);
            if (preg_match('!^https://!i', $request)) {
                $this->connect('https://' . $location['host'], $location['port']);
            } else {
                $this->connect('http://' . $location['host'], $location['port']);
            }
            $this->set_login($location['user'], $location['pass']);
            $request = $location['path'];
            $content = $location['query'];
            if (strlen($request) < 1) {
                $request = '/';
            }
        }
        if (preg_match('!^ssl://!i', $this->remote_host)) {
            $this->remote_host = 'https://' . substr($this->remote_host, 6);
        }
        if (preg_match('!^tcp://!i', $this->remote_host)) {
            $this->remote_host = 'http://' . substr($this->remote_host, 6);
        }
        if (preg_match('!^https://!i', $this->remote_host)) {
            $is_ssl = TRUE;
        }
        $array_headers = array('Host' => $this->remote_port == 80 ? $this->remote_host : "{$this->remote_host}:{$this->remote_port}", 'Accept' => '*/*', 'Connection' => 'Close');
        foreach ($this->extra_headers as $key => $value) {
            $array_headers[$key] = $value;
        }
        $this->result = $this->result_header = $this->result_body = '';
        if (is_array($content)) {
            $pairs = array();
            foreach ($content as $key => $value) {
                $pairs[] = "{$key}=" . urlencode($value);
            }
            $content = join('&', $pairs);
            unset($pairs);
        }
        $OK = TRUE;
        if ($this->method == 'GET' && isset($content) && $content != '') {
            $request .= '?' . $content;
        }
        $ch = curl_init($this->remote_host . ':' . $this->remote_port . $request);
        if ($is_ssl) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_USERAGENT, "HTTPSocket/{$this->version}");
        curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 100);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        if ($this->proxy) {
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
            curl_setopt($ch, CURLOPT_HEADER, false);
            curl_setopt($ch, CURLINFO_HEADER_OUT, false);
            curl_setopt($ch, CURLOPT_BUFFERSIZE, 8192);
            curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($this, "stream_chunk"));
            curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, "stream_header"));
        }
        curl_setopt($ch, CURLOPT_LOW_SPEED_LIMIT, 512);
        curl_setopt($ch, CURLOPT_LOW_SPEED_TIME, 120);
        if ($this->bind_host) {
            curl_setopt($ch, CURLOPT_INTERFACE, $this->bind_host);
        }
        if (isset($this->remote_uname) && isset($this->remote_passwd)) {
            curl_setopt($ch, CURLOPT_USERPWD, $this->remote_uname . ':' . $this->remote_passwd);
        }
        if (isset($this->remote_uname) && $this->remote_passwd == NULL) {
            curl_setopt($ch, CURLOPT_COOKIE, "session={$_SERVER['SESSION_ID']}; key={$_SERVER['SESSION_KEY']}");
        }
        if ($this->method == 'POST') {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
            $array_headers['Content-length'] = strlen($content);
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $array_headers);
        if (!($this->result = curl_exec($ch))) {
            $this->error[] .= curl_error($ch);
            $OK = FALSE;
        }
        $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $this->result_header = substr($this->result, 0, $header_size);
        $this->result_body = substr($this->result, $header_size);
        $this->result_status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $this->lastTransferSpeed = curl_getinfo($ch, CURLINFO_SPEED_DOWNLOAD) / 1024;
        curl_close($ch);
        $this->query_cache[] = $this->remote_host . ':' . $this->remote_port . $request;
        $headers = $this->fetch_header();
        if (!empty($headers['content-length']) && $headers['content-length'] != strlen($this->result_body)) {
            $this->result_status_code = 206;
        }
        if ($this->doFollowLocationHeader) {
            if (isset($headers['x-use-https']) && $headers['x-use-https'] == 'yes') {
                die($this->ssl_setting_message);
            }
            if (isset($headers['location'])) {
                if ($this->max_redirects <= 0) {
                    die("Too many redirects on: " . $headers['location']);
                }
                $this->max_redirects--;
                $this->redirectURL = $headers['location'];
                $this->query($headers['location']);
            }
        }
    }
    function getTransferSpeed()
    {
        return $this->lastTransferSpeed;
    }
    function get($location, $asArray = FALSE)
    {
        $this->query($location);
        if ($this->get_status_code() == 200) {
            if ($asArray) {
                return preg_split("/\n/", $this->fetch_body());
            }
            return $this->fetch_body();
        }
        return FALSE;
    }
    function get_status_code()
    {
        return $this->result_status_code;
    }
    function add_header($key, $value)
    {
        $this->extra_headers[$key] = $value;
    }
    function clear_headers()
    {
        $this->extra_headers = array();
    }
    function fetch_result()
    {
        return $this->result;
    }
    function fetch_header($header = '')
    {
        if ($this->proxy) {
            return $this->proxy_headers;
        }
        $array_headers = preg_split("/\r\n/", $this->result_header);
        $array_return = array(0 => $array_headers[0]);
        unset($array_headers[0]);
        foreach ($array_headers as $pair) {
            if ($pair == '' || $pair == "\r\n") {
                continue;
            }
            list($key, $value) = preg_split("/: /", $pair, 2);
            $array_return[strtolower($key)] = $value;
        }
        if ($header != '') {
            return $array_return[strtolower($header)];
        }
        return $array_return;
    }
    function fetch_body()
    {
        return $this->result_body;
    }
    function fetch_parsed_body()
    {
        parse_str($this->result_body, $x);
        return $x;
    }
    function set_ssl_setting_message($str)
    {
        $this->ssl_setting_message = $str;
    }
}