PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
← All changes | app/Services/FileSystem/Drivers/S3/S3FileDeleter.php +21 -3 1.6.3 → 1.6.5 View file →
@@ -29,12 +29,13 @@
29 29 $this->httpMethod = "DELETE";
30 30 $this->timeStamp = gmdate('Ymd\THis\Z');
31 31 $this->date = substr($this->timeStamp, 0, 8);
32 32 $hasDot = strpos($this->bucket, '.') !== false;
33 + $encodedFilePath = $this->encodeS3ObjectKey($this->s3FilePath);
33 34 if ($hasDot) {
34 - $this->requestUrl = "https://s3.{$this->region}.amazonaws.com/{$this->bucket}/{$this->s3FilePath}";
35 + $this->requestUrl = "https://s3.{$this->region}.amazonaws.com/{$this->bucket}/{$encodedFilePath}";
35 36 } else {
36 - $this->requestUrl = "https://{$this->bucket}.s3.{$this->region}.amazonaws.com/{$this->s3FilePath}";
37 + $this->requestUrl = "https://{$this->bucket}.s3.{$this->region}.amazonaws.com/{$encodedFilePath}";
37 38 }
38 39 $this->signature = $this->generateSignature();
39 40 }
40 41
@@ -83,13 +84,30 @@
83 84 }
84 85
85 86 private function createCanonicalUrl(): string
86 87 {
87 - $s3FilePath = '/' . ltrim($this->s3FilePath, '/');
88 + $s3FilePath = '/' . $this->encodeS3ObjectKey($this->s3FilePath);
88 89 $hasDot = strpos($this->bucket, '.') !== false;
89 90 $canonicalUri = $hasDot ? '/' . $this->bucket . $s3FilePath : $s3FilePath;
90 91
91 92 return "{$this->httpMethod}\n{$canonicalUri}\n\nhost:{$this->getHost()}\nx-amz-content-sha256:{$this->getContentHash()}\nx-amz-date:{$this->timeStamp}\n\nhost;x-amz-content-sha256;x-amz-date\n{$this->getContentHash()}";
93 + }
94 +
95 + /**
96 + * Percent-encodes each "/"-separated segment of an S3 object key using
97 + * AWS's UriEncode rules (rawurlencode leaves "/" alone). This keeps the
98 + * canonical signing path and the actual request URL identical to what
99 + * S3 receives on the wire, so multi-byte UTF-8 characters, spaces, and
100 + * reserved characters ("+", "#", "?", literal "%") all round-trip to
101 + * the exact key that was requested instead of a different object.
102 + *
103 + * Deliberately does not ltrim() leading slashes: "foo", "/foo", and
104 + * "//foo" are three distinct S3 keys, and stripping the slash made a
105 + * delete/upload targeting "/foo" silently operate on "foo" instead.
106 + */
107 + private function encodeS3ObjectKey(string $path): string
108 + {
109 + return implode('/', array_map('rawurlencode', explode('/', $path)));
92 110 }
93 111
94 112 private function getHost(): string
95 113 {