Location: PHPKode > projects > OpenNitro > trunk/Nitro/HTTPRequest.inc.php
<?php
//
// +---------------------------------------------------------------------------+
// | Nitro :: Libraries :: HTTPRequest                                         |
// +---------------------------------------------------------------------------+
// | Copyright (c) 2003-2006 June Systems BV                                   |
// +---------------------------------------------------------------------------+
// | This library is free software; you can redistribute it and/or modify it   |
// | under the terms of the GNU Lesser General Public License as published by  |
// | the Free Software Foundation; either version 2.1 of the License, or (at   |
// | your option) any later version.                                           |
// |                                                                           |
// | This library is distributed in the hope that it will be useful, but       |
// | WITHOUT ANY WARRANTY; without even the implied warranty of                |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser   |
// | General Public License for more details.                                  |
// |                                                                           |
// | You should have received a copy of the GNU Lesser General Public License  |
// | along with this library; if not, write to the Free Software Foundation,   |
// | Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA            |
// +---------------------------------------------------------------------------+
// | Authors: Siggi Oskarsson <hide@address.com>                          |
// +---------------------------------------------------------------------------+
//
// $Id: HTTPRequest.inc.php 229 2008-04-17 09:20:31Z oli $
//
// This file contains the HTTP Request class
//

/**
 * This file contains the HTTP Request class
 * 
 * @author			Siggi Oskarsson <hide@address.com>
 * @copyright		June Systems BV, 2006
 * @version			$Revision: 1.13 $
 * @package			Nitro
 * @subpackage	Libraries
 */

class HTTPRequest {
	var $Method;
	var $POST;
	var $FILE;
	var $COOKIE;
	
	var $Username;
	var $Password;
	
	var $UserAgent = 'OpenNitro HTTPRequest Object';
	var $Cookies;
	
	var $PostMethod = 'urlencoded';
	var $Boundary;
	
	function HTTPRequest($Method = 'GET')
	{
		$this->Method = $Method;
	}
	
	function SetPOSTData($POSTData)
	{
		$this->POST = $POSTData;
		$this->Method = 'POST';
	}
	
	function addPOSTData($VariableName, $Data)
	{
		$this->POST[$VariableName] = $Data;
		$this->Method = 'POST';
	}
	
	function setPOSTMethod($Method, $Boundary = FALSE)
	{
		$this->PostMethod = ($Method == 'multipart' ? 'multipart' : 'urlencoded');
		$this->Boundary = ($Boundary ? $Boundary : "-----------------------------".base64_encode(time()));
	}
	
	function addFILEData($VariableName, $FileName, $Contents = FALSE, $MimeType = FALSE)
	{
		if ($Contents === FALSE) {
			// get file contents from file name
			// only works on local files with correct path
			$Contents = file_get_contents($FileName);
			$FileName = basename($FileName);
		}
		
		if ($MimeType === FALSE) {
			// get mime type from file name
			$getMimeType = new getMimeType();
			$MimeType = $getMimeType->getType($FileName);
		}
		
		$this->FILE[$VariableName] = Array(
			'FileName' => $FileName,
			'FileContents' => $Contents,
			'MimeType' => $MimeType
		);
		$this->Method = 'POST';
		$this->setPOSTMethod('multipart');
	}
	
	function SetCOOKIEData($COOKIEData)
	{
		$this->COOKIE = $COOKIEData;
	}
	
	function SetUserAgent($UserAgent)
	{
		$this->UserAgent = $UserAgent;
	}
	
	function SetAuthorization($Username, $Password)
	{
		$this->Username = $Username;
		$this->Password = $Password;
		
		return TRUE;
	}
	
