PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.7
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.7
1.10.20 1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 All 164 releases
woocommerce-pos / vendor_prefixed / guzzlehttp / psr7 / src / ServerRequestGlobalsFactory.php

ServerRequestGlobalsFactory.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.10.7, at vendor_prefixed/guzzlehttp/psr7/src/ServerRequestGlobalsFactory.php

382 lines 15.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare (strict_types=1);
4 namespace WCPOS\Vendor\GuzzleHttp\Psr7;
5
6 use InvalidArgumentException;
7 use WCPOS\Vendor\Psr\Http\Message\ServerRequestInterface;
8 use WCPOS\Vendor\Psr\Http\Message\UriInterface;
9 /**
10 * @internal
11 */
12 final class ServerRequestGlobalsFactory
13 {
14 private function __construct()
15 {
16 }
17 /**
18 * @param array<array-key, mixed> $server Typically the $_SERVER superglobal
19 * @param array<array-key, mixed> $query Typically the $_GET superglobal
20 * @param array<array-key, mixed> $post Typically the $_POST superglobal
21 * @param array<array-key, mixed> $cookies Typically the $_COOKIE superglobal
22 * @param array<array-key, mixed> $files Typically the $_FILES superglobal
23 * @param (callable(): mixed)|null $headerProvider
24 */
25 public static function fromArrays(#[\SensitiveParameter] array $server, array $query, array $post, #[\SensitiveParameter] array $cookies, array $files, ?callable $headerProvider = null) : ServerRequestInterface
26 {
27 $method = self::getRequestMethodFromServer($server);
28 $headers = self::removeInvalidHostHeader(self::getAllHeaders($server, $headerProvider));
29 [$uri, $requestTarget] = self::getUriAndRequestTargetFromServer($server, $method);
30 $body = new CachingStream(new LazyOpenStream('php://input', 'r+'));
31 $serverRequest = new ServerRequest($method, $uri, $headers, $body, self::getProtocolFromServer($server), $server);
32 if ($requestTarget !== null) {
33 /** @var ServerRequestInterface $serverRequest */
34 $serverRequest = $serverRequest->withRequestTarget($requestTarget);
35 }
36 return $serverRequest->withCookieParams($cookies)->withQueryParams($query)->withParsedBody($post)->withUploadedFiles(UploadedFileNormalizer::normalize($files));
37 }
38 /**
39 * @param array<array-key, mixed> $server Typically the $_SERVER superglobal
40 */
41 public static function getUriFromServerParams(#[\SensitiveParameter] array $server) : UriInterface
42 {
43 $method = self::getRequestMethodFromServer($server);
44 return self::getUriAndRequestTargetFromServer($server, $method)[0];
45 }
46 /**
47 * @param array<array-key, mixed> $server
48 * @param (callable(): mixed)|null $headerProvider
49 *
50 * @return array<array-key, string>
51 */
52 private static function getAllHeaders(#[\SensitiveParameter] array $server, ?callable $headerProvider) : array
53 {
54 $headers = $headerProvider !== null ? $headerProvider() : \false;
55 if (!\is_array($headers)) {
56 $headers = self::getHeadersFromServer($server);
57 }
58 return self::normalizeHeaderValues($headers);
59 }
60 /**
61 * @param array<array-key, mixed> $headers
62 *
63 * @return array<array-key, string>
64 */
65 private static function normalizeHeaderValues(#[\SensitiveParameter] array $headers) : array
66 {
67 $normalized = [];
68 foreach ($headers as $name => $value) {
69 if (\is_scalar($value) || \is_object($value) && \method_exists($value, '__toString')) {
70 $normalized[$name] = (string) $value;
71 }
72 }
73 return $normalized;
74 }
75 /**
76 * @param array<array-key, mixed> $server Typically the $_SERVER superglobal
77 *
78 * @return array<array-key, string>
79 */
80 private static function getHeadersFromServer(array $server) : array
81 {
82 $headers = [];
83 $copyServer = ['CONTENT_TYPE' => 'Content-Type', 'CONTENT_LENGTH' => 'Content-Length', 'CONTENT_MD5' => 'Content-Md5'];
84 foreach ($server as $key => $value) {
85 if (!\is_string($key) || !\is_string($value)) {
86 continue;
87 }
88 if (\str_starts_with($key, 'HTTP_')) {
89 $header = \substr($key, 5);
90 if (isset($copyServer[$header], $server[$header]) && \is_string($server[$header])) {
91 continue;
92 }
93 $parts = \explode(' ', Utils::asciiToLower(\str_replace('_', ' ', $header)));
94 foreach ($parts as $i => $part) {
95 $parts[$i] = Utils::asciiUcFirst($part);
96 }
97 $header = \implode('-', $parts);
98 $headers[$header] = $value;
99 continue;
100 }
101 if (isset($copyServer[$key])) {
102 $headers[$copyServer[$key]] = $value;
103 }
104 }
105 if (!isset($headers['Authorization'])) {
106 if (isset($server['REDIRECT_HTTP_AUTHORIZATION']) && \is_string($server['REDIRECT_HTTP_AUTHORIZATION'])) {
107 $headers['Authorization'] = $server['REDIRECT_HTTP_AUTHORIZATION'];
108 } elseif (isset($server['PHP_AUTH_USER']) && \is_string($server['PHP_AUTH_USER'])) {
109 $password = isset($server['PHP_AUTH_PW']) && \is_string($server['PHP_AUTH_PW']) ? $server['PHP_AUTH_PW'] : '';
110 $headers['Authorization'] = 'Basic ' . \base64_encode($server['PHP_AUTH_USER'] . ':' . $password);
111 } elseif (isset($server['PHP_AUTH_DIGEST']) && \is_string($server['PHP_AUTH_DIGEST'])) {
112 $headers['Authorization'] = $server['PHP_AUTH_DIGEST'];
113 }
114 }
115 return $headers;
116 }
117 /**
118 * @param array<array-key, string> $headers
119 *
120 * @return array<array-key, string>
121 */
122 private static function removeInvalidHostHeader(array $headers) : array
123 {
124 foreach ($headers as $name => $value) {
125 if (Utils::asciiToLower((string) $name) !== 'host') {
126 continue;
127 }
128 [$host] = self::extractHostAndPortFromAuthority($value);
129 if ($host === null) {
130 unset($headers[$name]);
131 }
132 }
133 return $headers;
134 }
135 /**
136 * @param array<array-key, mixed> $server
137 */
138 private static function getServerParam(array $server, string $key) : ?string
139 {
140 return isset($server[$key]) && \is_string($server[$key]) ? $server[$key] : null;
141 }
142 /**
143 * @param array<array-key, mixed> $server
144 */
145 private static function getRequestMethodFromServer(array $server) : string
146 {
147 return Utils::asciiToUpper(self::getServerParam($server, 'REQUEST_METHOD') ?? 'GET');
148 }
149 /**
150 * @param array<array-key, mixed> $server
151 */
152 private static function getProtocolFromServer(array $server) : string
153 {
154 $serverProtocol = self::getServerParam($server, 'SERVER_PROTOCOL');
155 if ($serverProtocol === null) {
156 return '1.1';
157 }
158 return \str_starts_with($serverProtocol, 'HTTP/') ? \substr($serverProtocol, 5) : $serverProtocol;
159 }
160 /**
161 * @return array{0: string|null, 1: int|null}
162 */
163 private static function extractHostAndPortFromAuthority(string $authority) : array
164 {
165 return Rfc9112::parseHostHeader($authority) ?? [null, null];
166 }
167 private static function parseServerPort(string $port) : int
168 {
169 $parsed = Rfc9112::parsePort($port);
170 if ($parsed === null) {
171 throw new InvalidArgumentException('Invalid SERVER_PORT; expected an integer between 1 and 65535.');
172 }
173 return $parsed;
174 }
175 private static function withHostFromServer(UriInterface $uri, ?string $host) : ?UriInterface
176 {
177 if ($host === null) {
178 return null;
179 }
180 try {
181 return $uri->withHost($host);
182 } catch (InvalidArgumentException $e) {
183 return null;
184 }
185 }
186 /**
187 * @param array<array-key, mixed> $server
188 */
189 private static function getUriWithSchemeFromServer(array $server) : UriInterface
190 {
191 $uri = new Uri('');
192 $https = self::getServerParam($server, 'HTTPS');
193 return $uri->withScheme(!empty($https) && $https !== 'off' ? 'https' : 'http');
194 }
195 /**
196 * @param array<array-key, mixed> $server
197 */
198 private static function getAuthorityUriFromServer(#[\SensitiveParameter] array $server) : UriInterface
199 {
200 $uri = self::getUriWithSchemeFromServer($server);
201 $hasPort = \false;
202 $hasHost = \false;
203 $authority = self::getServerParam($server, 'HTTP_HOST');
204 if ($authority !== null) {
205 [$host, $port] = self::extractHostAndPortFromAuthority($authority);
206 if ($host !== null) {
207 $hostUri = self::withHostFromServer($uri, $host);
208 if ($hostUri !== null) {
209 $uri = $hostUri;
210 $hasHost = \true;
211 if ($port !== null) {
212 $hasPort = \true;
213 $uri = $uri->withPort($port);
214 }
215 }
216 }
217 }
218 foreach (['SERVER_NAME', 'SERVER_ADDR'] as $serverParam) {
219 if ($hasHost) {
220 continue;
221 }
222 $hostUri = self::withHostFromServer($uri, self::getServerParam($server, $serverParam));
223 if ($hostUri !== null) {
224 $uri = $hostUri;
225 $hasHost = \true;
226 }
227 }
228 $serverPort = self::getServerParam($server, 'SERVER_PORT');
229 if (!$hasPort && $serverPort !== null) {
230 $uri = $uri->withPort(self::parseServerPort($serverPort));
231 }
232 return $uri;
233 }
234 /**
235 * @param array<array-key, mixed> $server
236 *
237 * @return array{0: UriInterface, 1: string|null}
238 */
239 private static function getUriAndRequestTargetFromServer(#[\SensitiveParameter] array $server, string $method) : array
240 {
241 $requestUri = self::getServerParam($server, 'REQUEST_URI');
242 $queryString = self::getServerParam($server, 'QUERY_STRING');
243 if ($requestUri !== null) {
244 $connectAuthority = self::parseConnectAuthorityFormRequestTarget($method, $requestUri);
245 if ($connectAuthority !== null) {
246 [$host, $port] = $connectAuthority;
247 $uri = self::getUriWithSchemeFromServer($server);
248 return [$uri->withHost($host)->withPort($port)->withPath('')->withQuery(''), $requestUri];
249 }
250 $absoluteForm = self::getAbsoluteFormUriAndRequestTarget($requestUri, $queryString);
251 if ($absoluteForm !== null) {
252 return $absoluteForm;
253 }
254 }
255 $uri = self::getAuthorityUriFromServer($server);
256 if ($requestUri === null) {
257 if ($queryString !== null) {
258 $uri = $uri->withQuery($queryString);
259 }
260 return [$uri, null];
261 }
262 if (Rfc9112::isAsteriskFormRequestTarget($method, $requestUri)) {
263 return [$uri->withPath('')->withQuery(''), '*'];
264 }
265 [$path, $query, $hasQuery] = self::splitRequestTargetQuery($requestUri);
266 $uri = $uri->withPath(self::normalizeOriginFormPathFromServer($path));
267 if ($hasQuery) {
268 $uri = $uri->withQuery($query);
269 } elseif ($queryString !== null) {
270 $uri = $uri->withQuery($queryString);
271 }
272 return [$uri, null];
273 }
274 /**
275 * @return array{0: UriInterface, 1: string}|null
276 */
277 private static function getAbsoluteFormUriAndRequestTarget(#[\SensitiveParameter] string $requestUri, ?string $queryString) : ?array
278 {
279 if (!Rfc9112::isAbsoluteFormRequestTarget($requestUri)) {
280 return null;
281 }
282 try {
283 $targetUri = (new Uri($requestUri))->withFragment('');
284 } catch (InvalidArgumentException $e) {
285 return null;
286 }
287 if ($targetUri->getHost() === '') {
288 return null;
289 }
290 $requestTarget = self::removeRequestTargetFragment($requestUri);
291 $requestTargetWithoutUserInfo = self::removeUserInfoFromAbsoluteFormRequestTarget($requestTarget);
292 if ($requestTargetWithoutUserInfo !== $requestTarget) {
293 $targetUri = $targetUri->withUserInfo('');
294 $requestTarget = $requestTargetWithoutUserInfo;
295 }
296 if (!\str_contains($requestTarget, '?') && $queryString !== null && $queryString !== '') {
297 $targetUri = $targetUri->withQuery($queryString);
298 $requestTarget .= '?' . $queryString;
299 }
300 // Preserve the received absolute-form target unless it cannot be used as
301 // a PSR-7 request target without normalization.
302 $normalizeRequestTarget = !Rfc9112::isValidRequestTarget($requestTarget) || self::hasEmptyPortInAbsoluteFormRequestTarget($requestTarget);
303 return [$targetUri, $normalizeRequestTarget ? (string) $targetUri : $requestTarget];
304 }
305 private static function removeUserInfoFromAbsoluteFormRequestTarget(string $target) : string
306 {
307 $authorityStart = \strpos($target, '://');
308 if ($authorityStart === \false) {
309 return $target;
310 }
311 $authorityStart += 3;
312 $authorityLength = \strcspn($target, '/?#', $authorityStart);
313 $authority = \substr($target, $authorityStart, $authorityLength);
314 if ($authority === '') {
315 return $target;
316 }
317 $lastAt = \strrpos($authority, '@');
318 if ($lastAt === \false) {
319 return $target;
320 }
321 $authorityEnd = $authorityStart + $authorityLength;
322 return \substr($target, 0, $authorityStart) . \substr($authority, $lastAt + 1) . \substr($target, $authorityEnd);
323 }
324 private static function hasEmptyPortInAbsoluteFormRequestTarget(string $target) : bool
325 {
326 $authorityStart = \strpos($target, '://');
327 if ($authorityStart === \false) {
328 return \false;
329 }
330 $authorityStart += 3;
331 $authority = \substr($target, $authorityStart, \strcspn($target, '/?#', $authorityStart));
332 if ($authority === '') {
333 return \false;
334 }
335 $lastAt = \strrpos($authority, '@');
336 if ($lastAt !== \false) {
337 $authority = \substr($authority, $lastAt + 1);
338 }
339 if ($authority === '') {
340 return \false;
341 }
342 if (\str_starts_with($authority, '[')) {
343 $closingBracket = \strpos($authority, ']');
344 return $closingBracket !== \false && \substr($authority, $closingBracket + 1) === ':';
345 }
346 return \str_ends_with($authority, ':');
347 }
348 /**
349 * @return array{0: string, 1: int}|null
350 */
351 private static function parseConnectAuthorityFormRequestTarget(string $method, string $target) : ?array
352 {
353 if (!Rfc9112::isConnectAuthorityFormRequestTarget($method, $target)) {
354 return null;
355 }
356 [$host, $port] = self::extractHostAndPortFromAuthority($target);
357 if ($host === null || $port === null) {
358 return null;
359 }
360 return [$host, $port];
361 }
362 private static function removeRequestTargetFragment(string $target) : string
363 {
364 return \explode('#', $target, 2)[0];
365 }
366 /**
367 * @return array{0: string, 1: string, 2: bool}
368 */
369 private static function splitRequestTargetQuery(string $target) : array
370 {
371 $parts = \explode('?', $target, 2);
372 return [$parts[0], $parts[1] ?? '', isset($parts[1])];
373 }
374 private static function normalizeOriginFormPathFromServer(string $path) : string
375 {
376 if ($path === '' || \str_starts_with($path, '/')) {
377 return $path;
378 }
379 return '/' . $path;
380 }
381 }
382