761 lines
20 KiB
PHP
761 lines
20 KiB
PHP
|
|
<?php
|
||
|
|
/**
|
||
|
|
* PHP HTTP Tools is a library for working with the http protocol
|
||
|
|
* php_http_client_generic represents a basic http client
|
||
|
|
* @package php-http-tools
|
||
|
|
* @version 0.3
|
||
|
|
* @copyright (C) 2004 John Heinstein. All rights reserved
|
||
|
|
* @license http://www.gnu.org/copyleft/lesser.html LGPL License
|
||
|
|
* @author John Heinstein <johnkarl@nbnet.nb.ca>
|
||
|
|
* @link http://www.engageinteractive.com/php_http_tools/ PHP HTTP Tools Home Page
|
||
|
|
* PHP HTTP Tools are Free Software
|
||
|
|
**/
|
||
|
|
|
||
|
|
if (!defined('PHP_HTTP_TOOLS_INCLUDE_PATH')) {
|
||
|
|
define('PHP_HTTP_TOOLS_INCLUDE_PATH', (dirname(__FILE__) . "/"));
|
||
|
|
}
|
||
|
|
|
||
|
|
/** end-of-line character sequence as defined in HTTP spec */
|
||
|
|
define ('CRLF', "\r\n");
|
||
|
|
/** carriage return character */
|
||
|
|
define ('CR', "\r");
|
||
|
|
/** line feed character */
|
||
|
|
define ('LF', "\n");
|
||
|
|
|
||
|
|
//http read states for client
|
||
|
|
/** beginning read state */
|
||
|
|
define('HTTP_READ_STATE_BEGIN', 1);
|
||
|
|
/** state when reading headers */
|
||
|
|
define('HTTP_READ_STATE_HEADERS', 2);
|
||
|
|
/** state when reading body of message */
|
||
|
|
define('HTTP_READ_STATE_BODY', 3);
|
||
|
|
|
||
|
|
require_once(PHP_HTTP_TOOLS_INCLUDE_PATH . 'php_http_exceptions.php');
|
||
|
|
|
||
|
|
/**
|
||
|
|
|
||
|
|
* An HTTP Request class
|
||
|
|
*
|
||
|
|
* @package php-http-tools
|
||
|
|
* @author John Heinstein <johnkarl@nbnet.nb.ca>
|
||
|
|
*/
|
||
|
|
class php_http_request {
|
||
|
|
/** @var object A reference to the headers object */
|
||
|
|
var $headers = null;
|
||
|
|
/** @var string The requested method, e.g. GET, POST, HEAD */
|
||
|
|
var $requestMethod = 'POST';
|
||
|
|
/** @var string The requested path */
|
||
|
|
var $requestPath = '';
|
||
|
|
/** @var string The requested protocol */
|
||
|
|
var $protocol = 'HTTP';
|
||
|
|
/** @var string The version of the requested protocol */
|
||
|
|
var $protocolVersion= '1.1';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns the headers object
|
||
|
|
* @return object The headers object
|
||
|
|
*/
|
||
|
|
function &getHeaders() {
|
||
|
|
return $this->headers;
|
||
|
|
} //getHeaders
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sets the header to the specified value
|
||
|
|
* @param string The header name
|
||
|
|
* @param string The header value
|
||
|
|
* @param boolean True if multiple headers with the same name are allowed
|
||
|
|
*/
|
||
|
|
function setHeader($name, $value, $allowMultipleHeaders = false) {
|
||
|
|
$this->headers->setHeader($name, $value, $allowMultipleHeaders);
|
||
|
|
} //setHeader
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Default method for setting headers; meant to be overridden in subclasses
|
||
|
|
*/
|
||
|
|
function setHeaders() {
|
||
|
|
//you will want to override this method
|
||
|
|
$this->setHeader('User-Agent', 'PHP-HTTP-Client(Generic)/0.1');
|
||
|
|
$this->setHeader('Connection', 'Close');
|
||
|
|
} //setHeaders
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sets the request method, e.g., GET
|
||
|
|
* @param string The name of the request method
|
||
|
|
* @return boolean True if the version number is valid
|
||
|
|
*/
|
||
|
|
function setRequestMethod($method) {
|
||
|
|
$method = strtoupper($method);
|
||
|
|
|
||
|
|
switch ($method) {
|
||
|
|
case 'POST':
|
||
|
|
case 'GET':
|
||
|
|
case 'HEAD':
|
||
|
|
case 'PUT':
|
||
|
|
$this->requestMethod = $method;
|
||
|
|
return true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
} //setRequestMethod
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sets the request path, e.g., http://www.engageinteractive.com/domit/test.xml
|
||
|
|
* @param string The request path
|
||
|
|
*/
|
||
|
|
function setRequestPath($path) {
|
||
|
|
$this->requestPath = $path;
|
||
|
|
} //setRequestPath
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sets the version number of the protocol
|
||
|
|
* @param string The version number
|
||
|
|
* @return boolean True if the version number is valid
|
||
|
|
*/
|
||
|
|
function setProtocolVersion($version) {
|
||
|
|
if (($version == '1.0') || ($version == '1.1')) {
|
||
|
|
$this->protocolVersion = $version;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
} //setProtocolVersion
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Specifies a user name and password for basic authentication
|
||
|
|
* @param string The user name
|
||
|
|
* @param string The password
|
||
|
|
*/
|
||
|
|
function setAuthorization($user, $password) {
|
||
|
|
$encodedChallengeResponse = 'Basic ' . base64_encode($this->user . ':' . $this->password);
|
||
|
|
$this->setHeader('Authorization', $encodedChallengeResponse);
|
||
|
|
} //setAuthorization
|
||
|
|
} //php_http_request
|
||
|
|
|
||
|
|
|
||
|
|
class php_http_client_generic extends php_http_request {
|
||
|
|
/** @var object A reference to the connection object */
|
||
|
|
var $connection;
|
||
|
|
/** @var string True if response headers are to be generated as an object */
|
||
|
|
var $responseHeadersAsObject = false;
|
||
|
|
/** @var object The http response */
|
||
|
|
var $response = null;
|
||
|
|
/** @var string A list of event names that can be fired by the client */
|
||
|
|
var $events = array('onRequest' => null, 'onRead' => null,
|
||
|
|
'onResponse' => null, 'onResponseHeaders' => null,
|
||
|
|
'onResponseBody' => null);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* HTTP Client constructor
|
||
|
|
* @param string The client connection host name, with or without its protocol prefix
|
||
|
|
* @param string The client connection path, not including the host name
|
||
|
|
* @param int The port to establish the client connection on
|
||
|
|
* @param int The timeout value for the client connection
|
||
|
|
*/
|
||
|
|
function php_http_client_generic($host = '', $path = '/', $port = 80, $timeout = 0) {
|
||
|
|
$this->connection = new php_http_connection($host, $path, $port, $timeout);
|
||
|
|
$this->headers = new php_http_headers();
|
||
|
|
$this->requestPath = $path;
|
||
|
|
$this->response = new php_http_response();
|
||
|
|
$this->setHeaders();
|
||
|
|
} //php_http_client_generic
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Specifies that the response headers array should be generated
|
||
|
|
* @param boolean True if the response headers array should be built
|
||
|
|
*/
|
||
|
|
function generateResponseHeadersAsObject($responseHeadersAsObject) {
|
||
|
|
$this->responseHeadersAsObject = $responseHeadersAsObject;
|
||
|
|
|
||
|
|
if ($responseHeadersAsObject) {
|
||
|
|
$this->response->headers = new php_http_headers();
|
||
|
|
}
|
||
|
|
} //generateResponseHeadersAsObject
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fires an http event that has been registered
|
||
|
|
* @param string The name of the event, e.g., onRead
|
||
|
|
* @param string The data to be passed to the event
|
||
|
|
*/
|
||
|
|
function fireEvent($target, $data) {
|
||
|
|
if ($this->events[$target] != null) {
|
||
|
|
call_user_func($this->events[$target], $data);
|
||
|
|
}
|
||
|
|
} //fireEvent
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sets which http events are to be fired
|
||
|
|
* @param string The http event option to be set
|
||
|
|
* @param string True if the event is to be fired
|
||
|
|
* @param object A reference to a custom handler for the http event data
|
||
|
|
*/
|
||
|
|
function setHTTPEvent($option, $truthVal, $customHandler = null) {
|
||
|
|
if ($customHandler != null) {
|
||
|
|
$handler =& $customHandler;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$handler = array(&$this, 'defaultHTTPEventHandler');
|
||
|
|
}
|
||
|
|
|
||
|
|
switch($option) {
|
||
|
|
case 'onRequest':
|
||
|
|
case 'onRead':
|
||
|
|
case 'onResponse':
|
||
|
|
case 'onResponseHeaders':
|
||
|
|
case 'onResponseBody':
|
||
|
|
$truthVal ? ($this->events[$option] =& $handler) : ($this->events[$option] = null);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
} //setHTTPEvent
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Evaluates whether the specified http event option is active
|
||
|
|
* @param string The http event option to evaluate
|
||
|
|
* @return boolean True if the specified option is active
|
||
|
|
*/
|
||
|
|
function getHTTPEvent($option) {
|
||
|
|
switch($option) {
|
||
|
|
case 'onRequest':
|
||
|
|
case 'onRead':
|
||
|
|
case 'onResponse':
|
||
|
|
case 'onResponseHeaders':
|
||
|
|
case 'onResponseBody':
|
||
|
|
return ($this->events[$option] != null);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
} //getHTTPEvent
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The default http event handler; fired if no custom handler has been registered
|
||
|
|
* @param string The event data
|
||
|
|
*/
|
||
|
|
function defaultHTTPEventHandler($data) {
|
||
|
|
$this->printHTML($data);
|
||
|
|
} //defaultHTTPEventHandler
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Prints the data to the browser as preformatted, htmlentified output
|
||
|
|
* @param string The data to be printed
|
||
|
|
*/
|
||
|
|
function printHTML($html) {
|
||
|
|
print('<pre>' . htmlentities($html) . '</pre>');
|
||
|
|
} //printHTML
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Establishes a client connection
|
||
|
|
*/
|
||
|
|
function connect() {
|
||
|
|
if (!$this->headers->headerExists('Host')) {
|
||
|
|
$this->setHeader('Host', $this->connection->host);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this->connection->connect();
|
||
|
|
} //connect
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Disconnects the current client connection if one exists
|
||
|
|
*/
|
||
|
|
function disconnect() {
|
||
|
|
return $this->connection->disconnect();
|
||
|
|
} //disconnect
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Evaluated whether the current client is connected
|
||
|
|
* @return boolean True if a connection exists
|
||
|
|
*/
|
||
|
|
function isConnected() {
|
||
|
|
return $this->connection->isOpen();
|
||
|
|
} //isConnected
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Performs an HTTP GET
|
||
|
|
* @param string The target url
|
||
|
|
* @return object An HTTP response object
|
||
|
|
*/
|
||
|
|
function &get($url) {
|
||
|
|
$this->setRequestMethod('GET');
|
||
|
|
$this->setRequestPath($url);
|
||
|
|
|
||
|
|
$this->get_custom($url);
|
||
|
|
|
||
|
|
$this->connect();
|
||
|
|
|
||
|
|
$result = $this->send('');
|
||
|
|
|
||
|
|
return $result;
|
||
|
|
} //get
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Handler for customizing the HTTP GET call
|
||
|
|
* @param string The target url
|
||
|
|
*/
|
||
|
|
function get_custom($url) {
|
||
|
|
//do nothing; meant to be overridden
|
||
|
|
} //get_custom
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Performs an HTTP POST
|
||
|
|
* @param string The posted data
|
||
|
|
* @return object An HTTP response object
|
||
|
|
*/
|
||
|
|
function &post($data) {
|
||
|
|
$this->setRequestMethod('POST');
|
||
|
|
$this->setHeader('Content-Type', 'text/html');
|
||
|
|
$this->post_custom($data);
|
||
|
|
|
||
|
|
$this->connect();
|
||
|
|
|
||
|
|
return $this->send($data);
|
||
|
|
} //post
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Handler for customizing the HTTP POST call
|
||
|
|
* @param string The post data
|
||
|
|
*/
|
||
|
|
function post_custom($data) {
|
||
|
|
//do nothing; meant to be overridden
|
||
|
|
} //post_custom
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Performs an HTTP HEAD
|
||
|
|
* @param string The target url
|
||
|
|
* @return object An HTTP response object
|
||
|
|
*/
|
||
|
|
function &head($url) {
|
||
|
|
$this->setRequestMethod('HEAD');
|
||
|
|
$this->head_custom($url);
|
||
|
|
|
||
|
|
$this->connect();
|
||
|
|
|
||
|
|
return $this->send('');
|
||
|
|
} //head
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Handler for customizing the HTTP HEAD call
|
||
|
|
* @param string The target url
|
||
|
|
*/
|
||
|
|
function head_custom($url) {
|
||
|
|
//do nothing; meant to be overridden
|
||
|
|
} //head_custom
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sends data through the client connection
|
||
|
|
* @param string The message to be sent
|
||
|
|
* @return string The http response
|
||
|
|
*/
|
||
|
|
function send($message) {
|
||
|
|
$conn =& $this->connection;
|
||
|
|
|
||
|
|
if ($conn->isOpen()) {
|
||
|
|
//build header info
|
||
|
|
$request = $this->requestMethod . ' ' . $this->requestPath . ' ' . $this->protocol .
|
||
|
|
'/' . $this->protocolVersion . CRLF;
|
||
|
|
$request .= $this->headers->toString() . CRLF;
|
||
|
|
$request .= $message;
|
||
|
|
|
||
|
|
//init variables
|
||
|
|
$response = $headers = $body = '';
|
||
|
|
$readState = HTTP_READ_STATE_BEGIN;
|
||
|
|
|
||
|
|
$this->fireEvent('onRequest', $request);
|
||
|
|
|
||
|
|
//send request
|
||
|
|
$connResource =& $conn->connection;
|
||
|
|
fputs ($connResource, $request);
|
||
|
|
|
||
|
|
//read response
|
||
|
|
while (!feof($connResource)) {
|
||
|
|
$data = fgets($connResource, 4096);
|
||
|
|
$this->fireEvent('onRead', $data);
|
||
|
|
|
||
|
|
switch ($readState) {
|
||
|
|
case HTTP_READ_STATE_BEGIN:
|
||
|
|
$this->response->statusLine = $data;
|
||
|
|
$readState = HTTP_READ_STATE_HEADERS;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case HTTP_READ_STATE_HEADERS:
|
||
|
|
if (trim($data) == '') { //end of headers is signalled by a blank line
|
||
|
|
$readState = HTTP_READ_STATE_BODY;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if ($this->responseHeadersAsObject) {
|
||
|
|
$this->response->setUnformattedHeader($data);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$this->response->headers .= $data;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case HTTP_READ_STATE_BODY:
|
||
|
|
$this->response->message .= $data;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->normalizeResponseIfChunked();
|
||
|
|
|
||
|
|
$headerString = is_object($this->response->headers) ?
|
||
|
|
$this->response->headers->toString() : $this->response->headers;
|
||
|
|
|
||
|
|
$this->fireEvent('onResponseHeaders', $headerString);
|
||
|
|
$this->fireEvent('onResponseBody', $this->response->message);
|
||
|
|
|
||
|
|
$this->fireEvent('onResponse', $this->response->headers . $this->response->message);
|
||
|
|
|
||
|
|
return $this->response;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
HTTPExceptions::raiseException(HTTP_SOCKET_CONNECTION_ERR, ('HTTP Transport Error - Unable to establish connection to host ' .
|
||
|
|
$conn->host));
|
||
|
|
}
|
||
|
|
} //send
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Determines if response data is transfer encoding chunked, then decodes
|
||
|
|
*/
|
||
|
|
function normalizeResponseIfChunked() {
|
||
|
|
if (($this->protocolVersion = '1.1') && (!$this->response->isResponseChunkDecoded)) {
|
||
|
|
if ($this->responseHeadersAsObject) {
|
||
|
|
if ($this->response->headers->headerExists('Transfer-Encoding') &&
|
||
|
|
($this->response->headers->getHeader('Transfer-Encoding') == 'chunked')) {
|
||
|
|
$this->response->message = $this->decodeChunkedData($this->response->getResponse());
|
||
|
|
$this->response->isResponseChunkDecoded = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if ((strpos($this->response->headers, 'Transfer-Encoding') !== false) &&
|
||
|
|
(strpos($this->response->headers, 'chunked') !== false)){
|
||
|
|
$this->response->message = $this->decodeChunkedData($this->response->getResponse());
|
||
|
|
$this->response->isResponseChunkDecoded = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} //normalizeResponseIfChunked
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Decodes data if transfer encoding chunked
|
||
|
|
* @param string The encoded data
|
||
|
|
* @return string The decoded data
|
||
|
|
*/
|
||
|
|
function decodeChunkedData($data) {
|
||
|
|
$chunkStart = $chunkEnd = strpos($data, CRLF) + 2;
|
||
|
|
$chunkLengthInHex = substr($data, 0, $chunkEnd);
|
||
|
|
$chunkLength = hexdec(trim($chunkLengthInHex));
|
||
|
|
|
||
|
|
$decodedData = '';
|
||
|
|
|
||
|
|
while ($chunkLength > 0) {
|
||
|
|
$chunkEnd = strpos($data, CRLF, ($chunkStart + $chunkLength));
|
||
|
|
|
||
|
|
if (!$chunkEnd) {
|
||
|
|
//if the trailing CRLF is missing, return all the remaining data
|
||
|
|
$decodedData .= substr($data, $chunkStart);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
$decodedData .= substr($data, $chunkStart, ($chunkEnd - $chunkStart));
|
||
|
|
$chunkStart = $chunkEnd + 2;
|
||
|
|
$chunkEnd = strpos($data, CRLF, $chunkStart) + 2;
|
||
|
|
|
||
|
|
if (!$chunkEnd) break;
|
||
|
|
|
||
|
|
$chunkLengthInHex = substr($data, $chunkStart, ($chunkEnd - $chunkStart));
|
||
|
|
$chunkLength = hexdec(trim($chunkLengthInHex));
|
||
|
|
$chunkStart = $chunkEnd;
|
||
|
|
}
|
||
|
|
|
||
|
|
return $decodedData;
|
||
|
|
} //decodeChunkedData
|
||
|
|
} //php_http_client_generic
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* An HTTP Connection class
|
||
|
|
*
|
||
|
|
* @package php-http-tools
|
||
|
|
* @author John Heinstein <johnkarl@nbnet.nb.ca>
|
||
|
|
*/
|
||
|
|
class php_http_connection {
|
||
|
|
/** @var object A reference to the current connection */
|
||
|
|
var $connection = null;
|
||
|
|
/** @var string The host of the connection */
|
||
|
|
var $host;
|
||
|
|
/** @var string The path of the connection */
|
||
|
|
var $path;
|
||
|
|
/** @var int The port of the connection */
|
||
|
|
var $port;
|
||
|
|
/** @var int The timeout value for the connection */
|
||
|
|
var $timeout;
|
||
|
|
/** @var int The error number of the connection */
|
||
|
|
var $errorNumber = 0;
|
||
|
|
/** @var string The error string of the connection */
|
||
|
|
var $errorString = '';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* HTTP Connection constructor
|
||
|
|
* @param string The connection host name, with or without its protocol prefix
|
||
|
|
* @param string The connection path, not including the host name
|
||
|
|
* @param int The port to establish the client connection on
|
||
|
|
* @param int The timeout value for the client connection
|
||
|
|
*/
|
||
|
|
function php_http_connection($host = '', $path = '/', $port = 80, $timeout = 0) {
|
||
|
|
$this->host = $this->formatHost($host);
|
||
|
|
$this->path = $this->formatPath($path);
|
||
|
|
$this->port = $port;
|
||
|
|
$this->timeout = $timeout;
|
||
|
|
} //php_http_connection
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Formats a host string by stripping off the http:// prefix
|
||
|
|
* @param string The host name
|
||
|
|
* @return string The formatted host name
|
||
|
|
*/
|
||
|
|
function formatHost($hostString) {
|
||
|
|
$hasProtocol = (substr(strtoupper($hostString), 0, 7) == 'HTTP://');
|
||
|
|
|
||
|
|
if ($hasProtocol) {
|
||
|
|
$hostString = substr($hostString, 7);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $hostString;
|
||
|
|
} //formatHost
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Formats a path string
|
||
|
|
* @param string The path
|
||
|
|
* @return string The formatted path
|
||
|
|
*/
|
||
|
|
function formatPath($pathString) {
|
||
|
|
if (($pathString == '') || ($pathString == null)) {
|
||
|
|
$pathString = '/';
|
||
|
|
}
|
||
|
|
|
||
|
|
return $pathString;
|
||
|
|
} //formatPath
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Establishes a socket connection
|
||
|
|
* @return boolean True if the connection was successful
|
||
|
|
*/
|
||
|
|
function connect() {
|
||
|
|
if ($this->timeout == 0) {
|
||
|
|
$this->connection = @fsockopen($this->host, $this->port, $errorNumber, $errorString);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$this->connection = @fsockopen($this->host, $this->port, $errorNumber, $errorString, $this->timeout);
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->errorNumber = $errorNumber;
|
||
|
|
$this->errorString = $errorString;
|
||
|
|
|
||
|
|
return is_resource($this->connection);
|
||
|
|
} //connect
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Determines whether the connection is still open
|
||
|
|
* @return boolean True if the connection is still open
|
||
|
|
*/
|
||
|
|
function isOpen() {
|
||
|
|
return (is_resource($this->connection) && (!feof($this->connection)));
|
||
|
|
} //isOpen
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Disconnects the current connection
|
||
|
|
* @return boolean True if the connection has been disconnected
|
||
|
|
*/
|
||
|
|
function disconnect() {
|
||
|
|
fclose($this->connection);
|
||
|
|
$this->connection = null;
|
||
|
|
return true;
|
||
|
|
} //disconnect
|
||
|
|
} //php_http_connection
|
||
|
|
|
||
|
|
/**
|
||
|
|
* An HTTP Headers class
|
||
|
|
*
|
||
|
|
* @package php-http-tools
|
||
|
|
* @author John Heinstein <johnkarl@nbnet.nb.ca>
|
||
|
|
*/
|
||
|
|
class php_http_headers {
|
||
|
|
/** @var object An array of headers */
|
||
|
|
var $headers;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* HTTP Headers constructor
|
||
|
|
*/
|
||
|
|
function php_http_headers() {
|
||
|
|
$this->headers = array();
|
||
|
|
} //php_http_headers
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns the specified header value
|
||
|
|
* @param string The header name
|
||
|
|
* @return mixed The header value, or an array of header values
|
||
|
|
*/
|
||
|
|
function &getHeader($name) {
|
||
|
|
if ($this->headerExists($name)) {
|
||
|
|
return $this->headers[$name];
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
} //getHeader
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sets the named header to the specified value
|
||
|
|
* @param string The header name
|
||
|
|
* @param string The header value
|
||
|
|
* @param boolean True if multiple headers with the same name are allowed
|
||
|
|
*/
|
||
|
|
function setHeader($name, $value, $allowMultipleHeaders = false) {
|
||
|
|
if ($allowMultipleHeaders) {
|
||
|
|
if (isset($this->headers[$name])) {
|
||
|
|
if (is_array($this->headers[$name])) {
|
||
|
|
$this->headers[$name][count($this->headers)] = $value;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$tempVal = $this->headers[$name];
|
||
|
|
$this->headers[$name] = array($tempVal, $value);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$this->headers[$name] = array();
|
||
|
|
$this->headers[$name][0] = $value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$this->headers[$name] = $value;
|
||
|
|
}
|
||
|
|
} //setHeader
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Determines whether the specified header exists
|
||
|
|
* @param string The header name
|
||
|
|
* @return boolean True if the specified header exists
|
||
|
|
*/
|
||
|
|
function headerExists($name) {
|
||
|
|
return isset($this->headers[$name]);
|
||
|
|
} //headerExists
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Removes the specified header
|
||
|
|
* @param string The header name
|
||
|
|
* @return boolean True if the specified header has been removed
|
||
|
|
*/
|
||
|
|
function removeHeader($name) {
|
||
|
|
if ($this->headerExists($name)) {
|
||
|
|
unset($this->headers[$name]);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
} //removeHeader
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns a reference to the headers array
|
||
|
|
* @return array The headers array
|
||
|
|
*/
|
||
|
|
function getHeaders() {
|
||
|
|
return $this->headers;
|
||
|
|
} //getHeaders
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns a list of existing headers names
|
||
|
|
* @return array A list of existing header names
|
||
|
|
*/
|
||
|
|
function getHeaderList() {
|
||
|
|
return array_keys($this->headers);
|
||
|
|
} //getHeaderList
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns a string representation of the headers array
|
||
|
|
* @return string A string representation of the headers array
|
||
|
|
*/
|
||
|
|
function toString() {
|
||
|
|
$retString = '';
|
||
|
|
|
||
|
|
foreach ($this->headers as $key => $value) {
|
||
|
|
if (is_array($value)) {
|
||
|
|
foreach ($value as $key2 => $value2) {
|
||
|
|
$retString .= $key . ': ' . $value2 . CRLF;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$retString .= $key . ': ' . $value . CRLF;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $retString;
|
||
|
|
} //toString
|
||
|
|
} //php_http_headers
|
||
|
|
|
||
|
|
/**
|
||
|
|
* An HTTP Response class
|
||
|
|
*
|
||
|
|
* @package php-http-tools
|
||
|
|
* @author John Heinstein <johnkarl@nbnet.nb.ca>
|
||
|
|
*/
|
||
|
|
class php_http_response {
|
||
|
|
/** @var string Response number */
|
||
|
|
var $statusLine = '';
|
||
|
|
/** @var mixed Response headers, either as object or string */
|
||
|
|
var $headers = '';
|
||
|
|
/** @var string Response message */
|
||
|
|
var $message = '';
|
||
|
|
/** @var boolean True if the chunked transfer-encoding of the response has been decoded */
|
||
|
|
var $isResponseChunkDecoded = false;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns a reference to the headers array
|
||
|
|
* @return array The headers array
|
||
|
|
*/
|
||
|
|
function getResponse() {
|
||
|
|
return $this->message;
|
||
|
|
} //getResponse
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns the response status line
|
||
|
|
* @return string The response status line
|
||
|
|
*/
|
||
|
|
function getStatusLine() {
|
||
|
|
return $this->statusLine;
|
||
|
|
} //getStatusLine
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns the response status code
|
||
|
|
* @return int The response status code
|
||
|
|
*/
|
||
|
|
function getStatusCode() {
|
||
|
|
$statusArray = split(' ', $this->statusLine);
|
||
|
|
|
||
|
|
if (count($statusArray > 1)) {
|
||
|
|
return intval($statusArray[1], 10);
|
||
|
|
}
|
||
|
|
|
||
|
|
return -1;
|
||
|
|
} //getStatusCode
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns a reference to the headers array
|
||
|
|
* @return array The headers array
|
||
|
|
*/
|
||
|
|
function &getHeaders() {
|
||
|
|
return $this->headers;
|
||
|
|
} //getHeaders
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Converts a header string into a key value pair and sets header
|
||
|
|
*/
|
||
|
|
function setUnformattedHeader($headerString) {
|
||
|
|
$colonIndex = strpos($headerString, ':');
|
||
|
|
|
||
|
|
if ($colonIndex !== false) {
|
||
|
|
$key = trim(substr($headerString, 0, $colonIndex));
|
||
|
|
$value = trim(substr($headerString, ($colonIndex + 1)));
|
||
|
|
$this->headers->setHeader($key, $value, true);
|
||
|
|
}
|
||
|
|
} //setUnformattedHeader
|
||
|
|
} //php_http_response
|
||
|
|
|
||
|
|
?>
|