Header.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <?php
  2. declare(strict_types=1);
  3. namespace GuzzleHttp\Psr7;
  4. final class Header
  5. {
  6. /**
  7. * Parse an array of header values containing ";" separated data into an
  8. * array of associative arrays representing the header key value pair data
  9. * of the header. When a parameter does not contain a value, but just
  10. * contains a key, this function will inject a key with a '' string value.
  11. *
  12. * @param string|array $header Header to parse into components.
  13. */
  14. public static function parse($header): array
  15. {
  16. static $trimmed = "\"' \n\t\r";
  17. $params = $matches = [];
  18. foreach ((array) $header as $value) {
  19. foreach (self::splitList($value) as $val) {
  20. $part = [];
  21. foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
  22. if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) {
  23. $m = $matches[0];
  24. if (isset($m[1])) {
  25. $part[trim($m[0], $trimmed)] = trim($m[1], $trimmed);
  26. } else {
  27. $part[] = trim($m[0], $trimmed);
  28. }
  29. }
  30. }
  31. if ($part) {
  32. $params[] = $part;
  33. }
  34. }
  35. }
  36. return $params;
  37. }
  38. /**
  39. * Converts an array of header values that may contain comma separated
  40. * headers into an array of headers with no comma separated values.
  41. *
  42. * @param string|array $header Header to normalize.
  43. *
  44. * @deprecated Use self::splitList() instead.
  45. */
  46. public static function normalize($header): array
  47. {
  48. $result = [];
  49. foreach ((array) $header as $value) {
  50. foreach (self::splitList($value) as $parsed) {
  51. $result[] = $parsed;
  52. }
  53. }
  54. return $result;
  55. }
  56. /**
  57. * Splits a HTTP header defined to contain a comma-separated list into
  58. * each individual value. Empty values will be removed.
  59. *
  60. * Example headers include 'accept', 'cache-control' and 'if-none-match'.
  61. *
  62. * This method must not be used to parse headers that are not defined as
  63. * a list, such as 'user-agent' or 'set-cookie'.
  64. *
  65. * @param string|string[] $values Header value as returned by MessageInterface::getHeader()
  66. *
  67. * @return string[]
  68. */
  69. public static function splitList($values): array
  70. {
  71. if (!\is_array($values)) {
  72. $values = [$values];
  73. }
  74. $result = [];
  75. foreach ($values as $value) {
  76. if (!\is_string($value)) {
  77. throw new \TypeError('$header must either be a string or an array containing strings.');
  78. }
  79. $v = '';
  80. $isQuoted = false;
  81. $isEscaped = false;
  82. for ($i = 0, $max = \strlen($value); $i < $max; $i++) {
  83. if ($isEscaped) {
  84. $v .= $value[$i];
  85. $isEscaped = false;
  86. continue;
  87. }
  88. if (!$isQuoted && $value[$i] === ',') {
  89. $v = \trim($v);
  90. if ($v !== '') {
  91. $result[] = $v;
  92. }
  93. $v = '';
  94. continue;
  95. }
  96. if ($isQuoted && $value[$i] === '\\') {
  97. $isEscaped = true;
  98. $v .= $value[$i];
  99. continue;
  100. }
  101. if ($value[$i] === '"') {
  102. $isQuoted = !$isQuoted;
  103. $v .= $value[$i];
  104. continue;
  105. }
  106. $v .= $value[$i];
  107. }
  108. $v = \trim($v);
  109. if ($v !== '') {
  110. $result[] = $v;
  111. }
  112. }
  113. return $result;
  114. }
  115. }