PluginProbe
Gmail SMTP / trunk
Gmail SMTP vtrunk
1.2.3.21 1.2.3.20 trunk 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.9 1.2.0 1.2.3.14 1.2.3.15 1.2.3.16 1.2.3.18 1.2.3.5
gmail-smtp / google-api-php-client / vendor / guzzlehttp / psr7 / src / ServerRequest.php

ServerRequest.php in Gmail SMTP trunk, at google-api-php-client/vendor/guzzlehttp/psr7/src/ServerRequest.php

459 lines 13.2 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
5 namespace GuzzleHttp\Psr7;
6
7 use InvalidArgumentException;
8 use Psr\Http\Message\ServerRequestInterface;
9 use Psr\Http\Message\StreamInterface;
10 use Psr\Http\Message\UploadedFileInterface;
11 use Psr\Http\Message\UriInterface;
12
13 /**
14 * Server-side HTTP request
15 *
16 * Extends the Request definition to add methods for accessing incoming data,
17 * specifically server parameters, cookies, matched path parameters, query
18 * string arguments, body parameters, and upload file information.
19 *
20 * "Attributes" are discovered via decomposing the request (and usually
21 * specifically the URI path), and typically will be injected by the application.
22 *
23 * Requests are considered immutable; all methods that might change state are
24 * implemented such that they retain the internal state of the current
25 * message and return a new instance that contains the changed state.
26 */
27 class ServerRequest extends Request implements ServerRequestInterface
28 {
29 /**
30 * @var array
31 */
32 private $attributes = [];
33
34 /**
35 * @var array
36 */
37 private $cookieParams = [];
38
39 /**
40 * @var array|object|null
41 */
42 private $parsedBody;
43
44 /**
45 * @var array
46 */
47 private $queryParams = [];
48
49 /**
50 * @var array
51 */
52 private $serverParams;
53
54 /**
55 * @var array
56 */
57 private $uploadedFiles = [];
58
59 /**
60 * @param string $method HTTP method
61 * @param string|UriInterface $uri URI
62 * @param (string|string[])[] $headers Request headers
63 * @param string|resource|StreamInterface|null $body Request body
64 * @param string $version Protocol version
65 * @param array $serverParams Typically the $_SERVER superglobal
66 */
67 public function __construct(
68 string $method,
69 $uri,
70 array $headers = [],
71 $body = null,
72 string $version = '1.1',
73 array $serverParams = []
74 ) {
75 $this->serverParams = $serverParams;
76
77 parent::__construct($method, $uri, $headers, $body, $version);
78 }
79
80 /**
81 * Return an UploadedFile instance array.
82 *
83 * @param array $files An array which respect $_FILES structure
84 *
85 * @throws InvalidArgumentException for unrecognized values
86 */
87 public static function normalizeFiles(array $files): array
88 {
89 $normalized = [];
90
91 foreach ($files as $key => $value) {
92 if ($value instanceof UploadedFileInterface) {
93 $normalized[$key] = $value;
94 } elseif (is_array($value) && isset($value['tmp_name'])) {
95 $normalized[$key] = self::createUploadedFileFromSpec($value);
96 } elseif (is_array($value)) {
97 $normalized[$key] = self::normalizeFiles($value);
98 continue;
99 } else {
100 throw new InvalidArgumentException('Invalid value in files specification');
101 }
102 }
103
104 return $normalized;
105 }
106
107 /**
108 * Create and return an UploadedFile instance from a $_FILES specification.
109 *
110 * If the specification represents an array of values, this method will
111 * delegate to normalizeNestedFileSpec() and return that return value.
112 *
113 * @param array $value $_FILES struct
114 *
115 * @return UploadedFileInterface|UploadedFileInterface[]
116 */
117 private static function createUploadedFileFromSpec(array $value)
118 {
119 if (is_array($value['tmp_name'])) {
120 return self::normalizeNestedFileSpec($value);
121 }
122
123 return new UploadedFile(
124 $value['tmp_name'],
125 (int) $value['size'],
126 (int) $value['error'],
127 $value['name'],
128 $value['type']
129 );
130 }
131
132 /**
133 * Normalize an array of file specifications.
134 *
135 * Loops through all nested files and returns a normalized array of
136 * UploadedFileInterface instances.
137 *
138 * @return UploadedFileInterface[]
139 */
140 private static function normalizeNestedFileSpec(array $files = []): array
141 {
142 $normalizedFiles = [];
143
144 foreach (array_keys($files['tmp_name']) as $key) {
145 $spec = [
146 'tmp_name' => $files['tmp_name'][$key],
147 'size' => $files['size'][$key] ?? null,
148 'error' => $files['error'][$key] ?? null,
149 'name' => $files['name'][$key] ?? null,
150 'type' => $files['type'][$key] ?? null,
151 ];
152 $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec);
153 }
154
155 return $normalizedFiles;
156 }
157
158 /**
159 * Return a ServerRequest populated with superglobals:
160 * $_GET
161 * $_POST
162 * $_COOKIE
163 * $_FILES
164 * $_SERVER
165 */
166 public static function fromGlobals(): ServerRequestInterface
167 {
168 $method = strtoupper(self::getServerParam('REQUEST_METHOD') ?? 'GET');
169 $headers = self::removeInvalidHostHeader(self::getAllHeaders());
170 $uri = self::getUriFromGlobals();
171 $body = new CachingStream(new LazyOpenStream('php://input', 'r+'));
172 $serverProtocol = self::getServerParam('SERVER_PROTOCOL');
173 $protocol = $serverProtocol !== null ? str_replace('HTTP/', '', $serverProtocol) : '1.1';
174
175 $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER);
176
177 return $serverRequest
178 ->withCookieParams($_COOKIE)
179 ->withQueryParams($_GET)
180 ->withParsedBody($_POST)
181 ->withUploadedFiles(self::normalizeFiles($_FILES));
182 }
183
184 /**
185 * @return array<array-key, string>
186 */
187 private static function getAllHeaders(): array
188 {
189 return self::normalizeHeaderValues(getallheaders());
190 }
191
192 /**
193 * @param array<array-key, mixed> $headers
194 *
195 * @return array<array-key, string>
196 */
197 private static function normalizeHeaderValues(array $headers): array
198 {
199 $normalized = [];
200
201 foreach ($headers as $name => $value) {
202 if (is_scalar($value) || (is_object($value) && method_exists($value, '__toString'))) {
203 $normalized[$name] = (string) $value;
204 }
205 }
206
207 return $normalized;
208 }
209
210 private static function getServerParam(string $key): ?string
211 {
212 return isset($_SERVER[$key]) && is_string($_SERVER[$key]) ? $_SERVER[$key] : null;
213 }
214
215 /**
216 * @param array<array-key, string> $headers
217 *
218 * @return array<array-key, string>
219 */
220 private static function removeInvalidHostHeader(array $headers): array
221 {
222 foreach ($headers as $name => $value) {
223 if (strtolower((string) $name) !== 'host') {
224 continue;
225 }
226
227 if (Rfc7230::parseHostHeader($value) === null) {
228 unset($headers[$name]);
229 }
230 }
231
232 return $headers;
233 }
234
235 /**
236 * @return array{0: string|null, 1: int|null}
237 */
238 private static function extractHostAndPortFromAuthority(string $authority): array
239 {
240 return Rfc7230::parseHostHeader($authority) ?? [null, null];
241 }
242
243 /**
244 * Get a Uri populated with values from $_SERVER.
245 */
246 public static function getUriFromGlobals(): UriInterface
247 {
248 $uri = new Uri('');
249
250 $https = self::getServerParam('HTTPS');
251 $uri = $uri->withScheme(!empty($https) && $https !== 'off' ? 'https' : 'http');
252
253 $hasPort = false;
254 $authority = self::getServerParam('HTTP_HOST');
255 if ($authority !== null) {
256 [$host, $port] = self::extractHostAndPortFromAuthority($authority);
257 if ($host !== null) {
258 $uri = $uri->withHost($host);
259 }
260
261 if ($port !== null) {
262 $hasPort = true;
263 $uri = $uri->withPort($port);
264 }
265 } elseif (($serverName = self::getServerParam('SERVER_NAME')) !== null) {
266 $uri = $uri->withHost($serverName);
267 } elseif (($serverAddr = self::getServerParam('SERVER_ADDR')) !== null) {
268 $uri = $uri->withHost($serverAddr);
269 }
270
271 $serverPort = self::getServerParam('SERVER_PORT');
272 if (!$hasPort && $serverPort !== null && preg_match('/^[+-]?\d+$/', $serverPort) === 1) {
273 $uri = $uri->withPort((int) $serverPort);
274 }
275
276 $hasQuery = false;
277 $requestUri = self::getServerParam('REQUEST_URI');
278 if ($requestUri !== null) {
279 $requestUriParts = explode('?', $requestUri, 2);
280 $uri = $uri->withPath($requestUriParts[0]);
281 if (isset($requestUriParts[1])) {
282 $hasQuery = true;
283 $uri = $uri->withQuery($requestUriParts[1]);
284 }
285 }
286
287 $queryString = self::getServerParam('QUERY_STRING');
288 if (!$hasQuery && $queryString !== null) {
289 $uri = $uri->withQuery($queryString);
290 }
291
292 return $uri;
293 }
294
295 public function getServerParams(): array
296 {
297 return $this->serverParams;
298 }
299
300 public function getUploadedFiles(): array
301 {
302 return $this->uploadedFiles;
303 }
304
305 public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface
306 {
307 $invalidUploadedFileFound = false;
308 $invalidUploadedFile = null;
309 $stack = [$uploadedFiles];
310
311 while ($stack !== []) {
312 foreach (\array_pop($stack) as $uploadedFile) {
313 if ($uploadedFile instanceof UploadedFileInterface) {
314 continue;
315 }
316
317 if (\is_array($uploadedFile)) {
318 $stack[] = $uploadedFile;
319 continue;
320 }
321
322 $invalidUploadedFileFound = true;
323 $invalidUploadedFile = $uploadedFile;
324
325 break 2;
326 }
327 }
328
329 if ($invalidUploadedFileFound) {
330 \trigger_deprecation(
331 'guzzlehttp/psr7',
332 '2.11',
333 'Passing %s inside ServerRequestInterface::withUploadedFiles() is deprecated; guzzlehttp/psr7 3.0 requires an UploadedFileInterface[] tree.',
334 \get_debug_type($invalidUploadedFile)
335 );
336 }
337
338 $new = clone $this;
339 $new->uploadedFiles = $uploadedFiles;
340
341 return $new;
342 }
343
344 public function getCookieParams(): array
345 {
346 return $this->cookieParams;
347 }
348
349 public function withCookieParams(array $cookies): ServerRequestInterface
350 {
351 $new = clone $this;
352 $new->cookieParams = $cookies;
353
354 return $new;
355 }
356
357 public function getQueryParams(): array
358 {
359 return $this->queryParams;
360 }
361
362 public function withQueryParams(array $query): ServerRequestInterface
363 {
364 $new = clone $this;
365 $new->queryParams = $query;
366
367 return $new;
368 }
369
370 /**
371 * @return array|object|null
372 */
373 public function getParsedBody()
374 {
375 return $this->parsedBody;
376 }
377
378 public function withParsedBody($data): ServerRequestInterface
379 {
380 if ($data !== null && !\is_array($data) && !\is_object($data)) {
381 \trigger_deprecation(
382 'guzzlehttp/psr7',
383 '2.11',
384 'Passing %s to ServerRequestInterface::withParsedBody() is deprecated; guzzlehttp/psr7 3.0 requires array|object|null.',
385 \get_debug_type($data)
386 );
387 }
388
389 $new = clone $this;
390 $new->parsedBody = $data;
391
392 return $new;
393 }
394
395 public function getAttributes(): array
396 {
397 return $this->attributes;
398 }
399
400 /**
401 * @return mixed
402 */
403 public function getAttribute($attribute, $default = null)
404 {
405 if (!\is_string($attribute)) {
406 \trigger_deprecation(
407 'guzzlehttp/psr7',
408 '2.11',
409 'Passing %s to ServerRequestInterface::getAttribute() is deprecated; guzzlehttp/psr7 3.0 requires string for $attribute.',
410 \get_debug_type($attribute)
411 );
412 }
413
414 if (false === array_key_exists($attribute, $this->attributes)) {
415 return $default;
416 }
417
418 return $this->attributes[$attribute];
419 }
420
421 public function withAttribute($attribute, $value): ServerRequestInterface
422 {
423 if (!\is_string($attribute)) {
424 \trigger_deprecation(
425 'guzzlehttp/psr7',
426 '2.11',
427 'Passing %s to ServerRequestInterface::withAttribute() is deprecated; guzzlehttp/psr7 3.0 requires string for $attribute.',
428 \get_debug_type($attribute)
429 );
430 }
431
432 $new = clone $this;
433 $new->attributes[$attribute] = $value;
434
435 return $new;
436 }
437
438 public function withoutAttribute($attribute): ServerRequestInterface
439 {
440 if (!\is_string($attribute)) {
441 \trigger_deprecation(
442 'guzzlehttp/psr7',
443 '2.11',
444 'Passing %s to ServerRequestInterface::withoutAttribute() is deprecated; guzzlehttp/psr7 3.0 requires string for $attribute.',
445 \get_debug_type($attribute)
446 );
447 }
448
449 if (false === array_key_exists($attribute, $this->attributes)) {
450 return $this;
451 }
452
453 $new = clone $this;
454 unset($new->attributes[$attribute]);
455
456 return $new;
457 }
458 }
459