Subversion Repositories Sigmater

Rev

Blame | Last modification | View Log | Download | RSS feed

<?php
define('CRLF', "\r\n");
define('LF', "\n");
define('RLEN', 8192);

/*******************************************************************/
/* class: HTTP_Header                                              */
/* purpose: represents an http header string ie. "<name>: <value>" */
/*******************************************************************/

class HTTP_Header
  {
  var $m_name;
  var $m_value;
  var $m_header;

  /***********************************************************/
  /* Constructor                                             */
  /* input: fieldName - name of the header eg. 'Referer'     */
  /* input: filedValue - value of the header eg. 'localhost' */
  /***********************************************************/

  function HTTP_Header($fieldName, $fieldValue)
    {
    $this->m_name = $fieldName;
    $this->m_value = $fieldValue;
    $this->m_header = $fieldName.": ".$fieldValue;
    }   

  /***************************************/
  /* purpose: get the entire header line */
  /* return: header string without crlf  */
  /***************************************/

  function Get()
    {
    return($this->m_header);
    }

  /*********************************************/
  /* purpose: get just the value of the header */
  /* return: string value of header            */
  /*********************************************/

  function GetValue()
    {   
    return($this->m_value);
    }

  /********************************************/
  /* purpose: get just the name of the header */
  /* return: string name of header            */
  /********************************************/

  function GetName()
    {
    return($this->m_name);
    }
  };

/**************************************/
/* class: HTTP_Message_hr                */
/* purpose: represents a http message */
/**************************************/

class HTTP_Message_hr
  {
  var $m_headers;
  var $m_entityBody;

  /***********************************************************************/
  /* Constructor                                                         */
  /* input: HTTP_Headers - array of header objs to use with this message */
  /* input: entityBody - an entity body                                  */
  /***********************************************************************/

  function HTTP_Message_hr($HTTP_Headers, $entityBody = "")
    {           
    $this->m_headers = array();
    $this->SetHeaders($HTTP_Headers);
    $this->m_entityBody = $entityBody;
    }

  /***********************************************/
  /* purpose: append header objs to this message */
  /* input: array of header objs                 */
  /***********************************************/

  function SetHeaders($HTTP_Headers)
    {
    if(is_array($HTTP_Headers))
      {
      reset($HTTP_Headers);
      while(list(, $HTTP_Header) = each($HTTP_Headers))
        {
        $this->m_headers[] = $HTTP_Header;
        }       
      }         
    }

  /***************************************/
  /* purpose: append a single header obj */
  /* input: a header obj                 */
  /***************************************/

  function SetHeader($HTTP_Header)
    {
    $this->m_headers[] = $HTTP_Header;
    }

  /****************************************************************/
  /* purpose: return the first header obj found based on its name */
  /* return: header obj                                           */
  /****************************************************************/

  function GetHeader($fieldName)
    {
    if(is_array($this->m_headers))
      {
      reset($this->m_headers);
      while(list(, $HTTP_Header) = each($this->m_headers))                      
        {
        if($HTTP_Header->GetName() == $fieldName)
          return($HTTP_Header);
        }
      }
    return(0);
    }

  /*********************************************************/
  /* purpose: return array of header objs for this message */
  /* return: array of header objs                          */
  /*********************************************************/

  function GetHeaders()
    {
    return($this->m_headers);
    }

  /***********************************/
  /* purpose: return the entity body */
  /* return: entity body string      */
  /***********************************/

  function GetEntityBody()
    {
    return($this->m_entityBody);
    }
  };

/*******************************************************************/
/* class: HTTP_Req extends HTTP_Message_hr                            */
/* purpose: represents a http request to send to the server.       */
/*          Care must be taken with uri for use with proxy server. */
/*******************************************************************/

class HTTP_Req extends HTTP_Message_hr
  {     
  var $m_method;
  var $m_uri;
  var $m_version;

  /******************************************************/
  /* Constructor:                                       */
  /* input: method - the method for this request        */
  /* input: uri - the URI for this request              */
  /* input: version - the HTTP verison for this request */
  /* input: HTTP_Headers - array of header objs         */
  /* input: entityBody - entity body this request       */
  /******************************************************/

  function HTTP_Req($method, $uri, $version, $HTTP_Headers, $entityBody = "")
    {
    $this->HTTP_Message_hr($HTTP_Headers, $entityBody);
    $this->m_version = $version;
    $this->m_method = $method;
    $this->m_uri = $uri;
    }

  /*******************************/
  /* purpose: returns the method */
  /* return: method string       */
  /*******************************/

  function GetMethod()
    {
    return($this->m_method);
    }

  /********************************/
  /* purpose: returns request uri */
  /* return: uri string           */
  /********************************/

  function GetURI()
    {
    return($this->m_uri);
    }

  /************************************/
  /* purpose: return the http version */
  /* return: http version string      */
  /************************************/

  function GetVersion()
    {
    return($this->m_version);
    }
  };

