PluginProbe
Media Cloud Sync / 1.2.13
Media Cloud Sync v1.2.13
1.4.2 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 All 36 releases
media-cloud-sync / includes / sdk / s3 / Aws / S3 / BucketEndpointMiddleware.php

BucketEndpointMiddleware.php in Media Cloud Sync 1.2.13, at includes/sdk/s3/Aws/S3/BucketEndpointMiddleware.php

103 lines 3.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Dudlewebs\WPMCS\s3\Aws\S3;
4
5 use Dudlewebs\WPMCS\s3\Aws\CommandInterface;
6 use Dudlewebs\WPMCS\s3\Psr\Http\Message\RequestInterface;
7 /**
8 * Used to update the host used for S3 requests in the case of using a
9 * "bucket endpoint" or CNAME bucket.
10 *
11 * IMPORTANT: this middleware must be added after the "build" step.
12 *
13 * @internal
14 */
15 class BucketEndpointMiddleware
16 {
17 private static $exclusions = ['GetBucketLocation' => \true];
18 private $nextHandler;
19 /**
20 * Create a middleware wrapper function.
21 *
22 * @return callable
23 */
24 public static function wrap()
25 {
26 return function (callable $handler) {
27 return new self($handler);
28 };
29 }
30 public function __construct(callable $nextHandler)
31 {
32 $this->nextHandler = $nextHandler;
33 }
34 public function __invoke(CommandInterface $command, RequestInterface $request)
35 {
36 $nextHandler = $this->nextHandler;
37 $bucket = $command['Bucket'];
38 if ($bucket && !isset(self::$exclusions[$command->getName()])) {
39 $request = $this->modifyRequest($request, $command);
40 }
41 return $nextHandler($command, $request);
42 }
43 /**
44 * Performs a one-time removal of Bucket from path, then if
45 * the bucket name is duplicated in the path, performs additional
46 * removal which is dependent on the number of occurrences of the bucket
47 * name in a path-like format in the key name.
48 *
49 * @return string
50 */
51 private function removeBucketFromPath($path, $bucket, $key)
52 {
53 $occurrencesInKey = $this->getBucketNameOccurrencesInKey($key, $bucket);
54 do {
55 $len = \strlen($bucket) + 1;
56 if (\substr($path, 0, $len) === "/{$bucket}") {
57 $path = \substr($path, $len);
58 }
59 } while (\substr_count($path, "/{$bucket}") > $occurrencesInKey + 1);
60 return $path ?: '/';
61 }
62 private function removeDuplicateBucketFromHost($host, $bucket)
63 {
64 if (\substr_count($host, $bucket) > 1) {
65 while (\strpos($host, "{$bucket}.{$bucket}") === 0) {
66 $hostArr = \explode('.', $host);
67 \array_shift($hostArr);
68 $host = \implode('.', $hostArr);
69 }
70 }
71 return $host;
72 }
73 private function getBucketNameOccurrencesInKey($key, $bucket)
74 {
75 $occurrences = 0;
76 if (empty($key)) {
77 return $occurrences;
78 }
79 $segments = \explode('/', $key);
80 foreach ($segments as $segment) {
81 if (\strpos($segment, $bucket) === 0) {
82 $occurrences++;
83 }
84 }
85 return $occurrences;
86 }
87 private function modifyRequest(RequestInterface $request, CommandInterface $command)
88 {
89 $key = isset($command['Key']) ? $command['Key'] : null;
90 $uri = $request->getUri();
91 $path = $uri->getPath();
92 $host = $uri->getHost();
93 $bucket = $command['Bucket'];
94 $path = $this->removeBucketFromPath($path, $bucket, $key);
95 $host = $this->removeDuplicateBucketFromHost($host, $bucket);
96 // Modify the Key to make sure the key is encoded, but slashes are not.
97 if ($key) {
98 $path = S3Client::encodeKey(\rawurldecode($path));
99 }
100 return $request->withUri($uri->withHost($host)->withPath($path));
101 }
102 }
103