PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.6
Booking for Appointments and Events Calendar – Amelia v2.4.6
2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / vendor / slim / psr7 / src / Headers.php
ameliabooking / vendor / slim / psr7 / src Last commit date
Factory 2 months ago Interfaces 2 months ago Cookies.php 2 months ago Environment.php 2 months ago Header.php 2 months ago Headers.php 2 months ago Message.php 2 months ago NonBufferedBody.php 2 months ago Request.php 2 months ago Response.php 2 months ago Stream.php 2 months ago UploadedFile.php 2 months ago Uri.php 2 months ago
Headers.php
319 lines
1 <?php
2
3 /**
4 * Slim Framework (https://slimframework.com)
5 *
6 * @license https://github.com/slimphp/Slim-Psr7/blob/master/LICENSE.md (MIT License)
7 */
8
9 declare(strict_types=1);
10
11 namespace Slim\Psr7;
12
13 use InvalidArgumentException;
14 use Slim\Psr7\Interfaces\HeadersInterface;
15
16 use function base64_encode;
17 use function function_exists;
18 use function getallheaders;
19 use function is_array;
20 use function is_numeric;
21 use function is_string;
22 use function preg_match;
23 use function strpos;
24 use function strtolower;
25 use function strtr;
26 use function substr;
27 use function trim;
28
29 class Headers implements HeadersInterface
30 {
31 protected array $globals;
32
33 /**
34 * @var Header[]
35 */
36 protected array $headers;
37
38 /**
39 * @param array $headers
40 * @param array|null $globals
41 */
42 final public function __construct(array $headers = [], ?array $globals = null)
43 {
44 $this->globals = $globals ?? $_SERVER;
45 $this->setHeaders($headers);
46 }
47
48 /**
49 * {@inheritdoc}
50 */
51 public function addHeader($name, $value): HeadersInterface
52 {
53 [$values, $originalName, $normalizedName] = $this->prepareHeader($name, $value);
54
55 if (isset($this->headers[$normalizedName])) {
56 $header = $this->headers[$normalizedName];
57 $header->addValues($values);
58 } else {
59 $this->headers[$normalizedName] = new Header($originalName, $normalizedName, $values);
60 }
61
62 return $this;
63 }
64
65 /**
66 * {@inheritdoc}
67 */
68 public function removeHeader(string $name): HeadersInterface
69 {
70 $name = $this->normalizeHeaderName($name);
71 unset($this->headers[$name]);
72 return $this;
73 }
74
75 /**
76 * {@inheritdoc}
77 */
78 public function getHeader(string $name, $default = []): array
79 {
80 $name = $this->normalizeHeaderName($name);
81
82 if (isset($this->headers[$name])) {
83 $header = $this->headers[$name];
84 return $header->getValues();
85 }
86
87 if (empty($default)) {
88 return $default;
89 }
90
91 $this->validateHeader($name, $default);
92 return $this->trimHeaderValue($default);
93 }
94
95 /**
96 * {@inheritdoc}
97 */
98 public function setHeader($name, $value): HeadersInterface
99 {
100 [$values, $originalName, $normalizedName] = $this->prepareHeader($name, $value);
101
102 // Ensure we preserve original case if the header already exists in the stack
103 if (isset($this->headers[$normalizedName])) {
104 $existingHeader = $this->headers[$normalizedName];
105 $originalName = $existingHeader->getOriginalName();
106 }
107
108 $this->headers[$normalizedName] = new Header($originalName, $normalizedName, $values);
109
110 return $this;
111 }
112
113 /**
114 * {@inheritdoc}
115 */
116 public function setHeaders(array $headers): HeadersInterface
117 {
118 $this->headers = [];
119
120 foreach ($this->parseAuthorizationHeader($headers) as $name => $value) {
121 $this->addHeader($name, $value);
122 }
123
124 return $this;
125 }
126
127 /**
128 * {@inheritdoc}
129 */
130 public function hasHeader(string $name): bool
131 {
132 $name = $this->normalizeHeaderName($name);
133 return isset($this->headers[$name]);
134 }
135
136 /**
137 * {@inheritdoc}
138 */
139 public function getHeaders(bool $originalCase = false): array
140 {
141 $headers = [];
142
143 foreach ($this->headers as $header) {
144 $name = $originalCase ? $header->getOriginalName() : $header->getNormalizedName();
145 $headers[$name] = $header->getValues();
146 }
147
148 return $headers;
149 }
150
151 /**
152 * @param string $name
153 * @param bool $preserveCase
154 * @return string
155 */
156 protected function normalizeHeaderName(string $name, bool $preserveCase = false): string
157 {
158 $name = strtr($name, '_', '-');
159
160 if (!$preserveCase) {
161 $name = strtolower($name);
162 }
163
164 if (strpos(strtolower($name), 'http-') === 0) {
165 $name = substr($name, 5);
166 }
167
168 return $name;
169 }
170
171 /**
172 * Parse incoming headers and determine Authorization header from original headers
173 *
174 * @param array $headers
175 * @return array
176 */
177 protected function parseAuthorizationHeader(array $headers): array
178 {
179 $hasAuthorizationHeader = false;
180 foreach ($headers as $name => $value) {
181 if (strtolower((string) $name) === 'authorization') {
182 $hasAuthorizationHeader = true;
183 break;
184 }
185 }
186
187 if (!$hasAuthorizationHeader) {
188 if (isset($this->globals['REDIRECT_HTTP_AUTHORIZATION'])) {
189 $headers['Authorization'] = $this->globals['REDIRECT_HTTP_AUTHORIZATION'];
190 } elseif (isset($this->globals['PHP_AUTH_USER'])) {
191 $pw = $this->globals['PHP_AUTH_PW'] ?? '';
192 $headers['Authorization'] = 'Basic ' . base64_encode($this->globals['PHP_AUTH_USER'] . ':' . $pw);
193 } elseif (isset($this->globals['PHP_AUTH_DIGEST'])) {
194 $headers['Authorization'] = $this->globals['PHP_AUTH_DIGEST'];
195 }
196 }
197
198 return $headers;
199 }
200
201 /**
202 * @param array|string $value
203 *
204 * @return array
205 */
206 protected function trimHeaderValue($value): array
207 {
208 $items = is_array($value) ? $value : [$value];
209 $result = [];
210 foreach ($items as $item) {
211 $result[] = trim((string) $item, " \t");
212 }
213 return $result;
214 }
215
216 /**
217 * @param string $name
218 * @param array|string $value
219 *
220 * @throws InvalidArgumentException
221 *
222 * @return array
223 */
224 protected function prepareHeader($name, $value): array
225 {
226 $this->validateHeader($name, $value);
227 $values = $this->trimHeaderValue($value);
228 $originalName = $this->normalizeHeaderName($name, true);
229 $normalizedName = $this->normalizeHeaderName($name);
230 return [$values, $originalName, $normalizedName];
231 }
232
233 /**
234 * Make sure the header complies with RFC 7230.
235 *
236 * Header names must be a non-empty string consisting of token characters.
237 *
238 * Header values must be strings consisting of visible characters with all optional
239 * leading and trailing whitespace stripped. This method will always strip such
240 * optional whitespace. Note that the method does not allow folding whitespace within
241 * the values as this was deprecated for almost all instances by the RFC.
242 *
243 * header-field = field-name ":" OWS field-value OWS
244 * field-name = 1*( "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^"
245 * / "_" / "`" / "|" / "~" / %x30-39 / ( %x41-5A / %x61-7A ) )
246 * OWS = *( SP / HTAB )
247 * field-value = *( ( %x21-7E / %x80-FF ) [ 1*( SP / HTAB ) ( %x21-7E / %x80-FF ) ] )
248 *
249 * @see https://tools.ietf.org/html/rfc7230#section-3.2.4
250 *
251 * @param string $name
252 * @param array|string $value
253 *
254 * @throws InvalidArgumentException;
255 */
256 protected function validateHeader($name, $value): void
257 {
258 $this->validateHeaderName($name);
259 $this->validateHeaderValue($value);
260 }
261
262 /**
263 * @param mixed $name
264 *
265 * @throws InvalidArgumentException
266 */
267 protected function validateHeaderName($name): void
268 {
269 if (!is_string($name) || preg_match("@^[!#$%&'*+.^_`|~0-9A-Za-z-]+$@D", $name) !== 1) {
270 throw new InvalidArgumentException('Header name must be an RFC 7230 compatible string.');
271 }
272 }
273
274 /**
275 * @param mixed $value
276 *
277 * @throws InvalidArgumentException
278 */
279 protected function validateHeaderValue($value): void
280 {
281 $items = is_array($value) ? $value : [$value];
282
283 if (empty($items)) {
284 throw new InvalidArgumentException(
285 'Header values must be a string or an array of strings, empty array given.'
286 );
287 }
288
289 $pattern = "@^[ \t\x21-\x7E\x80-\xFF]*$@D";
290 foreach ($items as $item) {
291 $hasInvalidType = !is_numeric($item) && !is_string($item);
292 $rejected = $hasInvalidType || preg_match($pattern, (string) $item) !== 1;
293 if ($rejected) {
294 throw new InvalidArgumentException(
295 'Header values must be RFC 7230 compatible strings.'
296 );
297 }
298 }
299 }
300
301 /**
302 * @return static
303 */
304 public static function createFromGlobals()
305 {
306 $headers = null;
307
308 if (function_exists('getallheaders')) {
309 $headers = getallheaders();
310 }
311
312 if (!is_array($headers)) {
313 $headers = [];
314 }
315
316 return new static($headers);
317 }
318 }
319