PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.5.0
Defender Security – Malware Scanner, Login Security & Firewall v5.5.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / vendor / nyholm / psr7-server / src / ServerRequestCreator.php

ServerRequestCreator.php in Defender Security – Malware Scanner, Login Security & Firewall 5.5.0, at vendor/nyholm/psr7-server/src/ServerRequestCreator.php

304 lines 10.0 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 Nyholm\Psr7Server;
6
7 use Psr\Http\Message\ServerRequestFactoryInterface;
8 use Psr\Http\Message\ServerRequestInterface;
9 use Psr\Http\Message\StreamFactoryInterface;
10 use Psr\Http\Message\StreamInterface;
11 use Psr\Http\Message\UploadedFileFactoryInterface;
12 use Psr\Http\Message\UploadedFileInterface;
13 use Psr\Http\Message\UriFactoryInterface;
14 use Psr\Http\Message\UriInterface;
15
16 /**
17 * @author Tobias Nyholm <[email protected]>
18 * @author Martijn van der Ven <[email protected]>
19 */
20 final class ServerRequestCreator implements ServerRequestCreatorInterface
21 {
22 private $serverRequestFactory;
23
24 private $uriFactory;
25
26 private $uploadedFileFactory;
27
28 private $streamFactory;
29
30 public function __construct(
31 ServerRequestFactoryInterface $serverRequestFactory,
32 UriFactoryInterface $uriFactory,
33 UploadedFileFactoryInterface $uploadedFileFactory,
34 StreamFactoryInterface $streamFactory
35 ) {
36 $this->serverRequestFactory = $serverRequestFactory;
37 $this->uriFactory = $uriFactory;
38 $this->uploadedFileFactory = $uploadedFileFactory;
39 $this->streamFactory = $streamFactory;
40 }
41
42 /**
43 * {@inheritdoc}
44 */
45 public function fromGlobals(): ServerRequestInterface
46 {
47 $server = $_SERVER;
48 if (false === isset($server['REQUEST_METHOD'])) {
49 $server['REQUEST_METHOD'] = 'GET';
50 }
51
52 $headers = \function_exists('getallheaders') ? getallheaders() : static::getHeadersFromServer($_SERVER);
53
54 $post = null;
55 if ('POST' === $this->getMethodFromEnv($server)) {
56 foreach ($headers as $headerName => $headerValue) {
57 if (true === \is_int($headerName) || 'content-type' !== \strtolower($headerName)) {
58 continue;
59 }
60 if (\in_array(
61 \strtolower(\trim(\explode(';', $headerValue, 2)[0])),
62 ['application/x-www-form-urlencoded', 'multipart/form-data']
63 )) {
64 $post = $_POST;
65
66 break;
67 }
68 }
69 }
70
71 return $this->fromArrays($server, $headers, $_COOKIE, $_GET, $post, $_FILES, \fopen('php://input', 'r') ?: null);
72 }
73
74 /**
75 * {@inheritdoc}
76 */
77 public function fromArrays(array $server, array $headers = [], array $cookie = [], array $get = [], ?array $post = null, array $files = [], $body = null): ServerRequestInterface
78 {
79 $method = $this->getMethodFromEnv($server);
80 $uri = $this->getUriFromEnvWithHTTP($server);
81 $protocol = isset($server['SERVER_PROTOCOL']) ? \str_replace('HTTP/', '', $server['SERVER_PROTOCOL']) : '1.1';
82
83 $serverRequest = $this->serverRequestFactory->createServerRequest($method, $uri, $server);
84 foreach ($headers as $name => $value) {
85 // Because PHP automatically casts array keys set with numeric strings to integers, we have to make sure
86 // that numeric headers will not be sent along as integers, as withAddedHeader can only accept strings.
87 if (\is_int($name)) {
88 $name = (string) $name;
89 }
90 $serverRequest = $serverRequest->withAddedHeader($name, $value);
91 }
92
93 $serverRequest = $serverRequest
94 ->withProtocolVersion($protocol)
95 ->withCookieParams($cookie)
96 ->withQueryParams($get)
97 ->withParsedBody($post)
98 ->withUploadedFiles($this->normalizeFiles($files));
99
100 if (null === $body) {
101 return $serverRequest;
102 }
103
104 if (\is_resource($body)) {
105 $body = $this->streamFactory->createStreamFromResource($body);
106 } elseif (\is_string($body)) {
107 $body = $this->streamFactory->createStream($body);
108 } elseif (!$body instanceof StreamInterface) {
109 throw new \InvalidArgumentException('The $body parameter to ServerRequestCreator::fromArrays must be string, resource or StreamInterface');
110 }
111
112 return $serverRequest->withBody($body);
113 }
114
115 /**
116 * Implementation from Laminas\Diactoros\marshalHeadersFromSapi().
117 */
118 public static function getHeadersFromServer(array $server): array
119 {
120 $headers = [];
121 foreach ($server as $key => $value) {
122 // Apache prefixes environment variables with REDIRECT_
123 // if they are added by rewrite rules
124 if (0 === \strpos($key, 'REDIRECT_')) {
125 $key = \substr($key, 9);
126
127 // We will not overwrite existing variables with the
128 // prefixed versions, though
129 if (\array_key_exists($key, $server)) {
130 continue;
131 }
132 }
133
134 if ($value && 0 === \strpos($key, 'HTTP_')) {
135 $name = \strtr(\strtolower(\substr($key, 5)), '_', '-');
136 $headers[$name] = $value;
137
138 continue;
139 }
140
141 if ($value && 0 === \strpos($key, 'CONTENT_')) {
142 $name = 'content-'.\strtolower(\substr($key, 8));
143 $headers[$name] = $value;
144
145 continue;
146 }
147 }
148
149 return $headers;
150 }
151
152 private function getMethodFromEnv(array $environment): string
153 {
154 if (false === isset($environment['REQUEST_METHOD'])) {
155 throw new \InvalidArgumentException('Cannot determine HTTP method');
156 }
157
158 return $environment['REQUEST_METHOD'];
159 }
160
161 private function getUriFromEnvWithHTTP(array $environment): UriInterface
162 {
163 $uri = $this->createUriFromArray($environment);
164 if (empty($uri->getScheme())) {
165 $uri = $uri->withScheme('http');
166 }
167
168 return $uri;
169 }
170
171 /**
172 * Return an UploadedFile instance array.
173 *
174 * @param array $files A array which respect $_FILES structure
175 *
176 * @return UploadedFileInterface[]
177 *
178 * @throws \InvalidArgumentException for unrecognized values
179 */
180 private function normalizeFiles(array $files): array
181 {
182 $normalized = [];
183
184 foreach ($files as $key => $value) {
185 if ($value instanceof UploadedFileInterface) {
186 $normalized[$key] = $value;
187 } elseif (\is_array($value) && isset($value['tmp_name'])) {
188 $normalized[$key] = $this->createUploadedFileFromSpec($value);
189 } elseif (\is_array($value)) {
190 $normalized[$key] = $this->normalizeFiles($value);
191 } else {
192 throw new \InvalidArgumentException('Invalid value in files specification');
193 }
194 }
195
196 return $normalized;
197 }
198
199 /**
200 * Create and return an UploadedFile instance from a $_FILES specification.
201 *
202 * If the specification represents an array of values, this method will
203 * delegate to normalizeNestedFileSpec() and return that return value.
204 *
205 * @param array $value $_FILES struct
206 *
207 * @return array|UploadedFileInterface
208 */
209 private function createUploadedFileFromSpec(array $value)
210 {
211 if (\is_array($value['tmp_name'])) {
212 return $this->normalizeNestedFileSpec($value);
213 }
214
215 if (UPLOAD_ERR_OK !== $value['error']) {
216 $stream = $this->streamFactory->createStream();
217 } else {
218 try {
219 $stream = $this->streamFactory->createStreamFromFile($value['tmp_name']);
220 } catch (\RuntimeException $e) {
221 $stream = $this->streamFactory->createStream();
222 }
223 }
224
225 return $this->uploadedFileFactory->createUploadedFile(
226 $stream,
227 (int) $value['size'],
228 (int) $value['error'],
229 $value['name'],
230 $value['type']
231 );
232 }
233
234 /**
235 * Normalize an array of file specifications.
236 *
237 * Loops through all nested files and returns a normalized array of
238 * UploadedFileInterface instances.
239 *
240 * @return UploadedFileInterface[]
241 */
242 private function normalizeNestedFileSpec(array $files = []): array
243 {
244 $normalizedFiles = [];
245
246 foreach (\array_keys($files['tmp_name']) as $key) {
247 $spec = [
248 'tmp_name' => $files['tmp_name'][$key],
249 'size' => $files['size'][$key],
250 'error' => $files['error'][$key],
251 'name' => $files['name'][$key],
252 'type' => $files['type'][$key],
253 ];
254 $normalizedFiles[$key] = $this->createUploadedFileFromSpec($spec);
255 }
256
257 return $normalizedFiles;
258 }
259
260 /**
261 * Create a new uri from server variable.
262 *
263 * @param array $server typically $_SERVER or similar structure
264 */
265 private function createUriFromArray(array $server): UriInterface
266 {
267 $uri = $this->uriFactory->createUri('');
268
269 if (isset($server['HTTP_X_FORWARDED_PROTO'])) {
270 $uri = $uri->withScheme($server['HTTP_X_FORWARDED_PROTO']);
271 } else {
272 if (isset($server['REQUEST_SCHEME'])) {
273 $uri = $uri->withScheme($server['REQUEST_SCHEME']);
274 } elseif (isset($server['HTTPS'])) {
275 $uri = $uri->withScheme('on' === $server['HTTPS'] ? 'https' : 'http');
276 }
277
278 if (isset($server['SERVER_PORT'])) {
279 $uri = $uri->withPort($server['SERVER_PORT']);
280 }
281 }
282
283 if (isset($server['HTTP_HOST'])) {
284 if (1 === \preg_match('/^(.+)\:(\d+)$/', $server['HTTP_HOST'], $matches)) {
285 $uri = $uri->withHost($matches[1])->withPort($matches[2]);
286 } else {
287 $uri = $uri->withHost($server['HTTP_HOST']);
288 }
289 } elseif (isset($server['SERVER_NAME'])) {
290 $uri = $uri->withHost($server['SERVER_NAME']);
291 }
292
293 if (isset($server['REQUEST_URI'])) {
294 $uri = $uri->withPath(\current(\explode('?', $server['REQUEST_URI'])));
295 }
296
297 if (isset($server['QUERY_STRING'])) {
298 $uri = $uri->withQuery($server['QUERY_STRING']);
299 }
300
301 return $uri;
302 }
303 }
304