PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.2.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.2.0
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / vendor / prefixed / symfony / http-foundation / HeaderUtils.php
matomo / app / vendor / prefixed / symfony / http-foundation Last commit date
Exception 2 years ago File 1 year ago RateLimiter 2 years ago Session 1 year ago Test 1 year ago AcceptHeader.php 1 year ago AcceptHeaderItem.php 2 years ago BinaryFileResponse.php 1 year ago Cookie.php 1 year ago ExpressionRequestMatcher.php 2 years ago FileBag.php 1 year ago HeaderBag.php 1 year ago HeaderUtils.php 1 year ago InputBag.php 2 years ago IpUtils.php 1 year ago JsonResponse.php 1 year ago LICENSE 2 years ago ParameterBag.php 1 year ago README.md 2 years ago RedirectResponse.php 2 years ago Request.php 1 year ago RequestMatcher.php 1 year ago RequestMatcherInterface.php 2 years ago RequestStack.php 2 years ago Response.php 1 year ago ResponseHeaderBag.php 1 year ago ServerBag.php 1 year ago StreamedResponse.php 1 year ago UrlHelper.php 2 years ago
HeaderUtils.php
258 lines
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11 namespace Matomo\Dependencies\Symfony\Component\HttpFoundation;
12
13 /**
14 * HTTP header utility functions.
15 *
16 * @author Christian Schmidt <github@chsc.dk>
17 */
18 class HeaderUtils
19 {
20 public const DISPOSITION_ATTACHMENT = 'attachment';
21 public const DISPOSITION_INLINE = 'inline';
22 /**
23 * This class should not be instantiated.
24 */
25 private function __construct()
26 {
27 }
28 /**
29 * Splits an HTTP header by one or more separators.
30 *
31 * Example:
32 *
33 * HeaderUtils::split('da, en-gb;q=0.8', ',;')
34 * // => ['da'], ['en-gb', 'q=0.8']]
35 *
36 * @param string $separators List of characters to split on, ordered by
37 * precedence, e.g. ',', ';=', or ',;='
38 *
39 * @return array Nested array with as many levels as there are characters in
40 * $separators
41 */
42 public static function split(string $header, string $separators) : array
43 {
44 if ('' === $separators) {
45 throw new \InvalidArgumentException('At least one separator must be specified.');
46 }
47 $quotedSeparators = preg_quote($separators, '/');
48 preg_match_all('
49 /
50 (?!\\s)
51 (?:
52 # quoted-string
53 "(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$)
54 |
55 # token
56 [^"' . $quotedSeparators . ']+
57 )+
58 (?<!\\s)
59 |
60 # separator
61 \\s*
62 (?<separator>[' . $quotedSeparators . '])
63 \\s*
64 /x', trim($header), $matches, \PREG_SET_ORDER);
65 return self::groupParts($matches, $separators);
66 }
67 /**
68 * Combines an array of arrays into one associative array.
69 *
70 * Each of the nested arrays should have one or two elements. The first
71 * value will be used as the keys in the associative array, and the second
72 * will be used as the values, or true if the nested array only contains one
73 * element. Array keys are lowercased.
74 *
75 * Example:
76 *
77 * HeaderUtils::combine([['foo', 'abc'], ['bar']])
78 * // => ['foo' => 'abc', 'bar' => true]
79 */
80 public static function combine(array $parts) : array
81 {
82 $assoc = [];
83 foreach ($parts as $part) {
84 $name = strtolower($part[0]);
85 $value = $part[1] ?? \true;
86 $assoc[$name] = $value;
87 }
88 return $assoc;
89 }
90 /**
91 * Joins an associative array into a string for use in an HTTP header.
92 *
93 * The key and value of each entry are joined with '=', and all entries
94 * are joined with the specified separator and an additional space (for
95 * readability). Values are quoted if necessary.
96 *
97 * Example:
98 *
99 * HeaderUtils::toString(['foo' => 'abc', 'bar' => true, 'baz' => 'a b c'], ',')
100 * // => 'foo=abc, bar, baz="a b c"'
101 */
102 public static function toString(array $assoc, string $separator) : string
103 {
104 $parts = [];
105 foreach ($assoc as $name => $value) {
106 if (\true === $value) {
107 $parts[] = $name;
108 } else {
109 $parts[] = $name . '=' . self::quote($value);
110 }
111 }
112 return implode($separator . ' ', $parts);
113 }
114 /**
115 * Encodes a string as a quoted string, if necessary.
116 *
117 * If a string contains characters not allowed by the "token" construct in
118 * the HTTP specification, it is backslash-escaped and enclosed in quotes
119 * to match the "quoted-string" construct.
120 */
121 public static function quote(string $s) : string
122 {
123 if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) {
124 return $s;
125 }
126 return '"' . addcslashes($s, '"\\"') . '"';
127 }
128 /**
129 * Decodes a quoted string.
130 *
131 * If passed an unquoted string that matches the "token" construct (as
132 * defined in the HTTP specification), it is passed through verbatim.
133 */
134 public static function unquote(string $s) : string
135 {
136 return preg_replace('/\\\\(.)|"/', '$1', $s);
137 }
138 /**
139 * Generates an HTTP Content-Disposition field-value.
140 *
141 * @param string $disposition One of "inline" or "attachment"
142 * @param string $filename A unicode string
143 * @param string $filenameFallback A string containing only ASCII characters that
144 * is semantically equivalent to $filename. If the filename is already ASCII,
145 * it can be omitted, or just copied from $filename
146 *
147 * @throws \InvalidArgumentException
148 *
149 * @see RFC 6266
150 */
151 public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = '') : string
152 {
153 if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) {
154 throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
155 }
156 if ('' === $filenameFallback) {
157 $filenameFallback = $filename;
158 }
159 // filenameFallback is not ASCII.
160 if (!preg_match('/^[\\x20-\\x7e]*$/', $filenameFallback)) {
161 throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
162 }
163 // percent characters aren't safe in fallback.
164 if (str_contains($filenameFallback, '%')) {
165 throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
166 }
167 // path separators aren't allowed in either.
168 if (str_contains($filename, '/') || str_contains($filename, '\\') || str_contains($filenameFallback, '/') || str_contains($filenameFallback, '\\')) {
169 throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
170 }
171 $params = ['filename' => $filenameFallback];
172 if ($filename !== $filenameFallback) {
173 $params['filename*'] = "utf-8''" . rawurlencode($filename);
174 }
175 return $disposition . '; ' . self::toString($params, ';');
176 }
177 /**
178 * Like parse_str(), but preserves dots in variable names.
179 */
180 public static function parseQuery(string $query, bool $ignoreBrackets = \false, string $separator = '&') : array
181 {
182 $q = [];
183 foreach (explode($separator, $query) as $v) {
184 if (\false !== ($i = strpos($v, "\x00"))) {
185 $v = substr($v, 0, $i);
186 }
187 if (\false === ($i = strpos($v, '='))) {
188 $k = urldecode($v);
189 $v = '';
190 } else {
191 $k = urldecode(substr($v, 0, $i));
192 $v = substr($v, $i);
193 }
194 if (\false !== ($i = strpos($k, "\x00"))) {
195 $k = substr($k, 0, $i);
196 }
197 $k = ltrim($k, ' ');
198 if ($ignoreBrackets) {
199 $q[$k][] = urldecode(substr($v, 1));
200 continue;
201 }
202 if (\false === ($i = strpos($k, '['))) {
203 $q[] = bin2hex($k) . $v;
204 } else {
205 $q[] = bin2hex(substr($k, 0, $i)) . rawurlencode(substr($k, $i)) . $v;
206 }
207 }
208 if ($ignoreBrackets) {
209 return $q;
210 }
211 parse_str(implode('&', $q), $q);
212 $query = [];
213 foreach ($q as $k => $v) {
214 if (\false !== ($i = strpos($k, '_'))) {
215 $query[substr_replace($k, hex2bin(substr($k, 0, $i)) . '[', 0, 1 + $i)] = $v;
216 } else {
217 $query[hex2bin($k)] = $v;
218 }
219 }
220 return $query;
221 }
222 private static function groupParts(array $matches, string $separators, bool $first = \true) : array
223 {
224 $separator = $separators[0];
225 $separators = substr($separators, 1) ?: '';
226 $i = 0;
227 if ('' === $separators && !$first) {
228 $parts = [''];
229 foreach ($matches as $match) {
230 if (!$i && isset($match['separator'])) {
231 $i = 1;
232 $parts[1] = '';
233 } else {
234 $parts[$i] .= self::unquote($match[0]);
235 }
236 }
237 return $parts;
238 }
239 $parts = [];
240 $partMatches = [];
241 foreach ($matches as $match) {
242 if (($match['separator'] ?? null) === $separator) {
243 ++$i;
244 } else {
245 $partMatches[$i][] = $match;
246 }
247 }
248 foreach ($partMatches as $matches) {
249 if ('' === $separators && '' !== ($unquoted = self::unquote($matches[0][0]))) {
250 $parts[] = $unquoted;
251 } elseif ($groupedParts = self::groupParts($matches, $separators, \false)) {
252 $parts[] = $groupedParts;
253 }
254 }
255 return $parts;
256 }
257 }
258