Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- function dump($v) {
- echo('<pre>' . var_export($v, true) . '</pre>');
- }
- // header("http/1.0 404 \t\t\tNot Found\t");
- header("Content-Type:\t \t text/plain;charset \t\t\t\t= \"utf-8\" foo, bar");
- header('cache-control: no-cache');
- header('Cache-control: no-store'); // cache-control: no-store
- echo("Тест\n");
- preg_match('~;\s*charset\s*=\s*(?:"([^"]+)"|([^\s;]+))~i', "text/html; charset\t= utf-8\t\"q;", $matches);
- // var_dump($matches);
- // echo('charset: ' . (count($matches) ? (isset($matches[2]) ? $matches[2] : $matches[1]) : ''));
- // echo('\\\t\'\0 ');
- preg_match_all('/[\x00-\xff]/', 'тест', $m);
- // var_dump($m);
- $headers = "HTTP/1.1 200\r\n" .
- "Content-Type:" .
- "\r\n\ttext/html;" .
- "\r\n\t charset=utf-8";
- // echo("Headers:\n");
- // echo(preg_replace('/\r\n[ \t]+/', ' ', $headers));
- error_reporting(E_ALL);
- echo("<===================================================================>\n");
- // list($a, $b) = explode(':', '');
- // die;
- class HttpHeader {
- protected $name;
- protected $value;
- public function __construct($name, $value) {
- $this->setName($name);
- $this->setValue($value);
- }
- public function getName() {
- return $this->name;
- }
- public function getValue() {
- return $this->value;
- }
- public function setName($name) {
- // тут валидация
- $this->name = $name;
- }
- public function setValue($value) {
- // тут валидация
- $this->value = $value;
- }
- public function __toString() {
- return $this->name . ': ' . $this->value . "\r\n";
- }
- }
- /**
- * Класс для работы с http-заголовками.
- *
- * Имена полей регистронезависимы. Значения полей можно получить, обращаясь к
- * объекту как к массиву. К объекту применимы вызовы функций count, isset и
- * unset, а так же возможен по нему обход с помощью цикла foreach.
- */
- class HttpHeaders implements ArrayAccess, Countable, IteratorAggregate {
- protected $headers = array();
- public function __construct($headers = array()) {
- $this->update($headers);
- }
- public function __toString() {
- return implode('', $this->headers);
- }
- public function __clone() {
- //
- }
- public function set($name, $value) {
- $name = strtolower($name);
- if (isset($this->headers[$name]))
- $this->headers[] = new HttpHeader($name, $value);
- // возвращаем установленное значение
- return $value;
- }
- public function update($data) {
- foreach ($data as $name => $value) {
- $this->set($name, $value);
- }
- }
- public function get($name, $default = null) {
- $name = strtolower($name);
- return isset($this->headers[$name]) ? $this->headers[$name]->getValue() : $default;
- }
- /**
- * Возвращает оригинальное имя заголовка.
- */
- public function getOriginalName($name) {
- $name = strtolower($name);
- if (isset($this->headers[$name])) {
- return $this->headers[$name]->getName();
- }
- }
- public function has($name) {
- return isset($this->headers[strtolower($name)]);
- }
- public function remove($name) {
- unset($this->headers[strtolower($name)]);
- }
- public function toArray() {
- $headers = array();
- foreach ($this->headers as $header) {
- $headers[$header->getName()] = $header->getValue();
- }
- return $headers;
- }
- public static function parse($str) {
- // new self будет создавать экземпляр класса, где был объявлен метод
- $headers = new static;
- $length = strlen($str);
- if ($length) {
- if (substr($str, -2) != "\r\n") {
- throw new Exception('Header should end with CRLF');
- }
- // Значения заголовков могут располагаться на нескольких строках, если
- // перед значением следуют CRLF и хотя бы один пробел или таб (LWS):
- //
- // Header: value,
- // value2
- //
- // RFC советует заменять LWS на одиночный пробел:
- //
- // Header: value, value2
- //
- $str = preg_replace('/\r\n[ \t]+/', ' ', $str);
- $lines = explode("\r\n", $str);
- $limit = count($lines) - 1;
- for ($i = 0; $i < $limit; ++$i) {
- $parts = explode(':', $lines[$i], 2);
- if (count($parts) < 2) {
- throw new Exception('Header without colon');
- }
- list($name, $value) = $parts;
- $value = trim($value);
- if (isset($headers[$name])) {
- // по rfc заголовки со одинаковыми либо различающимися лишь регистром
- // именами могут быть объеденены в одно. Их значения должны быть
- // добавлены к значениям первого поля и разделены запятыми.
- //
- // Cache-Control: no-cache
- // cache-control: no-store
- //
- // Cache-Control: no-cache, no-store
- // cache-control: no-cache, no-store
- // $headers[$name] .= ', ' . $value;
- // используем первое объявленное имя заголовка
- $headers[$headers->getOriginalName($name)] .= ', ' . $value;
- } else {
- $headers[$name] = $value;
- }
- }
- }
- return $headers;
- }
- public function offsetSet($offset, $value) {
- return $this->set($offset, $value);
- }
- public function offsetExists($offset) {
- return $this->has($offset);
- }
- public function offsetUnset($offset) {
- $this->remove($offset);
- }
- public function offsetGet($offset) {
- return $this->get($offset);
- }
- public function count() {
- return count($this->headers);
- }
- public function getIterator() {
- return new ArrayIterator($this->toArray());
- }
- }
- $allowedSchemes = array(
- 'http',
- 'https',
- );
- $defaultPorts = array(
- 'http' => 80,
- 'https' => 443
- );
- $headers = new HttpHeaders(
- array(
- 'User-Agent' => 'Mozilla/5.0',
- 'Connection' => 'keep-alive',
- 'Accept-Encoding' => 'gzip, deflate',
- 'Accept' => '*/*',
- )
- );
- $method = 'GET';
- $url = 'HTTP://foo@google.com/?q=foo';
- $timeout = 0.1;
- $data = '';
- // scheme, user*, pass*, host, port*, path*, query*
- // * - необязательные элементы
- $url_parts = parse_url($url);
- var_export($url_parts);
- $scheme = strtolower($url_parts['scheme']);
- if (!in_array($scheme, $allowedSchemes)) {
- throw new Exception("Unsupported scheme: $scheme");
- }
- $hostname = $host = $url_parts['host'];
- // может содержать порт, если он не является портом по-умолчанию
- if (isset($url_parts['port'])) {
- $port = $url_parts['port'];
- if (!in_array($port, $defaultPorts)) {
- $host .= ':' . $port;
- }
- } else {
- $port = $defaultPorts[$scheme];
- }
- $abs_path = isset($url_parts['path']) ? $url_parts['path'] : '/';
- if (isset($url_parts['query'])) {
- $abs_path .= '?' . $url_parts['query'];
- }
- $request_headers = clone $headers;
- $request_headers['Host'] = $host;
- // if (isset($url_parts['user'])) {
- // $username = $url_parts['user'];
- // $password = isset($url_parts['pass']) ? $url_parts['pass'] : '';
- // $request_headers['Authorization'] = 'Basic ' . base64_encode($username . ':' . $password);
- // }
- $content_length = strlen($data);
- if ($content_length) {
- $request_headers['Content-Length'] = $content_length;
- }
- $fp = @pfsockopen($scheme == 'https' ? 'ssl://' . $hostname : $hostname, $port, $errno, $errstr, $timeout);
- if (!$fp) {
- // на винде не робит
- throw new Exception("Socket error: $errstr ($errno)");
- }
- $out = "$method $abs_path HTTP/1.1\r\n";
- $out .= $request_headers;
- $out .= "\r\n";
- $out .= $data;
- if (fwrite($fp, $out) === false) {
- throw new Exception('Cannot write to socket');
- }
- $status_line = fgets($fp, 4096);
- // HTTP-version is case-sensitive.
- if (!preg_match('/^HTTP\/(\d\.\d) ([1-9]\d\d) (.*)/', $status_line, $matches)) {
- throw new Exception('Invalid status line');
- }
- list( , $http_version, $status_code, $reason_phrase) = $matches;
- $header_str = '';
- while (!feof($fp)) {
- $line = fgets($fp, 4096);
- if ($line == "\r\n") {
- break;
- }
- $header_str .= $line;
- }
- $response_headers = HttpHeaders::parse($header_str);
- var_export($response_headers->toArray());
- $h = HttpHeaders::parse("Set-Cookie: foo=bar\r\nset-cookie: x=42\r\n");
- $h2 = clone $h;
- $h['Foo'] = 'Bar';
- $h2['Set-Cookie'] = 'q';
- print_r($h);
- print_r($h2);
- // http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p2-semantics-17.html#rfc.section.9.5
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement