"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; public function start() { $this->mHeader = new SplDoublyLinkedList(); $this->mStatusCode = 200; $this->mSended = false; } public function sent() { if($this->mSended == false) { $this->mSended = true; $sHeader = $this->to_string(); fcgi_echo($sHeader); } return $this->mSended; } 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"; } $sheader .= "\r\n"; return $sheader; } static public function instance() { if(self::$stHeader == NULL) { self::$stHeader = new http_header(); } return self::$stHeader; } public function setcookie($name, $value = null, $expire = null, $path = null, $domain = null, $secure = null,$url_encode = true, $httponly = null) { if(empty($name)) { return false; } elseif(strpbrk($name, "=,; \t\r\n\013\014") != false) { Log::record('Cookie names cannot contain any of the following \'=,; \\t\\r\\n\\013\\014\''); return false; } if(empty($value)) { $cookie = sprintf("Set-Cookie: %s=deleted; expires=%s; Max-Age=0", $name, gmdate("D, d-M-Y H:i:s T",1)); } else { if(!$url_encode && strpbrk($value,"=,; \t\r\n\013\014") != false) { Log::record('Cookie valuse cannot contain any of the following \'=,; \\t\\r\\n\\013\\014\''); return false; } if($url_encode) { $cookie = sprintf("Set-Cookie: %s=%s", $name, !empty($value) ? urlencode($value) : ""); } else { $cookie = sprintf("Set-Cookie: %s=%s", $name, !empty($value) ? $value : ""); } if($expire > 0) { $tmp = self::COOKIE_EXPIRES . gmdate("D, d-M-Y H:i:s T",$expire); $cookie .= $tmp; } $tsdelta = sprintf("%d", $expire - time()); $cookie .= self::COOKIE_MAX_AGE . $tsdelta; } if(!empty($path)) { $cookie .= self::COOKIE_PATH . $path; } if(!empty($domain)) { $cookie .= self::COOKIE_DOMAIN . $domain; } if(!empty($secure)) { $cookie .= self::COOKIE_SECURE . $secure; } if(!empty($httponly)) { $cookie .= self::COOKIE_HTTPONLY . $httponly; } $this->mHeader->push($cookie); return true; } private function replace($string) { $reg = '/^([^:]*): (.*)/i'; $string = trim($string); if(preg_match($reg,$string,$m)) { $sname =strtolower($m[1]); } $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($sname,$hname) == 0) { $this->mHeader->offsetUnset($index); break; } $index++; } } $this->mHeader->push($string); } private function newline_check($string) { $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 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 (!strncasecmp($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; } elseif ($method == 'get') { $this->mStatusCode = 303; } else { $this->mStatusCode = 302; } } } elseif(!strncasecmp($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++; } } } return true; } } function init_cookie($cookie) { $regxp = '/([^=]+=[^;]*)[;]?/i'; $val = preg_match_all($regxp,$cookie,$match); if($val == false) return false; if(count($match) == 2) { foreach($match[1] as $val) { $kv = preg_split('/=/',$val); if(!empty($kv)) { $k = trim($kv[0]); $v = trim($kv[1]); if(!empty($k)) { $_COOKIE[$k] = $v; } //Log::record("cookie {$k} = {$v}",Log::DEBUG); } } } return true; } function fcgi_setcookie($name, $value = null, $expire = null, $path = null, $domain = null, $secure = null, $httponly = null) { return http_header::instance()->setcookie($name,$value,$expire,$path,$domain,$secure,true,$httponly); } function fcgi_setrawcookie($name, $value = null, $expire = null, $path = null, $domain = null, $secure = null, $httponly = null) { return http_header::instance()->setcookie($name,$value,$expire,$path,$domain,$secure,false,$httponly); } function fcgi_header($string, $replace = true, $http_response_code = null) { http_header::instance()->header($string,$replace,$http_response_code); } function fcgi_header_remove($name) { return http_header::instance()->remove($name); } function fcgi_headers_sent() { return http_header::instance()->sent(); }