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