/********************************************************************/
/* class: HTTP_Response_hr extends HTTP_Message_hr                        */
/* purpose: represents a http response message read from the server */
/********************************************************************/

class HTTP_Response_hr extends HTTP_Message_hr
  {
  var $m_version;
  var $m_statusCode;
  var $m_phrase;

  /******************************************/
  /* Constructor                            */
  /* input: version - http version          */
  /* input: statusCode - statusCode         */
  /* input: phrase - phrase                 */
  /* input: headers - array of header objs  */
  /* input: entityBody - entity body        */
  /******************************************/

  function HTTP_Response_hr($version , $statusCode, $phrase, $HTTP_Headers = "",
                         $entityBody = "")
    {
    $this->HTTP_Message_hr($HTTP_Headers, $entityBody);
    $this->m_version = $version;
    $this->m_statusCode = $statusCode;
    $this->m_phrase = $phrase;
    }

  /************************************/
  /* purpose: return the http version */
  /* return: http version string      */
  /************************************/

  function GetVersion()
    {
    return($this->m_version);
    }

  /***********************************/
  /* purpose: return the status code */
  /* return: status code string      */
  /***********************************/

  function GetStatusCode()
    {
    return($this->m_statusCode);
    }

  /******************************/
  /* purpose: return the phrase */
  /* return: phrase string      */
  /******************************/

  function GetPhrase()
    {
    return($this->m_phrase);
    }
  };

/************************************************************/
/* class: HTTP_Connection                                   */
/* purpose: represents a http connection to the http server */
/*          use to send and read http messages from server  */
/************************************************************/

