123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- <?php
- /**
- * Created by PhpStorm.
- * User: stanley-king
- * Date: 16/1/30
- * Time: 下午3:46
- */
- class http_header
- {
- const COOKIE_EXPIRES = "; expires=";
- const COOKIE_MAX_AGE = "; Max-Age=";
- const COOKIE_DOMAIN = "; domain=";
- const COOKIE_PATH = "; path=";
- const COOKIE_SECURE = "; secure";
- 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;
- 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();
- }
|