PluginProbe
Media Cloud Sync / 1.4.1
Media Cloud Sync v1.4.1
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 / Aws / S3 / ValidateResponseChecksumParser.php

ValidateResponseChecksumParser.php in Media Cloud Sync 1.4.1, at includes/sdk/s3/Aws/S3/ValidateResponseChecksumParser.php

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