class HTTP_Connection
  {
  var $m_host;
  var $m_port;
  var $m_timeout;
  var $m_fp;

  /**********************************************************/
  /* Constructor                                            */
  /* input: host - host name to connect (ip or domain name) */
  /* input: port - port to use on host for http             */
  /* input: timeout - timeout for connection                */
  /**********************************************************/

  function HTTP_Connection($host, $port=80, $timeOut=30)
    {
    $this->m_host = $host;
    $this->m_port = $port;
    $this->m_timeOut = $timeOut;
    }

  /***********************************************/
  /* purpose: connect to the host in constructor */
  /***********************************************/

  function Connect()
    {
    $this->m_fp = fsockopen($this->m_host, $this->m_port, $errno, $errstr,
                            $this->m_timeOut);  
    if(!$this->m_fp)
      return(1);

    return(0);
    }

  /*********************************************/
  /* purpose: close the connection to the host */
  /*********************************************/

  function Close()
    {
    fclose($this->m_fp);
    }

  /****************************************************************/
  /* purpose: send a http request to the host/port in constructor */
  /* input: HTTP_Req - request obj                                */
  /****************************************************************/

  function Request($HTTP_Req)
    {
    // send method + URI + HTTP_version
    $buffer = $HTTP_Req->GetMethod()." ".$HTTP_Req->GetURI().
              " ".$HTTP_Req->GetVersion().CRLF;

    // send headers
    $HTTP_Headers = $HTTP_Req->GetHeaders();
    reset($HTTP_Headers);
    while(list(, $HTTP_Header) = each($HTTP_Headers))
      $buffer .= $HTTP_Header->Get().CRLF;
    $buffer .= CRLF;

    // send entity body
    $body = $HTTP_Req->GetEntityBody();
    if(!empty($body))
      {
      $HTTP_Header = $HTTP_Req->GetHeader("Content-Length");
      $buffer .= substr($body, 0, $HTTP_Header->GetValue());
      }
    fwrite($this->m_fp, $buffer);
    }

  /**************************************************/
  /* purpose: passthru response to calling browser. */
  /* NB: auto-closes the connection to the host     */
  /**************************************************/

  function Passthru()
    {
    // read status line
    $statusLine = fgets($this->m_fp, RLEN);
    Header(trim($statusLine));

    // read in headers
    $row = '';
    while(!feof($this->m_fp))
      {
      $line = fgets($this->m_fp, RLEN);
      if($line == CRLF)
        {
        if(!empty($row))
          Header($row);
        break;
        }
      $header = trim($line);
      $pos = strpos($header, ':');
      if($pos === false)
        {
        if(!empty($row))
          $row .= " $header";
        }
      else
        {
        if(!empty($row))
          Header($row);
        $row = $header;
        $fieldName = substr($header, 0, $pos);
        $fieldValue = substr($header, $pos+2);
        if(!strcasecmp($fieldName, 'Content-Length'))
          $len = $fieldValue;
        }
      }

    // read in entity body (if there is one)
    if(!$len)
      $len = RLEN;
    while(!feof($this->m_fp))
      $body .= fread($this->m_fp, $len);
    if(0 < strlen($body))
      {
      echo $body;
      unset($body);
      }

    // close connection
    $this->Close();
    }

  /**************************************************/
  /* purpose: proxy req/resp for calling browser.   */
  /* input: HTTP_Req - request obj                  */
  /**************************************************/

  function Proxy($HTTP_Req)
    {
    $rc = $this->Connect();
    if(!$rc)
      {
      $this->Request($HTTP_Req);
//      fpassthru($this->m_fp);
      $this->Passthru();
      }
    return($rc);
    }

  /******************************************************/
  /* purpose: SSL proxy req/resp for calling browser.   */
  /* input: HTTP_Req - request obj                      */
  /******************************************************/

  function Proxy_SSL($HTTP_Req)
    {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://'.$this->m_host.
                $HTTP_Req->GetURI());
    curl_setopt($ch, CURLOPT_TIMEOUT, $this->m_timeout);

    $HTTP_Headers = $HTTP_Req->GetHeaders();
    while(list(, $HTTP_Header) = each($HTTP_Headers))
      {
      if(!strcasecmp('User-Agent', $HTTP_Header->GetName()))
        $rc = curl_setopt($ch, CURLOPT_USERAGENT, $HTTP_Header->GetValue());
      elseif(!strcasecmp('Authorization', $HTTP_Header->GetName()))
        $rc = curl_setopt($ch, CURLOPT_USERPWD, $HTTP_Header->GetValue());
      elseif(!strcasecmp('Cookie', $HTTP_Header->GetName()))
        $rc = curl_setopt($ch, CURLOPT_COOKIE, $HTTP_Header->GetValue());
      elseif(stristr($HTTP_Header->GetName(), 'Accept'))
        $rc = curl_setopt($ch, CURLOPT_HTTPHEADER, $HTTP_Header->Get());
      }

    if('POST' == $HTTP_Req->GetMethod())
      {
      curl_setopt($ch, CURLOPT_POST, 1);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $HTTP_Req->GetEntityBody());
      }

    curl_exec($ch);
    curl_close($ch);
    }

  /**************************************************/
  /* purpose: read a http response from the host    */
  /* output: HTTP_Response_hr - creates a response obj */
  /*         20020225: Expand gzipped response      */
  /**************************************************/

  function Response(&$HTTP_Response_hr)
    {
    // read status line
    $statusLine = fgets($this->m_fp, RLEN);

    $this->_SplitResponseLine($statusLine, $version, $statusCode, $phrase);

    // read in headers
    $tmp_array = array();
    while(!feof($this->m_fp))
      {
      $line = fgets($this->m_fp, RLEN);
      if($line == CRLF)
        break;
      $header = trim($line);
      $pos = strpos($header, ':');
      $fieldName = substr($header, 0, $pos);
      $fieldValue = substr($header, $pos+2);
      if(!strcasecmp($fieldName, 'Content-Length'))
        $len = $fieldValue;
      if(!strcasecmp($fieldName, 'Content-Encoding') &&
         stristr($fieldValue, 'gzip'))
        $type = 'gzip';
      $tmp_array["$fieldName"] = $fieldValue;
      }

    // read in entity body (if there is one)
    if(!$len)
      $len = RLEN;
    while(!feof($this->m_fp))
      $body .= fread($this->m_fp, $len);

    // Expand gzipped response
    if('gzip' == $type)
      $body = gzinflate(substr($body, 10));

    // create the response object
    $HTTP_Headers = array();
    while(list($k, $v) = each($tmp_array))
      {
      if('gzip' == $type && !strcasecmp($k, 'Content-Length'))
        $v = strlen($body);
      if('gzip' == $type && !strcasecmp($k, 'Content-Encoding'))
        continue;
      $HTTP_Headers[] = new HTTP_Header($k, $v);
      }
    $HTTP_Response_hr = new HTTP_Response_hr($version, $statusCode, $phrase,
                                       $HTTP_Headers, $body);
    }

  /********************************************************/
  /* purpose: splits up a header into its different parts */
  /********************************************************/

  function _SplitHeader($header, &$fieldName, &$fieldValue)
    {
    $header = str_replace(CRLF, "", $header);
    $pos = strpos($header, ':');

    $fieldName = substr($header, 0, $pos);
    $fieldValue = substr($header, $pos+2);
    }

  /***************************************************************/
  /* purpose: splits up a response line into its different parts */
  /***************************************************************/

  function _SplitResponseLine($line, &$version, &$statusCode, &$phrase)
    {
    $line = str_replace(CRLF, "", $line);
    $regs = split("[[:space:]]+", $line, 3);

    $version = $regs[0];
    $statusCode = $regs[1];
    $phrase = $regs[2];
    }
  };

