* @author Davey Shafik * @author Michael Wallner * @copyright 2003-2005 The Authors * @license BSD, revised * @version CVS: $Id: Header.php,v 1.32 2005/11/08 19:06:10 mike Exp $ * @link http://pear.php.net/package/HTTP_Header */ /** * Requires HTTP */ require_once 'HTTP.php'; /**#@+ * Information Codes */ define('HTTP_HEADER_STATUS_100', '100 Continue'); define('HTTP_HEADER_STATUS_101', '101 Switching Protocols'); define('HTTP_HEADER_STATUS_102', '102 Processing'); define('HTTP_HEADER_STATUS_INFORMATIONAL',1); /**#@-*/ /**#+ * Success Codes */ define('HTTP_HEADER_STATUS_200', '200 OK'); define('HTTP_HEADER_STATUS_201', '201 Created'); define('HTTP_HEADER_STATUS_202', '202 Accepted'); define('HTTP_HEADER_STATUS_203', '203 Non-Authoritative Information'); define('HTTP_HEADER_STATUS_204', '204 No Content'); define('HTTP_HEADER_STATUS_205', '205 Reset Content'); define('HTTP_HEADER_STATUS_206', '206 Partial Content'); define('HTTP_HEADER_STATUS_207', '207 Multi-Status'); define('HTTP_HEADER_STATUS_SUCCESSFUL',2); /**#@-*/ /**#@+ * Redirection Codes */ define('HTTP_HEADER_STATUS_300', '300 Multiple Choices'); define('HTTP_HEADER_STATUS_301', '301 Moved Permanently'); define('HTTP_HEADER_STATUS_302', '302 Found'); define('HTTP_HEADER_STATUS_303', '303 See Other'); define('HTTP_HEADER_STATUS_304', '304 Not Modified'); define('HTTP_HEADER_STATUS_305', '305 Use Proxy'); define('HTTP_HEADER_STATUS_306', '306 (Unused)'); define('HTTP_HEADER_STATUS_307', '307 Temporary Redirect'); define('HTTP_HEADER_STATUS_REDIRECT',3); /**#@-*/ /**#@+ * Error Codes */ define('HTTP_HEADER_STATUS_400', '400 Bad Request'); define('HTTP_HEADER_STATUS_401', '401 Unauthorized'); define('HTTP_HEADER_STATUS_402', '402 Payment Granted'); define('HTTP_HEADER_STATUS_403', '403 Forbidden'); define('HTTP_HEADER_STATUS_404', '404 File Not Found'); define('HTTP_HEADER_STATUS_405', '405 Method Not Allowed'); define('HTTP_HEADER_STATUS_406', '406 Not Acceptable'); define('HTTP_HEADER_STATUS_407', '407 Proxy Authentication Required'); define('HTTP_HEADER_STATUS_408', '408 Request Time-out'); define('HTTP_HEADER_STATUS_409', '409 Conflict'); define('HTTP_HEADER_STATUS_410', '410 Gone'); define('HTTP_HEADER_STATUS_411', '411 Length Required'); define('HTTP_HEADER_STATUS_412', '412 Precondition Failed'); define('HTTP_HEADER_STATUS_413', '413 Request Entity Too Large'); define('HTTP_HEADER_STATUS_414', '414 Request-URI Too Large'); define('HTTP_HEADER_STATUS_415', '415 Unsupported Media Type'); define('HTTP_HEADER_STATUS_416', '416 Requested range not satisfiable'); define('HTTP_HEADER_STATUS_417', '417 Expectation Failed'); define('HTTP_HEADER_STATUS_422', '422 Unprocessable Entity'); define('HTTP_HEADER_STATUS_423', '423 Locked'); define('HTTP_HEADER_STATUS_424', '424 Failed Dependency'); define('HTTP_HEADER_STATUS_CLIENT_ERROR',4); /**#@-*/ /**#@+ * Server Errors */ define('HTTP_HEADER_STATUS_500', '500 Internal Server Error'); define('HTTP_HEADER_STATUS_501', '501 Not Implemented'); define('HTTP_HEADER_STATUS_502', '502 Bad Gateway'); define('HTTP_HEADER_STATUS_503', '503 Service Unavailable'); define('HTTP_HEADER_STATUS_504', '504 Gateway Time-out'); define('HTTP_HEADER_STATUS_505', '505 HTTP Version not supported'); define('HTTP_HEADER_STATUS_507', '507 Insufficient Storage'); define('HTTP_HEADER_STATUS_SERVER_ERROR',5); /**#@-*/ /** * HTTP_Header * * @package HTTP_Header * @category HTTP * @access public * @version $Revision: 1.32 $ */ class HTTP_Header extends HTTP { /** * Default Headers * * The values that are set as default, are the same as PHP sends by default. * * @var array * @access private */ var $_headers = array( 'content-type' => 'text/html', 'pragma' => 'no-cache', 'cache-control' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0' ); /** * HTTP version * * @var string * @access private */ var $_httpVersion = '1.0'; /** * Constructor * * Sets HTTP version. * * @access public * @return object HTTP_Header */ function __construct() { if (isset($_SERVER['SERVER_PROTOCOL'])) { $this->setHttpVersion(substr($_SERVER['SERVER_PROTOCOL'], -3)); } } /** * Set HTTP version * * @access public * @return bool Returns true on success or false if version doesn't * match 1.0 or 1.1 (note: 1 will result in 1.0) * @param mixed $version HTTP version, either 1.0 or 1.1 */ function setHttpVersion($version) { $version = round((float) $version, 1); if ($version < 1.0 || $version > 1.1) { return false; } $this->_httpVersion = sprintf('%0.1f', $version); return true; } /** * Get HTTP version * * @access public * @return string */ function getHttpVersion() { return $this->_httpVersion; } /** * Set Header * * The default value for the Last-Modified header will be current * date and atime if $value is omitted. * * @access public * @return bool Returns true on success or false if $key was empty or * $value was not of an scalar type. * @param string $key The name of the header. * @param string $value The value of the header. (NULL to unset header) */ function setHeader($key, $value = null) { if (empty($key) || (isset($value) && !is_scalar($value))) { return false; } $key = strToLower($key); if ($key == 'last-modified') { if (!isset($value)) { $value = HTTP::Date(time()); } elseif (is_numeric($value)) { $value = HTTP::Date($value); } } if (isset($value)) { $this->_headers[$key] = $value; } else { unset($this->_headers[$key]); } return true; } /** * Get Header * * If $key is omitted, all stored headers will be returned. * * @access public * @return mixed Returns string value of the requested header, * array values of all headers or false if header $key * is not set. * @param string $key The name of the header to fetch. */ function getHeader($key = null) { if (!isset($key)) { return $this->_headers; } $key = strToLower($key); if (!isset($this->_headers[$key])) { return false; } return $this->_headers[$key]; } /** * Send Headers * * Send out the header that you set via setHeader(). * * @access public * @return bool Returns true on success or false if headers are already * sent. * @param array $keys Headers to (not) send, see $include. * @param array $include If true only $keys matching headers will be * sent, if false only header not matching $keys will be * sent. */ function sendHeaders($keys = array(), $include = true) { if (headers_sent()) { return false; } if (count($keys)) { array_change_key_case($keys, CASE_LOWER); foreach ($this->_headers as $key => $value) { if ($include ? in_array($key, $keys) : !in_array($key, $keys)) { header($key .': '. $value); } } } else { foreach ($this->_headers as $header => $value) { header($header .': '. $value); } } return true; } /** * Send Satus Code * * Send out the given HTTP-Status code. Use this for example when you * want to tell the client this page is cached, then you would call * sendStatusCode(304). * * @see HTTP_Header_Cache::exitIfCached() * * @access public * @return bool Returns true on success or false if headers are already * sent. * @param int $code The status code to send, i.e. 404, 304, 200, etc. */ function sendStatusCode($code) { if (headers_sent()) { return false; } if ($code == (int) $code && defined('HTTP_HEADER_STATUS_'. $code)) { $code = constant('HTTP_HEADER_STATUS_'. $code); } if (strncasecmp(PHP_SAPI, 'cgi', 3)) { header('HTTP/'. $this->_httpVersion .' '. $code); } else { header('Status: '. $code); } return true; } /** * Date to Timestamp * * Converts dates like * Mon, 31 Mar 2003 15:26:34 GMT * Tue, 15 Nov 1994 12:45:26 GMT * into a timestamp, strtotime() didn't do it in older versions. * * @deprecated Use PHPs strtotime() instead. * @access public * @return mixed Returns int unix timestamp or false if the date doesn't * seem to be a valid GMT date. * @param string $date The GMT date. */ function dateToTimestamp($date) { static $months = array( null => 0, 'Jan' => 1, 'Feb' => 2, 'Mar' => 3, 'Apr' => 4, 'May' => 5, 'Jun' => 6, 'Jul' => 7, 'Aug' => 8, 'Sep' => 9, 'Oct' => 10, 'Nov' => 11, 'Dec' => 12 ); if (-1 < $timestamp = strToTime($date)) { return $timestamp; } if (!preg_match('~[^,]*,\s(\d+)\s(\w+)\s(\d+)\s(\d+):(\d+):(\d+).*~', $date, $m)) { return false; } // [0] => Mon, 31 Mar 2003 15:42:55 GMT // [1] => 31 [2] => Mar [3] => 2003 [4] => 15 [5] => 42 [6] => 55 return mktime($m[4], $m[5], $m[6], $months[$m[2]], $m[1], $m[3]); } /** * Redirect * * This function redirects the client. This is done by issuing a Location * header and exiting. Additionally to HTTP::redirect() you can also add * parameters to the url. * * If you dont need parameters to be added, simply use HTTP::redirect() * otherwise use HTTP_Header::redirect(). * * @see HTTP::redirect() * @author Wolfram Kriesing * @access public * @return void * @param string $url The URL to redirect to, if none is given it * redirects to the current page. * @param array $param Array of query string parameters to add; usually * a set of key => value pairs; if an array entry consists * only of an value it is used as key and the respective * value is fetched from $GLOBALS[$value] * @param bool $session Whether the session name/id should be added */ function redirect($url = null, $param = array(), $session = false) { if (!isset($url)) { $url = $_SERVER['PHP_SELF']; } $qs = array(); if ($session) { $qs[] = session_name() .'='. session_id(); } if (is_array($param) && count($param)) { if (count($param)) { foreach ($param as $key => $val) { if (is_string($key)) { $qs[] = urlencode($key) .'='. urlencode($val); } else { $qs[] = urlencode($val) .'='. urlencode(@$GLOBALS[$val]); } } } } if ($qstr = implode('&', $qs)) { $purl = parse_url($url); $url .= (isset($purl['query']) ? '&' : '?') . $qstr; } parent::redirect($url); } /**#@+ * @author Davey Shafik * @param int $http_code HTTP Code to check * @access public */ /** * Return HTTP Status Code Type * * @return int|false */ function getStatusType($http_code) { if(is_int($http_code) && defined('HTTP_HEADER_STATUS_' .$http_code) || defined($http_code)) { $type = substr($http_code,0,1); switch ($type) { case HTTP_HEADER_STATUS_INFORMATIONAL: case HTTP_HEADER_STATUS_SUCCESSFUL: case HTTP_HEADER_STATUS_REDIRECT: case HTTP_HEADER_STATUS_CLIENT_ERROR: case HTTP_HEADER_STATUS_SERVER_ERROR: return $type; break; default: return false; break; } } else { return false; } } /** * Return Status Code Message * * @return string|false */ function getStatusText($http_code) { if ($this->getStatusType($http_code)) { if (is_int($http_code) && defined('HTTP_HEADER_STATUS_' .$http_code)) { return substr(constant('HTTP_HEADER_STATUS_' .$http_code),4); } else { return substr($http_code,4); } } else { return false; } } /** * Checks if HTTP Status code is Information (1xx) * * @return boolean */ function isInformational($http_code) { if ($status_type = $this->getStatusType($http_code)) { return $status_type[0] == HTTP_HEADER_STATUS_INFORMATIONAL; } else { return false; } } /** * Checks if HTTP Status code is Successful (2xx) * * @return boolean */ function isSuccessful($http_code) { if ($status_type = $this->getStatusType($http_code)) { return $status_type[0] == HTTP_HEADER_STATUS_SUCCESSFUL; } else { return false; } } /** * Checks if HTTP Status code is a Redirect (3xx) * * @return boolean */ function isRedirect($http_code) { if ($status_type = $this->getStatusType($http_code)) { return $status_type[0] == HTTP_HEADER_STATUS_REDIRECT; } else { return false; } } /** * Checks if HTTP Status code is a Client Error (4xx) * * @return boolean */ function isClientError($http_code) { if ($status_type = $this->getStatusType($http_code)) { return $status_type[0] == HTTP_HEADER_STATUS_CLIENT_ERROR; } else { return false; } } /** * Checks if HTTP Status code is Server Error (5xx) * * @return boolean */ function isServerError($http_code) { if ($status_type = $this->getStatusType($http_code)) { return $status_type[0] == HTTP_HEADER_STATUS_SERVER_ERROR; } else { return false; } } /** * Checks if HTTP Status code is Server OR Client Error (4xx or 5xx) * * @return boolean */ function isError($http_code) { if ($status_type = $this->getStatusType($http_code)) { return (($status_type == HTTP_HEADER_STATUS_CLIENT_ERROR) || ($status_type == HTTP_HEADER_STATUS_SERVER_ERROR)) ? true : false; } else { return false; } } /**#@-*/ } ?>