Пример #1
0
 function stream_read($count)
 {
     switch ($this->cur_state) {
         case static::BUFFERING:
             $buffer =& $this->buffer;
             // sadly this blocks on Windows.
             // non-blocking pipes don't work in PHP on Windows, and stream_select doesn't know when the pipe has data
             $data = fread($this->stream, $count);
             if ($data !== false) {
                 $buffer .= $data;
                 // need to wait until CGI is finished to determine Content-Length
                 if (!feof($this->stream)) {
                     return '';
                 }
             }
             // now the CGI process has finished sending data.
             // CGI process sends HTTP status as regular header,
             // which we need to convert to HTTP status line.
             // also, need to add Content-Length header for HTTP keep-alive
             $end_response_headers = strpos($buffer, "\r\n\r\n");
             if ($end_response_headers === false) {
                 $response = $this->server->text_response(502, "Invalid Response from CGI process");
             } else {
                 $headers_str = substr($buffer, 0, $end_response_headers);
                 $headers = HTTPServer::parse_headers($headers_str);
                 if (isset($headers['Status'])) {
                     $status_arr = explode(' ', $headers['Status'], 2);
                     $status = (int) $status_arr[0];
                     $status_msg = trim($status_arr[1]);
                     unset($headers['Status']);
                 } else {
                     $status = 200;
                     $status_msg = null;
                 }
                 $content = substr($buffer, $end_response_headers + 4);
                 $response = $this->server->response($status, $content, $headers, $status_msg);
             }
             // set status and headers on the server's HTTPResponse object.
             // these aren't actually sent to the client,
             // but they could be referenced by HTTPServer::get_log_line
             $this->response->status = $response->status;
             $this->response->status_msg = $response->status_msg;
             $this->response->headers = $response->headers;
             $this->cur_state = static::BUFFERED;
             $this->buffer_stream = fopen('data://text/plain,', 'r+b');
             fwrite($this->buffer_stream, $response->render());
             fseek($this->buffer_stream, 0);
             // intentional fallthrough
         // intentional fallthrough
         case static::BUFFERED:
             $res = fread($this->buffer_stream, $count);
             if (feof($this->buffer_stream)) {
                 $this->cur_state = static::EOF;
             }
             return $res;
         case static::EOF:
             return false;
     }
 }
Пример #2
0
 function add_data($data)
 {
     switch ($this->cur_state) {
         case static::READ_HEADERS:
             if (!$this->start_time) {
                 $this->start_time = microtime(true);
             }
             $header_buf =& $this->header_buf;
             $header_buf .= $data;
             if (strlen($header_buf) < 4) {
                 break;
             }
             $end_headers = strpos($header_buf, "\r\n\r\n", 4);
             if ($end_headers === false) {
                 break;
             }
             // parse HTTP request line
             $end_req = strpos($header_buf, "\r\n");
             $this->request_line = substr($header_buf, 0, $end_req);
             $req_arr = explode(' ', $this->request_line, 3);
             $this->method = $req_arr[0];
             $this->request_uri = $req_arr[1];
             $this->http_version = $req_arr[2];
             $parsed_uri = parse_url($this->request_uri);
             $this->uri = urldecode($parsed_uri['path']);
             $this->query_string = @$parsed_uri['query'];
             // parse HTTP headers
             $start_headers = $end_req + 2;
             $headers_str = substr($header_buf, $start_headers, $end_headers - $start_headers);
             $this->headers = HTTPServer::parse_headers($headers_str);
             $this->lc_headers = array();
             foreach ($this->headers as $k => $v) {
                 $this->lc_headers[strtolower($k)] = $v;
             }
             if (isset($this->lc_headers['transfer-encoding'])) {
                 $this->is_chunked = $this->lc_headers['transfer-encoding'][0] == 'chunked';
                 unset($this->lc_headers['transfer-encoding']);
                 unset($this->headers['Transfer-Encoding']);
                 $this->content_len = 0;
             } else {
                 $this->content_len = (int) @$this->lc_headers['content-length'][0];
             }
             $start_content = $end_headers + 4;
             // $end_headers is before last \r\n\r\n
             $data = substr($header_buf, $start_content);
             $header_buf = '';
             $this->cur_state = static::READ_CONTENT;
             // fallthrough to READ_CONTENT with leftover data
         // fallthrough to READ_CONTENT with leftover data
         case static::READ_CONTENT:
             if ($this->is_chunked) {
                 $this->read_chunked_data($data);
             } else {
                 fwrite($this->content_stream, $data);
                 $this->content_len_read += strlen($data);
                 if ($this->content_len - $this->content_len_read <= 0) {
                     $this->cur_state = static::READ_COMPLETE;
                 }
             }
             break;
         case static::READ_COMPLETE:
             break;
     }
     if ($this->cur_state == static::READ_COMPLETE) {
         fseek($this->content_stream, 0);
     }
 }
Пример #3
0
 function add_data($data)
 {
     switch ($this->cur_state) {
         case static::READ_HEADERS:
             if (!$this->start_time) {
                 $this->start_time = microtime(true);
             }
             $header_buf =& $this->header_buf;
             $header_buf .= $data;
             $end_headers = strpos($header_buf, "\r\n\r\n", 4);
             if ($end_headers === false) {
                 break;
             }
             // parse HTTP request line
             $end_req = strpos($header_buf, "\r\n");
             $this->request_line = substr($header_buf, 0, $end_req);
             $req_arr = explode(' ', $this->request_line, 3);
             $this->method = $req_arr[0];
             $this->request_uri = $req_arr[1];
             $this->http_version = $req_arr[2];
             $parsed_uri = parse_url($this->request_uri);
             $this->uri = urldecode($parsed_uri['path']);
             $this->query_string = @$parsed_uri['query'];
             // parse HTTP headers
             $start_headers = $end_req + 2;
             $headers_str = substr($header_buf, $start_headers, $end_headers - $start_headers);
             $this->headers = HTTPServer::parse_headers($headers_str);
             $this->lc_headers = array();
             foreach ($this->headers as $k => $v) {
                 $this->lc_headers[strtolower($k)] = $v;
             }
             $this->content_len = (int) @$this->lc_headers['content-length'];
             $start_content = $end_headers + 4;
             // $end_headers is before last \r\n\r\n
             // add leftover to content
             $content = substr($header_buf, $start_content);
             fwrite($this->content_stream, $content);
             $this->content_len_read = strlen($content);
             $header_buf = '';
             break;
         case static::READ_CONTENT:
             fwrite($this->content_stream, $data);
             $this->content_len_read += strlen($data);
             break;
         case static::READ_COMPLETE:
             break;
     }
     if (!$this->headers) {
         $this->cur_state = static::READ_HEADERS;
     } else {
         if ($this->needs_content()) {
             $this->cur_state = static::READ_CONTENT;
         } else {
             fseek($this->content_stream, 0);
             $this->cur_state = static::READ_COMPLETE;
         }
     }
 }