|
@@ -17,21 +17,83 @@ class http_header
|
|
|
const COOKIE_HTTPONLY = "; HttpOnly";
|
|
|
|
|
|
private static $stHeader = NULL;
|
|
|
+ private static $http_status_map = array(100 =>"Continue",
|
|
|
+ 101 =>"Switching Protocols" ,
|
|
|
+ 200 =>"OK" ,
|
|
|
+ 201 =>"Created" ,
|
|
|
+ 202 =>"Accepted" ,
|
|
|
+ 203 =>"Non-Authoritative Information" ,
|
|
|
+ 204 =>"No Content" ,
|
|
|
+ 205 =>"Reset Content" ,
|
|
|
+ 206 =>"Partial Content" ,
|
|
|
+ 300 =>"Multiple Choices" ,
|
|
|
+ 301 =>"Moved Permanently" ,
|
|
|
+ 302 =>"Found" ,
|
|
|
+ 303 =>"See Other" ,
|
|
|
+ 304 =>"Not Modified" ,
|
|
|
+ 305 =>"Use Proxy" ,
|
|
|
+ 307 =>"Temporary Redirect" ,
|
|
|
+ 308 =>"Permanent Redirect" ,
|
|
|
+ 400 =>"Bad Request" ,
|
|
|
+ 401 =>"Unauthorized" ,
|
|
|
+ 402 =>"Payment Required" ,
|
|
|
+ 403 =>"Forbidden" ,
|
|
|
+ 404 =>"Not Found" ,
|
|
|
+ 405 =>"Method Not Allowed" ,
|
|
|
+ 406 =>"Not Acceptable" ,
|
|
|
+ 407 =>"Proxy Authentication Required" ,
|
|
|
+ 408 =>"Request Timeout" ,
|
|
|
+ 409 =>"Conflict" ,
|
|
|
+ 410 =>"Gone" ,
|
|
|
+ 411 =>"Length Required" ,
|
|
|
+ 412 =>"Precondition Failed" ,
|
|
|
+ 413 =>"Request Entity Too Large" ,
|
|
|
+ 414 =>"Request-URI Too Long" ,
|
|
|
+ 415 =>"Unsupported Media Type" ,
|
|
|
+ 416 =>"Requested Range Not Satisfiable" ,
|
|
|
+ 417 =>"Expectation Failed" ,
|
|
|
+ 426 =>"Upgrade Required" ,
|
|
|
+ 428 =>"Precondition Required" ,
|
|
|
+ 429 =>"Too Many Requests" ,
|
|
|
+ 431 =>"Request Header Fields Too Large" ,
|
|
|
+ 500 =>"Internal Server Error" ,
|
|
|
+ 501 =>"Not Implemented" ,
|
|
|
+ 502 =>"Bad Gateway" ,
|
|
|
+ 503 =>"Service Unavailable" ,
|
|
|
+ 504 =>"Gateway Timeout" ,
|
|
|
+ 505 =>"HTTP Version Not Supported" ,
|
|
|
+ 506 =>"Variant Also Negotiates" ,
|
|
|
+ 511 =>"Network Authentication Required");
|
|
|
|
|
|
private $mHeader = NULL;
|
|
|
+ private $mStatusLine = '';
|
|
|
+ private $mStatusCode = 200;
|
|
|
+ private $mSended = false;
|
|
|
|
|
|
- private function __construct()
|
|
|
+ public function start()
|
|
|
{
|
|
|
+ $this->mHeader = new SplDoublyLinkedList();
|
|
|
+ $this->mStatusCode = 200;
|
|
|
+ $this->mSended = false;
|
|
|
}
|
|
|
|
|
|
- public function start()
|
|
|
+ public function sent()
|
|
|
{
|
|
|
- $this->mHeader = new SplDoublyLinkedList();
|
|
|
+ if($this->sended == false) {
|
|
|
+ $this->mSended = true;
|
|
|
+ $sHeader = $this->to_string();
|
|
|
+ fcgi_echo($sHeader);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $this->mSended;
|
|
|
}
|
|
|
|
|
|
- public function end()
|
|
|
+ private function to_string()
|
|
|
{
|
|
|
$sheader = '';
|
|
|
+
|
|
|
+ $status_line = sprintf("HTTP/1.1 %d %s\r\n",$this->mStatusCode,self::$http_status_map[$this->mStatusCode]);
|
|
|
+ $sheader .= $status_line;
|
|
|
foreach($this->mHeader as $val)
|
|
|
{
|
|
|
$sheader .= $val . "\r\n";
|
|
@@ -132,24 +194,127 @@ class http_header
|
|
|
$this->mHeader->push($string);
|
|
|
}
|
|
|
|
|
|
- public function header ($string, $replace = true, $http_response_code = null)
|
|
|
+ private function newline_check($string)
|
|
|
{
|
|
|
- if(empty($string)) return;
|
|
|
-
|
|
|
$datas = str_split($string);
|
|
|
foreach($datas as $val) {
|
|
|
if($val == '\r' || $val == '\n') {
|
|
|
Log::record("Header may not contain more than a single header, new line detected",Log::ERR);
|
|
|
- return;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function extract_response_code($header_line)
|
|
|
+ {
|
|
|
+ $code = 200;
|
|
|
+ $nodes = explode($header_line);
|
|
|
+ if(count($nodes) > 1)
|
|
|
+ {
|
|
|
+ $datas = str_split($nodes[1]);
|
|
|
+
|
|
|
+ $max = intval('0') + 9;
|
|
|
+ $min = intval('0');
|
|
|
+
|
|
|
+ foreach($datas as $ch)
|
|
|
+ {
|
|
|
+ if($ch >$max || $ch < $min) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $code = intval($nodes[1]);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $code;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ private function special_line($header_line,$http_response_code)
|
|
|
+ {
|
|
|
+ $len = strlen($header_line);
|
|
|
+
|
|
|
+ if($len >= 5 && strncasecmp($header_line,"HTTP/", 5) == 0)
|
|
|
+ {
|
|
|
+ $this->mStatusCode = $this->extract_response_code($header_line);
|
|
|
+ $this->mStatusLine = $header_line;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ $colon_offset = strchr($header_line, ':');
|
|
|
+ if($colon_offset)
|
|
|
+ {
|
|
|
+ if (!strcasecmp($header_line, "Location",strlen("Location")))
|
|
|
+ {
|
|
|
+ if( ($this->mStatusCode < 300 || $this->mStatusCode > 399) && $this->mStatusCode != 201)
|
|
|
+ {
|
|
|
+ $method = strtolower(request_helper::method());
|
|
|
+ if ($http_response_code) { /* user specified redirect code */
|
|
|
+ $this->mStatusCode = $http_response_code;
|
|
|
+ } else if ($method == 'get') {
|
|
|
+ $this->mStatusCode = 303;
|
|
|
+ } else {
|
|
|
+ $this->mStatusCode = 302;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(!strcasecmp($header_line, "WWW-Authenticate",strlen("WWW-Authenticate"))) {
|
|
|
+ $this->mStatusCode = 401;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function header ($string, $replace = true, $http_response_code = null)
|
|
|
+ {
|
|
|
+ if(empty($string)) return;
|
|
|
+ if($this->newline_check($string) == false) return;
|
|
|
+
|
|
|
+ if($this->special_line($string,$http_response_code) == 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if($http_response_code) {
|
|
|
+ $this->mStatusCode = $http_response_code;
|
|
|
+ }
|
|
|
+
|
|
|
if($replace) {
|
|
|
$this->replace($string);
|
|
|
} else {
|
|
|
$this->mHeader->push($string);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ public function remove($name)
|
|
|
+ {
|
|
|
+ if(empty($name)) {
|
|
|
+ $this->mHeader->clear();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ $reg = '/^([^:]*): (.*)/i';
|
|
|
+
|
|
|
+ $index = 0;
|
|
|
+ for($this->mHeader->rewind();$this->mHeader->valid();$this->mHeader->next())
|
|
|
+ {
|
|
|
+ $val = $this->mHeader->current();
|
|
|
+ if(preg_match($reg,$val,$m))
|
|
|
+ {
|
|
|
+ $hname = strtolower($m[1]);
|
|
|
+ if(strcmp($name,$hname) == 0) {
|
|
|
+ $this->mHeader->offsetUnset($index);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ $index++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
function init_cookie($cookie)
|
|
@@ -195,5 +360,10 @@ function fcgi_header($string, $replace = true, $http_response_code = null)
|
|
|
|
|
|
function fcgi_header_remove($name)
|
|
|
{
|
|
|
+ return http_header::instance()->remove($name);
|
|
|
+}
|
|
|
|
|
|
+function fcgi_headers_sent()
|
|
|
+{
|
|
|
+ return http_header::instance()->sent();
|
|
|
}
|