139 $this->data_length = strlen($this->data);
149 while ($this->state && $this->state !==
'emit' && $this->
has_data())
155 if ($this->state ===
'emit' || $this->state ===
'body')
162 $this->status_code =
'';
164 $this->headers = array();
190 && isset($this->data[$this->position + 1])
191 && ($this->data[$this->position + 1] ===
"\x09" || $this->data[$this->position + 1] ===
"\x20")));
199 if (strpos($this->data,
"\x0A") !==
false && strtoupper(substr($this->data, 0, 5)) ===
'HTTP/')
201 $len = strspn($this->data,
'0123456789.', 5);
203 $this->position += 5 + $len;
207 $this->position += strspn($this->data,
"\x09\x20", $this->position);
208 $this->state =
'status';
212 $this->state =
false;
217 $this->state =
false;
226 if ($len = strspn($this->data,
'0123456789', $this->position))
228 $this->status_code = (int) substr($this->data, $this->position, $len);
229 $this->position += $len;
230 $this->state =
'reason';
234 $this->state =
false;
243 $len = strcspn($this->data,
"\x0A", $this->position);
244 $this->
reason = trim(substr($this->data, $this->position, $len),
"\x09\x0D\x20");
245 $this->position += $len + 1;
246 $this->state =
'new_line';
254 $this->
value = trim($this->
value,
"\x0D\x20");
255 if ($this->
name !==
'' && $this->
value !==
'')
257 $this->
name = strtolower($this->
name);
259 if (isset($this->headers[$this->
name]) && $this->name !==
'content-type')
270 if (substr($this->data[$this->position], 0, 2) ===
"\x0D\x0A")
272 $this->position += 2;
273 $this->state =
'body';
275 elseif ($this->data[$this->position] ===
"\x0A")
278 $this->state =
'body';
282 $this->state =
'name';
291 $len = strcspn($this->data,
"\x0A:", $this->position);
292 if (isset($this->data[$this->position + $len]))
294 if ($this->data[$this->position + $len] ===
"\x0A")
296 $this->position += $len;
297 $this->state =
'new_line';
301 $this->
name = substr($this->data, $this->position, $len);
302 $this->position += $len + 1;
303 $this->state =
'value';
308 $this->state =
false;
319 if (substr($this->data, $this->position, 2) ===
"\x0D\x0A")
321 $this->position += 2;
323 elseif ($this->data[$this->position] ===
"\x0A")
327 $this->position += strspn($this->data,
"\x09\x20", $this->position);
329 $this->
value .=
"\x20";
343 switch ($this->data[$this->position])
348 if (strtolower($this->
name) ===
'etag')
352 $this->state =
'value_char';
356 $this->state =
'quote';
361 $this->state =
'new_line';
365 $this->state =
'value_char';
376 $len = strcspn($this->data,
"\x09\x20\x0A\"", $this->position);
377 $this->
value .= substr($this->data, $this->position, $len);
378 $this->position += $len;
379 $this->state =
'value';
393 switch ($this->data[$this->position])
397 $this->state =
'value';
402 $this->state =
'new_line';
407 $this->state =
'quote_escaped';
411 $this->state =
'quote_char';
422 $len = strcspn($this->data,
"\x09\x20\x0A\"\\", $this->position);
423 $this->
value .= substr($this->data, $this->position, $len);
424 $this->position += $len;
425 $this->state =
'value';
435 $this->state =
'quote';
443 $this->
body = substr($this->data, $this->position);
444 if (!empty($this->headers[
'transfer-encoding']))
446 unset($this->headers[
'transfer-encoding']);
447 $this->state =
'chunked';
451 $this->state =
'emit';
460 if (!preg_match(
'/^([0-9a-f]+)[^\r\n]*\r\n/i', trim($this->
body)))
462 $this->state =
'emit';
471 $is_chunked = (bool) preg_match(
'/^([0-9a-f]+)[^\r\n]*\r\n/i', $encoded, $matches );
475 $this->state =
'emit';
479 $length = hexdec(trim($matches[1]));
483 $this->state =
'emit';
484 $this->
body = $decoded;
488 $chunk_length = strlen($matches[0]);
489 $decoded .= $part = substr($encoded, $chunk_length, $length);
490 $encoded = substr($encoded, $chunk_length + $length + 2);
492 if (trim($encoded) ===
'0' || empty($encoded))
494 $this->state =
'emit';
495 $this->
body = $decoded;