<?php

// http.class.php
// -------------------------------------------------------------------------------------------------
// Connection object for HTTP requests
//
// Project    > dmClubNewYear08:C37
// Copyright  > (C) Digital Mail Limited (2005-2008)
// Author     > RAK for DML
// -------------------------------------------------------------------------------------------------

require_once('debug.class.php');

class HTTP
{

	var $comobject;		 // The type of communication object
	
	var $serv_array;	 // An array of servers to contact
	var $serv_index;	 // The index of the current server
	var $url;			 // The URL of the current protocol server
	var $method;		 // The default method - 'POST' or 'GET'
	var $timeout;		 // The timeout in seconds
	var $useragent; 	 // The user agent to connect as
	var $followlocation; // Controls whether redirects are followed
	
	var $_R; // Requert vars to send using $method
	var $_G; // GET    vars to send
	var $_P; // POST   vars to send
	var $_C; // COOKIE vars to send
	
	var $_Last_R; // Contains last request
	var $_Last_G; // GET  	vars sent in last request
	var $_Last_P; // POST 	vars sent in last request
	var $_Last_C; // COOKIE vars sent in last request

	var $cookie_str;
	var $result; // Holds the result of the request
	
	var $debug; // Holds debugging object
	
	// ---------------------------------------------------------------------------------------------

	function HTTP($server = NULL, $method = 'POST', $timeout = 15)
	{
		// CONSTRUCTOR
		$this->comobject  = 'HTTP';
		
		is_array($server) ? $this->serv_array = $server : $this->serv_array[] = $server;
		shuffle($this->serv_array);
		$this->serv_index 		= 0;
		$this->url 		  		= $this->serv_array[0];
		$this->method     		= strtoupper($method);
		$this->timeout    		= $timeout;
		$this->useragent		= 'DML_PROXY';
		$this->followlocation 	= FALSE;

		$this->debug      		= new Debug(TRUE);

		$this->_R = array();
		$this->_G = array();
		$this->_P = array();
		$this->_C = array();

		$this->result = new stdClass();
	}
	
	// ---------------------------------------------------------------------------------------------
	// ---------------------------------------------------------------------------------------------
	// ---------------------------------------------------------------------------------------------

	function request()
	{
		// Execute a request via HTTP
		//
		$this->execute_request();
		return $this->result;
	}
	
	// ---------------------------------------------------------------------------------------------
	// ---------------------------------------------------------------------------------------------
	// ---------------------------------------------------------------------------------------------
	
	function execute_request()
	{

		$this->result->status		 = FALSE;
		$this->result->headers	 	 = ''; // NOT USED YET
		$this->result->response 	 = '';
		$this->result->response_code = 0;
		$this->result->total_time	 = 0;
		$this->result->cookie		 = array();
		$this->result->num_redircets = 0;
		$this->result->final_url	 = '';
		$this->result->error		 = FALSE;

		$this->fetch_url();
		
		// Has the request succeeded? If no reply
		// try to failover to an alternative protocol server
		
		if ($this->result->status == FALSE)
		{
			if (count($this->serv_array) > $this->serv_index + 1)
			{
				$this->debug->msg('<b>TRYING ALTERNATIVE SERVER</b>');
				$this->serv_index++;
				$this->url = $this->serv_array[$this->serv_index];
				$this->fetch_url();
			}
		}
	
		$this->flush_request();
	}

	// ---------------------------------------------------------------------------------------------

