PluginProbe
Media Cloud Sync / 1.2.13
Media Cloud Sync v1.2.13
1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 All 35 releases
media-cloud-sync / includes / sdk / s3 / GuzzleHttp / Psr7 / Utils.php

Utils.php in Media Cloud Sync 1.2.13, at includes/sdk/s3/GuzzleHttp/Psr7/Utils.php

387 lines 15.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 namespace Dudlewebs\WPMCS\s3\GuzzleHttp\Psr7;
5
6 use Dudlewebs\WPMCS\s3\Psr\Http\Message\RequestInterface;
7 use Dudlewebs\WPMCS\s3\Psr\Http\Message\ServerRequestInterface;
8 use Dudlewebs\WPMCS\s3\Psr\Http\Message\StreamInterface;
9 use Dudlewebs\WPMCS\s3\Psr\Http\Message\UriInterface;
10 final class Utils
11 {
12 /**
13 * Remove the items given by the keys, case insensitively from the data.
14 *
15 * @param (string|int)[] $keys
16 */
17 public static function caselessRemove(array $keys, array $data) : array
18 {
19 $result = [];
20 foreach ($keys as &$key) {
21 $key = \strtolower((string) $key);
22 }
23 foreach ($data as $k => $v) {
24 if (!\in_array(\strtolower((string) $k), $keys)) {
25 $result[$k] = $v;
26 }
27 }
28 return $result;
29 }
30 /**
31 * Copy the contents of a stream into another stream until the given number
32 * of bytes have been read.
33 *
34 * @param StreamInterface $source Stream to read from
35 * @param StreamInterface $dest Stream to write to
36 * @param int $maxLen Maximum number of bytes to read. Pass -1
37 * to read the entire stream.
38 *
39 * @throws \RuntimeException on error.
40 */
41 public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1) : void
42 {
43 $bufferSize = 8192;
44 if ($maxLen === -1) {
45 while (!$source->eof()) {
46 if (!$dest->write($source->read($bufferSize))) {
47 break;
48 }
49 }
50 } else {
51 $remaining = $maxLen;
52 while ($remaining > 0 && !$source->eof()) {
53 $buf = $source->read(\min($bufferSize, $remaining));
54 $len = \strlen($buf);
55 if (!$len) {
56 break;
57 }
58 $remaining -= $len;
59 $dest->write($buf);
60 }
61 }
62 }
63 /**
64 * Copy the contents of a stream into a string until the given number of
65 * bytes have been read.
66 *
67 * @param StreamInterface $stream Stream to read
68 * @param int $maxLen Maximum number of bytes to read. Pass -1
69 * to read the entire stream.
70 *
71 * @throws \RuntimeException on error.
72 */
73 public static function copyToString(StreamInterface $stream, int $maxLen = -1) : string
74 {
75 $buffer = '';
76 if ($maxLen === -1) {
77 while (!$stream->eof()) {
78 $buf = $stream->read(1048576);
79 if ($buf === '') {
80 break;
81 }
82 $buffer .= $buf;
83 }
84 return $buffer;
85 }
86 $len = 0;
87 while (!$stream->eof() && $len < $maxLen) {
88 $buf = $stream->read($maxLen - $len);
89 if ($buf === '') {
90 break;
91 }
92 $buffer .= $buf;
93 $len = \strlen($buffer);
94 }
95 return $buffer;
96 }
97 /**
98 * Calculate a hash of a stream.
99 *
100 * This method reads the entire stream to calculate a rolling hash, based
101 * on PHP's `hash_init` functions.
102 *
103 * @param StreamInterface $stream Stream to calculate the hash for
104 * @param string $algo Hash algorithm (e.g. md5, crc32, etc)
105 * @param bool $rawOutput Whether or not to use raw output
106 *
107 * @throws \RuntimeException on error.
108 */
109 public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = \false) : string
110 {
111 $pos = $stream->tell();
112 if ($pos > 0) {
113 $stream->rewind();
114 }
115 $ctx = \hash_init($algo);
116 while (!$stream->eof()) {
117 \hash_update($ctx, $stream->read(1048576));
118 }
119 $out = \hash_final($ctx, $rawOutput);
120 $stream->seek($pos);
121 return $out;
122 }
123 /**
124 * Clone and modify a request with the given changes.
125 *
126 * This method is useful for reducing the number of clones needed to mutate
127 * a message.
128 *
129 * The changes can be one of:
130 * - method: (string) Changes the HTTP method.
131 * - set_headers: (array) Sets the given headers.
132 * - remove_headers: (array) Remove the given headers.
133 * - body: (mixed) Sets the given body.
134 * - uri: (UriInterface) Set the URI.
135 * - query: (string) Set the query string value of the URI.
136 * - version: (string) Set the protocol version.
137 *
138 * @param RequestInterface $request Request to clone and modify.
139 * @param array $changes Changes to apply.
140 */
141 public static function modifyRequest(RequestInterface $request, array $changes) : RequestInterface
142 {
143 if (!$changes) {
144 return $request;
145 }
146 $headers = $request->getHeaders();
147 if (!isset($changes['uri'])) {
148 $uri = $request->getUri();
149 } else {
150 // Remove the host header if one is on the URI
151 if ($host = $changes['uri']->getHost()) {
152 $changes['set_headers']['Host'] = $host;
153 if ($port = $changes['uri']->getPort()) {
154 $standardPorts = ['http' => 80, 'https' => 443];
155 $scheme = $changes['uri']->getScheme();
156 if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) {
157 $changes['set_headers']['Host'] .= ':' . $port;
158 }
159 }
160 }
161 $uri = $changes['uri'];
162 }
163 if (!empty($changes['remove_headers'])) {
164 $headers = self::caselessRemove($changes['remove_headers'], $headers);
165 }
166 if (!empty($changes['set_headers'])) {
167 $headers = self::caselessRemove(\array_keys($changes['set_headers']), $headers);
168 $headers = $changes['set_headers'] + $headers;
169 }
170 if (isset($changes['query'])) {
171 $uri = $uri->withQuery($changes['query']);
172 }
173 if ($request instanceof ServerRequestInterface) {
174 $new = (new ServerRequest($changes['method'] ?? $request->getMethod(), $uri, $headers, $changes['body'] ?? $request->getBody(), $changes['version'] ?? $request->getProtocolVersion(), $request->getServerParams()))->withParsedBody($request->getParsedBody())->withQueryParams($request->getQueryParams())->withCookieParams($request->getCookieParams())->withUploadedFiles($request->getUploadedFiles());
175 foreach ($request->getAttributes() as $key => $value) {
176 $new = $new->withAttribute($key, $value);
177 }
178 return $new;
179 }
180 return new Request($changes['method'] ?? $request->getMethod(), $uri, $headers, $changes['body'] ?? $request->getBody(), $changes['version'] ?? $request->getProtocolVersion());
181 }
182 /**
183 * Read a line from the stream up to the maximum allowed buffer length.
184 *
185 * @param StreamInterface $stream Stream to read from
186 * @param int|null $maxLength Maximum buffer length
187 */
188 public static function readLine(StreamInterface $stream, ?int $maxLength = null) : string
189 {
190 $buffer = '';
191 $size = 0;
192 while (!$stream->eof()) {
193 if ('' === ($byte = $stream->read(1))) {
194 return $buffer;
195 }
196 $buffer .= $byte;
197 // Break when a new line is found or the max length - 1 is reached
198 if ($byte === "\n" || ++$size === $maxLength - 1) {
199 break;
200 }
201 }
202 return $buffer;
203 }
204 /**
205 * Redact the password in the user info part of a URI.
206 */
207 public static function redactUserInfo(UriInterface $uri) : UriInterface
208 {
209 $userInfo = $uri->getUserInfo();
210 if (\false !== ($pos = \strpos($userInfo, ':'))) {
211 return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***');
212 }
213 return $uri;
214 }
215 /**
216 * Create a new stream based on the input type.
217 *
218 * Options is an associative array that can contain the following keys:
219 * - metadata: Array of custom metadata.
220 * - size: Size of the stream.
221 *
222 * This method accepts the following `$resource` types:
223 * - `Psr\Http\Message\StreamInterface`: Returns the value as-is.
224 * - `string`: Creates a stream object that uses the given string as the contents.
225 * - `resource`: Creates a stream object that wraps the given PHP stream resource.
226 * - `Iterator`: If the provided value implements `Iterator`, then a read-only
227 * stream object will be created that wraps the given iterable. Each time the
228 * stream is read from, data from the iterator will fill a buffer and will be
229 * continuously called until the buffer is equal to the requested read size.
230 * Subsequent read calls will first read from the buffer and then call `next`
231 * on the underlying iterator until it is exhausted.
232 * - `object` with `__toString()`: If the object has the `__toString()` method,
233 * the object will be cast to a string and then a stream will be returned that
234 * uses the string value.
235 * - `NULL`: When `null` is passed, an empty stream object is returned.
236 * - `callable` When a callable is passed, a read-only stream object will be
237 * created that invokes the given callable. The callable is invoked with the
238 * number of suggested bytes to read. The callable can return any number of
239 * bytes, but MUST return `false` when there is no more data to return. The
240 * stream object that wraps the callable will invoke the callable until the
241 * number of requested bytes are available. Any additional bytes will be
242 * buffered and used in subsequent reads.
243 *
244 * @param resource|string|int|float|bool|StreamInterface|callable|\Iterator|null $resource Entity body data
245 * @param array{size?: int, metadata?: array} $options Additional options
246 *
247 * @throws \InvalidArgumentException if the $resource arg is not valid.
248 */
249 public static function streamFor($resource = '', array $options = []) : StreamInterface
250 {
251 if (\is_scalar($resource)) {
252 $stream = self::tryFopen('php://temp', 'r+');
253 if ($resource !== '') {
254 \fwrite($stream, (string) $resource);
255 \fseek($stream, 0);
256 }
257 return new Stream($stream, $options);
258 }
259 switch (\gettype($resource)) {
260 case 'resource':
261 /*
262 * The 'php://input' is a special stream with quirks and inconsistencies.
263 * We avoid using that stream by reading it into php://temp
264 */
265 /** @var resource $resource */
266 if ((\stream_get_meta_data($resource)['uri'] ?? '') === 'php://input') {
267 $stream = self::tryFopen('php://temp', 'w+');
268 \stream_copy_to_stream($resource, $stream);
269 \fseek($stream, 0);
270 $resource = $stream;
271 }
272 return new Stream($resource, $options);
273 case 'object':
274 /** @var object $resource */
275 if ($resource instanceof StreamInterface) {
276 return $resource;
277 } elseif ($resource instanceof \Iterator) {
278 return new PumpStream(function () use($resource) {
279 if (!$resource->valid()) {
280 return \false;
281 }
282 $result = $resource->current();
283 $resource->next();
284 return $result;
285 }, $options);
286 } elseif (\method_exists($resource, '__toString')) {
287 return self::streamFor((string) $resource, $options);
288 }
289 break;
290 case 'NULL':
291 return new Stream(self::tryFopen('php://temp', 'r+'), $options);
292 }
293 if (\is_callable($resource)) {
294 return new PumpStream($resource, $options);
295 }
296 throw new \InvalidArgumentException('Invalid resource type: ' . \gettype($resource));
297 }
298 /**
299 * Safely opens a PHP stream resource using a filename.
300 *
301 * When fopen fails, PHP normally raises a warning. This function adds an
302 * error handler that checks for errors and throws an exception instead.
303 *
304 * @param string $filename File to open
305 * @param string $mode Mode used to open the file
306 *
307 * @return resource
308 *
309 * @throws \RuntimeException if the file cannot be opened
310 */
311 public static function tryFopen(string $filename, string $mode)
312 {
313 $ex = null;
314 \set_error_handler(static function (int $errno, string $errstr) use($filename, $mode, &$ex) : bool {
315 $ex = new \RuntimeException(\sprintf('Unable to open "%s" using mode "%s": %s', $filename, $mode, $errstr));
316 return \true;
317 });
318 try {
319 /** @var resource $handle */
320 $handle = \fopen($filename, $mode);
321 } catch (\Throwable $e) {
322 $ex = new \RuntimeException(\sprintf('Unable to open "%s" using mode "%s": %s', $filename, $mode, $e->getMessage()), 0, $e);
323 }
324 \restore_error_handler();
325 if ($ex) {
326 /** @var $ex \RuntimeException */
327 throw $ex;
328 }
329 return $handle;
330 }
331 /**
332 * Safely gets the contents of a given stream.
333 *
334 * When stream_get_contents fails, PHP normally raises a warning. This
335 * function adds an error handler that checks for errors and throws an
336 * exception instead.
337 *
338 * @param resource $stream
339 *
340 * @throws \RuntimeException if the stream cannot be read
341 */
342 public static function tryGetContents($stream) : string
343 {
344 $ex = null;
345 \set_error_handler(static function (int $errno, string $errstr) use(&$ex) : bool {
346 $ex = new \RuntimeException(\sprintf('Unable to read stream contents: %s', $errstr));
347 return \true;
348 });
349 try {
350 /** @var string|false $contents */
351 $contents = \stream_get_contents($stream);
352 if ($contents === \false) {
353 $ex = new \RuntimeException('Unable to read stream contents');
354 }
355 } catch (\Throwable $e) {
356 $ex = new \RuntimeException(\sprintf('Unable to read stream contents: %s', $e->getMessage()), 0, $e);
357 }
358 \restore_error_handler();
359 if ($ex) {
360 /** @var $ex \RuntimeException */
361 throw $ex;
362 }
363 return $contents;
364 }
365 /**
366 * Returns a UriInterface for the given value.
367 *
368 * This function accepts a string or UriInterface and returns a
369 * UriInterface for the given value. If the value is already a
370 * UriInterface, it is returned as-is.
371 *
372 * @param string|UriInterface $uri
373 *
374 * @throws \InvalidArgumentException
375 */
376 public static function uriFor($uri) : UriInterface
377 {
378 if ($uri instanceof UriInterface) {
379 return $uri;
380 }
381 if (\is_string($uri)) {
382 return new Uri($uri);
383 }
384 throw new \InvalidArgumentException('URI must be a string or UriInterface');
385 }
386 }
387