Advertisement
Guest User

Untitled

a guest
Sep 20th, 2016
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 9.04 KB | None | 0 0
  1. <?php
  2.  
  3.  
  4. function dump($v) {
  5.   echo('<pre>' . var_export($v, true) . '</pre>');
  6. }
  7.  
  8.  
  9. // header("http/1.0              404                \t\t\tNot Found\t");
  10. header("Content-Type:\t \t  text/plain;charset   \t\t\t\t= \"utf-8\" foo, bar");
  11. header('cache-control: no-cache');
  12. header('Cache-control: no-store'); // cache-control: no-store
  13. echo("Тест\n");
  14.  
  15. preg_match('~;\s*charset\s*=\s*(?:"([^"]+)"|([^\s;]+))~i', "text/html;  charset\t=   utf-8\t\"q;", $matches);
  16. // var_dump($matches);
  17. // echo('charset: ' . (count($matches) ? (isset($matches[2]) ? $matches[2] : $matches[1]) : ''));
  18. // echo('\\\t\'\0 ');
  19.  
  20.  
  21. preg_match_all('/[\x00-\xff]/', 'тест', $m);
  22. // var_dump($m);
  23.  
  24. $headers = "HTTP/1.1 200\r\n" .
  25.            "Content-Type:" .
  26.            "\r\n\ttext/html;" .
  27.            "\r\n\t charset=utf-8";
  28.  
  29. // echo("Headers:\n");
  30. // echo(preg_replace('/\r\n[ \t]+/', ' ', $headers));
  31.  
  32. error_reporting(E_ALL);
  33. echo("<===================================================================>\n");
  34.  
  35. // list($a, $b) = explode(':', '');
  36.  
  37. // die;
  38.  
  39.  
  40. class HttpHeader {
  41.   protected $name;
  42.   protected $value;
  43.  
  44.   public function __construct($name, $value) {
  45.     $this->setName($name);
  46.     $this->setValue($value);
  47.   }
  48.  
  49.   public function getName() {
  50.     return $this->name;
  51.   }
  52.  
  53.   public function getValue() {
  54.     return $this->value;
  55.   }
  56.  
  57.   public function setName($name) {
  58.     // тут валидация
  59.     $this->name = $name;
  60.   }
  61.  
  62.   public function setValue($value) {
  63.     // тут валидация
  64.     $this->value = $value;
  65.   }
  66.  
  67.   public function __toString() {
  68.     return $this->name . ': ' . $this->value . "\r\n";
  69.   }
  70. }
  71.  
  72.  
  73. /**
  74.   * Класс для работы с http-заголовками.
  75.   *
  76.   * Имена полей регистронезависимы. Значения полей можно получить, обращаясь к
  77.   * объекту как к массиву. К объекту применимы вызовы функций count, isset и
  78.   * unset, а так же возможен по нему обход с помощью цикла foreach.
  79.   */
  80. class HttpHeaders implements ArrayAccess, Countable, IteratorAggregate {
  81.   protected $headers = array();
  82.  
  83.   public function __construct($headers = array()) {
  84.     $this->update($headers);
  85.   }
  86.  
  87.   public function __toString() {
  88.     return implode('', $this->headers);
  89.   }
  90.  
  91.   public function __clone() {
  92.     //
  93.   }
  94.  
  95.   public function set($name, $value) {
  96.     $name = strtolower($name);
  97.  
  98.     if (isset($this->headers[$name]))
  99.     $this->headers[] = new HttpHeader($name, $value);
  100.     // возвращаем установленное значение
  101.     return $value;
  102.   }
  103.  
  104.   public function update($data) {
  105.     foreach ($data as $name => $value) {
  106.       $this->set($name, $value);
  107.     }
  108.   }
  109.  
  110.   public function get($name, $default = null) {
  111.     $name = strtolower($name);
  112.     return isset($this->headers[$name]) ? $this->headers[$name]->getValue() : $default;
  113.   }
  114.  
  115.   /**
  116.     * Возвращает оригинальное имя заголовка.
  117.     */
  118.   public function getOriginalName($name) {
  119.     $name = strtolower($name);
  120.  
  121.     if (isset($this->headers[$name])) {
  122.       return $this->headers[$name]->getName();
  123.     }
  124.   }
  125.  
  126.   public function has($name) {
  127.     return isset($this->headers[strtolower($name)]);
  128.   }
  129.  
  130.   public function remove($name) {
  131.     unset($this->headers[strtolower($name)]);
  132.   }
  133.  
  134.   public function toArray() {
  135.     $headers = array();
  136.  
  137.     foreach ($this->headers as $header) {
  138.       $headers[$header->getName()] = $header->getValue();
  139.     }
  140.  
  141.     return $headers;
  142.   }
  143.  
  144.   public static function parse($str) {
  145.     // new self будет создавать экземпляр класса, где был объявлен метод
  146.     $headers = new static;
  147.     $length = strlen($str);
  148.  
  149.     if ($length) {
  150.       if (substr($str, -2) != "\r\n") {
  151.         throw new Exception('Header should end with CRLF');
  152.       }
  153.  
  154.       // Значения заголовков могут располагаться на нескольких строках, если
  155.       // перед значением следуют CRLF и хотя бы один пробел или таб (LWS):
  156.       //
  157.       // Header: value,
  158.       //         value2
  159.       //
  160.       // RFC советует заменять LWS на одиночный пробел:
  161.       //
  162.       // Header: value, value2
  163.       //
  164.       $str = preg_replace('/\r\n[ \t]+/', ' ', $str);
  165.       $lines = explode("\r\n", $str);
  166.       $limit = count($lines) - 1;
  167.  
  168.       for ($i = 0; $i < $limit; ++$i) {
  169.         $parts = explode(':', $lines[$i], 2);
  170.  
  171.         if (count($parts) < 2) {
  172.           throw new Exception('Header without colon');
  173.         }
  174.  
  175.         list($name, $value) = $parts;
  176.         $value = trim($value);
  177.        
  178.         if (isset($headers[$name])) {
  179.           // по rfc заголовки со одинаковыми либо различающимися лишь регистром
  180.           // именами могут быть объеденены в одно. Их значения должны быть
  181.           // добавлены к значениям первого поля и разделены запятыми.
  182.           //
  183.           // Cache-Control: no-cache
  184.           // cache-control: no-store
  185.           //
  186.           // Cache-Control: no-cache, no-store
  187.  
  188.           // cache-control: no-cache, no-store
  189.           // $headers[$name] .= ', ' . $value;
  190.  
  191.           // используем первое объявленное имя заголовка
  192.           $headers[$headers->getOriginalName($name)] .= ', ' . $value;
  193.         } else {
  194.           $headers[$name] = $value;
  195.         }
  196.       }
  197.     }
  198.  
  199.     return $headers;
  200.   }
  201.  
  202.   public function offsetSet($offset, $value) {
  203.     return $this->set($offset, $value);
  204.   }
  205.  
  206.   public function offsetExists($offset) {
  207.     return $this->has($offset);
  208.   }
  209.  
  210.   public function offsetUnset($offset) {
  211.     $this->remove($offset);
  212.   }
  213.  
  214.   public function offsetGet($offset) {
  215.     return $this->get($offset);
  216.   }
  217.  
  218.   public function count() {
  219.     return count($this->headers);
  220.   }
  221.  
  222.   public function getIterator() {
  223.     return new ArrayIterator($this->toArray());
  224.   }
  225. }
  226.  
  227.  
  228. $allowedSchemes = array(
  229.   'http',
  230.   'https',
  231. );
  232.  
  233. $defaultPorts = array(
  234.   'http' => 80,
  235.   'https' => 443
  236. );
  237.  
  238. $headers = new HttpHeaders(
  239.   array(
  240.     'User-Agent' => 'Mozilla/5.0',
  241.     'Connection' => 'keep-alive',
  242.     'Accept-Encoding' => 'gzip, deflate',
  243.     'Accept' => '*/*',
  244.   )
  245. );
  246.  
  247. $method = 'GET';
  248. $url = 'HTTP://foo@google.com/?q=foo';
  249. $timeout = 0.1;
  250. $data = '';
  251. // scheme, user*, pass*, host, port*, path*, query*
  252. // * - необязательные элементы
  253. $url_parts = parse_url($url);
  254. var_export($url_parts);
  255. $scheme = strtolower($url_parts['scheme']);
  256.  
  257. if (!in_array($scheme, $allowedSchemes)) {
  258.   throw new Exception("Unsupported scheme: $scheme");
  259. }
  260.  
  261. $hostname = $host = $url_parts['host'];
  262.  
  263. // может содержать порт, если он не является портом по-умолчанию
  264. if (isset($url_parts['port'])) {
  265.   $port = $url_parts['port'];
  266.  
  267.   if (!in_array($port, $defaultPorts)) {
  268.     $host .= ':' . $port;
  269.   }
  270. } else {
  271.   $port = $defaultPorts[$scheme];
  272. }
  273.  
  274. $abs_path = isset($url_parts['path']) ? $url_parts['path'] : '/';
  275.  
  276. if (isset($url_parts['query'])) {
  277.   $abs_path .= '?' . $url_parts['query'];
  278. }
  279.  
  280. $request_headers = clone $headers;
  281. $request_headers['Host'] = $host;
  282.  
  283. // if (isset($url_parts['user'])) {
  284. //   $username = $url_parts['user'];
  285. //   $password = isset($url_parts['pass']) ? $url_parts['pass'] : '';
  286. //   $request_headers['Authorization'] = 'Basic ' . base64_encode($username . ':' . $password);
  287. // }
  288.  
  289. $content_length = strlen($data);
  290.  
  291. if ($content_length) {
  292.   $request_headers['Content-Length'] = $content_length;
  293. }
  294.  
  295. $fp = @pfsockopen($scheme == 'https' ? 'ssl://' . $hostname : $hostname, $port, $errno, $errstr, $timeout);
  296.  
  297. if (!$fp) {
  298.   // на винде не робит
  299.   throw new Exception("Socket error: $errstr ($errno)");
  300. }
  301.  
  302. $out = "$method $abs_path HTTP/1.1\r\n";
  303. $out .= $request_headers;
  304. $out .= "\r\n";
  305. $out .= $data;
  306.  
  307. if (fwrite($fp, $out) === false) {
  308.   throw new Exception('Cannot write to socket');
  309. }
  310.  
  311. $status_line = fgets($fp, 4096);
  312.  
  313. // HTTP-version is case-sensitive.
  314. if (!preg_match('/^HTTP\/(\d\.\d) ([1-9]\d\d) (.*)/', $status_line, $matches)) {
  315.   throw new Exception('Invalid status line');
  316. }
  317.  
  318. list( , $http_version, $status_code, $reason_phrase) = $matches;
  319.  
  320. $header_str = '';
  321.  
  322. while (!feof($fp)) {
  323.   $line = fgets($fp, 4096);
  324.  
  325.   if ($line == "\r\n") {
  326.     break;
  327.   }
  328.  
  329.   $header_str .= $line;
  330. }
  331.  
  332. $response_headers = HttpHeaders::parse($header_str);
  333. var_export($response_headers->toArray());
  334.  
  335. $h = HttpHeaders::parse("Set-Cookie: foo=bar\r\nset-cookie: x=42\r\n");
  336. $h2 = clone $h;
  337. $h['Foo'] = 'Bar';
  338. $h2['Set-Cookie'] = 'q';
  339. print_r($h);
  340. print_r($h2);
  341.  
  342.  
  343. // 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