	/**
	 * Get URL
	 *
	 * URL is of the form http://www.example.com/index.php
	 * @param	string	$URL	Request URL
	 * @param	string	$IP	IP address of server to use for request, this is mainly used for load balancing setups
	 */
	function Get($URL, $IP = FALSE, $Port = FALSE, $timeout = 10)
	{
		$ParsedURL = $this->ParseURL($URL);

		if (strlen($ParsedURL['Username'])) {
			$Username = $ParsedURL['Username'];
			$Password = $ParsedURL['Password'];
		} elseif (isset($this->Username) && isset($this->Password)) {
			$Username = $this->Username;
			$Password = $this->Password;
		}

		// Begin request
		$Request = $this->Method." /".$ParsedURL['Script'].($ParsedURL['GetString'] ? '?'.$ParsedURL['GetString'] : '')." HTTP/1.1\r\n";
		$Request.= "Host: ".$ParsedURL['Host']."\r\n";
		$Request.= "Connection: Close\r\n";

		// Set user agent
		// User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
		$Request.= "User-Agent: ".($this->UserAgent ? $this->UserAgent : 'OpenNitro HTTPRequest Object')."\r\n";
		
		// Set authorization, if applicable
		if (isset($Username) && isset($Password)) $Request .= "Authorization: Basic ".base64_encode($Username.":".$Password)."\r\n";

		// Add cookies
		if ($this->Cookies) {
			$cookie = Array();
			foreach($this->Cookies AS $cookieID => $cookieData) {
				// TODO: check expires, path and domain if we should set the cookie
				$cookie[] = $cookieID.'='.$cookieData['data'];
			}
			$Request.= "Cookie: ".implode('; ', $cookie)."\r\n";
		}

		// Add POST data, if applicable
		if ($this->POST) {
			$post = $this->_processPostData();
			$postData = $post['postData'];
			$Request.= $post['Request'];
		}

		// Add cookie data to request header
		if (is_array($this->COOKIE)) {
			foreach ($this->COOKIE AS $id => $cookie) {
				$Cookies[] = "{$id}={$cookie}";
			}
			$Request.= "Cookie: ".implode('; ', $Cookies)."\r\n";
		}
		$Request.= "\r\n";

		// Finally add POST data to body of request
		if ($this->POST) $Request.= $postData."\r\n";

		// open socket to server and put request data
		if (!$conex = @fsockopen(($IP ? $IP : $ParsedURL['Host']), ($Port ? $Port : ($ParsedURL['Port'] ? (int)$ParsedURL['Port'] : 80)), $errno, $errstr, $timeout)) return FALSE;
		fwrite($conex, $Request);
		$data = '';
		while (!feof($conex)) {
		   $data.= fgets($conex, 512);
		}
		fclose($conex);
		
		// create response object to return
		$Response = new HTTPRequest_Response($data);
		
		// Extract cookie data and save in this HTTP Request object (otherwise lost in response object)
		// Set-Cookie: ZDEDebuggerPresent=php,phtml,php3; path=/
		$SetCookies = $Response->GetParsedHeader('Set-Cookie');
		if(!is_array($SetCookies)) { // multiple cookies set
			$SetCookies = Array($SetCookies);
		}
		foreach($SetCookies AS $cookies) {
			$cookie = explode(';', $cookies);
			$n = 0;
			foreach($cookie AS $c) {
				preg_match('/^(.*)=(.*)$/U', $c, $matches);
				if (!$n) {
					$cookieID = trim($matches[1]);
					$this->Cookies[$cookieID]['data'] = chop($matches[2]);
				} else {
					$this->Cookies[$cookieID][trim($matches[1])] = chop($matches[2]);
				}
				$n++;
			}
		}

		
		return $Response;
	}
	
	function ParseURL($URL)
	{
		if (preg_match("'([^:]+)://(([^:^@]+)?(:([^@]*))?@)?([^/^:]+)(:([0-9]+))?/([^\?]*)\??(.*)?'", $URL, $matches)) {
			$RV = Array();
			$RV['RequestType']= strtolower($matches[1]);
			$RV['Username']		= $matches[3];
			$RV['Password']		= $matches[5];
			$RV['Host']				= $matches[6];
			$RV['Port']				= $matches[8];
			$RV['Script']			= $matches[9];
			$RV['GetString']	= $matches[10];
		} else {
			$RV = FALSE;
		}
		
		return $RV;
	}

	/**
	 * NB be sure to rawurlencode $ParentKey outside this function!
	 * => can be called statically <=
	 */
	function _FlattenArray_R($ParentKey, $Mixed = '')
	{
		$RV = FALSE;
		if (is_array($Mixed)) {
			if (count($Mixed)) {
				$RV = array();
				foreach ($Mixed AS $key => $val) {
					$RV[] = HTTPRequest::_FlattenArray_R($ParentKey.'['.rawurlencode($key).']', $val); // recursion!
				}
				$RV = implode('&', $RV);
			} else {
				// recursion stop condition
				$RV = $ParentKey.'[]=';
			}
		} else {
			// recursion stop condition
			$RV = $ParentKey.'='.rawurlencode($Mixed);
		}

		return $RV;
	}

	function _processPostData()
	{
		$Request = '';
		$postData = '';

		if ($this->PostMethod == 'multipart') {
			// implement multipart/form-date POST method
			// -----------------------------7d7177292a0938 = boundary example
			/*
			-----------------------------7d7177292a0938
			Content-Disposition: form-data; name="VariableName"

			0
			-----------------------------7d7177292a0938
			Content-Disposition: form-data; name="FileVariableName"; filename="Example.xls"
			Content-Type: application/vnd.ms-excel

			Binary data in excel file ......
			-----------------------------7d7177292a0938--
			*/
			$Boundary = $this->Boundary;
			if (is_array($this->POST)) {
				foreach($this->POST AS $k => $v) {
					if (is_array($v)) {
						$post = explode('&', HTTPRequest::_FlattenArray_R(rawurlencode($k), $v));
						foreach($post AS $v2) {
							$tmp = explode('=', $v2);
							$postData.= $Boundary."\r\n";
							$postData.= "Content-Disposition: form-data; name=\"".$tmp[0]."\"\r\n";
							$postData.= "\r\n";
							$postData.= $tmp[1]."\r\n";
						}
					} else {
						$postData.= $Boundary."\r\n";
						$postData.= "Content-Disposition: form-data; name=\"".$k."\"\r\n";
						$postData.= "\r\n";
						$postData.= $v."\r\n";
					}
				}
			}

			if (is_array($this->FILE)) {
				foreach($this->FILE AS $k => $v) {
					$postData.= $Boundary."\r\n";
					$postData.= "Content-Disposition: form-data; name=\"".$k."\"; filename=\"".$v['FileName']."\"\r\n";
					$postData.= "Content-Type: ".$v['MimeType']."\r\n";
					$postData.= "\r\n";
					$postData.= $v['FileContents']."\r\n";
				}
			}

			$postData.= $Boundary."--\r\n";

			$Request.= "Content-Length: ".strlen($postData)."\r\n";
			$Request.= "Content-Type: multipart/form-data; boundary=".$Boundary."\r\n";
		} else {
			if (is_array($this->POST)) {
				// flatten array
				foreach($this->POST AS $k => $v) {
					if (is_array($v)) {
						$post[] = HTTPRequest::_FlattenArray_R(rawurlencode($k), $v);
					} else {
						$post[] = rawurlencode($k)."=".rawurlencode($v);
					}
				}
				$postData.= implode('&', $post)."\r\n";
			} else {
				$postData.= $this->POST."\r\n";
			}

			$Request.= "Content-Length: ".strlen($postData)."\r\n";
			$Request.= "Content-Type: application/x-www-form-urlencoded\r\n";
		}

		return Array('postData' => $postData, 'Request' => $Request);
	}
}

class HTTPRequest_Response {
	var $Response;
	var $Header;
	var $ParsedHeader;
	var $Body;
	
	function HTTPRequest_Response($Response)
	{
		$this->Response = $Response;
	}
	
	function GetHeader($Part = FALSE)
	{
		if (!$this->Header) {
			if (preg_match("/^(.*)\r\n\r\n/Ums", $this->Response, $matches)) {
				$RV = $matches[1];
			} else {
				$RV = FALSE;
			}
		} else {
			$RV = $this->Header;
		}
		
		return $RV;
	}
	
	function GetParsedHeader($Part = FALSE)
	{
		if (!$this->ParsedHeader) $this->ParsedHeader = $this->ParseHeader();
		
		if ($Part) {
			$RV = array_key_exists($Part, $this->ParsedHeader) ? $this->ParsedHeader[$Part] : NULL;
		} else {
			$RV = $this->ParsedHeader;
		}
		
		return $RV;
	}
	
	function GetBody()
	{
		if (preg_match("/[^\r\n\r\n]*\r\n\r\n(.*)/ms", $this->Response, $matches)) {
			$body = $matches[1];
			if ($body) {
				if($this->GetParsedHeader('Transfer-Encoding') === 'chunked') {
					if(!$body = $this->decodeChunked($body)) {
						return false;
					}
				}
				$RV = $body;
			} else {
				$RV = FALSE;
			}
		} else {
			$RV = FALSE;
		}
		
		return $RV;
	}

	function ParseHeader()
	{
		if (!$this->Header) $this->Header = $this->GetHeader();

		if ($this->Header) {
			// Set-Cookie: ZDEDebuggerPresent=php,phtml,php3; path=/
			$header = explode("\r\n", $this->Header);
			foreach($header AS $head) {
				if (ereg('^HTTP/', $head)) {
					$RV['Status'] = chop($head);
				} else {
					preg_match('/^(.*): (.*)$/U', $head, $matches);
					if (array_key_exists($matches[1], $RV)) { // exists, multiple statements, must create array
						if (!is_array($RV[$matches[1]])) $RV[$matches[1]] = Array($RV[$matches[1]]);
						$RV[$matches[1]][] = chop($matches[2]);
					} else {
						$RV[$matches[1]] = chop($matches[2]);
					}
				}
			}
		} else {
			$RV = FALSE;
		}
		
		return $RV;
	}

	function decodeChunked($buffer)
	{
		$length = 0;
		$new = '';
		
		// read chunk-size, chunk-extension (if any) and CRLF
		// get the position of the linebreak
		$chunkend = strpos($buffer,"\r\n") + 2;
		$temp = substr($buffer,0,$chunkend);
		$chunk_size = hexdec( trim($temp) );
		$chunkstart = $chunkend;
		while ($chunk_size > 0) {
			$chunkend = strpos( $buffer, "\r\n", $chunkstart + $chunk_size);
			
			// Just in case we got a broken connection
			if ($chunkend == FALSE) {
				$chunk = substr($buffer,$chunkstart);
				// append chunk-data to entity-body
				$new .= $chunk;
				$length += strlen($chunk);
				break;
			}
			
			// read chunk-data and CRLF
			$chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
			// append chunk-data to entity-body
			$new .= $chunk;
			// length := length + chunk-size
			$length += strlen($chunk);
			// read chunk-size and CRLF
			$chunkstart = $chunkend + 2;
			
			$chunkend = strpos($buffer,"\r\n",$chunkstart)+2;
			if ($chunkend == FALSE) {
				break; //Just in case we got a broken connection
			}
			$temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
			$chunk_size = hexdec( trim($temp) );
			$chunkstart = $chunkend;
		}

		return $new;
	}
}
?>
Return current item: OpenNitro