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 / Parser / ValidateResponseChecksumResultMutator.php

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

113 lines 4.6 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\Parser;
4
5 use Dudlewebs\WPMCS\s3\Aws\Api\Service;
6 use Dudlewebs\WPMCS\s3\Aws\CommandInterface;
7 use Dudlewebs\WPMCS\s3\Aws\ResultInterface;
8 use Dudlewebs\WPMCS\s3\Aws\S3\CalculatesChecksumTrait;
9 use Dudlewebs\WPMCS\s3\Aws\S3\Exception\S3Exception;
10 use Dudlewebs\WPMCS\s3\Psr\Http\Message\ResponseInterface;
11 /**
12 * A custom s3 result mutator that validates the response checksums.
13 *
14 * @internal
15 */
16 final class ValidateResponseChecksumResultMutator implements S3ResultMutator
17 {
18 use CalculatesChecksumTrait;
19 /** @var Service $api */
20 private $api;
21 /**
22 * @param Service $api
23 */
24 public function __construct(Service $api)
25 {
26 $this->api = $api;
27 }
28 /**
29 * @param ResultInterface $result
30 * @param CommandInterface|null $command
31 * @param ResponseInterface|null $response
32 *
33 * @return ResultInterface
34 */
35 public function __invoke(ResultInterface $result, CommandInterface $command = null, ResponseInterface $response = null) : ResultInterface
36 {
37 $operation = $this->api->getOperation($command->getName());
38 // Skip this middleware if the operation doesn't have an httpChecksum
39 $checksumInfo = empty($operation['httpChecksum']) ? null : $operation['httpChecksum'];
40 if (null === $checksumInfo) {
41 return $result;
42 }
43 // Skip this middleware if the operation doesn't send back a checksum,
44 // or the user doesn't opt in
45 $checksumModeEnabledMember = $checksumInfo['requestValidationModeMember'] ?? "";
46 $checksumModeEnabled = $command[$checksumModeEnabledMember] ?? "";
47 $responseAlgorithms = $checksumInfo['responseAlgorithms'] ?? [];
48 if (empty($responseAlgorithms) || \strtolower($checksumModeEnabled) !== "enabled") {
49 return $result;
50 }
51 if (\extension_loaded('awscrt')) {
52 $checksumPriority = ['CRC32C', 'CRC32', 'SHA1', 'SHA256'];
53 } else {
54 $checksumPriority = ['CRC32', 'SHA1', 'SHA256'];
55 }
56 $checksumsToCheck = \array_intersect($responseAlgorithms, $checksumPriority);
57 $checksumValidationInfo = $this->validateChecksum($checksumsToCheck, $response);
58 if ($checksumValidationInfo['status'] == "SUCCEEDED") {
59 $result['ChecksumValidated'] = $checksumValidationInfo['checksum'];
60 } elseif ($checksumValidationInfo['status'] == "FAILED") {
61 // Ignore failed validations on GetObject if it's a multipart get
62 // which returned a full multipart object
63 if ($command->getName() === "GetObject" && !empty($checksumValidationInfo['checksumHeaderValue'])) {
64 $headerValue = $checksumValidationInfo['checksumHeaderValue'];
65 $lastDashPos = \strrpos($headerValue, '-');
66 $endOfChecksum = \substr($headerValue, $lastDashPos + 1);
67 if (\is_numeric($endOfChecksum) && \intval($endOfChecksum) > 1 && \intval($endOfChecksum) < 10000) {
68 return $result;
69 }
70 }
71 throw new S3Exception("Calculated response checksum did not match the expected value", $command);
72 }
73 return $result;
74 }
75 /**
76 * @param $checksumPriority
77 * @param ResponseInterface $response
78 *
79 * @return array
80 */
81 private function validateChecksum($checksumPriority, ResponseInterface $response) : array
82 {
83 $checksumToValidate = $this->chooseChecksumHeaderToValidate($checksumPriority, $response);
84 $validationStatus = "SKIPPED";
85 $checksumHeaderValue = null;
86 if (!empty($checksumToValidate)) {
87 $checksumHeaderValue = $response->getHeader('x-amz-checksum-' . $checksumToValidate);
88 if (isset($checksumHeaderValue)) {
89 $checksumHeaderValue = $checksumHeaderValue[0];
90 $calculatedChecksumValue = $this->getEncodedValue($checksumToValidate, $response->getBody());
91 $validationStatus = $checksumHeaderValue == $calculatedChecksumValue ? "SUCCEEDED" : "FAILED";
92 }
93 }
94 return ["status" => $validationStatus, "checksum" => $checksumToValidate, "checksumHeaderValue" => $checksumHeaderValue];
95 }
96 /**
97 * @param $checksumPriority
98 * @param ResponseInterface $response
99 *
100 * @return string
101 */
102 private function chooseChecksumHeaderToValidate($checksumPriority, ResponseInterface $response) : ?string
103 {
104 foreach ($checksumPriority as $checksum) {
105 $checksumHeader = 'x-amz-checksum-' . $checksum;
106 if ($response->hasHeader($checksumHeader)) {
107 return $checksum;
108 }
109 }
110 return null;
111 }
112 }
113