/*************************************************/
/* class: HTTP_Cookie_Header extends HTTP_Header */
/* purpose: represents a http cookie header      */
/*************************************************/

class HTTP_Cookie_Header extends HTTP_Header
  {
  /*******************************************************************/
  /* constructor:                                                    */
  /* input: hash containing keys=>values to be stored in this cookie */
  /*******************************************************************/

  function HTTP_Cookie_Header($values)
    {
    while(list($k, $v) = each($values))
      $encValues .= $k."=".urlencode($v).";";
    $this->HTTP_Header("Cookie", $encValues);
    }
  };

/****************************************************/
/* class: HTTP_BasicAuth_Header extends HTTP_Header */
/* purpose: represents a http basic auth header     */
/****************************************************/

class HTTP_BasicAuth_Header extends HTTP_Header
  {
  /***************************************/
  /* constructor:                        */
  /* input: username - username for auth */
  /* input: password - password for auth */
  /***************************************/

  function HTTP_BasicAuth_Header($username, $password)
    {
    $this->HTTP_Header("Authorization",
                       "Basic ".base64_encode($username.":".$password));
    }
  };

/************************************************/
/* class: HTTP_GET_Request extends HTTP_Req     */
/* purpose: represents a http GET request       */
/************************************************/

class HTTP_GET_Request extends HTTP_Req
  {
  /***************************************************************/
  /* constructor:                                                */
  /* input: uri - uri to get                                     */
  /* input: HTTP_Headers - array of header objs for this request */
  /***************************************************************/

  function HTTP_GET_Request($uri, $HTTP_Headers = 0)
    {
    $this->HTTP_Req("GET", $uri, "HTTP/1.0", $HTTP_Headers);
    }
  };

/*************************************************/
/* class: HTTP_HEAD_Request extends HTTP_Req     */
/* purpose: represents a http HEAD request       */
/*************************************************/

class HTTP_HEAD_Request extends HTTP_Req
  {
  /***************************************************************/
  /* constructor:                                                */
  /* input: uri - uri to get headers for                         */
  /* input: HTTP_Headers - array of header objs for this request */
  /***************************************************************/

  function HTTP_HEAD_Request($uri, $HTTP_Headers = 0)
    {
    $this->HTTP_Req("HEAD", $uri, "HTTP/1.0", $HTTP_Headers);
    }
  };

/***********************************************************************/
/* class: HTTP_POST_Request extends HTTP_Req                           */
/* purpose: represent a POST http request.                             */
/* Headers (Content-Type, Content-Length) and entityBody sent for you. */
/***********************************************************************/

class HTTP_POST_Request extends HTTP_Req
  {
  /***************************************************************/
  /* constructor:                                                */
  /* input: uri - uri to post to                                 */
  /* input: postValues - associative array of unencoded post     */
  /*                     values to use                           */
  /* input: HTTP_Headers - array of header objs for this request */
  /***************************************************************/

  function HTTP_POST_Request($uri, $postValues, $HTTP_Headers)
    {
    while(list($key, $val) = each($postValues))
      $queryString .= urlencode($key)."=".urlencode($val)."&";

    $HTTP_Headers[] = new HTTP_Header("Content-Type",
                                      "application/x-www-form-urlencoded");
    $HTTP_Headers[] = new HTTP_Header("Content-Length", strlen($queryString));

    $this->HTTP_Req("POST", $uri, "HTTP/1.0", $HTTP_Headers, $queryString);
    }
  };
?>