Proyectos de Subversion Moodle

Rev

Rev 1 | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 1 Rev 1441
Línea 1... Línea 1...
1
<?php
1
<?php
2
namespace Aws\S3;
2
namespace Aws\S3;
Línea 3... Línea 3...
3
 
3
 
-
 
4
use Aws\Api\Service;
4
use Aws\Api\Service;
5
use Aws\Api\Shape;
-
 
6
use Aws\CommandInterface;
5
use Aws\CommandInterface;
7
use Aws\MetricsBuilder;
6
use GuzzleHttp\Psr7;
8
use GuzzleHttp\Psr7;
7
use InvalidArgumentException;
9
use InvalidArgumentException;
-
 
10
use Psr\Http\Message\RequestInterface;
Línea 8... Línea 11...
8
use Psr\Http\Message\RequestInterface;
11
use Psr\Http\Message\StreamInterface;
9
 
12
 
10
/**
13
/**
11
 * Apply required or optional checksums to requests before sending.
14
 * Apply required or optional checksums to requests before sending.
Línea 15... Línea 18...
15
 * @internal
18
 * @internal
16
 */
19
 */
17
class ApplyChecksumMiddleware
20
class ApplyChecksumMiddleware
18
{
21
{
19
    use CalculatesChecksumTrait;
22
    use CalculatesChecksumTrait;
-
 
23
 
-
 
24
    public const DEFAULT_CALCULATION_MODE = 'when_supported';
-
 
25
    public const DEFAULT_ALGORITHM = 'crc32';
-
 
26
 
-
 
27
    /**
-
 
28
     * @var true[]
-
 
29
     *
-
 
30
     * S3 Operations for which pre-calculated SHA256
-
 
31
     * Checksums can be added to the command
-
 
32
     */
20
    private static $sha256AndMd5 = [
33
    public static $sha256 = [
21
        'PutObject',
34
        'PutObject' => true,
22
        'UploadPart',
35
        'UploadPart' => true,
23
    ];
36
    ];
Línea 24... Línea 37...
24
 
37
 
25
    /** @var Service */
38
    /** @var Service */
Línea -... Línea 39...
-
 
39
    private $api;
-
 
40
 
-
 
41
    /** @var array */
-
 
42
    private $config;
26
    private $api;
43
 
Línea 27... Línea 44...
27
 
44
    /** @var callable */
28
    private $nextHandler;
45
    private $nextHandler;
29
 
46
 
30
    /**
47
    /**
31
     * Create a middleware wrapper function.
48
     * Create a middleware wrapper function.
32
     *
49
     *
33
     * @param Service $api
50
     * @param Service $api
34
     * @return callable
51
     * @return callable
35
     */
52
     */
36
    public static function wrap(Service $api)
53
    public static function wrap(Service $api, array $config = [])
37
    {
54
    {
38
        return function (callable $handler) use ($api) {
55
        return function (callable $handler) use ($api, $config) {
Línea 39... Línea 56...
39
            return new self($handler, $api);
56
            return new self($handler, $api, $config);
-
 
57
        };
-
 
58
    }
-
 
59
 
-
 
60
    public function __construct(
40
        };
61
        callable $nextHandler,
41
    }
62
        Service $api, 
42
 
63
        array $config = []
-
 
64
    )
43
    public function __construct(callable $nextHandler, Service $api)
65
    {
Línea 44... Línea 66...
44
    {
66
        $this->api = $api;
45
        $this->api = $api;
67
        $this->nextHandler = $nextHandler;
46
        $this->nextHandler = $nextHandler;
68
        $this->config = $config;
47
    }
69
    }
48
 
70
 
49
    public function __invoke(
71
    public function __invoke(
50
        CommandInterface $command,
72
        CommandInterface $command,
-
 
73
        RequestInterface $request
-
 
74
    ) {
-
 
75
        $next = $this->nextHandler;
51
        RequestInterface $request
76
        $name = $command->getName();
-
 
77
        $body = $request->getBody();
-
 
78
        $operation = $this->api->getOperation($name);
-
 
79
        $mode = $this->config['request_checksum_calculation']
-
 
80
            ?? self::DEFAULT_CALCULATION_MODE;
-
 
81
 
52
    ) {
82
        $command->getMetricsBuilder()->identifyMetricByValueAndAppend(
53
        $next = $this->nextHandler;
83
            'request_checksum_calculation',
-
 
84
            $mode
54
        $name = $command->getName();
85
        );
-
 
86
 
-
 
87
        // Trigger warning if AddContentMD5 is specified for PutObject or UploadPart
-
 
88
        $this->handleDeprecatedAddContentMD5($command);
55
        $body = $request->getBody();
89
 
-
 
90
        $checksumInfo = $operation['httpChecksum'] ?? [];
-
 
91
        $checksumMemberName = $checksumInfo['requestAlgorithmMember'] ?? '';
Línea 56... Línea -...
56
 
-
 
57
        //Checks if AddContentMD5 has been specified for PutObject or UploadPart
-
 
58
        $addContentMD5 = isset($command['AddContentMD5'])
92
        $checksumMember = !empty($checksumMemberName)
59
            ?  $command['AddContentMD5']
-
 
60
            : null;
93
            ? $operation->getInput()->getMember($checksumMemberName)
61
 
-
 
62
        $op = $this->api->getOperation($command->getName());
94
            : null;
63
 
95
        $checksumRequired = $checksumInfo['requestChecksumRequired'] ?? false;
64
        $checksumInfo = isset($op['httpChecksum'])
-
 
65
            ? $op['httpChecksum']
96
        $requestedAlgorithm = $command[$checksumMemberName] ?? null;
66
            : [];
97
 
67
        $checksumMemberName = array_key_exists('requestAlgorithmMember', $checksumInfo)
98
        $shouldAddChecksum = $this->shouldAddChecksum(
68
            ? $checksumInfo['requestAlgorithmMember']
99
            $mode,
69
            : "";
-
 
70
        $requestedAlgorithm = isset($command[$checksumMemberName])
100
            $checksumRequired,
71
            ? $command[$checksumMemberName]
101
            $checksumMember,
72
            : null;
-
 
73
        if (!empty($checksumMemberName) && !empty($requestedAlgorithm)) {
102
            $requestedAlgorithm
74
            $requestedAlgorithm = strtolower($requestedAlgorithm);
-
 
75
            $checksumMember = $op->getInput()->getMember($checksumMemberName);
-
 
76
            $supportedAlgorithms = isset($checksumMember['enum'])
103
        );
77
                ? array_map('strtolower', $checksumMember['enum'])
-
 
78
                : null;
104
        if ($shouldAddChecksum) {
79
            if (is_array($supportedAlgorithms)
-
 
80
                && in_array($requestedAlgorithm, $supportedAlgorithms)
-
 
81
            ) {
-
 
82
                $headerName = "x-amz-checksum-{$requestedAlgorithm}";
-
 
83
                $encoded = $this->getEncodedValue($requestedAlgorithm, $body);
-
 
84
                if (!$request->hasHeader($headerName)) {
-
 
85
                    $request = $request->withHeader($headerName, $encoded);
-
 
86
                }
105
            if (!$this->hasAlgorithmHeader($request)) {
87
            } else {
-
 
88
                throw new InvalidArgumentException(
106
                $supportedAlgorithms =  array_map('strtolower', $checksumMember['enum'] ?? []);
89
                    "Unsupported algorithm supplied for input variable {$checksumMemberName}."
-
 
Línea 90... Línea -...
90
                    . "  Supported checksums for this operation include: "
-
 
91
                    . implode(", ", $supportedAlgorithms) . "."
-
 
92
                );
-
 
93
            }
-
 
94
            return $next($command, $request);
-
 
95
        }
-
 
96
 
-
 
97
        if (!empty($checksumInfo)) {
-
 
98
        //if the checksum member is absent, check if it's required
107
                $algorithm = $this->determineChecksumAlgorithm(
99
        $checksumRequired = isset($checksumInfo['requestChecksumRequired'])
108
                    $supportedAlgorithms,
100
            ? $checksumInfo['requestChecksumRequired']
109
                    $requestedAlgorithm,
101
            : null;
-
 
102
            if ((!empty($checksumRequired) && !$request->hasHeader('Content-MD5'))
110
                    $checksumMemberName
103
                || (in_array($name, self::$sha256AndMd5) && $addContentMD5)
-
 
104
            ) {
111
                );
105
                // Set the content MD5 header for operations that require it.
112
                $request = $this->addAlgorithmHeader($algorithm, $request, $body);
Línea 106... Línea 113...
106
                $request = $request->withHeader(
113
 
107
                    'Content-MD5',
114
                $command->getMetricsBuilder()->identifyMetricByValueAndAppend(
108
                    base64_encode(Psr7\Utils::hash($body, 'md5', true))
115
                    'request_checksum',
109
                );
116
                    $algorithm
110
                return $next($command, $request);
117
                );
111
            }
118
            }
-
 
119
        }
-
 
120
 
-
 
121
        // Set the content hash header if ContentSHA256 is provided
112
        }
122
        if (isset(self::$sha256[$name]) && $command['ContentSHA256']) {
Línea 113... Línea 123...
113
 
123
            $request = $request->withHeader(
114
        if (in_array($name, self::$sha256AndMd5) && $command['ContentSHA256']) {
124
                'X-Amz-Content-Sha256',
-
 
125
                $command['ContentSHA256']
-
 
126
            );
-
 
127
            $command->getMetricsBuilder()->append(
-
 
128
                MetricsBuilder::FLEXIBLE_CHECKSUMS_REQ_SHA256
-
 
129
            );
-
 
130
        }
-
 
131
 
-
 
132
        return $next($command, $request);
-
 
133
    }
-
 
134
 
-
 
135
    /**
-
 
136
     * @param CommandInterface $command
-
 
137
     *
-
 
138
     * @return void
-
 
139
     */
-
 
140
    private function handleDeprecatedAddContentMD5(CommandInterface $command): void
-
 
141
    {
-
 
142
        if (!empty($command['AddContentMD5'])) {
-
 
143
            trigger_error(
-
 
144
                'S3 no longer supports MD5 checksums. ' .
-
 
145
                'A CRC32 checksum will be computed and applied on your behalf.',
-
 
146
                E_USER_DEPRECATED
-
 
147
            );
-
 
148
            $command['ChecksumAlgorithm'] = self::DEFAULT_ALGORITHM;
-
 
149
        }
-
 
150
    }
-
 
151
 
-
 
152
    /**
-
 
153
     * @param string $mode
-
 
154
     * @param Shape|null $checksumMember
-
 
155
     * @param string $name
-
 
156
     * @param bool $checksumRequired
-
 
157
     * @param string|null $requestedAlgorithm
-
 
158
     *
-
 
159
     * @return bool
-
 
160
     */
-
 
161
    private function shouldAddChecksum(
-
 
162
        string $mode,
-
 
163
        bool $checksumRequired,
-
 
164
        ?Shape $checksumMember,
-
 
165
        ?string $requestedAlgorithm
-
 
166
    ): bool
-
 
167
    {
-
 
168
        return ($mode === 'when_supported' && $checksumMember)
-
 
169
            || ($mode === 'when_required'
-
 
170
                && ($checksumRequired || ($checksumMember && $requestedAlgorithm)));
-
 
171
    }
-
 
172
 
-
 
173
    /**
-
 
174
     * @param Shape|null $checksumMember
-
 
175
     * @param string|null $requestedAlgorithm
-
 
176
     * @param string|null $checksumMemberName
-
 
177
     *
-
 
178
     * @return string
-
 
179
     */
-
 
180
    private function determineChecksumAlgorithm(
-
 
181
        array $supportedAlgorithms,
-
 
182
        ?string $requestedAlgorithm,
-
 
183
        ?string $checksumMemberName
-
 
184
    ): string
-
 
185
    {
-
 
186
        $algorithm = self::DEFAULT_ALGORITHM;
-
 
187
 
-
 
188
        if ($requestedAlgorithm) {
-
 
189
            $requestedAlgorithm = strtolower($requestedAlgorithm);
-
 
190
            if (!in_array($requestedAlgorithm, $supportedAlgorithms)) {
-
 
191
                throw new InvalidArgumentException(
-
 
192
                    "Unsupported algorithm supplied for input variable {$checksumMemberName}. " .
-
 
193
                    "Supported checksums for this operation include: "
-
 
194
                    . implode(", ", $supportedAlgorithms) . "."
-
 
195
                );
-
 
196
            }
-
 
197
            $algorithm = $requestedAlgorithm;
-
 
198
        }
-
 
199
 
-
 
200
        return $algorithm;
-
 
201
    }
-
 
202
 
-
 
203
    /**
-
 
204
     * @param string $requestedAlgorithm
-
 
205
     * @param RequestInterface $request
-
 
206
     * @param StreamInterface $body
-
 
207
     *
-
 
208
     * @return RequestInterface
-
 
209
     */
-
 
210
    private function addAlgorithmHeader(
-
 
211
        string $requestedAlgorithm,
-
 
212
        RequestInterface $request,
-
 
213
        StreamInterface $body
-
 
214
    ): RequestInterface
-
 
215
    {
-
 
216
        $headerName = "x-amz-checksum-{$requestedAlgorithm}";
-
 
217
        if (!$request->hasHeader($headerName)) {
-
 
218
            $encoded = self::getEncodedValue($requestedAlgorithm, $body);
-
 
219
            $request = $request->withHeader($headerName, $encoded);
-
 
220
        }
-
 
221
 
-
 
222
        return $request;
-
 
223
    }
-
 
224
 
-
 
225
    /**
-
 
226
     * @param RequestInterface $request
-
 
227
     *
-
 
228
     * @return bool
-
 
229
     */
-
 
230
    private function hasAlgorithmHeader(RequestInterface $request): bool
-
 
231
    {
-
 
232
        $headers = $request->getHeaders();
115
            // Set the content hash header if provided in the parameters.
233