	function fetch_url()
	{
		// Fetch a URL, passing through specified GPC variables
	
		$url = $this->url; // The URL to contact

		$cookie_jar = tempnam('/tmp', 'cookie'); // A temporary file to hold returned cookies
		
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_USERAGENT,      $this->useragent);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $this->followlocation);	
		curl_setopt($ch, CURLOPT_HEADER, 		 FALSE);	
		curl_setopt($ch, CURLOPT_TIMEOUT, 		 $this->timeout);
		curl_setopt($ch, CURLOPT_COOKIEJAR, 	 $cookie_jar);
		
		// SEND GENERAL REQUEST VARS BY $this->method (note _G and _P vars take precedence if names collide)
		if (count($this->_R))
		{
			if ($this->method == 'GET') 
			{	
				$this->_G = array_merge($this->_R, $this->_G);
			}
			else
			{
				$this->_P = array_merge($this->_R, $this->_P);
			}
		}
		
		if ($this->debug)
		{
			 $this->debug->msg('<b>EXECUTING REQUEST: ' . $url. '</b>');
			 $this->debug->msg('<b>GET VARS SENT</b>');
			 while (list($key, $value) = each($this->_G)) {
				$this->debug->msg($key . ' = ' . $value);
			 }
			 $this->debug->msg('<b>POST VARS SENT</b>');
			 while (list($key, $value) = each($this->_P)) {
				$this->debug->msg($key . ' = ' . $value);
			 }
			 $this->debug->msg('<b>COOKIE VARS SENT</b>');
			 while (list($key, $value) = each($this->_C)) {
				$this->debug->msg($key . ' = ' . $value);
			 }
			 $this->debug->msg();
		}

		// NOW SEND ALL GPC VARIABLES...
		if (count($this->_G))
		{
			// Send GET variables
			$url .= strpos($url, '?') === FALSE ? '?' : '&';
			$url .= $this->generate_name_value_pairs($this->_G);
		}
		if (count($this->_P))
		{
			// Send POST variables
			curl_setopt($ch, CURLOPT_POST, 1); // Alert cURL to the fact that we're doing a POST, and pass the associative array for POSTing.
			curl_setopt($ch, CURLOPT_POSTFIELDS, $this->_P);
		}
		if (count($this->_C))
		{
			//Send COOKIE variables
			$cookie = $this->generate_cookie_request_header($this->_C);
			curl_setopt($ch, CURLOPT_COOKIE, $cookie);
		}
		
		curl_setopt($ch, CURLOPT_URL, $url);
		$this->result->response = curl_exec($ch);
	
		if (curl_error($ch))
		{
			$this->debug->msg('<b>NO RESULT RECEIVED FROM</b> ' . $url);
			return;
		}
		
		if ($this->followlocation)
		{
			// Has there been a redirect?
			$this->result->num_redirects = (int) curl_getinfo($ch, CURLINFO_REDIRECT_COUNT);
			if ($this->result->num_redirects > 0)
			{
				$this->result->final_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
				$this->debug->msg('<b>REDIRECTED TO:</b> ' . $this->result->final_url);
			}
		}
		/*
		else if ($this->parse_header_4_redirects)
		{
			// PHP is running in safe mode, so cURL cannot follow redirects 
			// Therefore we will scan headers and follow them anyway
			
			// Split response into HTTP headers and body
			
			echo($response);
			$a = preg_split('/[\r\n]{2,}/', $response, 3);
			print_r($a); exit;
			
			$bits = preg_split('/[\r\n]{2,}/', $response, 3);
			if (!preg_match('/[\r\n]/', $bits[0]))
			{
				$this->result->headers  = $bits[0] + "\r\r" + $bits[1];
				$this->result->response = $bits[2];
			}
			else
			{
				$this->result->headers  = $bits[0];
				$this->result->response = $bits[1] + (isset($bits[2]) ? "\r\r" + $bits[2] : '');
			}
			$this->result->response = $response;
		}
		*/
		
		$this->result->response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		$this->result->total_time	 = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
		if ($this->result->response_code == '404')
		{
			$this->debug->msg('<b>404 NOT FOUND:</b> ' . $url);
			return;
		}
		curl_close($ch);
	
		$this->debug->msg("<b>RESULT RECEIVED</b>\n" . htmlentities($this->result->response));

		$this->cookie_str = @file_get_contents($cookie_jar); // Returned cookies
		if ($this->cookie_str) $this->result->cookie = $this->parse_cookie_string($this->cookie_str);
		$this->result->status = TRUE;
	}

	// ---------------------------------------------------------------------------------------------

	function generate_name_value_pairs($params)
	{
		// $params is an associative array containing name(key) and value pairs
		// This function returns a string eg. "firstname=peter&second=piper"
		// that can be appended to a GET URL (after a ?) or used as the
		// body of a POST
		
		$s = '';
		while (list($name, $value) = each($params)) {
			$s .=  "$name=$value&";
		}
		$s = substr($s, 0, -1);
		return $s;
	}
	
	// ---------------------------------------------------------------------------------------------
	
	function generate_cookie_request_header($params)
	{
		// $params is an associative array containing name(key) and value pairs
		// This function returns a string eg. "firstname=peter; second=piper;"
		// that can be sent as the value of the 'Cookie' request header
		
		$c = '';
		while (list($name, $value) = each($params)) {
			$c .=  "$name=$value; ";
		}
		$c = substr($c, 0, -2); // Don't send last '; '
		return $c;
	}
	
	// ---------------------------------------------------------------------------------------------

	function parse_cookie_string($cookie_str)
	{
		$c = array();
		$cookie_arr = explode("\n", $cookie_str);
		foreach($cookie_arr as $line)
		{
			if (substr($line, 0, 1) == '#' || trim($line) == '') continue; // Ignore comments and empty lines
			$args = preg_split('/\s+/', $line);
			$c[$args[5]] = array(
				'value'  => $args[6],
				'domain' => $args[0],
				'expire' => $args[4],
				'path'   => $args[2],
				'secure' => strtolower($args[3]) != 'false'
			);
		}
		return $c;
	}

	// ---------------------------------------------------------------------------------------------

	function flush_request()
	{
		$this->_Last_R = $this->_R;
		$this->_Last_G = $this->_G;
		$this->_Last_P = $this->_P;
		$this->_Last_C = $this->_C;
		
		$this->_R =
		$this->_G =
		$this->_P =
		$this->_C = array();
	}

	// ---------------------------------------------------------------------------------------------

}

?>