FV Flowplayer Video Player - Version 7.2.1.727

Version Description

Download this release

Release Info

Developer FolioVision
Plugin Icon 128x128 FV Flowplayer Video Player
Version 7.2.1.727
Comparing to
See all releases

Code changes from version 7.1.15.727 to 7.2.1.727

Files changed (195) hide show
  1. controller/backend.php +1 -18
  2. controller/editor.php +1 -1
  3. controller/settings.php +22 -0
  4. css/bigplay.svg +50 -1
  5. css/controls.svg +172 -1
  6. css/flowplayer.css +1 -0
  7. css/s3-browser.css +456 -0
  8. css/shortcode-editor.css +4 -0
  9. flowplayer.php +16 -11
  10. flowplayer/fv-flowplayer.min.js +2 -1
  11. includes/aws/Aws/Api/AbstractModel.php +67 -0
  12. includes/aws/Aws/Api/ApiProvider.php +241 -0
  13. includes/aws/Aws/Api/DateTimeResult.php +41 -0
  14. includes/aws/Aws/Api/DocModel.php +128 -0
  15. includes/aws/Aws/Api/ErrorParser/JsonParserTrait.php +26 -0
  16. includes/aws/Aws/Api/ErrorParser/JsonRpcErrorParser.php +31 -0
  17. includes/aws/Aws/Api/ErrorParser/RestJsonErrorParser.php +35 -0
  18. includes/aws/Aws/Api/ErrorParser/XmlErrorParser.php +82 -0
  19. includes/aws/Aws/Api/ListShape.php +35 -0
  20. includes/aws/Aws/Api/MapShape.php +54 -0
  21. includes/aws/Aws/Api/Operation.php +97 -0
  22. includes/aws/Aws/Api/Parser/AbstractParser.php +35 -0
  23. includes/aws/Aws/Api/Parser/AbstractRestParser.php +154 -0
  24. includes/aws/Aws/Api/Parser/Crc32ValidatingParser.php +47 -0
  25. includes/aws/Aws/Api/Parser/Exception/ParserException.php +4 -0
  26. includes/aws/Aws/Api/Parser/JsonParser.php +58 -0
  27. includes/aws/Aws/Api/Parser/JsonRpcParser.php +40 -0
  28. includes/aws/Aws/Api/Parser/PayloadParserTrait.php +51 -0
  29. includes/aws/Aws/Api/Parser/QueryParser.php +52 -0
  30. includes/aws/Aws/Api/Parser/RestJsonParser.php +39 -0
  31. includes/aws/Aws/Api/Parser/RestXmlParser.php +36 -0
  32. includes/aws/Aws/Api/Parser/XmlParser.php +134 -0
  33. includes/aws/Aws/Api/Serializer/Ec2ParamBuilder.php +40 -0
  34. includes/aws/Aws/Api/Serializer/JsonBody.php +90 -0
  35. includes/aws/Aws/Api/Serializer/JsonRpcSerializer.php +69 -0
  36. includes/aws/Aws/Api/Serializer/QueryParamBuilder.php +154 -0
  37. includes/aws/Aws/Api/Serializer/QuerySerializer.php +69 -0
  38. includes/aws/Aws/Api/Serializer/RestJsonSerializer.php +39 -0
  39. includes/aws/Aws/Api/Serializer/RestSerializer.php +193 -0
  40. includes/aws/Aws/Api/Serializer/RestXmlSerializer.php +34 -0
  41. includes/aws/Aws/Api/Serializer/XmlBody.php +217 -0
  42. includes/aws/Aws/Api/Service.php +404 -0
  43. includes/aws/Aws/Api/Shape.php +69 -0
  44. includes/aws/Aws/Api/ShapeMap.php +66 -0
  45. includes/aws/Aws/Api/StructureShape.php +79 -0
  46. includes/aws/Aws/Api/TimestampShape.php +48 -0
  47. includes/aws/Aws/Api/Validator.php +236 -0
  48. includes/aws/Aws/ApiGateway/ApiGatewayClient.php +166 -0
  49. includes/aws/Aws/ApiGateway/Exception/ApiGatewayException.php +9 -0
  50. includes/aws/Aws/AwsClient.php +351 -0
  51. includes/aws/Aws/AwsClientInterface.php +169 -0
  52. includes/aws/Aws/CacheInterface.php +34 -0
  53. includes/aws/Aws/ClientResolver.php +548 -0
  54. includes/aws/Aws/CloudFront/CloudFrontClient.php +142 -0
  55. includes/aws/Aws/CloudFront/CookieSigner.php +65 -0
  56. includes/aws/Aws/CloudFront/Exception/CloudFrontException.php +9 -0
  57. includes/aws/Aws/CloudFront/Signer.php +108 -0
  58. includes/aws/Aws/CloudFront/UrlSigner.php +119 -0
  59. includes/aws/Aws/Command.php +57 -0
  60. includes/aws/Aws/CommandInterface.php +42 -0
  61. includes/aws/Aws/CommandPool.php +144 -0
  62. includes/aws/Aws/ConfigService/ConfigServiceClient.php +56 -0
  63. includes/aws/Aws/ConfigService/Exception/ConfigServiceException.php +9 -0
  64. includes/aws/Aws/Credentials/CredentialProvider.php +324 -0
  65. includes/aws/Aws/Credentials/Credentials.php +91 -0
  66. includes/aws/Aws/Credentials/CredentialsInterface.php +52 -0
  67. includes/aws/Aws/Credentials/InstanceProfileProvider.php +102 -0
  68. includes/aws/Aws/DataPipeline/DataPipelineClient.php +48 -0
  69. includes/aws/Aws/DataPipeline/Exception/DataPipelineException.php +9 -0
  70. includes/aws/Aws/DirectConnect/DirectConnectClient.php +48 -0
  71. includes/aws/Aws/DirectConnect/Exception/DirectConnectException.php +9 -0
  72. includes/aws/Aws/DirectoryService/DirectoryServiceClient.php +54 -0
  73. includes/aws/Aws/DirectoryService/Exception/DirectoryServiceException.php +9 -0
  74. includes/aws/Aws/DoctrineCacheAdapter.php +55 -0
  75. includes/aws/Aws/Endpoint/EndpointProvider.php +96 -0
  76. includes/aws/Aws/Endpoint/PatternEndpointProvider.php +51 -0
  77. includes/aws/Aws/Exception/AwsException.php +160 -0
  78. includes/aws/Aws/Exception/CouldNotCreateChecksumException.php +19 -0
  79. includes/aws/Aws/Exception/CredentialsException.php +4 -0
  80. includes/aws/Aws/Exception/MultipartUploadException.php +57 -0
  81. includes/aws/Aws/Exception/UnresolvedApiException.php +4 -0
  82. includes/aws/Aws/Exception/UnresolvedEndpointException.php +4 -0
  83. includes/aws/Aws/Exception/UnresolvedSignatureException.php +4 -0
  84. includes/aws/Aws/Firehose/Exception/FirehoseException.php +9 -0
  85. includes/aws/Aws/Firehose/FirehoseClient.php +24 -0
  86. includes/aws/Aws/Glacier/Exception/GlacierException.php +9 -0
  87. includes/aws/Aws/Glacier/GlacierClient.php +247 -0
  88. includes/aws/Aws/Glacier/MultipartUploader.php +281 -0
  89. includes/aws/Aws/Glacier/TreeHash.php +118 -0
  90. includes/aws/Aws/Handler/GuzzleV5/GuzzleHandler.php +181 -0
  91. includes/aws/Aws/Handler/GuzzleV5/GuzzleStream.php +24 -0
  92. includes/aws/Aws/Handler/GuzzleV5/PsrStream.php +34 -0
  93. includes/aws/Aws/Handler/GuzzleV6/GuzzleHandler.php +59 -0
  94. includes/aws/Aws/HandlerList.php +424 -0
  95. includes/aws/Aws/HasDataTrait.php +60 -0
  96. includes/aws/Aws/HashInterface.php +27 -0
  97. includes/aws/Aws/HashingStream.php +60 -0
  98. includes/aws/Aws/History.php +152 -0
  99. includes/aws/Aws/Iam/Exception/IamException.php +9 -0
  100. includes/aws/Aws/Iam/IamClient.php +236 -0
  101. includes/aws/Aws/Inspector/Exception/InspectorException.php +9 -0
  102. includes/aws/Aws/Inspector/InspectorClient.php +82 -0
  103. includes/aws/Aws/Iot/Exception/IotException.php +9 -0
  104. includes/aws/Aws/Iot/IotClient.php +88 -0
  105. includes/aws/Aws/IotDataPlane/Exception/IotDataPlaneException.php +9 -0
  106. includes/aws/Aws/IotDataPlane/IotDataPlaneClient.php +18 -0
  107. includes/aws/Aws/JsonCompiler.php +25 -0
  108. includes/aws/Aws/LruArrayCache.php +74 -0
  109. includes/aws/Aws/Middleware.php +308 -0
  110. includes/aws/Aws/MockHandler.php +131 -0
  111. includes/aws/Aws/Multipart/AbstractUploadManager.php +297 -0
  112. includes/aws/Aws/Multipart/AbstractUploader.php +129 -0
  113. includes/aws/Aws/Multipart/UploadState.php +145 -0
  114. includes/aws/Aws/PhpHash.php +81 -0
  115. includes/aws/Aws/Result.php +56 -0
  116. includes/aws/Aws/ResultInterface.php +54 -0
  117. includes/aws/Aws/ResultPaginator.php +179 -0
  118. includes/aws/Aws/RetryMiddleware.php +125 -0
  119. includes/aws/Aws/S3/AmbiguousSuccessParser.php +60 -0
  120. includes/aws/Aws/S3/ApplyChecksumMiddleware.php +74 -0
  121. includes/aws/Aws/S3/BatchDelete.php +237 -0
  122. includes/aws/Aws/S3/BucketEndpointMiddleware.php +75 -0
  123. includes/aws/Aws/S3/Exception/DeleteMultipleObjectsException.php +62 -0
  124. includes/aws/Aws/S3/Exception/PermanentRedirectException.php +4 -0
  125. includes/aws/Aws/S3/Exception/S3Exception.php +9 -0
  126. includes/aws/Aws/S3/GetBucketLocationParser.php +42 -0
  127. includes/aws/Aws/S3/MultipartCopy.php +167 -0
  128. includes/aws/Aws/S3/MultipartUploader.php +144 -0
  129. includes/aws/Aws/S3/MultipartUploadingTrait.php +126 -0
  130. includes/aws/Aws/S3/PermanentRedirectMiddleware.php +62 -0
  131. includes/aws/Aws/S3/PostObject.php +159 -0
  132. includes/aws/Aws/S3/PutObjectUrlMiddleware.php +57 -0
  133. includes/aws/Aws/S3/RetryableMalformedResponseParser.php +48 -0
  134. includes/aws/Aws/S3/S3Client.php +855 -0
  135. includes/aws/Aws/S3/S3UriParser.php +110 -0
  136. includes/aws/Aws/S3/SSECMiddleware.php +75 -0
  137. includes/aws/Aws/S3/StreamWrapper.php +949 -0
  138. includes/aws/Aws/S3/Transfer.php +379 -0
  139. includes/aws/Aws/Sdk.php +149 -0
  140. includes/aws/Aws/Signature/AnonymousSignature.php +26 -0
  141. includes/aws/Aws/Signature/S3SignatureV4.php +45 -0
  142. includes/aws/Aws/Signature/SignatureInterface.php +44 -0
  143. includes/aws/Aws/Signature/SignatureProvider.php +123 -0
  144. includes/aws/Aws/Signature/SignatureV4.php +368 -0
  145. includes/aws/Aws/StorageGateway/Exception/StorageGatewayException.php +9 -0
  146. includes/aws/Aws/StorageGateway/StorageGatewayClient.php +116 -0
  147. includes/aws/Aws/Support/Exception/SupportException.php +9 -0
  148. includes/aws/Aws/Support/SupportClient.php +38 -0
  149. includes/aws/Aws/TraceMiddleware.php +302 -0
  150. includes/aws/Aws/Waiter.php +266 -0
  151. includes/aws/Aws/WorkSpaces/Exception/WorkSpacesException.php +9 -0
  152. includes/aws/Aws/WorkSpaces/WorkSpacesClient.php +24 -0
  153. includes/aws/Aws/WrappedHttpHandler.php +171 -0
  154. includes/aws/Aws/data/cloudfront/2015-09-17/api-2.json.php +3 -0
  155. includes/aws/Aws/data/cloudfront/2015-09-17/examples-1.json.php +3 -0
  156. includes/aws/Aws/data/cloudfront/2015-09-17/paginators-1.json.php +3 -0
  157. includes/aws/Aws/data/cloudfront/2015-09-17/waiters-2.json.php +3 -0
  158. includes/aws/Aws/data/config/2014-11-12/api-2.json.php +3 -0
  159. includes/aws/Aws/data/config/2014-11-12/paginators-1.json.php +3 -0
  160. includes/aws/Aws/data/endpoints.json.php +3 -0
  161. includes/aws/Aws/data/manifest.json.php +3 -0
  162. includes/aws/Aws/data/s3/2006-03-01/api-2.json.php +3 -0
  163. includes/aws/Aws/data/s3/2006-03-01/paginators-1.json.php +3 -0
  164. includes/aws/Aws/data/s3/2006-03-01/waiters-2.json.php +3 -0
  165. includes/aws/Aws/functions.php +351 -0
  166. includes/aws/CHANGELOG.md +1387 -0
  167. includes/aws/GuzzleHttp/Client.php +397 -0
  168. includes/aws/GuzzleHttp/ClientInterface.php +84 -0
  169. includes/aws/GuzzleHttp/Cookie/CookieJar.php +277 -0
  170. includes/aws/GuzzleHttp/Cookie/CookieJarInterface.php +84 -0
  171. includes/aws/GuzzleHttp/Cookie/FileCookieJar.php +87 -0
  172. includes/aws/GuzzleHttp/Cookie/SessionCookieJar.php +72 -0
  173. includes/aws/GuzzleHttp/Cookie/SetCookie.php +404 -0
  174. includes/aws/GuzzleHttp/Exception/BadResponseException.php +7 -0
  175. includes/aws/GuzzleHttp/Exception/ClientException.php +7 -0
  176. includes/aws/GuzzleHttp/Exception/ConnectException.php +37 -0
  177. includes/aws/GuzzleHttp/Exception/GuzzleException.php +4 -0
  178. includes/aws/GuzzleHttp/Exception/RequestException.php +188 -0
  179. includes/aws/GuzzleHttp/Exception/SeekException.php +27 -0
  180. includes/aws/GuzzleHttp/Exception/ServerException.php +7 -0
  181. includes/aws/GuzzleHttp/Exception/TooManyRedirectsException.php +4 -0
  182. includes/aws/GuzzleHttp/Exception/TransferException.php +4 -0
  183. includes/aws/GuzzleHttp/Handler/CurlFactory.php +531 -0
  184. includes/aws/GuzzleHttp/Handler/CurlFactoryInterface.php +27 -0
  185. includes/aws/GuzzleHttp/Handler/CurlHandler.php +45 -0
  186. includes/aws/GuzzleHttp/Handler/CurlMultiHandler.php +197 -0
  187. includes/aws/GuzzleHttp/Handler/EasyHandle.php +87 -0
  188. includes/aws/GuzzleHttp/Handler/MockHandler.php +176 -0
  189. includes/aws/GuzzleHttp/Handler/Proxy.php +55 -0
  190. includes/aws/GuzzleHttp/Handler/StreamHandler.php +458 -0
  191. includes/aws/GuzzleHttp/HandlerStack.php +273 -0
  192. includes/aws/GuzzleHttp/MessageFormatter.php +182 -0
  193. includes/aws/GuzzleHttp/Middleware.php +249 -0
  194. includes/aws/GuzzleHttp/Pool.php +123 -0
  195. includes/aws/GuzzleHttp/PrepareBodyMiddleware.php +50 -0
controller/backend.php CHANGED
@@ -608,23 +608,6 @@ function fv_wp_flowplayer_admin_notice() {
608
  </div>';
609
  }
610
 
611
- global $FV_Player_Pro;
612
- if( $FV_Player_Pro && version_compare($FV_Player_Pro->version,'0.5') == -1 ) :
613
- ?>
614
- <div class="error">
615
- <p><?php _e( 'FV Player: Your pro extension is installed, but it\'s not compatible with FV Player 6! Make sure you upgrade your FV Player Pro to version 0.5 or above.', 'my-text-domain' ); ?></p>
616
- </div>
617
- <?php
618
- endif;
619
-
620
- /*if( isset($_GET['page']) && $_GET['page'] == 'backend.php' ) {
621
- $options = get_option( 'fvwpflowplayer' );
622
- if( $options['key'] == 'false' ) {
623
- echo '<div class="updated"><p>';
624
- printf(__('Brand new version of Flowplayer for HTML5. <a href="http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer/buy">Licenses half price</a> in May.' ) );
625
- echo "</p></div>";
626
- }
627
- }*/
628
  }
629
 
630
 
@@ -803,7 +786,7 @@ function fv_player_pro_version_check() {
803
  if( isset($FV_Player_Pro) && !empty($FV_Player_Pro->version) && version_compare( str_replace('.beta','',$FV_Player_Pro->version),'7.1.14.727' ) == -1 ) :
804
  ?>
805
  <div class="error">
806
- <p><?php _e( 'FV Player: Please upgrade to FV Player Pro version 7.1.14.727 or above!', 'fv-player-pro' ); ?></p>
807
  </div>
808
  <?php
809
  endif;
608
  </div>';
609
  }
610
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
611
  }
612
 
613
 
786
  if( isset($FV_Player_Pro) && !empty($FV_Player_Pro->version) && version_compare( str_replace('.beta','',$FV_Player_Pro->version),'7.1.14.727' ) == -1 ) :
787
  ?>
788
  <div class="error">
789
+ <p><?php _e( 'FV Player: Please upgrade to FV Player Pro version 7.1.14.727 or above!', 'fv-wordpress-flowplayer' ); ?></p>
790
  </div>
791
  <?php
792
  endif;
controller/editor.php CHANGED
@@ -254,4 +254,4 @@ function fv_wp_flowplayer_save_to_media_library( $image_url, $post_id ) {
254
 
255
  return $attach_id;
256
 
257
- }
254
 
255
  return $attach_id;
256
 
257
+ }
controller/settings.php CHANGED
@@ -350,3 +350,25 @@ function flowplayer_admin_footer_wp_js_restore() {
350
  </script>
351
  <?php
352
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  </script>
351
  <?php
352
  }
353
+
354
+
355
+
356
+ function fv_player_get_aws_regions($translation_domain = 'fv-wordpress-flowplayer') {
357
+
358
+ return array(
359
+ 'us-east-1' => __('US East (N. Virginia)', $translation_domain),
360
+ 'us-east-2' => __('US East (Ohio)', $translation_domain),
361
+ 'us-west-1' => __('US West (N. California)', $translation_domain),
362
+ 'us-west-2' => __('US West (Oregon)', $translation_domain),
363
+ 'ca-central-1' => __('Canada (Central)', $translation_domain),
364
+ 'ap-south-1' => __('Asia Pacific (Mumbai)', $translation_domain),
365
+ 'ap-northeast-2' => __('Asia Pacific (Seoul)', $translation_domain),
366
+ 'ap-southeast-1' => __('Asia Pacific (Singapore)', $translation_domain),
367
+ 'ap-southeast-2' => __('Asia Pacific (Sydney)', $translation_domain),
368
+ 'ap-northeast-1' => __('Asia Pacific (Tokyo)', $translation_domain),
369
+ 'eu-central-1' => __('EU (Frankfurt)', $translation_domain),
370
+ 'eu-west-1' => __('EU (Ireland)', $translation_domain),
371
+ 'eu-west-2' => __('EU (London)', $translation_domain),
372
+ 'sa-east-1' => __('South America (S&atilde;o Paulo)', $translation_domain),
373
+ );
374
+ }
css/bigplay.svg CHANGED
@@ -1 +1,50 @@
1
- <?xml version="1.0" standalone="no"?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1 -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg id="bigplay-gradient.fw-Page%201" viewBox="0 0 100 200" style="background-color:#ffffff00" version="1.1"
5
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
6
+ x="0px" y="0px" width="100px" height="200px"
7
+ >
8
+ <defs>
9
+ <radialGradient id="gradient1" cx="50%" cy="50%" r="50%">
10
+ <stop stop-color="#222222" stop-opacity="0" offset="70%"/>
11
+ <stop stop-color="#222222" stop-opacity="0.0118" offset="70.202%"/>
12
+ <stop stop-color="#333333" stop-opacity="1" offset="85%"/>
13
+ <stop stop-color="#333333" stop-opacity="0" offset="100%"/>
14
+ </radialGradient>
15
+ <radialGradient id="gradient2" cx="50%" cy="50%" r="50%">
16
+ <stop stop-color="#bbbbbb" stop-opacity="0" offset="70%"/>
17
+ <stop stop-color="#bbbbbb" stop-opacity="0.0118" offset="70.202%"/>
18
+ <stop stop-color="#bbbbbb" stop-opacity="1" offset="85%"/>
19
+ <stop stop-color="#bbbbbb" stop-opacity="0" offset="100%"/>
20
+ </radialGradient>
21
+ <filter id="filter1" x="-100%" y="-100%" width="300%" height="300%">
22
+ <!-- Glow -->
23
+ <feColorMatrix result="out" in="SourceGraphic" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0"/>
24
+ <feMorphology result="out" in="out" operator="dilate" radius="3"/>
25
+ <feGaussianBlur result="out" in="out" stdDeviation="1.5"/>
26
+ <feBlend in="SourceGraphic" in2="out" mode="normal" result="Glow1"/>
27
+ </filter>
28
+ <filter id="filter2" x="-100%" y="-100%" width="300%" height="300%">
29
+ <!-- Glow -->
30
+ <feColorMatrix result="out" in="SourceGraphic" type="matrix" values="0 0 0 0.8667 0 0 0 0 0.8667 0 0 0 0 0.8667 0 0 0 0 0.251 0"/>
31
+ <feMorphology result="out" in="out" operator="dilate" radius="3"/>
32
+ <feGaussianBlur result="out" in="out" stdDeviation="1.5"/>
33
+ <feBlend in="SourceGraphic" in2="out" mode="normal" result="Glow2"/>
34
+ </filter>
35
+ </defs>
36
+ <g id="Background">
37
+ </g>
38
+ <g id="dark%20shadow">
39
+ <path d="M 22 50 C 22 34.5358 34.5358 22 50 22 C 65.4642 22 78 34.5358 78 50 C 78 65.4642 65.4642 78 50 78 C 34.5358 78 22 65.4642 22 50 ZM 5 50 C 5 74.8531 25.1469 95 50 95 C 74.8531 95 95 74.8531 95 50 C 95 25.1469 74.8531 5 50 5 C 25.1469 5 5 25.1469 5 50 Z" fill="url(#gradient1)"/>
40
+ <path d="M 22 150 C 22 134.5358 34.5358 122 50 122 C 65.4642 122 78 134.5358 78 150 C 78 165.4642 65.4642 178 50 178 C 34.5358 178 22 165.4642 22 150 ZM 5 150 C 5 174.8531 25.1469 195 50 195 C 74.8531 195 95 174.8531 95 150 C 95 125.1469 74.8531 105 50 105 C 25.1469 105 5 125.1469 5 150 Z" fill="url(#gradient2)"/>
41
+ </g>
42
+ <g id="dark">
43
+ <path id="Polygon" filter="url(#filter1)" d="M 72.5 49.5 L 38.75 68.9856 L 38.75 30.0144 L 72.5 49.5 Z" fill="#ffffff"/>
44
+ <path id="Ellipse" d="M 13 50.5 C 13 29.7891 29.7891 13 50.5 13 C 71.2109 13 88 29.7891 88 50.5 C 88 71.2109 71.2109 88 50.5 88 C 29.7891 88 13 71.2109 13 50.5 Z" stroke="#ffffff" stroke-width="5" fill="none"/>
45
+ </g>
46
+ <g id="light">
47
+ <path id="Polygon2" filter="url(#filter2)" d="M 72.5 149.5 L 38.75 168.9856 L 38.75 130.0144 L 72.5 149.5 Z" fill="#ffffff"/>
48
+ <path id="Ellipse2" d="M 13 150.5 C 13 129.7891 29.7891 113 50.5 113 C 71.2109 113 88 129.7891 88 150.5 C 88 171.211 71.2109 188 50.5 188 C 29.7891 188 13 171.211 13 150.5 Z" stroke="#ffffff" stroke-width="5" fill="none"/>
49
+ </g>
50
+ </svg>
css/controls.svg CHANGED
@@ -1 +1,172 @@
1
- <?xml version="1.0" standalone="no"?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1 -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg id="controls.fw-Page%201" viewBox="0 0 144 32" style="background-color:#ffffff00" version="1.1"
5
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
6
+ x="0px" y="0px" width="144px" height="32px"
7
+ >
8
+ <defs>
9
+ <radialGradient id="gradient1" cx="50%" cy="50%" r="50%">
10
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
11
+ <stop stop-color="#f2f2f2" stop-opacity="0.2" offset="100%"/>
12
+ </radialGradient>
13
+ <linearGradient id="gradient2" x1="50%" y1="-7.8652%" x2="50%" y2="249.6629%">
14
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
15
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
16
+ </linearGradient>
17
+ <linearGradient id="gradient3" x1="50%" y1="0%" x2="50%" y2="238.75%">
18
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
19
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
20
+ </linearGradient>
21
+ <linearGradient id="gradient4" x1="50%" y1="0%" x2="50%" y2="100%">
22
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
23
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
24
+ </linearGradient>
25
+ <linearGradient id="gradient5" x1="50%" y1="-33.3333%" x2="50%" y2="152.0833%">
26
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
27
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
28
+ </linearGradient>
29
+ <linearGradient id="gradient6" x1="50%" y1="0%" x2="50%" y2="100%">
30
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
31
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
32
+ </linearGradient>
33
+ <linearGradient id="gradient7" x1="50%" y1="-33.3333%" x2="50%" y2="152.0833%">
34
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
35
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
36
+ </linearGradient>
37
+ <linearGradient id="gradient8" x1="50%" y1="0%" x2="50%" y2="100%">
38
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
39
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
40
+ </linearGradient>
41
+ <linearGradient id="gradient9" x1="50%" y1="0%" x2="50%" y2="100%">
42
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
43
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
44
+ </linearGradient>
45
+ <linearGradient id="gradient10" x1="50%" y1="0%" x2="50%" y2="100%">
46
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
47
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
48
+ </linearGradient>
49
+ <linearGradient id="gradient11" x1="50%" y1="0%" x2="50%" y2="100%">
50
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
51
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
52
+ </linearGradient>
53
+ <linearGradient id="gradient12" x1="50%" y1="0%" x2="50%" y2="238.75%">
54
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
55
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
56
+ </linearGradient>
57
+ <linearGradient id="gradient13" x1="40%" y1="-140%" x2="40%" y2="98.75%">
58
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
59
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
60
+ </linearGradient>
61
+ <linearGradient id="gradient14" x1="50%" y1="0%" x2="50%" y2="238.75%">
62
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
63
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
64
+ </linearGradient>
65
+ <linearGradient id="gradient15" x1="60%" y1="-140%" x2="60%" y2="98.75%">
66
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
67
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
68
+ </linearGradient>
69
+ <linearGradient id="gradient16" x1="50%" y1="0%" x2="50%" y2="298.4375%">
70
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
71
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
72
+ </linearGradient>
73
+ <linearGradient id="gradient17" x1="50%" y1="0%" x2="50%" y2="238.75%">
74
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
75
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
76
+ </linearGradient>
77
+ <linearGradient id="gradient18" x1="50%" y1="-200%" x2="50%" y2="100%">
78
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
79
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
80
+ </linearGradient>
81
+ <linearGradient id="gradient19" x1="50%" y1="-200%" x2="50%" y2="110.9375%">
82
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
83
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
84
+ </linearGradient>
85
+ <linearGradient id="gradient20" x1="55%" y1="0%" x2="55%" y2="100%">
86
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
87
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
88
+ </linearGradient>
89
+ <linearGradient id="gradient21" x1="50%" y1="0%" x2="50%" y2="100%">
90
+ <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
91
+ <stop stop-color="#c8c8c8" stop-opacity="1" offset="99.4444%"/>
92
+ </linearGradient>
93
+ </defs>
94
+ <g id="BG">
95
+ </g>
96
+ <g id="controls">
97
+ <path id="Line" d="M 98.5 7.5 L 109.5 7.5 " stroke="#ffffff" stroke-width="1" fill="none"/>
98
+ <path id="Line2" d="M 98.5 3.5 L 109.5 3.5 " stroke="#ffffff" stroke-width="1" fill="none"/>
99
+ <path id="Line3" d="M 98.5 11.5 L 109.5 11.5 " stroke="#ffffff" stroke-width="1" fill="none"/>
100
+ <path id="Ellipse" d="M 108 11.5 C 108 10.6716 108.4477 10 109 10 C 109.5523 10 110 10.6716 110 11.5 C 110 12.3284 109.5523 13 109 13 C 108.4477 13 108 12.3284 108 11.5 Z" fill="#ffffff"/>
101
+ <path id="Ellipse2" d="M 104 7.5 C 104 6.6716 104.4477 6 105 6 C 105.5523 6 106 6.6716 106 7.5 C 106 8.3284 105.5523 9 105 9 C 104.4477 9 104 8.3284 104 7.5 Z" fill="#ffffff"/>
102
+ <path id="Ellipse3" d="M 108 3.5 C 108 2.6716 108.4477 2 109 2 C 109.5523 2 110 2.6716 110 3.5 C 110 4.3284 109.5523 5 109 5 C 108.4477 5 108 4.3284 108 3.5 Z" fill="#ffffff"/>
103
+ </g>
104
+ <g id="backlight">
105
+ <g id="off">
106
+ <rect x="83" y="21" width="10" height="6" stroke="#ffffff" stroke-width="1" fill="#333333"/>
107
+ </g>
108
+ <g id="on">
109
+ <path id="Ellipse4" d="M 81 8 C 81 5.2385 84.134 3 88 3 C 91.866 3 95 5.2385 95 8 C 95 10.7615 91.866 13 88 13 C 84.134 13 81 10.7615 81 8 Z" fill="url(#gradient1)"/>
110
+ <rect x="83" y="5" width="10" height="6" stroke="#ffffff" stroke-width="1" fill="#333333"/>
111
+ </g>
112
+ </g>
113
+ <g id="loop">
114
+ <g id="on2">
115
+ <path d="M 73.795 4.205 C 75.2155 4.8785 76.2 6.3234 76.2 8 C 76.2 10.3196 74.3196 12.2 72 12.2 C 69.6804 12.2 67.8 10.3196 67.8 8 C 67.8 6.3234 68.7845 4.8785 70.205 4.205 L 68.875 2.875 C 67.1501 3.9289 66 5.8306 66 8 C 66 11.3138 68.6862 14 72 14 C 75.3138 14 78 11.3138 78 8 C 78 5.8306 76.8499 3.9289 75.125 2.875 L 73.795 4.205 Z" fill="url(#gradient2)"/>
116
+ <path d="M 71 2 L 66 2 L 71 7 L 71 2 Z" fill="url(#gradient3)"/>
117
+ </g>
118
+ <g id="off2">
119
+ <path d="M 73.795 20.205 C 75.2155 20.8785 76.2 22.3234 76.2 24 C 76.2 26.3196 74.3196 28.2 72 28.2 C 69.6804 28.2 67.8 26.3196 67.8 24 C 67.8 22.3234 68.7845 20.8785 70.205 20.205 L 68.875 18.875 C 67.1501 19.9289 66 21.8306 66 24 C 66 27.3138 68.6862 30 72 30 C 75.3138 30 78 27.3138 78 24 C 78 21.8306 76.8499 19.9289 75.125 18.875 L 73.795 20.205 Z" fill="#a8a8b7"/>
120
+ <path d="M 71 18 L 66 18 L 71 23 L 71 18 Z" fill="#a8a8b7"/>
121
+ </g>
122
+ </g>
123
+ <g id="cc">
124
+ <rect visibility="hidden" x="49" y="2" width="14" height="12" stroke="#b0b0b0" stroke-width="1" fill="none"/>
125
+ <text visibility="hidden" x="49" y="17" width="14" fill="#ffffff" style="font-size: 10px; color: #ffffff; font-family: Arial; text-align: center; "><tspan><![CDATA[cc]]></tspan></text>
126
+ <path d="M 55 7 C 50.2813 3.7813 50.063 12.9405 55 10 " stroke="#ffffff" stroke-width="1" fill="none"/>
127
+ <path d="M 60 7 C 55.2813 3.7813 55.063 12.9405 60 10 " stroke="#ffffff" stroke-width="1" fill="none"/>
128
+ <path d="M 50 3 L 62 3 L 62 13 L 50 13 L 50 3 ZM 49 2 L 49 14 L 63 14 L 63 2 L 49 2 Z" fill="url(#gradient4)"/>
129
+ <rect x="49" y="2" width="14" height="12" fill="none"/>
130
+ </g>
131
+ <g id="volume">
132
+ <g id="no%20sound">
133
+ <rect x="17" y="5" width="5" height="6" fill="url(#gradient5)"/>
134
+ <path d="M 21 5 L 25 2 L 25 14 L 21 11.0625 L 21 5 Z" fill="url(#gradient6)"/>
135
+ </g>
136
+ <g id="sound%20bars">
137
+ <rect x="17" y="21" width="5" height="6" fill="url(#gradient7)"/>
138
+ <path d="M 21 21 L 25 18 L 25 30 L 21 27.0625 L 21 21 Z" fill="url(#gradient8)"/>
139
+ <path d="M 27 18 C 27 18 30.0625 17.375 30 24 C 29.9375 30.625 27 30 27 30 " stroke="#ffffff" stroke-width="1" fill="none"/>
140
+ <path d="M 26 21.0079 C 26 21.0079 28.041 20.6962 27.9994 24 C 27.9577 27.3038 26 26.9921 26 26.9921 " stroke="#ffffff" stroke-width="1" fill="none"/>
141
+ </g>
142
+ </g>
143
+ <g id="play/pause">
144
+ <g id="play">
145
+ <path id="Polygon" d="M 14 8.5 L 3 14 L 3 3 L 14 8.5 Z" fill="url(#gradient9)"/>
146
+ </g>
147
+ <g id="pause">
148
+ <rect x="3" y="18" width="3" height="12" fill="url(#gradient10)"/>
149
+ <rect x="10" y="18" width="3" height="12" fill="url(#gradient11)"/>
150
+ </g>
151
+ </g>
152
+ <g id="fullscreen">
153
+ <g id="enter%201">
154
+ <path d="M 34 2 L 39 2 L 34 7 L 34 2 Z" fill="url(#gradient12)"/>
155
+ <path d="M 34 14 L 39 14 L 34 9 L 34 14 Z" fill="url(#gradient13)"/>
156
+ <path d="M 46 2 L 41 2 L 46 7 L 46 2 Z" fill="url(#gradient14)"/>
157
+ <path d="M 46 14 L 41 14 L 46 9 L 46 14 Z" fill="url(#gradient15)"/>
158
+ </g>
159
+ <g id="exit">
160
+ <path d="M 42 22 L 46 22 L 42 18 L 42 22 Z" fill="url(#gradient16)"/>
161
+ <path d="M 38 22 L 38 18 L 34 22 L 38 22 Z" fill="url(#gradient17)"/>
162
+ <path d="M 38 26 L 34 26 L 38 30 L 38 26 Z" fill="url(#gradient18)"/>
163
+ <path d="M 42 26 L 42 30 L 46 26 L 42 26 Z" fill="url(#gradient19)"/>
164
+ </g>
165
+ </g>
166
+ <g id="stop">
167
+ <rect x="115" y="3" width="10" height="10" fill="url(#gradient20)"/>
168
+ </g>
169
+ <g id="chooser">
170
+ <path d="M 135.2346 6.1522 C 136.2551 5.7295 137.4251 6.2141 137.8478 7.2346 C 138.2704 8.2551 137.7859 9.425 136.7654 9.8478 C 135.7449 10.2705 134.5749 9.7859 134.1522 8.7654 C 133.7295 7.7449 134.2141 6.5749 135.2346 6.1522 ZM 133.2735 1.4176 L 136 4.0054 L 138.7265 1.4176 L 138.8246 5.1754 L 142.5824 5.2735 L 139.9946 8 L 142.5824 10.7265 L 138.8246 10.8246 L 138.7265 14.5824 L 136 11.9946 L 133.2735 14.5824 L 133.1754 10.8246 L 129.4176 10.7265 L 132.0054 8 L 129.4176 5.2735 L 133.1754 5.1754 L 133.2735 1.4176 Z" fill="url(#gradient21)"/>
171
+ </g>
172
+ </svg>
css/flowplayer.css CHANGED
@@ -1095,6 +1095,7 @@
1095
  padding: 0 !important;
1096
  float: left;
1097
  font-family: "Lucida Console", Monaco, monospace;
 
1098
  }
1099
  .fvp-share-bar label {
1100
  text-align: center !important;
1095
  padding: 0 !important;
1096
  float: left;
1097
  font-family: "Lucida Console", Monaco, monospace;
1098
+ list-style: none;
1099
  }
1100
  .fvp-share-bar label {
1101
  text-align: center !important;
css/s3-browser.css ADDED
@@ -0,0 +1,456 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Amazon S3 Browser */
2
+ @charset "utf-8";
3
+
4
+
5
+ .files-div .search {
6
+
7
+ margin-top: 45px;
8
+
9
+
10
+ }
11
+
12
+ .files-div {
13
+ font-size: 14px;
14
+ z-index: -4;
15
+ border-radius:20px;
16
+ min-height:440px;
17
+ padding: 10px 10px 10px 10px;
18
+ }
19
+
20
+
21
+ /* File manager */
22
+
23
+ .filemanager {
24
+ width: 95%;
25
+ max-width:1340px;
26
+ position: relative;
27
+ }
28
+ .filemanager input[type='search'] {
29
+ width:200px!important;
30
+ }
31
+
32
+ @media all and (max-width: 965px) {
33
+ .filemanager {
34
+ margin: 30px auto 0;
35
+ padding: 1px;
36
+ }
37
+ }
38
+
39
+
40
+ /* Breadcrumps */
41
+
42
+ .filemanager .breadcrumbs {
43
+ color: #000;
44
+ font-size: 18px;
45
+ font-weight: 700;
46
+ line-height: 35px;
47
+ }
48
+ .filemanager .breadcrumbs a:link, .breadcrumbs a:visited {
49
+ color: #000;
50
+ text-decoration: none;
51
+ }
52
+ .filemanager .breadcrumbs a:hover {
53
+ text-decoration: underline;
54
+ }
55
+ .filemanager .breadcrumbs .arrow {
56
+ color: #000;
57
+ font-size: 24px;
58
+ font-weight: 700;
59
+ line-height: 20px;
60
+ }
61
+
62
+
63
+ /* Search box */
64
+
65
+ .filemanager .search {
66
+ margin-top: 0 !important;
67
+ background-color: #fff;
68
+ position: absolute;
69
+ cursor: pointer;
70
+ right: 0 !important;
71
+ font-size: 17px;
72
+ color: #ffffff !important;
73
+ display: block !important;
74
+ width: 40px !important;
75
+ height: 40px !important;
76
+ }
77
+ .filemanager .search:before {
78
+ content: '';
79
+ position: absolute;
80
+ margin-top:11px;
81
+ width: 10px;
82
+ height: 11px;
83
+ border-radius: 50%;
84
+ border: 2px solid #333;
85
+ right: 8px;
86
+ }
87
+ .filemanager .search:after {
88
+ content: '';
89
+ width: 3px;
90
+ height: 10px;
91
+ background-color: #333;
92
+ border-radius: 2px;
93
+ position: absolute;
94
+ top: 25px;
95
+ right: 6px;
96
+ -webkit-transform: rotate(-45deg);
97
+ transform: rotate(-45deg);
98
+ }
99
+ .filemanager .search input[type=search] {
100
+ color: #4D535E;
101
+ background-color: #FFF;
102
+ width: 250px;
103
+ height: 44px;
104
+ margin-left: -215px;
105
+ padding-left: 20px;
106
+ text-decoration-color: #4d535e;
107
+ font-size: 16px;
108
+ font-weight: 400;
109
+ line-height: 20px;
110
+ display: none;
111
+ outline: none;
112
+ border: none;
113
+ padding-right: 10px;
114
+ -webkit-appearance: none;
115
+ }
116
+ ::-webkit-input-placeholder { /* WebKit browsers */
117
+ color: #4d535e;
118
+ }
119
+ :-moz-placeholder { /* Mozilla Firefox 4 to 18 */
120
+ color: #4d535e;
121
+ opacity: 1;
122
+ }
123
+ ::-moz-placeholder { /* Mozilla Firefox 19+ */
124
+ color: #4d535e;
125
+ opacity: 1;
126
+ }
127
+ :-ms-input-placeholder { /* Internet Explorer 10+ */
128
+ color: #4d535e;
129
+ }
130
+
131
+
132
+ /* Content area */
133
+
134
+ .filemanager .data {
135
+ margin-top: 60px;
136
+ z-index: -3;
137
+ }
138
+ .filemanager .data.animated {
139
+ -webkit-animation: showSlowlyElement 700ms; /* Chrome, Safari, Opera */
140
+ animation: showSlowlyElement 700ms; /* Standard syntax */
141
+ }
142
+ .filemanager .data li {
143
+ border-radius: 3px;
144
+ background-color: #373743;
145
+ width: 11.5%;
146
+ height: 151px;
147
+ list-style-type: none;
148
+ margin: 0 1% 1% 0;
149
+ display: inline-block;
150
+ position: relative;
151
+ overflow: hidden;
152
+ padding: 0.3em;
153
+ z-index: 1;
154
+ cursor: pointer;
155
+ box-sizing: border-box;
156
+ border: 1px solid #ddd;
157
+ transition: 0.3s background-color;
158
+ box-shadow: inset 0 0 0 1px rgba(0,0,0,.1);
159
+ }
160
+ .filemanager .data li:hover {
161
+ background-color: #42424E;
162
+ }
163
+ .filemanager .data li a {
164
+ position: absolute;
165
+ top: 0;
166
+ left: 0;
167
+ width: 100%;
168
+ height: 100%;
169
+ text-decoration: none;
170
+ display: block;
171
+ text-align: center;
172
+ background: #eee;
173
+ box-shadow: inset 0 0 15px rgba(0,0,0,.1),inset 0 0 0 1px rgba(0,0,0,.05);
174
+ z-index: 0;
175
+ color: #333;
176
+ }
177
+ .filemanager .data li:hover a {
178
+ color: #fff;
179
+ background-color: #333;
180
+ }
181
+ .filemanager .data li .name {
182
+ font-size: 14px;
183
+ font-weight: 400;
184
+ line-height: 1.2;
185
+ width: 100%;
186
+ padding: 0 6px;
187
+ display: block;
188
+ position: absolute;
189
+ overflow: hidden;
190
+ bottom: 25px;
191
+ z-index: 1;
192
+ }
193
+ .filemanager .data li .details {
194
+ color: #b6c1c9;
195
+ font-size: 13px;
196
+ font-weight: 400;
197
+ width: 100%;
198
+ height: 13px;
199
+ bottom: 10px;
200
+ white-space: nowrap;
201
+ position: absolute;
202
+ display: block;
203
+ z-index: 1;
204
+ }
205
+ .filemanager .nothingfound {
206
+ background-color: #373743;
207
+ width: 23em;
208
+ height: 21em;
209
+ margin: 0 auto;
210
+ display: none;
211
+ font-family: Arial;
212
+ -webkit-animation: showSlowlyElement 700ms; /* Chrome, Safari, Opera */
213
+ animation: showSlowlyElement 700ms; /* Standard syntax */
214
+ }
215
+ .filemanager .nothingfound .nofiles {
216
+ margin: 30px auto;
217
+ top: 3em;
218
+ border-radius: 50%;
219
+ position:relative;
220
+ background-color: #d72f6e;
221
+ width: 11em;
222
+ height: 11em;
223
+ line-height: 11.4em;
224
+ }
225
+ .filemanager .nothingfound .nofiles:after {
226
+ content: '×';
227
+ position: absolute;
228
+ color: #ffffff;
229
+ font-size: 14em;
230
+ margin-right: 0.092em;
231
+ right: 0;
232
+ }
233
+ .filemanager .nothingfound span {
234
+ margin: 0 auto auto 6.8em;
235
+ color: #ffffff;
236
+ font-size: 16px;
237
+ font-weight: 700;
238
+ line-height: 20px;
239
+ height: 13px;
240
+ position: relative;
241
+ top: 2em;
242
+ }
243
+ @media all and (max-width:965px) {
244
+
245
+ .filemanager .data li {
246
+ width: 100%;
247
+ margin: 5px 0;
248
+ }
249
+
250
+ }
251
+
252
+ /* Chrome, Safari, Opera */
253
+ @-webkit-keyframes showSlowlyElement {
254
+ 100% { transform: scale(1); opacity: 1; }
255
+ 0% { transform: scale(1.2); opacity: 0; }
256
+ }
257
+ /* Standard syntax */
258
+ @keyframes showSlowlyElement {
259
+ 100% { transform: scale(1); opacity: 1; }
260
+ 0% { transform: scale(1.2); opacity: 0; }
261
+ }
262
+
263
+
264
+ /* Icons */
265
+
266
+ .files-div .icon {
267
+ font-size: 18px;
268
+ width: 3em;
269
+ }
270
+ .files-div .icon.folder {
271
+ display: inline-block;
272
+ margin: 1em;
273
+ background-color: transparent;
274
+ overflow: hidden;
275
+ }
276
+ .files-div .icon.folder:before {
277
+ content: '';
278
+ float: left;
279
+ background-color: #7ba1ad;
280
+ width: 1.5em;
281
+ height: 0.45em;
282
+ margin-left: 0.07em;
283
+ margin-bottom: -0.07em;
284
+ border-top-left-radius: 0.1em;
285
+ border-top-right-radius: 0.1em;
286
+ box-shadow: 1.25em 0.25em 0 0em #7ba1ad;
287
+ }
288
+ .files-div .icon.folder:after {
289
+ content: '';
290
+ float: left;
291
+ clear: left;
292
+ background-color: #a0d4e4;
293
+ width: 3em;
294
+ height: 2.25em;
295
+ border-radius: 0.1em;
296
+ }
297
+ .files-div .icon.folder.full:before {
298
+ height: 0.55em;
299
+ }
300
+ .files-div .icon.folder.full:after {
301
+ height: 2.15em;
302
+ box-shadow: 0 -0.12em 0 0 #ffffff;
303
+ }
304
+ .files-div .icon.file {
305
+ width: 2.5em;
306
+ height: 3em;
307
+ line-height: 3em;
308
+ text-align: center;
309
+ border-radius: 0.25em;
310
+ color: #FFF;
311
+ display: inline-block;
312
+ margin: 0.9em 1.2em 0.8em 1.3em;
313
+ position: relative;
314
+ overflow: hidden;
315
+ box-shadow: 1.74em -2.1em 0 0 #A4A7AC inset;
316
+ }
317
+ .files-div .icon.file:first-line {
318
+ font-size: 13px;
319
+ font-weight: 700;
320
+ }
321
+ .files-div .icon.file:after {
322
+ content: '';
323
+ position: absolute;
324
+ z-index: -1;
325
+ border-width: 0;
326
+ border-bottom: 2.6em solid #c0c0c0;
327
+ border-right: 2.22em solid rgba(0, 0, 0, 0);
328
+ top: -30.5px;
329
+ right: 0;
330
+ }
331
+ .files-div .icon.file.f-avi,
332
+ .files-div .icon.file.f-flv,
333
+ .files-div .icon.file.f-mkv,
334
+ .files-div .icon.file.f-mov,
335
+ .files-div .icon.file.f-mpeg,
336
+ .files-div .icon.file.f-mpg,
337
+ .files-div .icon.file.f-mp4,
338
+ .files-div .icon.file.f-m4v,
339
+ .files-div .icon.file.f-wmv {
340
+ box-shadow: 1.74em -2.1em 0 0 #7e70ee inset;
341
+ }
342
+ .files-div .icon.file.f-avi:after,
343
+ .files-div .icon.file.f-flv:after,
344
+ .files-div .icon.file.f-mkv:after,
345
+ .files-div .icon.file.f-mov:after,
346
+ .files-div .icon.file.f-mpeg:after,
347
+ .files-div .icon.file.f-mpg:after,
348
+ .files-div .icon.file.f-mp4:after,
349
+ .files-div .icon.file.f-m4v:after,
350
+ .files-div .icon.file.f-wmv:after {
351
+ border-bottom-color: #5649c1;
352
+ }
353
+ .files-div .icon.file.f-mp2,
354
+ .files-div .icon.file.f-mp3,
355
+ .files-div .icon.file.f-m3u,
356
+ .files-div .icon.file.f-wma,
357
+ .files-div .icon.file.f-xls,
358
+ .files-div .icon.file.f-xlsx {
359
+ box-shadow: 1.74em -2.1em 0 0 #5bab6e inset;
360
+ }
361
+ .files-div .icon.file.f-mp2:after,
362
+ .files-div .icon.file.f-mp3:after,
363
+ .files-div .icon.file.f-m3u:after,
364
+ .files-div .icon.file.f-wma:after,
365
+ .files-div .icon.file.f-xls:after,
366
+ .files-div .icon.file.f-xlsx:after {
367
+ border-bottom-color: #448353;
368
+ }
369
+ .files-div .icon.file.f-doc,
370
+ .files-div .icon.file.f-docx,
371
+ .files-div .icon.file.f-psd{
372
+ box-shadow: 1.74em -2.1em 0 0 #03689b inset;
373
+ }
374
+ .files-div .icon.file.f-doc:after,
375
+ .files-div .icon.file.f-docx:after,
376
+ .files-div .icon.file.f-psd:after {
377
+ border-bottom-color: #2980b9;
378
+ }
379
+ .files-div .icon.file.f-gif,
380
+ .files-div .icon.file.f-jpg,
381
+ .files-div .icon.file.f-jpeg,
382
+ .files-div .icon.file.f-pdf,
383
+ .files-div .icon.file.f-png {
384
+ box-shadow: 1.74em -2.1em 0 0 #e15955 inset;
385
+ }
386
+ .files-div .icon.file.f-gif:after,
387
+ .files-div .icon.file.f-jpg:after,
388
+ .files-div .icon.file.f-jpeg:after,
389
+ .files-div .icon.file.f-pdf:after,
390
+ .files-div .icon.file.f-png:after {
391
+ border-bottom-color: #c6393f;
392
+ }
393
+ .files-div .icon.file.f-deb,
394
+ .files-div .icon.file.f-dmg,
395
+ .files-div .icon.file.f-gz,
396
+ .files-div .icon.file.f-rar,
397
+ .files-div .icon.file.f-zip,
398
+ .files-div .icon.file.f-7z {
399
+ box-shadow: 1.74em -2.1em 0 0 #867c75 inset;
400
+ }
401
+ .files-div .icon.file.f-deb:after,
402
+ .files-div .icon.file.f-dmg:after,
403
+ .files-div .icon.file.f-gz:after,
404
+ .files-div .icon.file.f-rar:after,
405
+ .files-div .icon.file.f-zip:after,
406
+ .files-div .icon.file.f-7z:after {
407
+ border-bottom-color: #685f58;
408
+ }
409
+ .files-div .icon.file.f-html,
410
+ .files-div .icon.file.f-rtf,
411
+ .files-div .icon.file.f-xml,
412
+ .files-div .icon.file.f-xhtml {
413
+ box-shadow: 1.74em -2.1em 0 0 #a94bb7 inset;
414
+ }
415
+ .files-div .icon.file.f-html:after,
416
+ .files-div .icon.file.f-rtf:after,
417
+ .files-div .icon.file.f-xml:after,
418
+ .files-div .icon.file.f-xhtml:after {
419
+ border-bottom-color: #d65de8;
420
+ }
421
+ .files-div .icon.file.f-js {
422
+ box-shadow: 1.74em -2.1em 0 0 #d0c54d inset;
423
+ }
424
+ .files-div .icon.file.f-js:after {
425
+ border-bottom-color: #a69f4e;
426
+ }
427
+ .files-div .icon.file.f-css,
428
+ .files-div .icon.file.f-saas,
429
+ .files-div .icon.file.f-scss {
430
+ box-shadow: 1.74em -2.1em 0 0 #44afa6 inset;
431
+ }
432
+ .files-div .icon.file.f-css:after,
433
+ .files-div .icon.file.f-saas:after,
434
+ .files-div .icon.file.f-scss:after {
435
+ border-bottom-color: #30837c;
436
+ }
437
+
438
+ @media screen and (max-width: 600px) {
439
+ .files-div .icon {
440
+ font-size:1em!important;
441
+ margin-top:2em!important;
442
+ }
443
+ .files-div .icon.file:after {
444
+ top: -27.5px!important;
445
+ }
446
+ .filemanager .data li {
447
+
448
+ width:100%!important;
449
+ }
450
+ .files-div ul.data {
451
+
452
+ margin-left:0px!important;
453
+ margin-right:0px!important;
454
+
455
+ }
456
+ }
css/shortcode-editor.css CHANGED
@@ -144,4 +144,8 @@ a #add-format, a #add-rtmp {
144
  }
145
  #fv-wordpress-flowplayer-popup table td {
146
  padding: 4px 2px;
 
 
 
 
147
  }
144
  }
145
  #fv-wordpress-flowplayer-popup table td {
146
  padding: 4px 2px;
147
+ }
148
+
149
+ #fv-player-shortcode-editor-editor ::placeholder {
150
+ opacity:.5;
151
  }
flowplayer.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: FV Player
4
  Plugin URI: http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer
5
  Description: Formerly FV WordPress Flowplayer. Supports MP4, HLS, MPEG-DASH, WebM and OGV. Advanced features such as overlay ads or popups. Uses Flowplayer 7.2.7.
6
- Version: 7.1.15.727
7
  Author URI: http://foliovision.com/
8
  License: GPL-3.0
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.txt
@@ -26,15 +26,17 @@ License URI: http://www.gnu.org/licenses/gpl-3.0.txt
26
  along with this program. If not, see <http://www.gnu.org/licenses/>.
27
  */
28
 
29
- $fv_wp_flowplayer_ver = '7.1.15.727';
30
  $fv_wp_flowplayer_core_ver = '7.2.7.1';
31
 
32
- include( dirname( __FILE__ ) . '/includes/extra-functions.php' );
33
  if( file_exists( dirname( __FILE__ ) . '/includes/module.php' ) ) {
34
- include( dirname( __FILE__ ) . '/includes/module.php' );
35
  }
36
 
37
- include( dirname( __FILE__ ) . '/models/checker.php' );
 
 
38
  $FV_Player_Checker = new FV_Player_Checker();
39
 
40
  include_once(dirname( __FILE__ ) . '/models/flowplayer.php');
@@ -64,13 +66,16 @@ global $fv_fp;
64
  $fv_fp = new flowplayer_frontend();
65
 
66
  if( is_admin() ) {
67
- include( dirname( __FILE__ ) . '/controller/backend.php' );
68
- include( dirname( __FILE__ ) . '/controller/editor.php' );
69
- include( dirname( __FILE__ ) . '/controller/settings.php' );
70
-
 
 
 
71
  register_deactivation_hook( __FILE__, 'flowplayer_deactivate' );
72
 
73
  }
74
 
75
- include( dirname( __FILE__ ) . '/controller/frontend.php' );
76
- require_once( dirname( __FILE__ ) . '/controller/shortcodes.php');
3
  Plugin Name: FV Player
4
  Plugin URI: http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer
5
  Description: Formerly FV WordPress Flowplayer. Supports MP4, HLS, MPEG-DASH, WebM and OGV. Advanced features such as overlay ads or popups. Uses Flowplayer 7.2.7.
6
+ Version: 7.2.1.727
7
  Author URI: http://foliovision.com/
8
  License: GPL-3.0
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.txt
26
  along with this program. If not, see <http://www.gnu.org/licenses/>.
27
  */
28
 
29
+ $fv_wp_flowplayer_ver = '7.2.1.727';
30
  $fv_wp_flowplayer_core_ver = '7.2.7.1';
31
 
32
+ include_once( dirname( __FILE__ ) . '/includes/extra-functions.php' );
33
  if( file_exists( dirname( __FILE__ ) . '/includes/module.php' ) ) {
34
+ include_once( dirname( __FILE__ ) . '/includes/module.php' );
35
  }
36
 
37
+ include_once( dirname( __FILE__ ) . '/models/checker.php' );
38
+
39
+ global $FV_Player_Checker;
40
  $FV_Player_Checker = new FV_Player_Checker();
41
 
42
  include_once(dirname( __FILE__ ) . '/models/flowplayer.php');
66
  $fv_fp = new flowplayer_frontend();
67
 
68
  if( is_admin() ) {
69
+ include_once( dirname( __FILE__ ) . '/controller/backend.php' );
70
+ include_once( dirname( __FILE__ ) . '/controller/editor.php' );
71
+ include_once( dirname( __FILE__ ) . '/controller/settings.php' );
72
+ if( version_compare(phpversion(),'5.5.0') != -1 ) {
73
+ include_once(dirname( __FILE__ ) . '/models/media-browser.php');
74
+ include_once(dirname( __FILE__ ) . '/models/media-browser-s3.php');
75
+ }
76
  register_deactivation_hook( __FILE__, 'flowplayer_deactivate' );
77
 
78
  }
79
 
80
+ include_once( dirname( __FILE__ ) . '/controller/frontend.php' );
81
+ include_once( dirname( __FILE__ ) . '/controller/shortcodes.php');
flowplayer/fv-flowplayer.min.js CHANGED
@@ -2701,7 +2701,7 @@ flowplayer( function(api,root) {
2701
  });
2702
 
2703
  api.on('ready', function() {
2704
- if( api.video.is_fv_recoverable && api.engine.engineName == 'html5' && ( api.video.type == 'application/x-mpegurl' || api.video.type == 'video/fv-mp4' ) ) {
2705
 
2706
  time_delay = new Date().getTime() - time_start;
2707
 
@@ -2722,6 +2722,7 @@ flowplayer( function(api,root) {
2722
 
2723
  function hls_check() {
2724
  if( api.ready && api.playing && !api.loading && !api.finished ) {
 
2725
  console.log('HLS stream stale for '+time_delay+' ms, triggering error!');
2726
  fv_player_notice(root,fv_flowplayer_translations.video_reload+' <a class="fv-player-reload" href="#">&#x21bb;</a>','progress error unload');
2727
  jQuery('.fv-player-reload').click( function() {
2701
  });
2702
 
2703
  api.on('ready', function() {
2704
+ if( api.video.is_fv_recoverable && api.engine.engineName == 'html5' && ( api.video.type == 'application/x-mpegurl' || api.video.type == 'video/fv-mp4' && api.video.src.match(/m3u8/) ) ) {
2705
 
2706
  time_delay = new Date().getTime() - time_start;
2707
 
2722
 
2723
  function hls_check() {
2724
  if( api.ready && api.playing && !api.loading && !api.finished ) {
2725
+ clearInterval(no_progress);
2726
  console.log('HLS stream stale for '+time_delay+' ms, triggering error!');
2727
  fv_player_notice(root,fv_flowplayer_translations.video_reload+' <a class="fv-player-reload" href="#">&#x21bb;</a>','progress error unload');
2728
  jQuery('.fv-player-reload').click( function() {
includes/aws/Aws/Api/AbstractModel.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ /**
5
+ * Base class that is used by most API shapes
6
+ */
7
+ abstract class AbstractModel implements \ArrayAccess
8
+ {
9
+ /** @var array */
10
+ protected $definition;
11
+
12
+ /** @var ShapeMap */
13
+ protected $shapeMap;
14
+
15
+ /**
16
+ * @param array $definition Service description
17
+ * @param ShapeMap $shapeMap Shapemap used for creating shapes
18
+ */
19
+ public function __construct(array $definition, ShapeMap $shapeMap)
20
+ {
21
+ $this->definition = $definition;
22
+ $this->shapeMap = $shapeMap;
23
+ }
24
+
25
+ public function toArray()
26
+ {
27
+ return $this->definition;
28
+ }
29
+
30
+ public function offsetGet($offset)
31
+ {
32
+ return isset($this->definition[$offset])
33
+ ? $this->definition[$offset] : null;
34
+ }
35
+
36
+ public function offsetSet($offset, $value)
37
+ {
38
+ $this->definition[$offset] = $value;
39
+ }
40
+
41
+ public function offsetExists($offset)
42
+ {
43
+ return isset($this->definition[$offset]);
44
+ }
45
+
46
+ public function offsetUnset($offset)
47
+ {
48
+ unset($this->definition[$offset]);
49
+ }
50
+
51
+ protected function shapeAt($key)
52
+ {
53
+ if (!isset($this->definition[$key])) {
54
+ throw new \InvalidArgumentException('Expected shape definition at '
55
+ . $key);
56
+ }
57
+
58
+ return $this->shapeFor($this->definition[$key]);
59
+ }
60
+
61
+ protected function shapeFor(array $definition)
62
+ {
63
+ return isset($definition['shape'])
64
+ ? $this->shapeMap->resolve($definition)
65
+ : Shape::create($definition, $this->shapeMap);
66
+ }
67
+ }
includes/aws/Aws/Api/ApiProvider.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ use Aws\Exception\UnresolvedApiException;
5
+
6
+ /**
7
+ * API providers.
8
+ *
9
+ * An API provider is a function that accepts a type, service, and version and
10
+ * returns an array of API data on success or NULL if no API data can be created
11
+ * for the provided arguments.
12
+ *
13
+ * You can wrap your calls to an API provider with the
14
+ * {@see ApiProvider::resolve} method to ensure that API data is created. If the
15
+ * API data is not created, then the resolve() method will throw a
16
+ * {@see Aws\Exception\UnresolvedApiException}.
17
+ *
18
+ * use Aws\Api\ApiProvider;
19
+ * $provider = ApiProvider::defaultProvider();
20
+ * // Returns an array or NULL.
21
+ * $data = $provider('api', 's3', '2006-03-01');
22
+ * // Returns an array or throws.
23
+ * $data = ApiProvider::resolve($provider, 'api', 'elasticfood', '2020-01-01');
24
+ *
25
+ * You can compose multiple providers into a single provider using
26
+ * {@see Aws\or_chain}. This method accepts providers as arguments and
27
+ * returns a new function that will invoke each provider until a non-null value
28
+ * is returned.
29
+ *
30
+ * $a = ApiProvider::filesystem(sys_get_temp_dir() . '/aws-beta-models');
31
+ * $b = ApiProvider::manifest();
32
+ *
33
+ * $c = \Aws\or_chain($a, $b);
34
+ * $data = $c('api', 'betaservice', '2015-08-08'); // $a handles this.
35
+ * $data = $c('api', 's3', '2006-03-01'); // $b handles this.
36
+ * $data = $c('api', 'invalid', '2014-12-15'); // Neither handles this.
37
+ */
38
+ class ApiProvider
39
+ {
40
+ /** @var array A map of public API type names to their file suffix. */
41
+ private static $typeMap = [
42
+ 'api' => 'api-2',
43
+ 'paginator' => 'paginators-1',
44
+ 'waiter' => 'waiters-2',
45
+ 'docs' => 'docs-2',
46
+ ];
47
+
48
+ /** @var array API manifest */
49
+ private $manifest;
50
+
51
+ /** @var string The directory containing service models. */
52
+ private $modelsDir;
53
+
54
+ /**
55
+ * Resolves an API provider and ensures a non-null return value.
56
+ *
57
+ * @param callable $provider Provider function to invoke.
58
+ * @param string $type Type of data ('api', 'waiter', 'paginator').
59
+ * @param string $service Service name.
60
+ * @param string $version API version.
61
+ *
62
+ * @return array
63
+ * @throws UnresolvedApiException
64
+ */
65
+ public static function resolve(callable $provider, $type, $service, $version)
66
+ {
67
+ // Execute the provider and return the result, if there is one.
68
+ $result = $provider($type, $service, $version);
69
+ if (is_array($result)) {
70
+ return $result;
71
+ }
72
+
73
+ // Throw an exception with a message depending on the inputs.
74
+ if (!isset(self::$typeMap[$type])) {
75
+ $msg = "The type must be one of: " . implode(', ', self::$typeMap);
76
+ } elseif ($service) {
77
+ $msg = "The {$service} service does not have version: {$version}.";
78
+ } else {
79
+ $msg = "You must specify a service name to retrieve its API data.";
80
+ }
81
+
82
+ throw new UnresolvedApiException($msg);
83
+ }
84
+
85
+ /**
86
+ * Default SDK API provider.
87
+ *
88
+ * This provider loads pre-built manifest data from the `data` directory.
89
+ *
90
+ * @return self
91
+ */
92
+ public static function defaultProvider()
93
+ {
94
+ return new self(__DIR__ . '/../data', \Aws\manifest());
95
+ }
96
+
97
+ /**
98
+ * Loads API data after resolving the version to the latest, compatible,
99
+ * available version based on the provided manifest data.
100
+ *
101
+ * Manifest data is essentially an associative array of service names to
102
+ * associative arrays of API version aliases.
103
+ *
104
+ * [
105
+ * ...
106
+ * 'ec2' => [
107
+ * 'latest' => '2014-10-01',
108
+ * '2014-10-01' => '2014-10-01',
109
+ * '2014-09-01' => '2014-10-01',
110
+ * '2014-06-15' => '2014-10-01',
111
+ * ...
112
+ * ],
113
+ * 'ecs' => [...],
114
+ * 'elasticache' => [...],
115
+ * ...
116
+ * ]
117
+ *
118
+ * @param string $dir Directory containing service models.
119
+ * @param array $manifest The API version manifest data.
120
+ *
121
+ * @return self
122
+ */
123
+ public static function manifest($dir, array $manifest)
124
+ {
125
+ return new self($dir, $manifest);
126
+ }
127
+
128
+ /**
129
+ * Loads API data from the specified directory.
130
+ *
131
+ * If "latest" is specified as the version, this provider must glob the
132
+ * directory to find which is the latest available version.
133
+ *
134
+ * @param string $dir Directory containing service models.
135
+ *
136
+ * @return self
137
+ * @throws \InvalidArgumentException if the provided `$dir` is invalid.
138
+ */
139
+ public static function filesystem($dir)
140
+ {
141
+ return new self($dir);
142
+ }
143
+
144
+ /**
145
+ * Retrieves a list of valid versions for the specified service.
146
+ *
147
+ * @param string $service Service name
148
+ *
149
+ * @return array
150
+ */
151
+ public function getVersions($service)
152
+ {
153
+ if (!isset($this->manifest)) {
154
+ $this->buildVersionsList($service);
155
+ }
156
+
157
+ if (!isset($this->manifest[$service]['versions'])) {
158
+ return [];
159
+ }
160
+
161
+ return array_values(array_unique($this->manifest[$service]['versions']));
162
+ }
163
+
164
+ /**
165
+ * Execute the the provider.
166
+ *
167
+ * @param string $type Type of data ('api', 'waiter', 'paginator').
168
+ * @param string $service Service name.
169
+ * @param string $version API version.
170
+ *
171
+ * @return array|null
172
+ */
173
+ public function __invoke($type, $service, $version)
174
+ {
175
+ // Resolve the type or return null.
176
+ if (isset(self::$typeMap[$type])) {
177
+ $type = self::$typeMap[$type];
178
+ } else {
179
+ return null;
180
+ }
181
+
182
+ // Resolve the version or return null.
183
+ if (!isset($this->manifest)) {
184
+ $this->buildVersionsList($service);
185
+ }
186
+
187
+ if (!isset($this->manifest[$service]['versions'][$version])) {
188
+ return null;
189
+ }
190
+
191
+ $version = $this->manifest[$service]['versions'][$version];
192
+ $path = "{$this->modelsDir}/{$service}/{$version}/{$type}.json";
193
+
194
+ try {
195
+ return \Aws\load_compiled_json($path);
196
+ } catch (\InvalidArgumentException $e) {
197
+ return null;
198
+ }
199
+ }
200
+
201
+ /**
202
+ * @param string $modelsDir Directory containing service models.
203
+ * @param array $manifest The API version manifest data.
204
+ */
205
+ private function __construct($modelsDir, array $manifest = null)
206
+ {
207
+ $this->manifest = $manifest;
208
+ $this->modelsDir = rtrim($modelsDir, '/');
209
+ if (!is_dir($this->modelsDir)) {
210
+ throw new \InvalidArgumentException(
211
+ "The specified models directory, {$modelsDir}, was not found."
212
+ );
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Build the versions list for the specified service by globbing the dir.
218
+ */
219
+ private function buildVersionsList($service)
220
+ {
221
+ $dir = "{$this->modelsDir}/{$service}/";
222
+
223
+ if (!is_dir($dir)) {
224
+ return;
225
+ }
226
+
227
+ // Get versions, remove . and .., and sort in descending order.
228
+ $results = array_diff(scandir($dir, SCANDIR_SORT_DESCENDING), ['..', '.']);
229
+
230
+ if (!$results) {
231
+ $this->manifest[$service] = ['versions' => []];
232
+ } else {
233
+ $this->manifest[$service] = [
234
+ 'versions' => [
235
+ 'latest' => $results[0]
236
+ ]
237
+ ];
238
+ $this->manifest[$service]['versions'] += array_combine($results, $results);
239
+ }
240
+ }
241
+ }
includes/aws/Aws/Api/DateTimeResult.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ /**
5
+ * DateTime overrides that make DateTime work more seamlessly as a string,
6
+ * with JSON documents, and with JMESPath.
7
+ */
8
+ class DateTimeResult extends \DateTime implements \JsonSerializable
9
+ {
10
+ /**
11
+ * Create a new DateTimeResult from a unix timestamp.
12
+ *
13
+ * @param $unixTimestamp
14
+ *
15
+ * @return DateTimeResult
16
+ */
17
+ public static function fromEpoch($unixTimestamp)
18
+ {
19
+ return new self(gmdate('c', $unixTimestamp));
20
+ }
21
+
22
+ /**
23
+ * Serialize the DateTimeResult as an ISO 8601 date string.
24
+ *
25
+ * @return string
26
+ */
27
+ public function __toString()
28
+ {
29
+ return $this->format('c');
30
+ }
31
+
32
+ /**
33
+ * Serialize the date as an ISO 8601 date when serializing as JSON.
34
+ *
35
+ * @return mixed|string
36
+ */
37
+ public function jsonSerialize()
38
+ {
39
+ return (string) $this;
40
+ }
41
+ }
includes/aws/Aws/Api/DocModel.php ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ /**
5
+ * Encapsulates the documentation strings for a given service-version and
6
+ * provides methods for extracting the desired parts related to a service,
7
+ * operation, error, or shape (i.e., parameter).
8
+ */
9
+ class DocModel
10
+ {
11
+ /** @var array */
12
+ private $docs;
13
+
14
+ /**
15
+ * @param array $docs
16
+ *
17
+ * @throws \RuntimeException
18
+ */
19
+ public function __construct(array $docs)
20
+ {
21
+ if (!extension_loaded('tidy')) {
22
+ throw new \RuntimeException('The "tidy" PHP extension is required.');
23
+ }
24
+
25
+ $this->docs = $docs;
26
+ }
27
+
28
+ /**
29
+ * Convert the doc model to an array.
30
+ *
31
+ * @return array
32
+ */
33
+ public function toArray()
34
+ {
35
+ return $this->docs;
36
+ }
37
+
38
+ /**
39
+ * Retrieves documentation about the service.
40
+ *
41
+ * @return null|string
42
+ */
43
+ public function getServiceDocs()
44
+ {
45
+ return isset($this->docs['service']) ? $this->docs['service'] : null;
46
+ }
47
+
48
+ /**
49
+ * Retrieves documentation about an operation.
50
+ *
51
+ * @param string $operation Name of the operation
52
+ *
53
+ * @return null|string
54
+ */
55
+ public function getOperationDocs($operation)
56
+ {
57
+ return isset($this->docs['operations'][$operation])
58
+ ? $this->docs['operations'][$operation]
59
+ : null;
60
+ }
61
+
62
+ /**
63
+ * Retrieves documentation about an error.
64
+ *
65
+ * @param string $error Name of the error
66
+ *
67
+ * @return null|string
68
+ */
69
+ public function getErrorDocs($error)
70
+ {
71
+ return isset($this->docs['shapes'][$error]['base'])
72
+ ? $this->docs['shapes'][$error]['base']
73
+ : null;
74
+ }
75
+
76
+ /**
77
+ * Retrieves documentation about a shape, specific to the context.
78
+ *
79
+ * @param string $shapeName Name of the shape.
80
+ * @param string $parentName Name of the parent/context shape.
81
+ * @param string $ref Name used by the context to reference the shape.
82
+ *
83
+ * @return null|string
84
+ */
85
+ public function getShapeDocs($shapeName, $parentName, $ref)
86
+ {
87
+ if (!isset($this->docs['shapes'][$shapeName])) {
88
+ return '';
89
+ }
90
+
91
+ $result = '';
92
+ $d = $this->docs['shapes'][$shapeName];
93
+ if (isset($d['refs']["{$parentName}\$${ref}"])) {
94
+ $result = $d['refs']["{$parentName}\$${ref}"];
95
+ } elseif (isset($d['base'])) {
96
+ $result = $d['base'];
97
+ }
98
+
99
+ if (isset($d['append'])) {
100
+ $result .= $d['append'];
101
+ }
102
+
103
+ return $this->clean($result);
104
+ }
105
+
106
+ private function clean($content)
107
+ {
108
+ if (!$content) {
109
+ return '';
110
+ }
111
+
112
+ $tidy = new \Tidy();
113
+ $tidy->parseString($content, [
114
+ 'indent' => true,
115
+ 'doctype' => 'omit',
116
+ 'output-html' => true,
117
+ 'show-body-only' => true,
118
+ 'drop-empty-paras' => true,
119
+ 'drop-font-tags' => true,
120
+ 'drop-proprietary-attributes' => true,
121
+ 'hide-comments' => true,
122
+ 'logical-emphasis' => true
123
+ ]);
124
+ $tidy->cleanRepair();
125
+
126
+ return (string) $content;
127
+ }
128
+ }
includes/aws/Aws/Api/ErrorParser/JsonParserTrait.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\ErrorParser;
3
+
4
+ use Aws\Api\Parser\PayloadParserTrait;
5
+ use Psr\Http\Message\ResponseInterface;
6
+
7
+ /**
8
+ * Provides basic JSON error parsing functionality.
9
+ */
10
+ trait JsonParserTrait
11
+ {
12
+ use PayloadParserTrait;
13
+
14
+ private function genericHandler(ResponseInterface $response)
15
+ {
16
+ $code = (string) $response->getStatusCode();
17
+
18
+ return [
19
+ 'request_id' => (string) $response->getHeaderLine('x-amzn-requestid'),
20
+ 'code' => null,
21
+ 'message' => null,
22
+ 'type' => $code[0] == '4' ? 'client' : 'server',
23
+ 'parsed' => $this->parseJson($response->getBody())
24
+ ];
25
+ }
26
+ }
includes/aws/Aws/Api/ErrorParser/JsonRpcErrorParser.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\ErrorParser;
3
+
4
+ use Psr\Http\Message\ResponseInterface;
5
+
6
+ /**
7
+ * Parsers JSON-RPC errors.
8
+ */
9
+ class JsonRpcErrorParser
10
+ {
11
+ use JsonParserTrait;
12
+
13
+ public function __invoke(ResponseInterface $response)
14
+ {
15
+ $data = $this->genericHandler($response);
16
+ // Make the casing consistent across services.
17
+ if ($data['parsed']) {
18
+ $data['parsed'] = array_change_key_case($data['parsed']);
19
+ }
20
+
21
+ if (isset($data['parsed']['__type'])) {
22
+ $parts = explode('#', $data['parsed']['__type']);
23
+ $data['code'] = isset($parts[1]) ? $parts[1] : $parts[0];
24
+ $data['message'] = isset($data['parsed']['message'])
25
+ ? $data['parsed']['message']
26
+ : null;
27
+ }
28
+
29
+ return $data;
30
+ }
31
+ }
includes/aws/Aws/Api/ErrorParser/RestJsonErrorParser.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\ErrorParser;
3
+
4
+ use Psr\Http\Message\ResponseInterface;
5
+
6
+ /**
7
+ * Parses JSON-REST errors.
8
+ */
9
+ class RestJsonErrorParser
10
+ {
11
+ use JsonParserTrait;
12
+
13
+ public function __invoke(ResponseInterface $response)
14
+ {
15
+ $data = $this->genericHandler($response);
16
+
17
+ // Merge in error data from the JSON body
18
+ if ($json = $data['parsed']) {
19
+ $data = array_replace($data, $json);
20
+ }
21
+
22
+ // Correct error type from services like Amazon Glacier
23
+ if (!empty($data['type'])) {
24
+ $data['type'] = strtolower($data['type']);
25
+ }
26
+
27
+ // Retrieve the error code from services like Amazon Elastic Transcoder
28
+ if ($code = $response->getHeaderLine('x-amzn-errortype')) {
29
+ $colon = strpos($code, ':');
30
+ $data['code'] = $colon ? substr($code, 0, $colon) : $code;
31
+ }
32
+
33
+ return $data;
34
+ }
35
+ }
includes/aws/Aws/Api/ErrorParser/XmlErrorParser.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\ErrorParser;
3
+
4
+ use Aws\Api\Parser\PayloadParserTrait;
5
+ use Psr\Http\Message\ResponseInterface;
6
+
7
+ /**
8
+ * Parses XML errors.
9
+ */
10
+ class XmlErrorParser
11
+ {
12
+ use PayloadParserTrait;
13
+
14
+ public function __invoke(ResponseInterface $response)
15
+ {
16
+ $code = (string) $response->getStatusCode();
17
+
18
+ $data = [
19
+ 'type' => $code[0] == '4' ? 'client' : 'server',
20
+ 'request_id' => null,
21
+ 'code' => null,
22
+ 'message' => null,
23
+ 'parsed' => null
24
+ ];
25
+
26
+ $body = $response->getBody();
27
+ if ($body->getSize() > 0) {
28
+ $this->parseBody($this->parseXml($body), $data);
29
+ } else {
30
+ $this->parseHeaders($response, $data);
31
+ }
32
+
33
+ return $data;
34
+ }
35
+
36
+ private function parseHeaders(ResponseInterface $response, array &$data)
37
+ {
38
+ if ($response->getStatusCode() == '404') {
39
+ $data['code'] = 'NotFound';
40
+ }
41
+
42
+ $data['message'] = $response->getStatusCode() . ' '
43
+ . $response->getReasonPhrase();
44
+
45
+ if ($requestId = $response->getHeaderLine('x-amz-request-id')) {
46
+ $data['request_id'] = $requestId;
47
+ $data['message'] .= " (Request-ID: $requestId)";
48
+ }
49
+ }
50
+
51
+ private function parseBody(\SimpleXMLElement $body, array &$data)
52
+ {
53
+ $data['parsed'] = $body;
54
+
55
+ $namespaces = $body->getDocNamespaces();
56
+ if (!isset($namespaces[''])) {
57
+ $prefix = '';
58
+ } else {
59
+ // Account for the default namespace being defined and PHP not
60
+ // being able to handle it :(.
61
+ $body->registerXPathNamespace('ns', $namespaces['']);
62
+ $prefix = 'ns:';
63
+ }
64
+
65
+ if ($tempXml = $body->xpath("//{$prefix}Code[1]")) {
66
+ $data['code'] = (string) $tempXml[0];
67
+ }
68
+
69
+ if ($tempXml = $body->xpath("//{$prefix}Message[1]")) {
70
+ $data['message'] = (string) $tempXml[0];
71
+ }
72
+
73
+ $tempXml = $body->xpath("//{$prefix}RequestId[1]");
74
+ if (empty($tempXml)) {
75
+ $tempXml = $body->xpath("//{$prefix}RequestID[1]");
76
+ }
77
+
78
+ if (isset($tempXml[0])) {
79
+ $data['request_id'] = (string) $tempXml[0];
80
+ }
81
+ }
82
+ }
includes/aws/Aws/Api/ListShape.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ /**
5
+ * Represents a list shape.
6
+ */
7
+ class ListShape extends Shape
8
+ {
9
+ private $member;
10
+
11
+ public function __construct(array $definition, ShapeMap $shapeMap)
12
+ {
13
+ $definition['type'] = 'list';
14
+ parent::__construct($definition, $shapeMap);
15
+ }
16
+
17
+ /**
18
+ * @return Shape
19
+ * @throws \RuntimeException if no member is specified
20
+ */
21
+ public function getMember()
22
+ {
23
+ if (!$this->member) {
24
+ if (!isset($this->definition['member'])) {
25
+ throw new \RuntimeException('No member attribute specified');
26
+ }
27
+ $this->member = Shape::create(
28
+ $this->definition['member'],
29
+ $this->shapeMap
30
+ );
31
+ }
32
+
33
+ return $this->member;
34
+ }
35
+ }
includes/aws/Aws/Api/MapShape.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ /**
5
+ * Represents a map shape.
6
+ */
7
+ class MapShape extends Shape
8
+ {
9
+ /** @var Shape */
10
+ private $value;
11
+
12
+ /** @var Shape */
13
+ private $key;
14
+
15
+ public function __construct(array $definition, ShapeMap $shapeMap)
16
+ {
17
+ $definition['type'] = 'map';
18
+ parent::__construct($definition, $shapeMap);
19
+ }
20
+
21
+ /**
22
+ * @return Shape
23
+ * @throws \RuntimeException if no value is specified
24
+ */
25
+ public function getValue()
26
+ {
27
+ if (!$this->value) {
28
+ if (!isset($this->definition['value'])) {
29
+ throw new \RuntimeException('No value specified');
30
+ }
31
+
32
+ $this->value = Shape::create(
33
+ $this->definition['value'],
34
+ $this->shapeMap
35
+ );
36
+ }
37
+
38
+ return $this->value;
39
+ }
40
+
41
+ /**
42
+ * @return Shape
43
+ */
44
+ public function getKey()
45
+ {
46
+ if (!$this->key) {
47
+ $this->key = isset($this->definition['key'])
48
+ ? Shape::create($this->definition['key'], $this->shapeMap)
49
+ : new Shape(['type' => 'string'], $this->shapeMap);
50
+ }
51
+
52
+ return $this->key;
53
+ }
54
+ }
includes/aws/Aws/Api/Operation.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ /**
5
+ * Represents an API operation.
6
+ */
7
+ class Operation extends AbstractModel
8
+ {
9
+ private $input;
10
+ private $output;
11
+ private $errors;
12
+
13
+ public function __construct(array $definition, ShapeMap $shapeMap)
14
+ {
15
+ $definition['type'] = 'structure';
16
+
17
+ if (!isset($definition['http']['method'])) {
18
+ $definition['http']['method'] = 'POST';
19
+ }
20
+
21
+ if (!isset($definition['http']['requestUri'])) {
22
+ $definition['http']['requestUri'] = '/';
23
+ }
24
+
25
+ parent::__construct($definition, $shapeMap);
26
+ }
27
+
28
+ /**
29
+ * Returns an associative array of the HTTP attribute of the operation:
30
+ *
31
+ * - method: HTTP method of the operation
32
+ * - requestUri: URI of the request (can include URI template placeholders)
33
+ *
34
+ * @return array
35
+ */
36
+ public function getHttp()
37
+ {
38
+ return $this->definition['http'];
39
+ }
40
+
41
+ /**
42
+ * Get the input shape of the operation.
43
+ *
44
+ * @return StructureShape
45
+ */
46
+ public function getInput()
47
+ {
48
+ if (!$this->input) {
49
+ if ($input = $this['input']) {
50
+ $this->input = $this->shapeFor($input);
51
+ } else {
52
+ $this->input = new StructureShape([], $this->shapeMap);
53
+ }
54
+ }
55
+
56
+ return $this->input;
57
+ }
58
+
59
+ /**
60
+ * Get the output shape of the operation.
61
+ *
62
+ * @return StructureShape
63
+ */
64
+ public function getOutput()
65
+ {
66
+ if (!$this->output) {
67
+ if ($output = $this['output']) {
68
+ $this->output = $this->shapeFor($output);
69
+ } else {
70
+ $this->output = new StructureShape([], $this->shapeMap);
71
+ }
72
+ }
73
+
74
+ return $this->output;
75
+ }
76
+
77
+ /**
78
+ * Get an array of operation error shapes.
79
+ *
80
+ * @return Shape[]
81
+ */
82
+ public function getErrors()
83
+ {
84
+ if ($this->errors === null) {
85
+ if ($errors = $this['errors']) {
86
+ foreach ($errors as &$error) {
87
+ $error = $this->shapeFor($error);
88
+ }
89
+ $this->errors = $errors;
90
+ } else {
91
+ $this->errors = [];
92
+ }
93
+ }
94
+
95
+ return $this->errors;
96
+ }
97
+ }
includes/aws/Aws/Api/Parser/AbstractParser.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Parser;
3
+
4
+ use Aws\Api\Service;
5
+ use Aws\CommandInterface;
6
+ use Aws\ResultInterface;
7
+ use Psr\Http\Message\ResponseInterface;
8
+
9
+ /**
10
+ * @internal
11
+ */
12
+ abstract class AbstractParser
13
+ {
14
+ /** @var \Aws\Api\Service Representation of the service API*/
15
+ protected $api;
16
+
17
+ /**
18
+ * @param Service $api Service description.
19
+ */
20
+ public function __construct(Service $api)
21
+ {
22
+ $this->api = $api;
23
+ }
24
+
25
+ /**
26
+ * @param CommandInterface $command Command that was executed.
27
+ * @param ResponseInterface $response Response that was received.
28
+ *
29
+ * @return ResultInterface
30
+ */
31
+ abstract public function __invoke(
32
+ CommandInterface $command,
33
+ ResponseInterface $response
34
+ );
35
+ }
includes/aws/Aws/Api/Parser/AbstractRestParser.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Parser;
3
+
4
+ use Aws\Api\DateTimeResult;
5
+ use Aws\Api\Shape;
6
+ use Aws\Api\StructureShape;
7
+ use Aws\Result;
8
+ use Aws\CommandInterface;
9
+ use Psr\Http\Message\ResponseInterface;
10
+
11
+ /**
12
+ * @internal
13
+ */
14
+ abstract class AbstractRestParser extends AbstractParser
15
+ {
16
+ /**
17
+ * Parses a payload from a response.
18
+ *
19
+ * @param ResponseInterface $response Response to parse.
20
+ * @param StructureShape $member Member to parse
21
+ * @param array $result Result value
22
+ *
23
+ * @return mixed
24
+ */
25
+ abstract protected function payload(
26
+ ResponseInterface $response,
27
+ StructureShape $member,
28
+ array &$result
29
+ );
30
+
31
+ public function __invoke(
32
+ CommandInterface $command,
33
+ ResponseInterface $response
34
+ ) {
35
+ $output = $this->api->getOperation($command->getName())->getOutput();
36
+ $result = [];
37
+
38
+ if ($payload = $output['payload']) {
39
+ $this->extractPayload($payload, $output, $response, $result);
40
+ }
41
+
42
+ foreach ($output->getMembers() as $name => $member) {
43
+ switch ($member['location']) {
44
+ case 'header':
45
+ $this->extractHeader($name, $member, $response, $result);
46
+ break;
47
+ case 'headers':
48
+ $this->extractHeaders($name, $member, $response, $result);
49
+ break;
50
+ case 'statusCode':
51
+ $this->extractStatus($name, $response, $result);
52
+ break;
53
+ }
54
+ }
55
+
56
+ if (!$payload && $response->getBody()->getSize() > 0) {
57
+ // if no payload was found, then parse the contents of the body
58
+ $this->payload($response, $output, $result);
59
+ }
60
+
61
+ return new Result($result);
62
+ }
63
+
64
+ private function extractPayload(
65
+ $payload,
66
+ StructureShape $output,
67
+ ResponseInterface $response,
68
+ array &$result
69
+ ) {
70
+ $member = $output->getMember($payload);
71
+
72
+ if ($member instanceof StructureShape) {
73
+ // Structure members parse top-level data into a specific key.
74
+ $result[$payload] = [];
75
+ $this->payload($response, $member, $result[$payload]);
76
+ } else {
77
+ // Streaming data is just the stream from the response body.
78
+ $result[$payload] = $response->getBody();
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Extract a single header from the response into the result.
84
+ */
85
+ private function extractHeader(
86
+ $name,
87
+ Shape $shape,
88
+ ResponseInterface $response,
89
+ &$result
90
+ ) {
91
+ $value = $response->getHeaderLine($shape['locationName'] ?: $name);
92
+
93
+ switch ($shape->getType()) {
94
+ case 'float':
95
+ case 'double':
96
+ $value = (float) $value;
97
+ break;
98
+ case 'long':
99
+ $value = (int) $value;
100
+ break;
101
+ case 'boolean':
102
+ $value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
103
+ break;
104
+ case 'blob':
105
+ $value = base64_decode($value);
106
+ break;
107
+ case 'timestamp':
108
+ try {
109
+ $value = new DateTimeResult($value);
110
+ break;
111
+ } catch (\Exception $e) {
112
+ // If the value cannot be parsed, then do not add it to the
113
+ // output structure.
114
+ return;
115
+ }
116
+ }
117
+
118
+ $result[$name] = $value;
119
+ }
120
+
121
+ /**
122
+ * Extract a map of headers with an optional prefix from the response.
123
+ */
124
+ private function extractHeaders(
125
+ $name,
126
+ Shape $shape,
127
+ ResponseInterface $response,
128
+ &$result
129
+ ) {
130
+ // Check if the headers are prefixed by a location name
131
+ $result[$name] = [];
132
+ $prefix = $shape['locationName'];
133
+ $prefixLen = strlen($prefix);
134
+
135
+ foreach ($response->getHeaders() as $k => $values) {
136
+ if (!$prefixLen) {
137
+ $result[$name][$k] = implode(', ', $values);
138
+ } elseif (stripos($k, $prefix) === 0) {
139
+ $result[$name][substr($k, $prefixLen)] = implode(', ', $values);
140
+ }
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Places the status code of the response into the result array.
146
+ */
147
+ private function extractStatus(
148
+ $name,
149
+ ResponseInterface $response,
150
+ array &$result
151
+ ) {
152
+ $result[$name] = (int) $response->getStatusCode();
153
+ }
154
+ }
includes/aws/Aws/Api/Parser/Crc32ValidatingParser.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Parser;
3
+
4
+ use Aws\CommandInterface;
5
+ use Aws\Exception\AwsException;
6
+ use Psr\Http\Message\ResponseInterface;
7
+ use GuzzleHttp\Psr7;
8
+
9
+ /**
10
+ * @internal Decorates a parser and validates the x-amz-crc32 header.
11
+ */
12
+ class Crc32ValidatingParser extends AbstractParser
13
+ {
14
+ /** @var callable */
15
+ private $parser;
16
+
17
+ /**
18
+ * @param callable $parser Parser to wrap.
19
+ */
20
+ public function __construct(callable $parser)
21
+ {
22
+ $this->parser = $parser;
23
+ }
24
+
25
+ public function __invoke(
26
+ CommandInterface $command,
27
+ ResponseInterface $response
28
+ ) {
29
+ if ($expected = $response->getHeaderLine('x-amz-crc32')) {
30
+ $hash = hexdec(Psr7\hash($response->getBody(), 'crc32b'));
31
+ if ($expected != $hash) {
32
+ throw new AwsException(
33
+ "crc32 mismatch. Expected {$expected}, found {$hash}.",
34
+ $command,
35
+ [
36
+ 'code' => 'ClientChecksumMismatch',
37
+ 'connection_error' => true,
38
+ 'response' => $response
39
+ ]
40
+ );
41
+ }
42
+ }
43
+
44
+ $fn = $this->parser;
45
+ return $fn($command, $response);
46
+ }
47
+ }
includes/aws/Aws/Api/Parser/Exception/ParserException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Parser\Exception;
3
+
4
+ class ParserException extends \RuntimeException {}
includes/aws/Aws/Api/Parser/JsonParser.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Parser;
3
+
4
+ use Aws\Api\DateTimeResult;
5
+ use Aws\Api\Shape;
6
+
7
+ /**
8
+ * @internal Implements standard JSON parsing.
9
+ */
10
+ class JsonParser
11
+ {
12
+ public function parse(Shape $shape, $value)
13
+ {
14
+ if ($value === null) {
15
+ return $value;
16
+ }
17
+
18
+ switch ($shape['type']) {
19
+ case 'structure':
20
+ $target = [];
21
+ foreach ($shape->getMembers() as $name => $member) {
22
+ $locationName = $member['locationName'] ?: $name;
23
+ if (isset($value[$locationName])) {
24
+ $target[$name] = $this->parse($member, $value[$locationName]);
25
+ }
26
+ }
27
+ return $target;
28
+
29
+ case 'list':
30
+ $member = $shape->getMember();
31
+ $target = [];
32
+ foreach ($value as $v) {
33
+ $target[] = $this->parse($member, $v);
34
+ }
35
+ return $target;
36
+
37
+ case 'map':
38
+ $values = $shape->getValue();
39
+ $target = [];
40
+ foreach ($value as $k => $v) {
41
+ $target[$k] = $this->parse($values, $v);
42
+ }
43
+ return $target;
44
+
45
+ case 'timestamp':
46
+ // The Unix epoch (or Unix time or POSIX time or Unix
47
+ // timestamp) is the number of seconds that have elapsed since
48
+ // January 1, 1970 (midnight UTC/GMT).
49
+ return DateTimeResult::fromEpoch($value);
50
+
51
+ case 'blob':
52
+ return base64_decode($value);
53
+
54
+ default:
55
+ return $value;
56
+ }
57
+ }
58
+ }
includes/aws/Aws/Api/Parser/JsonRpcParser.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Parser;
3
+
4
+ use Aws\Api\Service;
5
+ use Aws\Result;
6
+ use Aws\CommandInterface;
7
+ use Psr\Http\Message\ResponseInterface;
8
+
9
+ /**
10
+ * @internal Implements JSON-RPC parsing (e.g., DynamoDB)
11
+ */
12
+ class JsonRpcParser extends AbstractParser
13
+ {
14
+ use PayloadParserTrait;
15
+
16
+ private $parser;
17
+
18
+ /**
19
+ * @param Service $api Service description
20
+ * @param JsonParser $parser JSON body builder
21
+ */
22
+ public function __construct(Service $api, JsonParser $parser = null)
23
+ {
24
+ parent::__construct($api);
25
+ $this->parser = $parser ?: new JsonParser();
26
+ }
27
+
28
+ public function __invoke(
29
+ CommandInterface $command,
30
+ ResponseInterface $response
31
+ ) {
32
+ $operation = $this->api->getOperation($command->getName());
33
+ $result = $this->parser->parse(
34
+ $operation->getOutput(),
35
+ $this->parseJson($response->getBody())
36
+ );
37
+
38
+ return new Result($result ?: []);
39
+ }
40
+ }
includes/aws/Aws/Api/Parser/PayloadParserTrait.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Parser;
3
+
4
+ use Aws\Api\Parser\Exception\ParserException;
5
+
6
+ trait PayloadParserTrait
7
+ {
8
+ /**
9
+ * @param string $json
10
+ *
11
+ * @throws ParserException
12
+ *
13
+ * @return array
14
+ */
15
+ private function parseJson($json)
16
+ {
17
+ $jsonPayload = json_decode($json, true);
18
+
19
+ if (JSON_ERROR_NONE !== json_last_error()) {
20
+ throw new ParserException('Error parsing JSON: '
21
+ . json_last_error_msg());
22
+ }
23
+
24
+ return $jsonPayload;
25
+ }
26
+
27
+ /**
28
+ * @param string $xml
29
+ *
30
+ * @throws ParserException
31
+ *
32
+ * @return \SimpleXMLElement
33
+ */
34
+ private function parseXml($xml)
35
+ {
36
+ $priorSetting = libxml_use_internal_errors(true);
37
+ try {
38
+ libxml_clear_errors();
39
+ $xmlPayload = new \SimpleXMLElement($xml);
40
+ if ($error = libxml_get_last_error()) {
41
+ throw new \RuntimeException($error->message);
42
+ }
43
+ } catch (\Exception $e) {
44
+ throw new ParserException("Error parsing XML: {$e->getMessage()}", 0, $e);
45
+ } finally {
46
+ libxml_use_internal_errors($priorSetting);
47
+ }
48
+
49
+ return $xmlPayload;
50
+ }
51
+ }
includes/aws/Aws/Api/Parser/QueryParser.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Parser;
3
+
4
+ use Aws\Api\Service;
5
+ use Aws\Result;
6
+ use Aws\CommandInterface;
7
+ use Psr\Http\Message\ResponseInterface;
8
+
9
+ /**
10
+ * @internal Parses query (XML) responses (e.g., EC2, SQS, and many others)
11
+ */
12
+ class QueryParser extends AbstractParser
13
+ {
14
+ use PayloadParserTrait;
15
+
16
+ /** @var XmlParser */
17
+ private $xmlParser;
18
+
19
+ /** @var bool */
20
+ private $honorResultWrapper;
21
+
22
+ /**
23
+ * @param Service $api Service description
24
+ * @param XmlParser $xmlParser Optional XML parser
25
+ * @param bool $honorResultWrapper Set to false to disable the peeling
26
+ * back of result wrappers from the
27
+ * output structure.
28
+ */
29
+ public function __construct(
30
+ Service $api,
31
+ XmlParser $xmlParser = null,
32
+ $honorResultWrapper = true
33
+ ) {
34
+ parent::__construct($api);
35
+ $this->xmlParser = $xmlParser ?: new XmlParser();
36
+ $this->honorResultWrapper = $honorResultWrapper;
37
+ }
38
+
39
+ public function __invoke(
40
+ CommandInterface $command,
41
+ ResponseInterface $response
42
+ ) {
43
+ $output = $this->api->getOperation($command->getName())->getOutput();
44
+ $xml = $this->parseXml($response->getBody());
45
+
46
+ if ($this->honorResultWrapper && $output['resultWrapper']) {
47
+ $xml = $xml->{$output['resultWrapper']};
48
+ }
49
+
50
+ return new Result($this->xmlParser->parse($output, $xml));
51
+ }
52
+ }
includes/aws/Aws/Api/Parser/RestJsonParser.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Parser;
3
+
4
+ use Aws\Api\Service;
5
+ use Aws\Api\StructureShape;
6
+ use Psr\Http\Message\ResponseInterface;
7
+
8
+ /**
9
+ * @internal Implements REST-JSON parsing (e.g., Glacier, Elastic Transcoder)
10
+ */
11
+ class RestJsonParser extends AbstractRestParser
12
+ {
13
+ use PayloadParserTrait;
14
+
15
+ /** @var JsonParser */
16
+ private $parser;
17
+
18
+ /**
19
+ * @param Service $api Service description
20
+ * @param JsonParser $parser JSON body builder
21
+ */
22
+ public function __construct(Service $api, JsonParser $parser = null)
23
+ {
24
+ parent::__construct($api);
25
+ $this->parser = $parser ?: new JsonParser();
26
+ }
27
+
28
+ protected function payload(
29
+ ResponseInterface $response,
30
+ StructureShape $member,
31
+ array &$result
32
+ ) {
33
+ $jsonBody = $this->parseJson($response->getBody());
34
+
35
+ if ($jsonBody) {
36
+ $result += $this->parser->parse($member, $jsonBody);
37
+ }
38
+ }
39
+ }
includes/aws/Aws/Api/Parser/RestXmlParser.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Parser;
3
+
4
+ use Aws\Api\StructureShape;
5
+ use Aws\Api\Service;
6
+ use Psr\Http\Message\ResponseInterface;
7
+
8
+ /**
9
+ * @internal Implements REST-XML parsing (e.g., S3, CloudFront, etc...)
10
+ */
11
+ class RestXmlParser extends AbstractRestParser
12
+ {
13
+ use PayloadParserTrait;
14
+
15
+ /** @var XmlParser */
16
+ private $parser;
17
+
18
+ /**
19
+ * @param Service $api Service description
20
+ * @param XmlParser $parser XML body parser
21
+ */
22
+ public function __construct(Service $api, XmlParser $parser = null)
23
+ {
24
+ parent::__construct($api);
25
+ $this->parser = $parser ?: new XmlParser();
26
+ }
27
+
28
+ protected function payload(
29
+ ResponseInterface $response,
30
+ StructureShape $member,
31
+ array &$result
32
+ ) {
33
+ $xml = $this->parseXml($response->getBody());
34
+ $result += $this->parser->parse($member, $xml);
35
+ }
36
+ }
includes/aws/Aws/Api/Parser/XmlParser.php ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Parser;
3
+
4
+ use Aws\Api\DateTimeResult;
5
+ use Aws\Api\ListShape;
6
+ use Aws\Api\MapShape;
7
+ use Aws\Api\Shape;
8
+ use Aws\Api\StructureShape;
9
+
10
+ /**
11
+ * @internal Implements standard XML parsing for REST-XML and Query protocols.
12
+ */
13
+ class XmlParser
14
+ {
15
+ public function parse(StructureShape $shape, \SimpleXMLElement $value)
16
+ {
17
+ return $this->dispatch($shape, $value);
18
+ }
19
+
20
+ private function dispatch($shape, \SimpleXMLElement $value)
21
+ {
22
+ static $methods = [
23
+ 'structure' => 'parse_structure',
24
+ 'list' => 'parse_list',
25
+ 'map' => 'parse_map',
26
+ 'blob' => 'parse_blob',
27
+ 'boolean' => 'parse_boolean',
28
+ 'integer' => 'parse_integer',
29
+ 'float' => 'parse_float',
30
+ 'double' => 'parse_float',
31
+ 'timestamp' => 'parse_timestamp',
32
+ ];
33
+
34
+ $type = $shape['type'];
35
+ if (isset($methods[$type])) {
36
+ return $this->{$methods[$type]}($shape, $value);
37
+ }
38
+
39
+ return (string) $value;
40
+ }
41
+
42
+ private function parse_structure(
43
+ StructureShape $shape,
44
+ \SimpleXMLElement $value
45
+ ) {
46
+ $target = [];
47
+
48
+ foreach ($shape->getMembers() as $name => $member) {
49
+ // Extract the name of the XML node
50
+ $node = $this->memberKey($member, $name);
51
+ if (isset($value->{$node})) {
52
+ $target[$name] = $this->dispatch($member, $value->{$node});
53
+ }
54
+ }
55
+
56
+ return $target;
57
+ }
58
+
59
+ private function memberKey(Shape $shape, $name)
60
+ {
61
+ if (null !== $shape['locationName']) {
62
+ return $shape['locationName'];
63
+ }
64
+
65
+ if ($shape instanceof ListShape && $shape['flattened']) {
66
+ return $shape->getMember()['locationName'] ?: $name;
67
+ }
68
+
69
+ return $name;
70
+ }
71
+
72
+ private function parse_list(ListShape $shape, \SimpleXMLElement $value)
73
+ {
74
+ $target = [];
75
+ $member = $shape->getMember();
76
+
77
+ if (!$shape['flattened']) {
78
+ $value = $value->{$member['locationName'] ?: 'member'};
79
+ }
80
+
81
+ foreach ($value as $v) {
82
+ $target[] = $this->dispatch($member, $v);
83
+ }
84
+
85
+ return $target;
86
+ }
87
+
88
+ private function parse_map(MapShape $shape, \SimpleXMLElement $value)
89
+ {
90
+ $target = [];
91
+
92
+ if (!$shape['flattened']) {
93
+ $value = $value->entry;
94
+ }
95
+
96
+ $mapKey = $shape->getKey();
97
+ $mapValue = $shape->getValue();
98
+ $keyName = $shape->getKey()['locationName'] ?: 'key';
99
+ $valueName = $shape->getValue()['locationName'] ?: 'value';
100
+
101
+ foreach ($value as $node) {
102
+ $key = $this->dispatch($mapKey, $node->{$keyName});
103
+ $value = $this->dispatch($mapValue, $node->{$valueName});
104
+ $target[$key] = $value;
105
+ }
106
+
107
+ return $target;
108
+ }
109
+
110
+ private function parse_blob(Shape $shape, $value)
111
+ {
112
+ return base64_decode((string) $value);
113
+ }
114
+
115
+ private function parse_float(Shape $shape, $value)
116
+ {
117
+ return (float) (string) $value;
118
+ }
119
+
120
+ private function parse_integer(Shape $shape, $value)
121
+ {
122
+ return (int) (string) $value;
123
+ }
124
+
125
+ private function parse_boolean(Shape $shape, $value)
126
+ {
127
+ return $value == 'true' ? true : false;
128
+ }
129
+
130
+ private function parse_timestamp(Shape $shape, $value)
131
+ {
132
+ return new DateTimeResult($value);
133
+ }
134
+ }
includes/aws/Aws/Api/Serializer/Ec2ParamBuilder.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Serializer;
3
+
4
+ use Aws\Api\Shape;
5
+ use Aws\Api\ListShape;
6
+
7
+ /**
8
+ * @internal
9
+ */
10
+ class Ec2ParamBuilder extends QueryParamBuilder
11
+ {
12
+ protected function queryName(Shape $shape, $default = null)
13
+ {
14
+ return ($shape['queryName']
15
+ ?: ucfirst($shape['locationName']))
16
+ ?: $default;
17
+ }
18
+
19
+ protected function isFlat(Shape $shape)
20
+ {
21
+ return false;
22
+ }
23
+
24
+ protected function format_list(
25
+ ListShape $shape,
26
+ array $value,
27
+ $prefix,
28
+ &$query
29
+ ) {
30
+ // Handle empty list serialization
31
+ if (!$value) {
32
+ $query[$prefix] = false;
33
+ } else {
34
+ $items = $shape->getMember();
35
+ foreach ($value as $k => $v) {
36
+ $this->format($items, $v, $prefix . '.' . ($k + 1), $query);
37
+ }
38
+ }
39
+ }
40
+ }
includes/aws/Aws/Api/Serializer/JsonBody.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Serializer;
3
+
4
+ use Aws\Api\Service;
5
+ use Aws\Api\Shape;
6
+ use Aws\Api\TimestampShape;
7
+
8
+ /**
9
+ * Formats the JSON body of a JSON-REST or JSON-RPC operation.
10
+ * @internal
11
+ */
12
+ class JsonBody
13
+ {
14
+ private $api;
15
+
16
+ public function __construct(Service $api)
17
+ {
18
+ $this->api = $api;
19
+ }
20
+
21
+ /**
22
+ * Gets the JSON Content-Type header for a service API
23
+ *
24
+ * @param Service $service
25
+ *
26
+ * @return string
27
+ */
28
+ public static function getContentType(Service $service)
29
+ {
30
+ return 'application/x-amz-json-'
31
+ . number_format($service->getMetadata('jsonVersion'), 1);
32
+ }
33
+
34
+ /**
35
+ * Builds the JSON body based on an array of arguments.
36
+ *
37
+ * @param Shape $shape Operation being constructed
38
+ * @param array $args Associative array of arguments
39
+ *
40
+ * @return string
41
+ */
42
+ public function build(Shape $shape, array $args)
43
+ {
44
+ $result = json_encode($this->format($shape, $args));
45
+
46
+ return $result == '[]' ? '{}' : $result;
47
+ }
48
+
49
+ private function format(Shape $shape, $value)
50
+ {
51
+ switch ($shape['type']) {
52
+ case 'structure':
53
+ $data = [];
54
+ foreach ($value as $k => $v) {
55
+ if ($v !== null && $shape->hasMember($k)) {
56
+ $valueShape = $shape->getMember($k);
57
+ $data[$valueShape['locationName'] ?: $k]
58
+ = $this->format($valueShape, $v);
59
+ }
60
+ }
61
+ return $data;
62
+
63
+ case 'list':
64
+ $items = $shape->getMember();
65
+ foreach ($value as &$v) {
66
+ $v = $this->format($items, $v);
67
+ }
68
+ return $value;
69
+
70
+ case 'map':
71
+ if (empty($value)) {
72
+ return new \stdClass;
73
+ }
74
+ $values = $shape->getValue();
75
+ foreach ($value as &$v) {
76
+ $v = $this->format($values, $v);
77
+ }
78
+ return $value;
79
+
80
+ case 'blob':
81
+ return base64_encode($value);
82
+
83
+ case 'timestamp':
84
+ return TimestampShape::format($value, 'unixTimestamp');
85
+
86
+ default:
87
+ return $value;
88
+ }
89
+ }
90
+ }
includes/aws/Aws/Api/Serializer/JsonRpcSerializer.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Serializer;
3
+
4
+ use Aws\Api\Service;
5
+ use Aws\CommandInterface;
6
+ use GuzzleHttp\Psr7\Request;
7
+ use Psr\Http\Message\RequestInterface;
8
+
9
+ /**
10
+ * Prepares a JSON-RPC request for transfer.
11
+ * @internal
12
+ */
13
+ class JsonRpcSerializer
14
+ {
15
+ /** @var JsonBody */
16
+ private $jsonFormatter;
17
+
18
+ /** @var string */
19
+ private $endpoint;
20
+
21
+ /** @var Service */
22
+ private $api;
23
+
24
+ /** @var string */
25
+ private $contentType;
26
+
27
+ /**
28
+ * @param Service $api Service description
29
+ * @param string $endpoint Endpoint to connect to
30
+ * @param JsonBody $jsonFormatter Optional JSON formatter to use
31
+ */
32
+ public function __construct(
33
+ Service $api,
34
+ $endpoint,
35
+ JsonBody $jsonFormatter = null
36
+ ) {
37
+ $this->endpoint = $endpoint;
38
+ $this->api = $api;
39
+ $this->jsonFormatter = $jsonFormatter ?: new JsonBody($this->api);
40
+ $this->contentType = JsonBody::getContentType($api);
41
+ }
42
+
43
+ /**
44
+ * When invoked with an AWS command, returns a serialization array
45
+ * containing "method", "uri", "headers", and "body" key value pairs.
46
+ *
47
+ * @param CommandInterface $command
48
+ *
49
+ * @return RequestInterface
50
+ */
51
+ public function __invoke(CommandInterface $command)
52
+ {
53
+ $name = $command->getName();
54
+ $operation = $this->api->getOperation($name);
55
+
56
+ return new Request(
57
+ $operation['http']['method'],
58
+ $this->endpoint,
59
+ [
60
+ 'X-Amz-Target' => $this->api->getMetadata('targetPrefix') . '.' . $name,
61
+ 'Content-Type' => $this->contentType
62
+ ],
63
+ $this->jsonFormatter->build(
64
+ $operation->getInput(),
65
+ $command->toArray()
66
+ )
67
+ );
68
+ }
69
+ }
includes/aws/Aws/Api/Serializer/QueryParamBuilder.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Serializer;
3
+
4
+ use Aws\Api\StructureShape;
5
+ use Aws\Api\ListShape;
6
+ use Aws\Api\MapShape;
7
+ use Aws\Api\Shape;
8
+ use Aws\Api\TimestampShape;
9
+
10
+ /**
11
+ * @internal
12
+ */
13
+ class QueryParamBuilder
14
+ {
15
+ private $methods;
16
+
17
+ protected function queryName(Shape $shape, $default = null)
18
+ {
19
+ if (null !== $shape['queryName']) {
20
+ return $shape['queryName'];
21
+ }
22
+
23
+ if (null !== $shape['locationName']) {
24
+ return $shape['locationName'];
25
+ }
26
+
27
+ if ($this->isFlat($shape) && !empty($shape['member']['locationName'])) {
28
+ return $shape['member']['locationName'];
29
+ }
30
+
31
+ return $default;
32
+ }
33
+
34
+ protected function isFlat(Shape $shape)
35
+ {
36
+ return $shape['flattened'] === true;
37
+ }
38
+
39
+ public function __invoke(StructureShape $shape, array $params)
40
+ {
41
+ if (!$this->methods) {
42
+ $this->methods = array_fill_keys(get_class_methods($this), true);
43
+ }
44
+
45
+ $query = [];
46
+ $this->format_structure($shape, $params, '', $query);
47
+
48
+ return $query;
49
+ }
50
+
51
+ protected function format(Shape $shape, $value, $prefix, array &$query)
52
+ {
53
+ $type = 'format_' . $shape['type'];
54
+ if (isset($this->methods[$type])) {
55
+ $this->{$type}($shape, $value, $prefix, $query);
56
+ } else {
57
+ $query[$prefix] = (string) $value;
58
+ }
59
+ }
60
+
61
+ protected function format_structure(
62
+ StructureShape $shape,
63
+ array $value,
64
+ $prefix,
65
+ &$query
66
+ ) {
67
+ if ($prefix) {
68
+ $prefix .= '.';
69
+ }
70
+
71
+ foreach ($value as $k => $v) {
72
+ if ($shape->hasMember($k)) {
73
+ $member = $shape->getMember($k);
74
+ $this->format(
75
+ $member,
76
+ $v,
77
+ $prefix . $this->queryName($member, $k),
78
+ $query
79
+ );
80
+ }
81
+ }
82
+ }
83
+
84
+ protected function format_list(
85
+ ListShape $shape,
86
+ array $value,
87
+ $prefix,
88
+ &$query
89
+ ) {
90
+ // Handle empty list serialization
91
+ if (!$value) {
92
+ $query[$prefix] = '';
93
+ return;
94
+ }
95
+
96
+ $items = $shape->getMember();
97
+
98
+ if (!$this->isFlat($shape)) {
99
+ $locationName = $shape->getMember()['locationName'] ?: 'member';
100
+ $prefix .= ".$locationName";
101
+ } elseif ($name = $this->queryName($items)) {
102
+ $parts = explode('.', $prefix);
103
+ $parts[count($parts) - 1] = $name;
104
+ $prefix = implode('.', $parts);
105
+ }
106
+
107
+ foreach ($value as $k => $v) {
108
+ $this->format($items, $v, $prefix . '.' . ($k + 1), $query);
109
+ }
110
+ }
111
+
112
+ protected function format_map(
113
+ MapShape $shape,
114
+ array $value,
115
+ $prefix,
116
+ array &$query
117
+ ) {
118
+ $vals = $shape->getValue();
119
+ $keys = $shape->getKey();
120
+
121
+ if (!$this->isFlat($shape)) {
122
+ $prefix .= '.entry';
123
+ }
124
+
125
+ $i = 0;
126
+ $keyName = '%s.%d.' . $this->queryName($keys, 'key');
127
+ $valueName = '%s.%s.' . $this->queryName($vals, 'value');
128
+
129
+ foreach ($value as $k => $v) {
130
+ $i++;
131
+ $this->format($keys, $k, sprintf($keyName, $prefix, $i), $query);
132
+ $this->format($vals, $v, sprintf($valueName, $prefix, $i), $query);
133
+ }
134
+ }
135
+
136
+ protected function format_blob(Shape $shape, $value, $prefix, array &$query)
137
+ {
138
+ $query[$prefix] = base64_encode($value);
139
+ }
140
+
141
+ protected function format_timestamp(
142
+ TimestampShape $shape,
143
+ $value,
144
+ $prefix,
145
+ array &$query
146
+ ) {
147
+ $query[$prefix] = TimestampShape::format($value, 'iso8601');
148
+ }
149
+
150
+ protected function format_boolean(Shape $shape, $value, $prefix, array &$query)
151
+ {
152
+ $query[$prefix] = ($value) ? 'true' : 'false';
153
+ }
154
+ }
includes/aws/Aws/Api/Serializer/QuerySerializer.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Serializer;
3
+
4
+ use Aws\Api\Service;
5
+ use Aws\CommandInterface;
6
+ use GuzzleHttp\Psr7\Request;
7
+ use Psr\Http\Message\RequestInterface;
8
+
9
+ /**
10
+ * Serializes a query protocol request.
11
+ * @internal
12
+ */
13
+ class QuerySerializer
14
+ {
15
+ private $endpoint;
16
+ private $api;
17
+ private $paramBuilder;
18
+
19
+ public function __construct(
20
+ Service $api,
21
+ $endpoint,
22
+ callable $paramBuilder = null
23
+ ) {
24
+ $this->api = $api;
25
+ $this->endpoint = $endpoint;
26
+ $this->paramBuilder = $paramBuilder ?: new QueryParamBuilder();
27
+ }
28
+
29
+ /**
30
+ * When invoked with an AWS command, returns a serialization array
31
+ * containing "method", "uri", "headers", and "body" key value pairs.
32
+ *
33
+ * @param CommandInterface $command
34
+ *
35
+ * @return RequestInterface
36
+ */
37
+ public function __invoke(CommandInterface $command)
38
+ {
39
+ $operation = $this->api->getOperation($command->getName());
40
+
41
+ $body = [
42
+ 'Action' => $command->getName(),
43
+ 'Version' => $this->api->getMetadata('apiVersion')
44
+ ];
45
+
46
+ $params = $command->toArray();
47
+
48
+ // Only build up the parameters when there are parameters to build
49
+ if ($params) {
50
+ $body += call_user_func(
51
+ $this->paramBuilder,
52
+ $operation->getInput(),
53
+ $params
54
+ );
55
+ }
56
+
57
+ $body = http_build_query($body, null, '&', PHP_QUERY_RFC3986);
58
+
59
+ return new Request(
60
+ 'POST',
61
+ $this->endpoint,
62
+ [
63
+ 'Content-Length' => strlen($body),
64
+ 'Content-Type' => 'application/x-www-form-urlencoded'
65
+ ],
66
+ $body
67
+ );
68
+ }
69
+ }
includes/aws/Aws/Api/Serializer/RestJsonSerializer.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Serializer;
3
+
4
+ use Aws\Api\Service;
5
+ use Aws\Api\StructureShape;
6
+
7
+ /**
8
+ * Serializes requests for the REST-JSON protocol.
9
+ * @internal
10
+ */
11
+ class RestJsonSerializer extends RestSerializer
12
+ {
13
+ /** @var JsonBody */
14
+ private $jsonFormatter;
15
+
16
+ /** @var string */
17
+ private $contentType;
18
+
19
+ /**
20
+ * @param Service $api Service API description
21
+ * @param string $endpoint Endpoint to connect to
22
+ * @param JsonBody $jsonFormatter Optional JSON formatter to use
23
+ */
24
+ public function __construct(
25
+ Service $api,
26
+ $endpoint,
27
+ JsonBody $jsonFormatter = null
28
+ ) {
29
+ parent::__construct($api, $endpoint);
30
+ $this->contentType = JsonBody::getContentType($api);
31
+ $this->jsonFormatter = $jsonFormatter ?: new JsonBody($api);
32
+ }
33
+
34
+ protected function payload(StructureShape $member, array $value, array &$opts)
35
+ {
36
+ $opts['headers']['Content-Type'] = $this->contentType;
37
+ $opts['body'] = (string) $this->jsonFormatter->build($member, $value);
38
+ }
39
+ }
includes/aws/Aws/Api/Serializer/RestSerializer.php ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Serializer;
3
+
4
+ use Aws\Api\MapShape;
5
+ use Aws\Api\Service;
6
+ use Aws\Api\Operation;
7
+ use Aws\Api\Shape;
8
+ use Aws\Api\StructureShape;
9
+ use Aws\Api\TimestampShape;
10
+ use Aws\CommandInterface;
11
+ use GuzzleHttp\Psr7;
12
+ use Psr\Http\Message\RequestInterface;
13
+
14
+ /**
15
+ * Serializes HTTP locations like header, uri, payload, etc...
16
+ * @internal
17
+ */
18
+ abstract class RestSerializer
19
+ {
20
+ /** @var Service */
21
+ private $api;
22
+
23
+ /** @var Psr7\Uri */
24
+ private $endpoint;
25
+
26
+ /**
27
+ * @param Service $api Service API description
28
+ * @param string $endpoint Endpoint to connect to
29
+ */
30
+ public function __construct(Service $api, $endpoint)
31
+ {
32
+ $this->api = $api;
33
+ $this->endpoint = Psr7\uri_for($endpoint);
34
+ }
35
+
36
+ /**
37
+ * @param CommandInterface $command Command to serialized
38
+ *
39
+ * @return RequestInterface
40
+ */
41
+ public function __invoke(CommandInterface $command)
42
+ {
43
+ $operation = $this->api->getOperation($command->getName());
44
+ $args = $command->toArray();
45
+ $opts = $this->serialize($operation, $args);
46
+ $uri = $this->buildEndpoint($operation, $args, $opts);
47
+
48
+ return new Psr7\Request(
49
+ $operation['http']['method'],
50
+ $uri,
51
+ isset($opts['headers']) ? $opts['headers'] : [],
52
+ isset($opts['body']) ? $opts['body'] : null
53
+ );
54
+ }
55
+
56
+ /**
57
+ * Modifies a hash of request options for a payload body.
58
+ *
59
+ * @param StructureShape $member Member to serialize
60
+ * @param array $value Value to serialize
61
+ * @param array $opts Request options to modify.
62
+ */
63
+ abstract protected function payload(
64
+ StructureShape $member,
65
+ array $value,
66
+ array &$opts
67
+ );
68
+
69
+ private function serialize(Operation $operation, array $args)
70
+ {
71
+ $opts = [];
72
+ $input = $operation->getInput();
73
+
74
+ // Apply the payload trait if present
75
+ if ($payload = $input['payload']) {
76
+ $this->applyPayload($input, $payload, $args, $opts);
77
+ }
78
+
79
+ foreach ($args as $name => $value) {
80
+ if ($input->hasMember($name)) {
81
+ $member = $input->getMember($name);
82
+ $location = $member['location'];
83
+ if (!$payload && !$location) {
84
+ $bodyMembers[$name] = $value;
85
+ } elseif ($location == 'header') {
86
+ $this->applyHeader($name, $member, $value, $opts);
87
+ } elseif ($location == 'querystring') {
88
+ $this->applyQuery($name, $member, $value, $opts);
89
+ } elseif ($location == 'headers') {
90
+ $this->applyHeaderMap($name, $member, $value, $opts);
91
+ }
92
+ }
93
+ }
94
+
95
+ if (isset($bodyMembers)) {
96
+ $this->payload($operation->getInput(), $bodyMembers, $opts);
97
+ }
98
+
99
+ return $opts;
100
+ }
101
+
102
+ private function applyPayload(StructureShape $input, $name, array $args, array &$opts)
103
+ {
104
+ if (!isset($args[$name])) {
105
+ return;
106
+ }
107
+
108
+ $m = $input->getMember($name);
109
+
110
+ if ($m['streaming'] ||
111
+ ($m['type'] == 'string' || $m['type'] == 'blob')
112
+ ) {
113
+ // Streaming bodies or payloads that are strings are
114
+ // always just a stream of data.
115
+ $opts['body'] = Psr7\stream_for($args[$name]);
116
+ return;
117
+ }
118
+
119
+ $this->payload($m, $args[$name], $opts);
120
+ }
121
+
122
+ private function applyHeader($name, Shape $member, $value, array &$opts)
123
+ {
124
+ if ($member->getType() == 'timestamp') {
125
+ $value = TimestampShape::format($value, 'rfc822');
126
+ }
127
+
128
+ $opts['headers'][$member['locationName'] ?: $name] = $value;
129
+ }
130
+
131
+ /**
132
+ * Note: This is currently only present in the Amazon S3 model.
133
+ */
134
+ private function applyHeaderMap($name, Shape $member, array $value, array &$opts)
135
+ {
136
+ $prefix = $member['locationName'];
137
+ foreach ($value as $k => $v) {
138
+ $opts['headers'][$prefix . $k] = $v;
139
+ }
140
+ }
141
+
142
+ private function applyQuery($name, Shape $member, $value, array &$opts)
143
+ {
144
+ if ($member instanceof MapShape) {
145
+ $opts['query'] = isset($opts['query']) && is_array($opts['query'])
146
+ ? $opts['query'] + $value
147
+ : $value;
148
+ } elseif ($value !== null) {
149
+ $opts['query'][$member['locationName'] ?: $name] = $value;
150
+ }
151
+ }
152
+
153
+ private function buildEndpoint(Operation $operation, array $args, array $opts)
154
+ {
155
+ $varspecs = [];
156
+
157
+ // Create an associative array of varspecs used in expansions
158
+ foreach ($operation->getInput()->getMembers() as $name => $member) {
159
+ if ($member['location'] == 'uri') {
160
+ $varspecs[$member['locationName'] ?: $name] =
161
+ isset($args[$name])
162
+ ? $args[$name]
163
+ : null;
164
+ }
165
+ }
166
+
167
+ $relative = preg_replace_callback(
168
+ '/\{([^\}]+)\}/',
169
+ function (array $matches) use ($varspecs) {
170
+ $isGreedy = substr($matches[1], -1, 1) == '+';
171
+ $k = $isGreedy ? substr($matches[1], 0, -1) : $matches[1];
172
+ if (!isset($varspecs[$k])) {
173
+ return '';
174
+ } elseif ($isGreedy) {
175
+ return str_replace('%2F', '/', rawurlencode($varspecs[$k]));
176
+ } else {
177
+ return rawurlencode($varspecs[$k]);
178
+ }
179
+ },
180
+ $operation['http']['requestUri']
181
+ );
182
+
183
+ // Add the query string variables or appending to one if needed.
184
+ if (!empty($opts['query'])) {
185
+ $append = Psr7\build_query($opts['query']);
186
+ $relative .= strpos($relative, '?') ? "&{$append}" : "?$append";
187
+ }
188
+
189
+ // Expand path place holders using Amazon's slightly different URI
190
+ // template syntax.
191
+ return Psr7\Uri::resolve($this->endpoint, $relative);
192
+ }
193
+ }
includes/aws/Aws/Api/Serializer/RestXmlSerializer.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Serializer;
3
+
4
+ use Aws\Api\StructureShape;
5
+ use Aws\Api\Service;
6
+
7
+ /**
8
+ * @internal
9
+ */
10
+ class RestXmlSerializer extends RestSerializer
11
+ {
12
+ /** @var XmlBody */
13
+ private $xmlBody;
14
+
15
+ /**
16
+ * @param Service $api Service API description
17
+ * @param string $endpoint Endpoint to connect to
18
+ * @param XmlBody $xmlBody Optional XML formatter to use
19
+ */
20
+ public function __construct(
21
+ Service $api,
22
+ $endpoint,
23
+ XmlBody $xmlBody = null
24
+ ) {
25
+ parent::__construct($api, $endpoint);
26
+ $this->xmlBody = $xmlBody ?: new XmlBody($api);
27
+ }
28
+
29
+ protected function payload(StructureShape $member, array $value, array &$opts)
30
+ {
31
+ $opts['headers']['Content-Type'] = 'application/xml';
32
+ $opts['body'] = (string) $this->xmlBody->build($member, $value);
33
+ }
34
+ }
includes/aws/Aws/Api/Serializer/XmlBody.php ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api\Serializer;
3
+
4
+ use Aws\Api\MapShape;
5
+ use Aws\Api\Service;
6
+ use Aws\Api\Shape;
7
+ use Aws\Api\StructureShape;
8
+ use Aws\Api\ListShape;
9
+ use Aws\Api\TimestampShape;
10
+ use XMLWriter;
11
+
12
+ /**
13
+ * @internal Formats the XML body of a REST-XML services.
14
+ */
15
+ class XmlBody
16
+ {
17
+ /** @var \Aws\Api\Service */
18
+ private $api;
19
+
20
+ /**
21
+ * @param Service $api API being used to create the XML body.
22
+ */
23
+ public function __construct(Service $api)
24
+ {
25
+ $this->api = $api;
26
+ }
27
+
28
+ /**
29
+ * Builds the XML body based on an array of arguments.
30
+ *
31
+ * @param Shape $shape Operation being constructed
32
+ * @param array $args Associative array of arguments
33
+ *
34
+ * @return string
35
+ */
36
+ public function build(Shape $shape, array $args)
37
+ {
38
+ $xml = new XMLWriter();
39
+ $xml->openMemory();
40
+ $xml->startDocument('1.0', 'UTF-8');
41
+ $this->format($shape, $shape['locationName'], $args, $xml);
42
+ $xml->endDocument();
43
+
44
+ return $xml->outputMemory();
45
+ }
46
+
47
+ private function startElement(Shape $shape, $name, XMLWriter $xml)
48
+ {
49
+ $xml->startElement($name);
50
+
51
+ if ($ns = $shape['xmlNamespace']) {
52
+ $xml->writeAttribute(
53
+ isset($ns['prefix']) ? "xmlns:{$ns['prefix']}" : 'xmlns',
54
+ $shape['xmlNamespace']['uri']
55
+ );
56
+ }
57
+ }
58
+
59
+ private function format(Shape $shape, $name, $value, XMLWriter $xml)
60
+ {
61
+ // Any method mentioned here has a custom serialization handler.
62
+ static $methods = [
63
+ 'add_structure' => true,
64
+ 'add_list' => true,
65
+ 'add_blob' => true,
66
+ 'add_timestamp' => true,
67
+ 'add_boolean' => true,
68
+ 'add_map' => true,
69
+ 'add_string' => true
70
+ ];
71
+
72
+ $type = 'add_' . $shape['type'];
73
+ if (isset($methods[$type])) {
74
+ $this->{$type}($shape, $name, $value, $xml);
75
+ } else {
76
+ $this->defaultShape($shape, $name, $value, $xml);
77
+ }
78
+ }
79
+
80
+ private function defaultShape(Shape $shape, $name, $value, XMLWriter $xml)
81
+ {
82
+ $this->startElement($shape, $name, $xml);
83
+ $xml->writeRaw($value);
84
+ $xml->endElement();
85
+ }
86
+
87
+ private function add_structure(
88
+ StructureShape $shape,
89
+ $name,
90
+ array $value,
91
+ \XMLWriter $xml
92
+ ) {
93
+ $this->startElement($shape, $name, $xml);
94
+
95
+ foreach ($this->getStructureMembers($shape, $value) as $k => $definition) {
96
+ $this->format(
97
+ $definition['member'],
98
+ $definition['member']['locationName'] ?: $k,
99
+ $definition['value'],
100
+ $xml
101
+ );
102
+ }
103
+
104
+ $xml->endElement();
105
+ }
106
+
107
+ private function getStructureMembers(StructureShape $shape, array $value)
108
+ {
109
+ $members = [];
110
+
111
+ foreach ($value as $k => $v) {
112
+ if ($v !== null && $shape->hasMember($k)) {
113
+ $definition = [
114
+ 'member' => $shape->getMember($k),
115
+ 'value' => $v,
116
+ ];
117
+
118
+ if ($definition['member']['xmlAttribute']) {
119
+ // array_unshift_associative
120
+ $members = [$k => $definition] + $members;
121
+ } else {
122
+ $members[$k] = $definition;
123
+ }
124
+ }
125
+ }
126
+
127
+ return $members;
128
+ }
129
+
130
+ private function add_list(
131
+ ListShape $shape,
132
+ $name,
133
+ array $value,
134
+ XMLWriter $xml
135
+ ) {
136
+ $items = $shape->getMember();
137
+
138
+ if ($shape['flattened']) {
139
+ $elementName = $name;
140
+ } else {
141
+ $this->startElement($shape, $name, $xml);
142
+ $elementName = $items['locationName'] ?: 'member';
143
+ }
144
+
145
+ foreach ($value as &$v) {
146
+ $this->format($items, $elementName, $v, $xml);
147
+ }
148
+
149
+ if (!$shape['flattened']) {
150
+ $xml->endElement();
151
+ }
152
+ }
153
+
154
+ private function add_map(
155
+ MapShape $shape,
156
+ $name,
157
+ array $value,
158
+ XMLWriter $xml
159
+ ) {
160
+ $xmlEntry = $shape['flattened'] ? $shape['locationName'] : 'entry';
161
+ $xmlKey = $shape->getKey()['locationName'] ?: 'key';
162
+ $xmlValue = $shape->getValue()['locationName'] ?: 'value';
163
+
164
+ $this->startElement($shape, $name, $xml);
165
+
166
+ foreach ($value as $key => $v) {
167
+ $this->startElement($shape, $xmlEntry, $xml);
168
+ $this->format($shape->getKey(), $xmlKey, $key, $xml);
169
+ $this->format($shape->getValue(), $xmlValue, $v, $xml);
170
+ $xml->endElement();
171
+ }
172
+
173
+ $xml->endElement();
174
+ }
175
+
176
+ private function add_blob(Shape $shape, $name, $value, XMLWriter $xml)
177
+ {
178
+ $this->startElement($shape, $name, $xml);
179
+ $xml->writeRaw(base64_encode($value));
180
+ $xml->endElement();
181
+ }
182
+
183
+ private function add_timestamp(
184
+ TimestampShape $shape,
185
+ $name,
186
+ $value,
187
+ XMLWriter $xml
188
+ ) {
189
+ $this->startElement($shape, $name, $xml);
190
+ $xml->writeRaw(TimestampShape::format($value, 'iso8601'));
191
+ $xml->endElement();
192
+ }
193
+
194
+ private function add_boolean(
195
+ Shape $shape,
196
+ $name,
197
+ $value,
198
+ XMLWriter $xml
199
+ ) {
200
+ $this->startElement($shape, $name, $xml);
201
+ $xml->writeRaw($value ? 'true' : 'false');
202
+ $xml->endElement();
203
+ }
204
+
205
+ private function add_string(
206
+ Shape $shape,
207
+ $name,
208
+ $value,
209
+ XMLWriter $xml
210
+ ) {
211
+ if ($shape['xmlAttribute']) {
212
+ $xml->writeAttribute($shape['locationName'] ?: $name, $value);
213
+ } else {
214
+ $this->defaultShape($shape, $name, $value, $xml);
215
+ }
216
+ }
217
+ }
includes/aws/Aws/Api/Service.php ADDED
@@ -0,0 +1,404 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ use Aws\Api\Serializer\QuerySerializer;
5
+ use Aws\Api\Serializer\Ec2ParamBuilder;
6
+ use Aws\Api\Parser\QueryParser;
7
+
8
+ /**
9
+ * Represents a web service API model.
10
+ */
11
+ class Service extends AbstractModel
12
+ {
13
+ /** @var callable */
14
+ private $apiProvider;
15
+
16
+ /** @var string */
17
+ private $serviceName;
18
+
19
+ /** @var string */
20
+ private $apiVersion;
21
+
22
+ /** @var Operation[] */
23
+ private $operations = [];
24
+
25
+ /** @var array */
26
+ private $paginators = null;
27
+
28
+ /** @var array */
29
+ private $waiters = null;
30
+
31
+ /**
32
+ * @param array $definition
33
+ * @param callable $provider
34
+ *
35
+ * @internal param array $definition Service description
36
+ */
37
+ public function __construct(array $definition, callable $provider)
38
+ {
39
+ static $defaults = [
40
+ 'operations' => [],
41
+ 'shapes' => [],
42
+ 'metadata' => []
43
+ ], $defaultMeta = [
44
+ 'apiVersion' => null,
45
+ 'serviceFullName' => null,
46
+ 'endpointPrefix' => null,
47
+ 'signingName' => null,
48
+ 'signatureVersion' => null,
49
+ 'protocol' => null
50
+ ];
51
+
52
+ $definition += $defaults;
53
+ $definition['metadata'] += $defaultMeta;
54
+ $this->definition = $definition;
55
+ $this->apiProvider = $provider;
56
+ parent::__construct($definition, new ShapeMap($definition['shapes']));
57
+ $this->serviceName = $this->getEndpointPrefix();
58
+ $this->apiVersion = $this->getApiVersion();
59
+ }
60
+
61
+ /**
62
+ * Creates a request serializer for the provided API object.
63
+ *
64
+ * @param Service $api API that contains a protocol.
65
+ * @param string $endpoint Endpoint to send requests to.
66
+ *
67
+ * @return callable
68
+ * @throws \UnexpectedValueException
69
+ */
70
+ public static function createSerializer(Service $api, $endpoint)
71
+ {
72
+ static $mapping = [
73
+ 'json' => 'Aws\Api\Serializer\JsonRpcSerializer',
74
+ 'query' => 'Aws\Api\Serializer\QuerySerializer',
75
+ 'rest-json' => 'Aws\Api\Serializer\RestJsonSerializer',
76
+ 'rest-xml' => 'Aws\Api\Serializer\RestXmlSerializer'
77
+ ];
78
+
79
+ $proto = $api->getProtocol();
80
+
81
+ if (isset($mapping[$proto])) {
82
+ return new $mapping[$proto]($api, $endpoint);
83
+ } elseif ($proto == 'ec2') {
84
+ return new QuerySerializer($api, $endpoint, new Ec2ParamBuilder());
85
+ }
86
+
87
+ throw new \UnexpectedValueException(
88
+ 'Unknown protocol: ' . $api->getProtocol()
89
+ );
90
+ }
91
+
92
+ /**
93
+ * Creates an error parser for the given protocol.
94
+ *
95
+ * @param string $protocol Protocol to parse (e.g., query, json, etc.)
96
+ *
97
+ * @return callable
98
+ * @throws \UnexpectedValueException
99
+ */
100
+ public static function createErrorParser($protocol)
101
+ {
102
+ static $mapping = [
103
+ 'json' => 'Aws\Api\ErrorParser\JsonRpcErrorParser',
104
+ 'query' => 'Aws\Api\ErrorParser\XmlErrorParser',
105
+ 'rest-json' => 'Aws\Api\ErrorParser\RestJsonErrorParser',
106
+ 'rest-xml' => 'Aws\Api\ErrorParser\XmlErrorParser',
107
+ 'ec2' => 'Aws\Api\ErrorParser\XmlErrorParser'
108
+ ];
109
+
110
+ if (isset($mapping[$protocol])) {
111
+ return new $mapping[$protocol]();
112
+ }
113
+
114
+ throw new \UnexpectedValueException("Unknown protocol: $protocol");
115
+ }
116
+
117
+ /**
118
+ * Applies the listeners needed to parse client models.
119
+ *
120
+ * @param Service $api API to create a parser for
121
+ * @return callable
122
+ * @throws \UnexpectedValueException
123
+ */
124
+ public static function createParser(Service $api)
125
+ {
126
+ static $mapping = [
127
+ 'json' => 'Aws\Api\Parser\JsonRpcParser',
128
+ 'query' => 'Aws\Api\Parser\QueryParser',
129
+ 'rest-json' => 'Aws\Api\Parser\RestJsonParser',
130
+ 'rest-xml' => 'Aws\Api\Parser\RestXmlParser'
131
+ ];
132
+
133
+ $proto = $api->getProtocol();
134
+ if (isset($mapping[$proto])) {
135
+ return new $mapping[$proto]($api);
136
+ } elseif ($proto == 'ec2') {
137
+ return new QueryParser($api, null, false);
138
+ }
139
+
140
+ throw new \UnexpectedValueException(
141
+ 'Unknown protocol: ' . $api->getProtocol()
142
+ );
143
+ }
144
+
145
+ /**
146
+ * Get the full name of the service
147
+ *
148
+ * @return string
149
+ */
150
+ public function getServiceFullName()
151
+ {
152
+ return $this->definition['metadata']['serviceFullName'];
153
+ }
154
+
155
+ /**
156
+ * Get the API version of the service
157
+ *
158
+ * @return string
159
+ */
160
+ public function getApiVersion()
161
+ {
162
+ return $this->definition['metadata']['apiVersion'];
163
+ }
164
+
165
+ /**
166
+ * Get the API version of the service
167
+ *
168
+ * @return string
169
+ */
170
+ public function getEndpointPrefix()
171
+ {
172
+ return $this->definition['metadata']['endpointPrefix'];
173
+ }
174
+
175
+ /**
176
+ * Get the signing name used by the service.
177
+ *
178
+ * @return string
179
+ */
180
+ public function getSigningName()
181
+ {
182
+ return $this->definition['metadata']['signingName']
183
+ ?: $this->definition['metadata']['endpointPrefix'];
184
+ }
185
+
186
+ /**
187
+ * Get the default signature version of the service.
188
+ *
189
+ * Note: this method assumes "v4" when not specified in the model.
190
+ *
191
+ * @return string
192
+ */
193
+ public function getSignatureVersion()
194
+ {
195
+ return $this->definition['metadata']['signatureVersion'] ?: 'v4';
196
+ }
197
+
198
+ /**
199
+ * Get the protocol used by the service.
200
+ *
201
+ * @return string
202
+ */
203
+ public function getProtocol()
204
+ {
205
+ return $this->definition['metadata']['protocol'];
206
+ }
207
+
208
+ /**
209
+ * Check if the description has a specific operation by name.
210
+ *
211
+ * @param string $name Operation to check by name
212
+ *
213
+ * @return bool
214
+ */
215
+ public function hasOperation($name)
216
+ {
217
+ return isset($this['operations'][$name]);
218
+ }
219
+
220
+ /**
221
+ * Get an operation by name.
222
+ *
223
+ * @param string $name Operation to retrieve by name
224
+ *
225
+ * @return Operation
226
+ * @throws \InvalidArgumentException If the operation is not found
227
+ */
228
+ public function getOperation($name)
229
+ {
230
+ if (!isset($this->operations[$name])) {
231
+ if (!isset($this->definition['operations'][$name])) {
232
+ throw new \InvalidArgumentException("Unknown operation: $name");
233
+ }
234
+ $this->operations[$name] = new Operation(
235
+ $this->definition['operations'][$name],
236
+ $this->shapeMap
237
+ );
238
+ }
239
+
240
+ return $this->operations[$name];
241
+ }
242
+
243
+ /**
244
+ * Get all of the operations of the description.
245
+ *
246
+ * @return Operation[]
247
+ */
248
+ public function getOperations()
249
+ {
250
+ $result = [];
251
+ foreach ($this->definition['operations'] as $name => $definition) {
252
+ $result[$name] = $this->getOperation($name);
253
+ }
254
+
255
+ return $result;
256
+ }
257
+
258
+ /**
259
+ * Get all of the service metadata or a specific metadata key value.
260
+ *
261
+ * @param string|null $key Key to retrieve or null to retrieve all metadata
262
+ *
263
+ * @return mixed Returns the result or null if the key is not found
264
+ */
265
+ public function getMetadata($key = null)
266
+ {
267
+ if (!$key) {
268
+ return $this['metadata'];
269
+ } elseif (isset($this->definition['metadata'][$key])) {
270
+ return $this->definition['metadata'][$key];
271
+ }
272
+
273
+ return null;
274
+ }
275
+
276
+ /**
277
+ * Gets an associative array of available paginator configurations where
278
+ * the key is the name of the paginator, and the value is the paginator
279
+ * configuration.
280
+ *
281
+ * @return array
282
+ * @unstable The configuration format of paginators may change in the future
283
+ */
284
+ public function getPaginators()
285
+ {
286
+ if (!isset($this->paginators)) {
287
+ $res = call_user_func(
288
+ $this->apiProvider,
289
+ 'paginator',
290
+ $this->serviceName,
291
+ $this->apiVersion
292
+ );
293
+ $this->paginators = isset($res['pagination'])
294
+ ? $res['pagination']
295
+ : [];
296
+ }
297
+
298
+ return $this->paginators;
299
+ }
300
+
301
+ /**
302
+ * Determines if the service has a paginator by name.
303
+ *
304
+ * @param string $name Name of the paginator.
305
+ *
306
+ * @return bool
307
+ */
308
+ public function hasPaginator($name)
309
+ {
310
+ return isset($this->getPaginators()[$name]);
311
+ }
312
+
313
+ /**
314
+ * Retrieve a paginator by name.
315
+ *
316
+ * @param string $name Paginator to retrieve by name. This argument is
317
+ * typically the operation name.
318
+ * @return array
319
+ * @throws \UnexpectedValueException if the paginator does not exist.
320
+ * @unstable The configuration format of paginators may change in the future
321
+ */
322
+ public function getPaginatorConfig($name)
323
+ {
324
+ static $defaults = [
325
+ 'input_token' => null,
326
+ 'output_token' => null,
327
+ 'limit_key' => null,
328
+ 'result_key' => null,
329
+ 'more_results' => null,
330
+ ];
331
+
332
+ if ($this->hasPaginator($name)) {
333
+ return $this->paginators[$name] + $defaults;
334
+ }
335
+
336
+ throw new \UnexpectedValueException("There is no {$name} "
337
+ . "paginator defined for the {$this->serviceName} service.");
338
+ }
339
+
340
+ /**
341
+ * Gets an associative array of available waiter configurations where the
342
+ * key is the name of the waiter, and the value is the waiter
343
+ * configuration.
344
+ *
345
+ * @return array
346
+ */
347
+ public function getWaiters()
348
+ {
349
+ if (!isset($this->waiters)) {
350
+ $res = call_user_func(
351
+ $this->apiProvider,
352
+ 'waiter',
353
+ $this->serviceName,
354
+ $this->apiVersion
355
+ );
356
+ $this->waiters = isset($res['waiters'])
357
+ ? $res['waiters']
358
+ : [];
359
+ }
360
+
361
+ return $this->waiters;
362
+ }
363
+
364
+ /**
365
+ * Determines if the service has a waiter by name.
366
+ *
367
+ * @param string $name Name of the waiter.
368
+ *
369
+ * @return bool
370
+ */
371
+ public function hasWaiter($name)
372
+ {
373
+ return isset($this->getWaiters()[$name]);
374
+ }
375
+
376
+ /**
377
+ * Get a waiter configuration by name.
378
+ *
379
+ * @param string $name Name of the waiter by name.
380
+ *
381
+ * @return array
382
+ * @throws \UnexpectedValueException if the waiter does not exist.
383
+ */
384
+ public function getWaiterConfig($name)
385
+ {
386
+ // Error if the waiter is not defined
387
+ if ($this->hasWaiter($name)) {
388
+ return $this->waiters[$name];
389
+ }
390
+
391
+ throw new \UnexpectedValueException("There is no {$name} waiter "
392
+ . "defined for the {$this->serviceName} service.");
393
+ }
394
+
395
+ /**
396
+ * Get the shape map used by the API.
397
+ *
398
+ * @return ShapeMap
399
+ */
400
+ public function getShapeMap()
401
+ {
402
+ return $this->shapeMap;
403
+ }
404
+ }
includes/aws/Aws/Api/Shape.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ /**
5
+ * Base class representing a modeled shape.
6
+ */
7
+ class Shape extends AbstractModel
8
+ {
9
+ /**
10
+ * Get a concrete shape for the given definition.
11
+ *
12
+ * @param array $definition
13
+ * @param ShapeMap $shapeMap
14
+ *
15
+ * @return mixed
16
+ * @throws \RuntimeException if the type is invalid
17
+ */
18
+ public static function create(array $definition, ShapeMap $shapeMap)
19
+ {
20
+ static $map = [
21
+ 'structure' => 'Aws\Api\StructureShape',
22
+ 'map' => 'Aws\Api\MapShape',
23
+ 'list' => 'Aws\Api\ListShape',
24
+ 'timestamp' => 'Aws\Api\TimestampShape',
25
+ 'integer' => 'Aws\Api\Shape',
26
+ 'double' => 'Aws\Api\Shape',
27
+ 'float' => 'Aws\Api\Shape',
28
+ 'long' => 'Aws\Api\Shape',
29
+ 'string' => 'Aws\Api\Shape',
30
+ 'byte' => 'Aws\Api\Shape',
31
+ 'character' => 'Aws\Api\Shape',
32
+ 'blob' => 'Aws\Api\Shape',
33
+ 'boolean' => 'Aws\Api\Shape'
34
+ ];
35
+
36
+ if (isset($definition['shape'])) {
37
+ return $shapeMap->resolve($definition);
38
+ }
39
+
40
+ if (!isset($map[$definition['type']])) {
41
+ throw new \RuntimeException('Invalid type: '
42
+ . print_r($definition, true));
43
+ }
44
+
45
+ $type = $map[$definition['type']];
46
+
47
+ return new $type($definition, $shapeMap);
48
+ }
49
+
50
+ /**
51
+ * Get the type of the shape
52
+ *
53
+ * @return string
54
+ */
55
+ public function getType()
56
+ {
57
+ return $this->definition['type'];
58
+ }
59
+
60
+ /**
61
+ * Get the name of the shape
62
+ *
63
+ * @return string
64
+ */
65
+ public function getName()
66
+ {
67
+ return $this->definition['name'];
68
+ }
69
+ }
includes/aws/Aws/Api/ShapeMap.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ /**
5
+ * Builds shape based on shape references.
6
+ */
7
+ class ShapeMap
8
+ {
9
+ /** @var array */
10
+ private $definitions;
11
+
12
+ /** @var Shape[] */
13
+ private $simple;
14
+
15
+ /**
16
+ * @param array $shapeModels Associative array of shape definitions.
17
+ */
18
+ public function __construct(array $shapeModels)
19
+ {
20
+ $this->definitions = $shapeModels;
21
+ }
22
+
23
+ /**
24
+ * Get an array of shape names.
25
+ *
26
+ * @return array
27
+ */
28
+ public function getShapeNames()
29
+ {
30
+ return array_keys($this->definitions);
31
+ }
32
+
33
+ /**
34
+ * Resolve a shape reference
35
+ *
36
+ * @param array $shapeRef Shape reference shape
37
+ *
38
+ * @return Shape
39
+ * @throws \InvalidArgumentException
40
+ */
41
+ public function resolve(array $shapeRef)
42
+ {
43
+ $shape = $shapeRef['shape'];
44
+
45
+ if (!isset($this->definitions[$shape])) {
46
+ throw new \InvalidArgumentException('Shape not found: ' . $shape);
47
+ }
48
+
49
+ $isSimple = count($shapeRef) == 1;
50
+ if ($isSimple && isset($this->simple[$shape])) {
51
+ return $this->simple[$shape];
52
+ }
53
+
54
+ $definition = $shapeRef + $this->definitions[$shape];
55
+ $definition['name'] = $definition['shape'];
56
+ unset($definition['shape']);
57
+
58
+ $result = Shape::create($definition, $this);
59
+
60
+ if ($isSimple) {
61
+ $this->simple[$shape] = $result;
62
+ }
63
+
64
+ return $result;
65
+ }
66
+ }
includes/aws/Aws/Api/StructureShape.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ /**
5
+ * Represents a structure shape and resolve member shape references.
6
+ */
7
+ class StructureShape extends Shape
8
+ {
9
+ /**
10
+ * @var Shape[]
11
+ */
12
+ private $members;
13
+
14
+ public function __construct(array $definition, ShapeMap $shapeMap)
15
+ {
16
+ $definition['type'] = 'structure';
17
+
18
+ if (!isset($definition['members'])) {
19
+ $definition['members'] = [];
20
+ }
21
+
22
+ parent::__construct($definition, $shapeMap);
23
+ }
24
+
25
+ /**
26
+ * Gets a list of all members
27
+ *
28
+ * @return Shape[]
29
+ */
30
+ public function getMembers()
31
+ {
32
+ if (empty($this->members)) {
33
+ $this->generateMembersHash();
34
+ }
35
+
36
+ return $this->members;
37
+ }
38
+
39
+ /**
40
+ * Check if a specific member exists by name.
41
+ *
42
+ * @param string $name Name of the member to check
43
+ *
44
+ * @return bool
45
+ */
46
+ public function hasMember($name)
47
+ {
48
+ return isset($this->definition['members'][$name]);
49
+ }
50
+
51
+ /**
52
+ * Retrieve a member by name.
53
+ *
54
+ * @param string $name Name of the member to retrieve
55
+ *
56
+ * @return Shape
57
+ * @throws \InvalidArgumentException if the member is not found.
58
+ */
59
+ public function getMember($name)
60
+ {
61
+ $members = $this->getMembers();
62
+
63
+ if (!isset($members[$name])) {
64
+ throw new \InvalidArgumentException('Unknown member ' . $name);
65
+ }
66
+
67
+ return $members[$name];
68
+ }
69
+
70
+
71
+ private function generateMembersHash()
72
+ {
73
+ $this->members = [];
74
+
75
+ foreach ($this->definition['members'] as $name => $definition) {
76
+ $this->members[$name] = $this->shapeFor($definition);
77
+ }
78
+ }
79
+ }
includes/aws/Aws/Api/TimestampShape.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ /**
5
+ * Represents a timestamp shape.
6
+ */
7
+ class TimestampShape extends Shape
8
+ {
9
+ public function __construct(array $definition, ShapeMap $shapeMap)
10
+ {
11
+ $definition['type'] = 'timestamp';
12
+ parent::__construct($definition, $shapeMap);
13
+ }
14
+
15
+ /**
16
+ * Formats a timestamp value for a service.
17
+ *
18
+ * @param mixed $value Value to format
19
+ * @param string $format Format used to serialize the value
20
+ *
21
+ * @return int|string
22
+ * @throws \UnexpectedValueException if the format is unknown.
23
+ * @throws \InvalidArgumentException if the value is an unsupported type.
24
+ */
25
+ public static function format($value, $format)
26
+ {
27
+ if ($value instanceof \DateTime) {
28
+ $value = $value->getTimestamp();
29
+ } elseif (is_string($value)) {
30
+ $value = strtotime($value);
31
+ } elseif (!is_int($value)) {
32
+ throw new \InvalidArgumentException('Unable to handle the provided'
33
+ . ' timestamp type: ' . gettype($value));
34
+ }
35
+
36
+ switch ($format) {
37
+ case 'iso8601':
38
+ return gmdate('Y-m-d\TH:i:s\Z', $value);
39
+ case 'rfc822':
40
+ return gmdate('D, d M Y H:i:s \G\M\T', $value);
41
+ case 'unixTimestamp':
42
+ return $value;
43
+ default:
44
+ throw new \UnexpectedValueException('Unknown timestamp format: '
45
+ . $format);
46
+ }
47
+ }
48
+ }
includes/aws/Aws/Api/Validator.php ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Api;
3
+
4
+ use Aws;
5
+
6
+ /**
7
+ * Validates a schema against a hash of input.
8
+ */
9
+ class Validator
10
+ {
11
+ private $path = [];
12
+ private $errors = [];
13
+
14
+ /**
15
+ * Validates the given input against the schema.
16
+ *
17
+ * @param string $name Operation name
18
+ * @param Shape $shape Shape to validate
19
+ * @param array $input Input to validate
20
+ *
21
+ * @throws \InvalidArgumentException if the input is invalid.
22
+ */
23
+ public function validate($name, Shape $shape, array $input)
24
+ {
25
+ $this->dispatch($shape, $input);
26
+
27
+ if ($this->errors) {
28
+ $message = sprintf(
29
+ "Found %d error%s while validating the input provided for the "
30
+ . "%s operation:\n%s",
31
+ count($this->errors),
32
+ count($this->errors) > 1 ? 's' : '',
33
+ $name,
34
+ implode("\n", $this->errors)
35
+ );
36
+ $this->errors = [];
37
+
38
+ throw new \InvalidArgumentException($message);
39
+ }
40
+ }
41
+
42
+ private function dispatch(Shape $shape, $value)
43
+ {
44
+ static $methods = [
45
+ 'structure' => 'check_structure',
46
+ 'list' => 'check_list',
47
+ 'map' => 'check_map',
48
+ 'blob' => 'check_blob',
49
+ 'boolean' => 'check_boolean',
50
+ 'integer' => 'check_numeric',
51
+ 'float' => 'check_numeric',
52
+ 'long' => 'check_numeric',
53
+ 'string' => 'check_string',
54
+ 'byte' => 'check_string',
55
+ 'char' => 'check_string'
56
+ ];
57
+
58
+ $type = $shape->getType();
59
+ if (isset($methods[$type])) {
60
+ $this->{$methods[$type]}($shape, $value);
61
+ }
62
+ }
63
+
64
+ private function check_structure(StructureShape $shape, $value)
65
+ {
66
+ if (!$this->checkAssociativeArray($value)) {
67
+ return;
68
+ }
69
+
70
+ if ($shape['required']) {
71
+ foreach ($shape['required'] as $req) {
72
+ if (!isset($value[$req])) {
73
+ $this->path[] = $req;
74
+ $this->addError('is missing and is a required parameter');
75
+ array_pop($this->path);
76
+ }
77
+ }
78
+ }
79
+
80
+ foreach ($value as $name => $v) {
81
+ if ($shape->hasMember($name)) {
82
+ $this->path[] = $name;
83
+ $this->dispatch(
84
+ $shape->getMember($name),
85
+ isset($value[$name]) ? $value[$name] : null
86
+ );
87
+ array_pop($this->path);
88
+ }
89
+ }
90
+ }
91
+
92
+ private function check_list(ListShape $shape, $value)
93
+ {
94
+ if (!is_array($value)) {
95
+ $this->addError('must be an array. Found '
96
+ . Aws\describe_type($value));
97
+ return;
98
+ }
99
+
100
+ list($min, $max, $count) = [$shape['min'], $shape['max'], count($value)];
101
+
102
+ if ($min && $count < $min) {
103
+ $this->addError("must have at least $min members."
104
+ . " Value provided has $count.");
105
+ }
106
+
107
+ if ($max && $count > $max) {
108
+ $this->addError("must have no more than $max members."
109
+ . " Value provided has $count.");
110
+ }
111
+
112
+ $items = $shape->getMember();
113
+ foreach ($value as $index => $v) {
114
+ $this->path[] = $index;
115
+ $this->dispatch($items, $v);
116
+ array_pop($this->path);
117
+ }
118
+ }
119
+
120
+ private function check_map(MapShape $shape, $value)
121
+ {
122
+ if (!$this->checkAssociativeArray($value)) {
123
+ return;
124
+ }
125
+
126
+ $values = $shape->getValue();
127
+ foreach ($value as $key => $v) {
128
+ $this->path[] = $key;
129
+ $this->dispatch($values, $v);
130
+ array_pop($this->path);
131
+ }
132
+ }
133
+
134
+ private function check_blob(Shape $shape, $value)
135
+ {
136
+ static $valid = [
137
+ 'string' => true,
138
+ 'integer' => true,
139
+ 'double' => true,
140
+ 'resource' => true
141
+ ];
142
+
143
+ $type = gettype($value);
144
+ if (!isset($valid[$type])) {
145
+ if ($type != 'object' || !method_exists($value, '__toString')) {
146
+ $this->addError('must be an fopen resource, a '
147
+ . 'GuzzleHttp\Stream\StreamInterface object, or something '
148
+ . 'that can be cast to a string. Found '
149
+ . Aws\describe_type($value));
150
+ }
151
+ }
152
+ }
153
+
154
+ private function check_numeric(Shape $shape, $value)
155
+ {
156
+ if (!is_numeric($value)) {
157
+ $this->addError('must be numeric. Found '
158
+ . Aws\describe_type($value));
159
+ return;
160
+ }
161
+
162
+ list($min, $max) = [$shape['min'], $shape['max']];
163
+
164
+ if ($min && $value < $min) {
165
+ $this->addError("must be at least $min. Value provided is $value.");
166
+ }
167
+
168
+ if ($max && $value > $max) {
169
+ $this->addError("must be no more than $max."
170
+ . " Value provided is $value.");
171
+ }
172
+ }
173
+
174
+ private function check_boolean(Shape $shape, $value)
175
+ {
176
+ if (!is_bool($value)) {
177
+ $this->addError('must be a boolean. Found '
178
+ . Aws\describe_type($value));
179
+ }
180
+ }
181
+
182
+ private function check_string(Shape $shape, $value)
183
+ {
184
+ if (!$this->checkCanString($value)) {
185
+ $this->addError('must be a string or an object that implements '
186
+ . '__toString(). Found ' . Aws\describe_type($value));
187
+ return;
188
+ }
189
+
190
+ list($min, $max, $len) = [$shape['min'], $shape['max'], strlen($value)];
191
+
192
+ if ($min && $len < $min) {
193
+ $this->addError("must be at least $min characters long."
194
+ . " Value provided is $len characters long.");
195
+ }
196
+
197
+ if ($max && $len > $max) {
198
+ $this->addError("must be no more than $max characters long."
199
+ . " Value provided is $len characters long.");
200
+ }
201
+ }
202
+
203
+ private function checkCanString($value)
204
+ {
205
+ static $valid = [
206
+ 'string' => true,
207
+ 'integer' => true,
208
+ 'double' => true,
209
+ 'NULL' => true,
210
+ ];
211
+
212
+ $type = gettype($value);
213
+
214
+ return isset($valid[$type]) ||
215
+ ($type == 'object' && method_exists($value, '__toString'));
216
+ }
217
+
218
+ private function checkAssociativeArray($value)
219
+ {
220
+ if (!is_array($value) || isset($value[0])) {
221
+ $this->addError('must be an associative array. Found '
222
+ . Aws\describe_type($value));
223
+ return false;
224
+ }
225
+
226
+ return true;
227
+ }
228
+
229
+ private function addError($message)
230
+ {
231
+ $this->errors[] =
232
+ implode('', array_map(function ($s) { return "[{$s}]"; }, $this->path))
233
+ . ' '
234
+ . $message;
235
+ }
236
+ }
includes/aws/Aws/ApiGateway/ApiGatewayClient.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\ApiGateway;
3
+
4
+ use Aws\AwsClient;
5
+ use Aws\CommandInterface;
6
+ use Psr\Http\Message\RequestInterface;
7
+
8
+ /**
9
+ * This client is used to interact with the **AWS API Gateway** service.
10
+ *
11
+ * @method \Aws\Result createApiKey(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise createApiKeyAsync(array $args = [])
13
+ * @method \Aws\Result createBasePathMapping(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise createBasePathMappingAsync(array $args = [])
15
+ * @method \Aws\Result createDeployment(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise createDeploymentAsync(array $args = [])
17
+ * @method \Aws\Result createDomainName(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise createDomainNameAsync(array $args = [])
19
+ * @method \Aws\Result createModel(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise createModelAsync(array $args = [])
21
+ * @method \Aws\Result createResource(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise createResourceAsync(array $args = [])
23
+ * @method \Aws\Result createRestApi(array $args = [])
24
+ * @method \GuzzleHttp\Promise\Promise createRestApiAsync(array $args = [])
25
+ * @method \Aws\Result createStage(array $args = [])
26
+ * @method \GuzzleHttp\Promise\Promise createStageAsync(array $args = [])
27
+ * @method \Aws\Result deleteApiKey(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise deleteApiKeyAsync(array $args = [])
29
+ * @method \Aws\Result deleteBasePathMapping(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise deleteBasePathMappingAsync(array $args = [])
31
+ * @method \Aws\Result deleteClientCertificate(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise deleteClientCertificateAsync(array $args = [])
33
+ * @method \Aws\Result deleteDeployment(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise deleteDeploymentAsync(array $args = [])
35
+ * @method \Aws\Result deleteDomainName(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise deleteDomainNameAsync(array $args = [])
37
+ * @method \Aws\Result deleteIntegration(array $args = [])
38
+ * @method \GuzzleHttp\Promise\Promise deleteIntegrationAsync(array $args = [])
39
+ * @method \Aws\Result deleteIntegrationResponse(array $args = [])
40
+ * @method \GuzzleHttp\Promise\Promise deleteIntegrationResponseAsync(array $args = [])
41
+ * @method \Aws\Result deleteMethod(array $args = [])
42
+ * @method \GuzzleHttp\Promise\Promise deleteMethodAsync(array $args = [])
43
+ * @method \Aws\Result deleteMethodResponse(array $args = [])
44
+ * @method \GuzzleHttp\Promise\Promise deleteMethodResponseAsync(array $args = [])
45
+ * @method \Aws\Result deleteModel(array $args = [])
46
+ * @method \GuzzleHttp\Promise\Promise deleteModelAsync(array $args = [])
47
+ * @method \Aws\Result deleteResource(array $args = [])
48
+ * @method \GuzzleHttp\Promise\Promise deleteResourceAsync(array $args = [])
49
+ * @method \Aws\Result deleteRestApi(array $args = [])
50
+ * @method \GuzzleHttp\Promise\Promise deleteRestApiAsync(array $args = [])
51
+ * @method \Aws\Result deleteStage(array $args = [])
52
+ * @method \GuzzleHttp\Promise\Promise deleteStageAsync(array $args = [])
53
+ * @method \Aws\Result flushStageCache(array $args = [])
54
+ * @method \GuzzleHttp\Promise\Promise flushStageCacheAsync(array $args = [])
55
+ * @method \Aws\Result generateClientCertificate(array $args = [])
56
+ * @method \GuzzleHttp\Promise\Promise generateClientCertificateAsync(array $args = [])
57
+ * @method \Aws\Result getAccount(array $args = [])
58
+ * @method \GuzzleHttp\Promise\Promise getAccountAsync(array $args = [])
59
+ * @method \Aws\Result getApiKey(array $args = [])
60
+ * @method \GuzzleHttp\Promise\Promise getApiKeyAsync(array $args = [])
61
+ * @method \Aws\Result getApiKeys(array $args = [])
62
+ * @method \GuzzleHttp\Promise\Promise getApiKeysAsync(array $args = [])
63
+ * @method \Aws\Result getBasePathMapping(array $args = [])
64
+ * @method \GuzzleHttp\Promise\Promise getBasePathMappingAsync(array $args = [])
65
+ * @method \Aws\Result getBasePathMappings(array $args = [])
66
+ * @method \GuzzleHttp\Promise\Promise getBasePathMappingsAsync(array $args = [])
67
+ * @method \Aws\Result getClientCertificate(array $args = [])
68
+ * @method \GuzzleHttp\Promise\Promise getClientCertificateAsync(array $args = [])
69
+ * @method \Aws\Result getClientCertificates(array $args = [])
70
+ * @method \GuzzleHttp\Promise\Promise getClientCertificatesAsync(array $args = [])
71
+ * @method \Aws\Result getDeployment(array $args = [])
72
+ * @method \GuzzleHttp\Promise\Promise getDeploymentAsync(array $args = [])
73
+ * @method \Aws\Result getDeployments(array $args = [])
74
+ * @method \GuzzleHttp\Promise\Promise getDeploymentsAsync(array $args = [])
75
+ * @method \Aws\Result getDomainName(array $args = [])
76
+ * @method \GuzzleHttp\Promise\Promise getDomainNameAsync(array $args = [])
77
+ * @method \Aws\Result getDomainNames(array $args = [])
78
+ * @method \GuzzleHttp\Promise\Promise getDomainNamesAsync(array $args = [])
79
+ * @method \Aws\Result getIntegration(array $args = [])
80
+ * @method \GuzzleHttp\Promise\Promise getIntegrationAsync(array $args = [])
81
+ * @method \Aws\Result getIntegrationResponse(array $args = [])
82
+ * @method \GuzzleHttp\Promise\Promise getIntegrationResponseAsync(array $args = [])
83
+ * @method \Aws\Result getMethod(array $args = [])
84
+ * @method \GuzzleHttp\Promise\Promise getMethodAsync(array $args = [])
85
+ * @method \Aws\Result getMethodResponse(array $args = [])
86
+ * @method \GuzzleHttp\Promise\Promise getMethodResponseAsync(array $args = [])
87
+ * @method \Aws\Result getModel(array $args = [])
88
+ * @method \GuzzleHttp\Promise\Promise getModelAsync(array $args = [])
89
+ * @method \Aws\Result getModelTemplate(array $args = [])
90
+ * @method \GuzzleHttp\Promise\Promise getModelTemplateAsync(array $args = [])
91
+ * @method \Aws\Result getModels(array $args = [])
92
+ * @method \GuzzleHttp\Promise\Promise getModelsAsync(array $args = [])
93
+ * @method \Aws\Result getResource(array $args = [])
94
+ * @method \GuzzleHttp\Promise\Promise getResourceAsync(array $args = [])
95
+ * @method \Aws\Result getResources(array $args = [])
96
+ * @method \GuzzleHttp\Promise\Promise getResourcesAsync(array $args = [])
97
+ * @method \Aws\Result getRestApi(array $args = [])
98
+ * @method \GuzzleHttp\Promise\Promise getRestApiAsync(array $args = [])
99
+ * @method \Aws\Result getRestApis(array $args = [])
100
+ * @method \GuzzleHttp\Promise\Promise getRestApisAsync(array $args = [])
101
+ * @method \Aws\Result getSdk(array $args = [])
102
+ * @method \GuzzleHttp\Promise\Promise getSdkAsync(array $args = [])
103
+ * @method \Aws\Result getStage(array $args = [])
104
+ * @method \GuzzleHttp\Promise\Promise getStageAsync(array $args = [])
105
+ * @method \Aws\Result getStages(array $args = [])
106
+ * @method \GuzzleHttp\Promise\Promise getStagesAsync(array $args = [])
107
+ * @method \Aws\Result putIntegration(array $args = [])
108
+ * @method \GuzzleHttp\Promise\Promise putIntegrationAsync(array $args = [])
109
+ * @method \Aws\Result putIntegrationResponse(array $args = [])
110
+ * @method \GuzzleHttp\Promise\Promise putIntegrationResponseAsync(array $args = [])
111
+ * @method \Aws\Result putMethod(array $args = [])
112
+ * @method \GuzzleHttp\Promise\Promise putMethodAsync(array $args = [])
113
+ * @method \Aws\Result putMethodResponse(array $args = [])
114
+ * @method \GuzzleHttp\Promise\Promise putMethodResponseAsync(array $args = [])
115
+ * @method \Aws\Result testInvokeMethod(array $args = [])
116
+ * @method \GuzzleHttp\Promise\Promise testInvokeMethodAsync(array $args = [])
117
+ * @method \Aws\Result updateAccount(array $args = [])
118
+ * @method \GuzzleHttp\Promise\Promise updateAccountAsync(array $args = [])
119
+ * @method \Aws\Result updateApiKey(array $args = [])
120
+ * @method \GuzzleHttp\Promise\Promise updateApiKeyAsync(array $args = [])
121
+ * @method \Aws\Result updateBasePathMapping(array $args = [])
122
+ * @method \GuzzleHttp\Promise\Promise updateBasePathMappingAsync(array $args = [])
123
+ * @method \Aws\Result updateClientCertificate(array $args = [])
124
+ * @method \GuzzleHttp\Promise\Promise updateClientCertificateAsync(array $args = [])
125
+ * @method \Aws\Result updateDeployment(array $args = [])
126
+ * @method \GuzzleHttp\Promise\Promise updateDeploymentAsync(array $args = [])
127
+ * @method \Aws\Result updateDomainName(array $args = [])
128
+ * @method \GuzzleHttp\Promise\Promise updateDomainNameAsync(array $args = [])
129
+ * @method \Aws\Result updateIntegration(array $args = [])
130
+ * @method \GuzzleHttp\Promise\Promise updateIntegrationAsync(array $args = [])
131
+ * @method \Aws\Result updateIntegrationResponse(array $args = [])
132
+ * @method \GuzzleHttp\Promise\Promise updateIntegrationResponseAsync(array $args = [])
133
+ * @method \Aws\Result updateMethod(array $args = [])
134
+ * @method \GuzzleHttp\Promise\Promise updateMethodAsync(array $args = [])
135
+ * @method \Aws\Result updateMethodResponse(array $args = [])
136
+ * @method \GuzzleHttp\Promise\Promise updateMethodResponseAsync(array $args = [])
137
+ * @method \Aws\Result updateModel(array $args = [])
138
+ * @method \GuzzleHttp\Promise\Promise updateModelAsync(array $args = [])
139
+ * @method \Aws\Result updateResource(array $args = [])
140
+ * @method \GuzzleHttp\Promise\Promise updateResourceAsync(array $args = [])
141
+ * @method \Aws\Result updateRestApi(array $args = [])
142
+ * @method \GuzzleHttp\Promise\Promise updateRestApiAsync(array $args = [])
143
+ * @method \Aws\Result updateStage(array $args = [])
144
+ * @method \GuzzleHttp\Promise\Promise updateStageAsync(array $args = [])
145
+ */
146
+ class ApiGatewayClient extends AwsClient
147
+ {
148
+ public function __construct(array $args)
149
+ {
150
+ parent::__construct($args);
151
+ $stack = $this->getHandlerList();
152
+ $stack->appendBuild([__CLASS__, '_add_accept_header']);
153
+ }
154
+
155
+ public static function _add_accept_header(callable $handler)
156
+ {
157
+ return function (
158
+ CommandInterface $command,
159
+ RequestInterface $request
160
+ ) use ($handler) {
161
+ $request = $request->withHeader('Accept', 'application/json');
162
+
163
+ return $handler($command, $request);
164
+ };
165
+ }
166
+ }
includes/aws/Aws/ApiGateway/Exception/ApiGatewayException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\ApiGateway\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the **AWS API Gateway** service.
8
+ */
9
+ class ApiGatewayException extends AwsException {}
includes/aws/Aws/AwsClient.php ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Aws\Api\ApiProvider;
5
+ use Aws\Api\DocModel;
6
+ use Aws\Api\Service;
7
+ use Aws\Signature\SignatureProvider;
8
+ use GuzzleHttp\Psr7\Uri;
9
+
10
+ /**
11
+ * Default AWS client implementation
12
+ */
13
+ class AwsClient implements AwsClientInterface
14
+ {
15
+ /** @var string */
16
+ private $region;
17
+
18
+ /** @var string */
19
+ private $endpoint;
20
+
21
+ /** @var Service */
22
+ private $api;
23
+
24
+ /** @var callable */
25
+ private $signatureProvider;
26
+
27
+ /** @var callable */
28
+ private $credentialProvider;
29
+
30
+ /** @var HandlerList */
31
+ private $handlerList;
32
+
33
+ /** @var array*/
34
+ private $defaultRequestOptions;
35
+
36
+ /**
37
+ * Get an array of client constructor arguments used by the client.
38
+ *
39
+ * @return array
40
+ */
41
+ public static function getArguments()
42
+ {
43
+ return ClientResolver::getDefaultArguments();
44
+ }
45
+
46
+ /**
47
+ * The client constructor accepts the following options:
48
+ *
49
+ * - api_provider: (callable) An optional PHP callable that accepts a
50
+ * type, service, and version argument, and returns an array of
51
+ * corresponding configuration data. The type value can be one of api,
52
+ * waiter, or paginator.
53
+ * - credentials:
54
+ * (Aws\Credentials\CredentialsInterface|array|bool|callable) Specifies
55
+ * the credentials used to sign requests. Provide an
56
+ * Aws\Credentials\CredentialsInterface object, an associative array of
57
+ * "key", "secret", and an optional "token" key, `false` to use null
58
+ * credentials, or a callable credentials provider used to create
59
+ * credentials or return null. See Aws\Credentials\CredentialProvider for
60
+ * a list of built-in credentials providers. If no credentials are
61
+ * provided, the SDK will attempt to load them from the environment.
62
+ * - debug: (bool|array) Set to true to display debug information when
63
+ * sending requests. Alternatively, you can provide an associative array
64
+ * with the following keys: logfn: (callable) Function that is invoked
65
+ * with log messages; stream_size: (int) When the size of a stream is
66
+ * greater than this number, the stream data will not be logged (set to
67
+ * "0" to not log any stream data); scrub_auth: (bool) Set to false to
68
+ * disable the scrubbing of auth data from the logged messages; http:
69
+ * (bool) Set to false to disable the "debug" feature of lower level HTTP
70
+ * adapters (e.g., verbose curl output).
71
+ * - endpoint: (string) The full URI of the webservice. This is only
72
+ * required when connecting to a custom endpoint (e.g., a local version
73
+ * of S3).
74
+ * - endpoint_provider: (callable) An optional PHP callable that
75
+ * accepts a hash of options including a "service" and "region" key and
76
+ * returns NULL or a hash of endpoint data, of which the "endpoint" key
77
+ * is required. See Aws\Endpoint\EndpointProvider for a list of built-in
78
+ * providers.
79
+ * - handler: (callable) A handler that accepts a command object,
80
+ * request object and returns a promise that is fulfilled with an
81
+ * Aws\ResultInterface object or rejected with an
82
+ * Aws\Exception\AwsException. A handler does not accept a next handler
83
+ * as it is terminal and expected to fulfill a command. If no handler is
84
+ * provided, a default Guzzle handler will be utilized.
85
+ * - http: (array, default=array(0)) Set to an array of SDK request
86
+ * options to apply to each request (e.g., proxy, verify, etc.).
87
+ * - http_handler: (callable) An HTTP handler is a function that
88
+ * accepts a PSR-7 request object and returns a promise that is fulfilled
89
+ * with a PSR-7 response object or rejected with an array of exception
90
+ * data. NOTE: This option supersedes any provided "handler" option.
91
+ * - profile: (string) Allows you to specify which profile to use when
92
+ * credentials are created from the AWS credentials file in your HOME
93
+ * directory. This setting overrides the AWS_PROFILE environment
94
+ * variable. Note: Specifying "profile" will cause the "credentials" key
95
+ * to be ignored.
96
+ * - region: (string, required) Region to connect to. See
97
+ * http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of
98
+ * available regions.
99
+ * - retries: (int, default=int(3)) Configures the maximum number of
100
+ * allowed retries for a client (pass 0 to disable retries).
101
+ * - scheme: (string, default=string(5) "https") URI scheme to use when
102
+ * connecting connect. The SDK will utilize "https" endpoints (i.e.,
103
+ * utilize SSL/TLS connections) by default. You can attempt to connect to
104
+ * a service over an unencrypted "http" endpoint by setting ``scheme`` to
105
+ * "http".
106
+ * - signature_provider: (callable) A callable that accepts a signature
107
+ * version name (e.g., "v4"), a service name, and region, and
108
+ * returns a SignatureInterface object or null. This provider is used to
109
+ * create signers utilized by the client. See
110
+ * Aws\Signature\SignatureProvider for a list of built-in providers
111
+ * - signature_version: (string) A string representing a custom
112
+ * signature version to use with a service (e.g., v4). Note that
113
+ * per/operation signature version MAY override this requested signature
114
+ * version.
115
+ * - validate: (bool, default=bool(true)) Set to false to disable
116
+ * client-side parameter validation.
117
+ * - version: (string, required) The version of the webservice to
118
+ * utilize (e.g., 2006-03-01).
119
+ *
120
+ * @param array $args Client configuration arguments.
121
+ *
122
+ * @throws \InvalidArgumentException if any required options are missing or
123
+ * the service is not supported.
124
+ */
125
+ public function __construct(array $args)
126
+ {
127
+ list($service, $exceptionClass) = $this->parseClass();
128
+ if (!isset($args['service'])) {
129
+ $args['service'] = manifest($service)['endpoint'];
130
+ }
131
+ if (!isset($args['exception_class'])) {
132
+ $args['exception_class'] = $exceptionClass;
133
+ }
134
+
135
+ $this->handlerList = new HandlerList();
136
+ $resolver = new ClientResolver(static::getArguments());
137
+ $config = $resolver->resolve($args, $this->handlerList);
138
+ $this->api = $config['api'];
139
+ $this->signatureProvider = $config['signature_provider'];
140
+ $this->endpoint = new Uri($config['endpoint']);
141
+ $this->credentialProvider = $config['credentials'];
142
+ $this->region = isset($config['region']) ? $config['region'] : null;
143
+ $this->config = $config['config'];
144
+ $this->defaultRequestOptions = $config['http'];
145
+ $this->addSignatureMiddleware();
146
+
147
+ if (isset($args['with_resolved'])) {
148
+ $args['with_resolved']($config);
149
+ }
150
+ }
151
+
152
+ public function getHandlerList()
153
+ {
154
+ return $this->handlerList;
155
+ }
156
+
157
+ public function __call($name, array $args)
158
+ {
159
+ $params = isset($args[0]) ? $args[0] : [];
160
+
161
+ if (substr($name, -5) === 'Async') {
162
+ return $this->executeAsync(
163
+ $this->getCommand(substr($name, 0, -5), $params)
164
+ );
165
+ }
166
+
167
+ return $this->execute($this->getCommand($name, $params));
168
+ }
169
+
170
+ public function getConfig($option = null)
171
+ {
172
+ return $option === null
173
+ ? $this->config
174
+ : (isset($this->config[$option])
175
+ ? $this->config[$option]
176
+ : null);
177
+ }
178
+
179
+ public function getCredentials()
180
+ {
181
+ $fn = $this->credentialProvider;
182
+ return $fn();
183
+ }
184
+
185
+ public function getEndpoint()
186
+ {
187
+ return $this->endpoint;
188
+ }
189
+
190
+ public function getRegion()
191
+ {
192
+ return $this->region;
193
+ }
194
+
195
+ public function getApi()
196
+ {
197
+ return $this->api;
198
+ }
199
+
200
+ public function execute(CommandInterface $command)
201
+ {
202
+ return $this->executeAsync($command)->wait();
203
+ }
204
+
205
+ public function executeAsync(CommandInterface $command)
206
+ {
207
+ $handler = $command->getHandlerList()->resolve();
208
+ return $handler($command);
209
+ }
210
+
211
+ public function getCommand($name, array $args = [])
212
+ {
213
+ // Fail fast if the command cannot be found in the description.
214
+ if (!isset($this->api['operations'][$name])) {
215
+ $name = ucfirst($name);
216
+ if (!isset($this->api['operations'][$name])) {
217
+ throw new \InvalidArgumentException("Operation not found: $name");
218
+ }
219
+ }
220
+
221
+ if (!isset($args['@http'])) {
222
+ $args['@http'] = $this->defaultRequestOptions;
223
+ } else {
224
+ $args['@http'] += $this->defaultRequestOptions;
225
+ }
226
+
227
+ return new Command($name, $args, clone $this->getHandlerList());
228
+ }
229
+
230
+ public function getIterator($name, array $args = [])
231
+ {
232
+ $config = $this->api->getPaginatorConfig($name);
233
+ if (!$config['result_key']) {
234
+ throw new \UnexpectedValueException(sprintf(
235
+ 'There are no resources to iterate for the %s operation of %s',
236
+ $name, $this->api['serviceFullName']
237
+ ));
238
+ }
239
+
240
+ $key = is_array($config['result_key'])
241
+ ? $config['result_key'][0]
242
+ : $config['result_key'];
243
+
244
+ if ($config['output_token'] && $config['input_token']) {
245
+ return $this->getPaginator($name, $args)->search($key);
246
+ }
247
+
248
+ $result = $this->execute($this->getCommand($name, $args))->search($key);
249
+
250
+ return new \ArrayIterator((array) $result);
251
+ }
252
+
253
+ public function getPaginator($name, array $args = [])
254
+ {
255
+ $config = $this->api->getPaginatorConfig($name);
256
+
257
+ return new ResultPaginator($this, $name, $args, $config);
258
+ }
259
+
260
+ public function waitUntil($name, array $args = [])
261
+ {
262
+ return $this->getWaiter($name, $args)->promise()->wait();
263
+ }
264
+
265
+ public function getWaiter($name, array $args = [])
266
+ {
267
+ $config = isset($args['@waiter']) ? $args['@waiter'] : [];
268
+ $config += $this->api->getWaiterConfig($name);
269
+
270
+ return new Waiter($this, $name, $args, $config);
271
+ }
272
+
273
+ /**
274
+ * Get the signature_provider function of the client.
275
+ *
276
+ * @return callable
277
+ */
278
+ final protected function getSignatureProvider()
279
+ {
280
+ return $this->signatureProvider;
281
+ }
282
+
283
+ /**
284
+ * Parse the class name and setup the custom exception class of the client
285
+ * and return the "service" name of the client and "exception_class".
286
+ *
287
+ * @return array
288
+ */
289
+ private function parseClass()
290
+ {
291
+ $klass = get_class($this);
292
+
293
+ if ($klass === __CLASS__) {
294
+ return ['', 'Aws\Exception\AwsException'];
295
+ }
296
+
297
+ $service = substr($klass, strrpos($klass, '\\') + 1, -6);
298
+
299
+ return [
300
+ strtolower($service),
301
+ "Aws\\{$service}\\Exception\\{$service}Exception"
302
+ ];
303
+ }
304
+
305
+ private function addSignatureMiddleware()
306
+ {
307
+ // Sign requests. This may need to be modified later to support
308
+ // variable signatures per/operation.
309
+ $this->handlerList->appendSign(
310
+ Middleware::signer(
311
+ $this->credentialProvider,
312
+ constantly(SignatureProvider::resolve(
313
+ $this->signatureProvider,
314
+ $this->config['signature_version'],
315
+ $this->api->getSigningName(),
316
+ $this->region
317
+ ))
318
+ ),
319
+ 'signer'
320
+ );
321
+ }
322
+
323
+ /**
324
+ * Returns a service model and doc model with any necessary changes
325
+ * applied.
326
+ *
327
+ * @param array $api Array of service data being documented.
328
+ * @param array $docs Array of doc model data.
329
+ *
330
+ * @return array Tuple containing a [Service, DocModel]
331
+ *
332
+ * @internal This should only used to document the service API.
333
+ * @codeCoverageIgnore
334
+ */
335
+ public static function applyDocFilters(array $api, array $docs)
336
+ {
337
+ return [
338
+ new Service($api, ApiProvider::defaultProvider()),
339
+ new DocModel($docs)
340
+ ];
341
+ }
342
+
343
+ /**
344
+ * @deprecated
345
+ * @return static
346
+ */
347
+ public static function factory(array $config = [])
348
+ {
349
+ return new static($config);
350
+ }
351
+ }
includes/aws/Aws/AwsClientInterface.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Psr\Http\Message\UriInterface;
5
+ use GuzzleHttp\Promise\PromiseInterface;
6
+
7
+ /**
8
+ * Represents an AWS client.
9
+ */
10
+ interface AwsClientInterface
11
+ {
12
+ /**
13
+ * Creates and executes a command for an operation by name.
14
+ *
15
+ * Suffixing an operation name with "Async" will return a
16
+ * promise that can be used to execute commands asynchronously.
17
+ *
18
+ * @param string $name Name of the command to execute.
19
+ * @param array $arguments Arguments to pass to the getCommand method.
20
+ *
21
+ * @return ResultInterface
22
+ * @throws \Exception
23
+ */
24
+ public function __call($name, array $arguments);
25
+
26
+ /**
27
+ * Create a command for an operation name.
28
+ *
29
+ * Special keys may be set on the command to control how it behaves,
30
+ * including:
31
+ *
32
+ * - @http: Associative array of transfer specific options to apply to the
33
+ * request that is serialized for this command. Available keys include
34
+ * "proxy", "verify", "timeout", "connect_timeout", "debug", "delay", and
35
+ * "headers".
36
+ *
37
+ * @param string $name Name of the operation to use in the command
38
+ * @param array $args Arguments to pass to the command
39
+ *
40
+ * @return CommandInterface
41
+ * @throws \InvalidArgumentException if no command can be found by name
42
+ */
43
+ public function getCommand($name, array $args = []);
44
+
45
+ /**
46
+ * Execute a single command.
47
+ *
48
+ * @param CommandInterface $command Command to execute
49
+ *
50
+ * @return ResultInterface
51
+ * @throws \Exception
52
+ */
53
+ public function execute(CommandInterface $command);
54
+
55
+ /**
56
+ * Execute a command asynchronously.
57
+ *
58
+ * @param CommandInterface $command Command to execute
59
+ *
60
+ * @return \GuzzleHttp\Promise\PromiseInterface
61
+ */
62
+ public function executeAsync(CommandInterface $command);
63
+
64
+ /**
65
+ * Returns a promise that is fulfilled with an
66
+ * {@see \Aws\Credentials\CredentialsInterface} object.
67
+ *
68
+ * If you need the credentials synchronously, then call the wait() method
69
+ * on the returned promise.
70
+ *
71
+ * @return PromiseInterface
72
+ */
73
+ public function getCredentials();
74
+
75
+ /**
76
+ * Get the region to which the client is configured to send requests.
77
+ *
78
+ * @return string
79
+ */
80
+ public function getRegion();
81
+
82
+ /**
83
+ * Gets the default endpoint, or base URL, used by the client.
84
+ *
85
+ * @return UriInterface
86
+ */
87
+ public function getEndpoint();
88
+
89
+ /**
90
+ * Get the service description associated with the client.
91
+ *
92
+ * @return \Aws\Api\Service
93
+ */
94
+ public function getApi();
95
+
96
+ /**
97
+ * Get a client configuration value.
98
+ *
99
+ * @param string|null $option The option to retrieve. Pass null to retrieve
100
+ * all options.
101
+ * @return mixed|null
102
+ */
103
+ public function getConfig($option = null);
104
+
105
+ /**
106
+ * Get the handler list used to transfer commands.
107
+ *
108
+ * This list can be modified to add middleware or to change the underlying
109
+ * handler used to send HTTP requests.
110
+ *
111
+ * @return HandlerList
112
+ */
113
+ public function getHandlerList();
114
+
115
+ /**
116
+ * Get a resource iterator for the specified operation.
117
+ *
118
+ * @param string $name Name of the iterator to retrieve.
119
+ * @param array $args Command arguments to use with each command.
120
+ *
121
+ * @return \Iterator
122
+ * @throws \UnexpectedValueException if the iterator config is invalid.
123
+ */
124
+ public function getIterator($name, array $args = []);
125
+
126
+ /**
127
+ * Get a result paginator for the specified operation.
128
+ *
129
+ * @param string $name Name of the operation used for iterator
130
+ * @param array $args Command args to be used with each command
131
+ *
132
+ * @return \Aws\ResultPaginator
133
+ * @throws \UnexpectedValueException if the iterator config is invalid.
134
+ */
135
+ public function getPaginator($name, array $args = []);
136
+
137
+ /**
138
+ * Wait until a resource is in a particular state.
139
+ *
140
+ * @param string|callable $name Name of the waiter that defines the wait
141
+ * configuration and conditions.
142
+ * @param array $args Args to be used with each command executed
143
+ * by the waiter. Waiter configuration options
144
+ * can be provided in an associative array in
145
+ * the @waiter key.
146
+ * @return void
147
+ * @throws \UnexpectedValueException if the waiter is invalid.
148
+ */
149
+ public function waitUntil($name, array $args = []);
150
+
151
+ /**
152
+ * Get a waiter that waits until a resource is in a particular state.
153
+ *
154
+ * Retrieving a waiter can be useful when you wish to wait asynchronously:
155
+ *
156
+ * $waiter = $client->getWaiter('foo', ['bar' => 'baz']);
157
+ * $waiter->promise()->then(function () { echo 'Done!'; });
158
+ *
159
+ * @param string|callable $name Name of the waiter that defines the wait
160
+ * configuration and conditions.
161
+ * @param array $args Args to be used with each command executed
162
+ * by the waiter. Waiter configuration options
163
+ * can be provided in an associative array in
164
+ * the @waiter key.
165
+ * @return \Aws\Waiter
166
+ * @throws \UnexpectedValueException if the waiter is invalid.
167
+ */
168
+ public function getWaiter($name, array $args = []);
169
+ }
includes/aws/Aws/CacheInterface.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ /**
5
+ * Represents a simple cache interface.
6
+ */
7
+ interface CacheInterface
8
+ {
9
+ /**
10
+ * Get a cache item by key.
11
+ *
12
+ * @param string $key Key to retrieve.
13
+ *
14
+ * @return mixed|null Returns the value or null if not found.
15
+ */
16
+ public function get($key);
17
+
18
+ /**
19
+ * Set a cache key value.
20
+ *
21
+ * @param string $key Key to set
22
+ * @param mixed $value Value to set.
23
+ * @param int $ttl Number of seconds the item is allowed to live. Set
24
+ * to 0 to allow an unlimited lifetime.
25
+ */
26
+ public function set($key, $value, $ttl = 0);
27
+
28
+ /**
29
+ * Remove a cache key.
30
+ *
31
+ * @param string $key Key to remove.
32
+ */
33
+ public function remove($key);
34
+ }
includes/aws/Aws/ClientResolver.php ADDED
@@ -0,0 +1,548 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Aws\Api\Validator;
5
+ use Aws\Api\ApiProvider;
6
+ use Aws\Api\Service;
7
+ use Aws\Credentials\Credentials;
8
+ use Aws\Credentials\CredentialsInterface;
9
+ use Aws\Signature\SignatureProvider;
10
+ use Aws\Endpoint\EndpointProvider;
11
+ use Aws\Credentials\CredentialProvider;
12
+ use GuzzleHttp\Promise;
13
+ use InvalidArgumentException as IAE;
14
+ use Psr\Http\Message\RequestInterface;
15
+
16
+ /**
17
+ * @internal Resolves a hash of client arguments to construct a client.
18
+ */
19
+ class ClientResolver
20
+ {
21
+ /** @var array */
22
+ private $argDefinitions;
23
+
24
+ /** @var array Map of types to a corresponding function */
25
+ private static $typeMap = [
26
+ 'resource' => 'is_resource',
27
+ 'callable' => 'is_callable',
28
+ 'int' => 'is_int',
29
+ 'bool' => 'is_bool',
30
+ 'string' => 'is_string',
31
+ 'object' => 'is_object',
32
+ 'array' => 'is_array',
33
+ ];
34
+
35
+ private static $defaultArgs = [
36
+ 'service' => [
37
+ 'type' => 'value',
38
+ 'valid' => ['string'],
39
+ 'doc' => 'Name of the service to utilize. This value will be supplied by default when using one of the SDK clients (e.g., Aws\\S3\\S3Client).',
40
+ 'required' => true,
41
+ 'internal' => true
42
+ ],
43
+ 'exception_class' => [
44
+ 'type' => 'value',
45
+ 'valid' => ['string'],
46
+ 'doc' => 'Exception class to create when an error occurs.',
47
+ 'default' => 'Aws\Exception\AwsException',
48
+ 'internal' => true
49
+ ],
50
+ 'scheme' => [
51
+ 'type' => 'value',
52
+ 'valid' => ['string'],
53
+ 'default' => 'https',
54
+ 'doc' => 'URI scheme to use when connecting connect. The SDK will utilize "https" endpoints (i.e., utilize SSL/TLS connections) by default. You can attempt to connect to a service over an unencrypted "http" endpoint by setting ``scheme`` to "http".',
55
+ ],
56
+ 'endpoint' => [
57
+ 'type' => 'value',
58
+ 'valid' => ['string'],
59
+ 'doc' => 'The full URI of the webservice. This is only required when connecting to a custom endpoint (e.g., a local version of S3).',
60
+ 'fn' => [__CLASS__, '_apply_endpoint'],
61
+ ],
62
+ 'region' => [
63
+ 'type' => 'value',
64
+ 'valid' => ['string'],
65
+ 'required' => [__CLASS__, '_missing_region'],
66
+ 'doc' => 'Region to connect to. See http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of available regions.',
67
+ ],
68
+ 'version' => [
69
+ 'type' => 'value',
70
+ 'valid' => ['string'],
71
+ 'required' => [__CLASS__, '_missing_version'],
72
+ 'doc' => 'The version of the webservice to utilize (e.g., 2006-03-01).',
73
+ ],
74
+ 'signature_provider' => [
75
+ 'type' => 'value',
76
+ 'valid' => ['callable'],
77
+ 'doc' => 'A callable that accepts a signature version name (e.g., "v4"), a service name, and region, and returns a SignatureInterface object or null. This provider is used to create signers utilized by the client. See Aws\\Signature\\SignatureProvider for a list of built-in providers',
78
+ 'default' => [__CLASS__, '_default_signature_provider'],
79
+ ],
80
+ 'endpoint_provider' => [
81
+ 'type' => 'value',
82
+ 'valid' => ['callable'],
83
+ 'fn' => [__CLASS__, '_apply_endpoint_provider'],
84
+ 'doc' => 'An optional PHP callable that accepts a hash of options including a "service" and "region" key and returns NULL or a hash of endpoint data, of which the "endpoint" key is required. See Aws\\Endpoint\\EndpointProvider for a list of built-in providers.',
85
+ 'default' => [__CLASS__, '_default_endpoint_provider'],
86
+ ],
87
+ 'api_provider' => [
88
+ 'type' => 'value',
89
+ 'valid' => ['callable'],
90
+ 'doc' => 'An optional PHP callable that accepts a type, service, and version argument, and returns an array of corresponding configuration data. The type value can be one of api, waiter, or paginator.',
91
+ 'fn' => [__CLASS__, '_apply_api_provider'],
92
+ 'default' => [ApiProvider::class, 'defaultProvider'],
93
+ ],
94
+ 'signature_version' => [
95
+ 'type' => 'config',
96
+ 'valid' => ['string'],
97
+ 'doc' => 'A string representing a custom signature version to use with a service (e.g., v4). Note that per/operation signature version MAY override this requested signature version.',
98
+ 'default' => [__CLASS__, '_default_signature_version'],
99
+ ],
100
+ 'profile' => [
101
+ 'type' => 'config',
102
+ 'valid' => ['string'],
103
+ 'doc' => 'Allows you to specify which profile to use when credentials are created from the AWS credentials file in your HOME directory. This setting overrides the AWS_PROFILE environment variable. Note: Specifying "profile" will cause the "credentials" key to be ignored.',
104
+ 'fn' => [__CLASS__, '_apply_profile'],
105
+ ],
106
+ 'credentials' => [
107
+ 'type' => 'value',
108
+ 'valid' => [CredentialsInterface::class, CacheInterface::class, 'array', 'bool', 'callable'],
109
+ 'doc' => 'Specifies the credentials used to sign requests. Provide an Aws\Credentials\CredentialsInterface object, an associative array of "key", "secret", and an optional "token" key, `false` to use null credentials, or a callable credentials provider used to create credentials or return null. See Aws\\Credentials\\CredentialProvider for a list of built-in credentials providers. If no credentials are provided, the SDK will attempt to load them from the environment.',
110
+ 'fn' => [__CLASS__, '_apply_credentials'],
111
+ 'default' => [CredentialProvider::class, 'defaultProvider'],
112
+ ],
113
+ 'retries' => [
114
+ 'type' => 'value',
115
+ 'valid' => ['int'],
116
+ 'doc' => 'Configures the maximum number of allowed retries for a client (pass 0 to disable retries). ',
117
+ 'fn' => [__CLASS__, '_apply_retries'],
118
+ 'default' => 3,
119
+ ],
120
+ 'validate' => [
121
+ 'type' => 'value',
122
+ 'valid' => ['bool'],
123
+ 'default' => true,
124
+ 'doc' => 'Set to false to disable client-side parameter validation.',
125
+ 'fn' => [__CLASS__, '_apply_validate'],
126
+ ],
127
+ 'debug' => [
128
+ 'type' => 'value',
129
+ 'valid' => ['bool', 'array'],
130
+ 'doc' => 'Set to true to display debug information when sending requests. Alternatively, you can provide an associative array with the following keys: logfn: (callable) Function that is invoked with log messages; stream_size: (int) When the size of a stream is greater than this number, the stream data will not be logged (set to "0" to not log any stream data); scrub_auth: (bool) Set to false to disable the scrubbing of auth data from the logged messages; http: (bool) Set to false to disable the "debug" feature of lower level HTTP adapters (e.g., verbose curl output).',
131
+ 'fn' => [__CLASS__, '_apply_debug'],
132
+ ],
133
+ 'http' => [
134
+ 'type' => 'value',
135
+ 'valid' => ['array'],
136
+ 'default' => [],
137
+ 'doc' => 'Set to an array of SDK request options to apply to each request (e.g., proxy, verify, etc.).',
138
+ ],
139
+ 'http_handler' => [
140
+ 'type' => 'value',
141
+ 'valid' => ['callable'],
142
+ 'doc' => 'An HTTP handler is a function that accepts a PSR-7 request object and returns a promise that is fulfilled with a PSR-7 response object or rejected with an array of exception data. NOTE: This option supersedes any provided "handler" option.',
143
+ 'fn' => [__CLASS__, '_apply_http_handler']
144
+ ],
145
+ 'handler' => [
146
+ 'type' => 'value',
147
+ 'valid' => ['callable'],
148
+ 'doc' => 'A handler that accepts a command object, request object and returns a promise that is fulfilled with an Aws\ResultInterface object or rejected with an Aws\Exception\AwsException. A handler does not accept a next handler as it is terminal and expected to fulfill a command. If no handler is provided, a default Guzzle handler will be utilized.',
149
+ 'fn' => [__CLASS__, '_apply_handler'],
150
+ 'default' => [__CLASS__, '_default_handler']
151
+ ],
152
+ 'ua_append' => [
153
+ 'type' => 'value',
154
+ 'valid' => ['string', 'array'],
155
+ 'doc' => 'Provide a string or array of strings to send in the User-Agent header.',
156
+ 'fn' => [__CLASS__, '_apply_user_agent'],
157
+ 'default' => [],
158
+ ],
159
+ ];
160
+
161
+ /**
162
+ * Gets an array of default client arguments, each argument containing a
163
+ * hash of the following:
164
+ *
165
+ * - type: (string, required) option type described as follows:
166
+ * - value: The default option type.
167
+ * - config: The provided value is made available in the client's
168
+ * getConfig() method.
169
+ * - valid: (array, required) Valid PHP types or class names. Note: null
170
+ * is not an allowed type.
171
+ * - required: (bool, callable) Whether or not the argument is required.
172
+ * Provide a function that accepts an array of arguments and returns a
173
+ * string to provide a custom error message.
174
+ * - default: (mixed) The default value of the argument if not provided. If
175
+ * a function is provided, then it will be invoked to provide a default
176
+ * value. The function is provided the array of options and is expected
177
+ * to return the default value of the option.
178
+ * - doc: (string) The argument documentation string.
179
+ * - fn: (callable) Function used to apply the argument. The function
180
+ * accepts the provided value, array of arguments by reference, and an
181
+ * event emitter.
182
+ *
183
+ * Note: Order is honored and important when applying arguments.
184
+ *
185
+ * @return array
186
+ */
187
+ public static function getDefaultArguments()
188
+ {
189
+ return self::$defaultArgs;
190
+ }
191
+
192
+ /**
193
+ * @param array $argDefinitions Client arguments.
194
+ */
195
+ public function __construct(array $argDefinitions)
196
+ {
197
+ $this->argDefinitions = $argDefinitions;
198
+ }
199
+
200
+ /**
201
+ * Resolves client configuration options and attached event listeners.
202
+ *
203
+ * @param array $args Provided constructor arguments.
204
+ * @param HandlerList $list Handler list to augment.
205
+ *
206
+ * @return array Returns the array of provided options.
207
+ * @throws \InvalidArgumentException
208
+ * @see Aws\AwsClient::__construct for a list of available options.
209
+ */
210
+ public function resolve(array $args, HandlerList $list)
211
+ {
212
+ $args['config'] = [];
213
+ foreach ($this->argDefinitions as $key => $a) {
214
+ // Add defaults, validate required values, and skip if not set.
215
+ if (!isset($args[$key])) {
216
+ if (isset($a['default'])) {
217
+ // Merge defaults in when not present.
218
+ $args[$key] = is_callable($a['default'])
219
+ ? $a['default']($args)
220
+ : $a['default'];
221
+ } elseif (empty($a['required'])) {
222
+ continue;
223
+ } else {
224
+ $this->throwRequired($args);
225
+ }
226
+ }
227
+
228
+ // Validate the types against the provided value.
229
+ foreach ($a['valid'] as $check) {
230
+ if (isset(self::$typeMap[$check])) {
231
+ $fn = self::$typeMap[$check];
232
+ if ($fn($args[$key])) {
233
+ goto is_valid;
234
+ }
235
+ } elseif ($args[$key] instanceof $check) {
236
+ goto is_valid;
237
+ }
238
+ }
239
+
240
+ $this->invalidType($key, $args[$key]);
241
+
242
+ // Apply the value
243
+ is_valid:
244
+ if (isset($a['fn'])) {
245
+ $a['fn']($args[$key], $args, $list);
246
+ }
247
+
248
+ if ($a['type'] === 'config') {
249
+ $args['config'][$key] = $args[$key];
250
+ }
251
+ }
252
+
253
+ return $args;
254
+ }
255
+
256
+ /**
257
+ * Creates a verbose error message for an invalid argument.
258
+ *
259
+ * @param string $name Name of the argument that is missing.
260
+ * @param array $args Provided arguments
261
+ * @param bool $useRequired Set to true to show the required fn text if
262
+ * available instead of the documentation.
263
+ * @return string
264
+ */
265
+ private function getArgMessage($name, $args = [], $useRequired = false)
266
+ {
267
+ $arg = $this->argDefinitions[$name];
268
+ $msg = '';
269
+ $modifiers = [];
270
+ if (isset($arg['valid'])) {
271
+ $modifiers[] = implode('|', $arg['valid']);
272
+ }
273
+ if (isset($arg['choice'])) {
274
+ $modifiers[] = 'One of ' . implode(', ', $arg['choice']);
275
+ }
276
+ if ($modifiers) {
277
+ $msg .= '(' . implode('; ', $modifiers) . ')';
278
+ }
279
+ $msg = wordwrap("{$name}: {$msg}", 75, "\n ");
280
+
281
+ if ($useRequired && is_callable($arg['required'])) {
282
+ $msg .= "\n\n ";
283
+ $msg .= str_replace("\n", "\n ", call_user_func($arg['required'], $args));
284
+ } elseif (isset($arg['doc'])) {
285
+ $msg .= wordwrap("\n\n {$arg['doc']}", 75, "\n ");
286
+ }
287
+
288
+ return $msg;
289
+ }
290
+
291
+ /**
292
+ * Throw when an invalid type is encountered.
293
+ *
294
+ * @param string $name Name of the value being validated.
295
+ * @param mixed $provided The provided value.
296
+ * @throws \InvalidArgumentException
297
+ */
298
+ private function invalidType($name, $provided)
299
+ {
300
+ $expected = implode('|', $this->argDefinitions[$name]['valid']);
301
+ $msg = "Invalid configuration value "
302
+ . "provided for \"{$name}\". Expected {$expected}, but got "
303
+ . describe_type($provided) . "\n\n"
304
+ . $this->getArgMessage($name);
305
+ throw new IAE($msg);
306
+ }
307
+
308
+ /**
309
+ * Throws an exception for missing required arguments.
310
+ *
311
+ * @param array $args Passed in arguments.
312
+ * @throws \InvalidArgumentException
313
+ */
314
+ private function throwRequired(array $args)
315
+ {
316
+ $missing = [];
317
+ foreach ($this->argDefinitions as $k => $a) {
318
+ if (empty($a['required'])
319
+ || isset($a['default'])
320
+ || array_key_exists($k, $args)
321
+ ) {
322
+ continue;
323
+ }
324
+ $missing[] = $this->getArgMessage($k, $args, true);
325
+ }
326
+ $msg = "Missing required client configuration options: \n\n";
327
+ $msg .= implode("\n\n", $missing);
328
+ throw new IAE($msg);
329
+ }
330
+
331
+ public static function _apply_retries($value, array &$args, HandlerList $list)
332
+ {
333
+ if ($value) {
334
+ $decider = RetryMiddleware::createDefaultDecider($value);
335
+ $list->appendSign(Middleware::retry($decider), 'retry');
336
+ }
337
+ }
338
+
339
+ public static function _apply_credentials($value, array &$args)
340
+ {
341
+ if (is_callable($value)) {
342
+ return;
343
+ } elseif ($value instanceof CredentialsInterface) {
344
+ $args['credentials'] = CredentialProvider::fromCredentials($value);
345
+ } elseif (is_array($value)
346
+ && isset($value['key'])
347
+ && isset($value['secret'])
348
+ ) {
349
+ $args['credentials'] = CredentialProvider::fromCredentials(
350
+ new Credentials(
351
+ $value['key'],
352
+ $value['secret'],
353
+ isset($value['token']) ? $value['token'] : null,
354
+ isset($value['expires']) ? $value['expires'] : null
355
+ )
356
+ );
357
+ } elseif ($value === false) {
358
+ $args['credentials'] = CredentialProvider::fromCredentials(
359
+ new Credentials('', '')
360
+ );
361
+ $args['config']['signature_version'] = 'anonymous';
362
+ } elseif ($value instanceof CacheInterface) {
363
+ $args['credentials'] = CredentialProvider::defaultProvider($args);
364
+ } else {
365
+ throw new IAE('Credentials must be an instance of '
366
+ . 'Aws\Credentials\CredentialsInterface, an associative '
367
+ . 'array that contains "key", "secret", and an optional "token" '
368
+ . 'key-value pairs, a credentials provider function, or false.');
369
+ }
370
+ }
371
+
372
+ public static function _apply_api_provider(callable $value, array &$args, HandlerList $list)
373
+ {
374
+ $api = new Service(
375
+ ApiProvider::resolve(
376
+ $value,
377
+ 'api',
378
+ $args['service'],
379
+ $args['version']
380
+ ),
381
+ $value
382
+ );
383
+ $args['api'] = $api;
384
+ $args['serializer'] = Service::createSerializer($api, $args['endpoint']);
385
+ $args['parser'] = Service::createParser($api);
386
+ $args['error_parser'] = Service::createErrorParser($api->getProtocol());
387
+ $list->prependBuild(Middleware::requestBuilder($args['serializer']), 'builder');
388
+ }
389
+
390
+ public static function _apply_endpoint_provider(callable $value, array &$args)
391
+ {
392
+ if (!isset($args['endpoint'])) {
393
+ // Invoke the endpoint provider and throw if it does not resolve.
394
+ $result = EndpointProvider::resolve($value, [
395
+ 'service' => $args['service'],
396
+ 'region' => $args['region'],
397
+ 'scheme' => $args['scheme']
398
+ ]);
399
+
400
+ $args['endpoint'] = $result['endpoint'];
401
+
402
+ if (isset($result['signatureVersion'])) {
403
+ $args['config']['signature_version'] = $result['signatureVersion'];
404
+ }
405
+ }
406
+ }
407
+
408
+ public static function _apply_debug($value, array &$args, HandlerList $list)
409
+ {
410
+ if ($value !== false) {
411
+ $list->interpose(new TraceMiddleware($value === true ? [] : $value));
412
+ }
413
+ }
414
+
415
+ public static function _apply_profile($_, array &$args)
416
+ {
417
+ $args['credentials'] = CredentialProvider::ini($args['profile']);
418
+ }
419
+
420
+ public static function _apply_validate($value, array &$args, HandlerList $list)
421
+ {
422
+ if ($value === true) {
423
+ $list->appendValidate(
424
+ Middleware::validation($args['api'], new Validator()),
425
+ 'validation'
426
+ );
427
+ }
428
+ }
429
+
430
+ public static function _apply_handler($value, array &$args, HandlerList $list)
431
+ {
432
+ $list->setHandler($value);
433
+ }
434
+
435
+ public static function _default_handler(array &$args)
436
+ {
437
+ return new WrappedHttpHandler(
438
+ default_http_handler(),
439
+ $args['parser'],
440
+ $args['error_parser'],
441
+ $args['exception_class']
442
+ );
443
+ }
444
+
445
+ public static function _apply_http_handler($value, array &$args, HandlerList $list)
446
+ {
447
+ $args['handler'] = new WrappedHttpHandler(
448
+ $value,
449
+ $args['parser'],
450
+ $args['error_parser'],
451
+ $args['exception_class']
452
+ );
453
+ }
454
+
455
+ public static function _apply_user_agent($value, array &$args, HandlerList $list)
456
+ {
457
+ if (!is_array($value)) {
458
+ $value = [$value];
459
+ }
460
+
461
+ $value = array_map('strval', $value);
462
+
463
+ array_unshift($value, 'aws-sdk-php/' . Sdk::VERSION);
464
+ $args['ua_append'] = $value;
465
+
466
+ $list->appendBuild(static function (callable $handler) use ($value) {
467
+ return function (
468
+ CommandInterface $command,
469
+ RequestInterface $request
470
+ ) use ($handler, $value) {
471
+ return $handler($command, $request->withHeader(
472
+ 'User-Agent',
473
+ implode(' ', array_merge(
474
+ $value,
475
+ $request->getHeader('User-Agent')
476
+ ))
477
+ ));
478
+ };
479
+ });
480
+ }
481
+
482
+ public static function _apply_endpoint($value, array &$args, HandlerList $list)
483
+ {
484
+ $parts = parse_url($value);
485
+ if (empty($parts['scheme']) || empty($parts['host'])) {
486
+ throw new IAE(
487
+ 'Endpoints must be full URIs and include a scheme and host'
488
+ );
489
+ }
490
+
491
+ $args['endpoint'] = $value;
492
+ }
493
+
494
+ public static function _default_endpoint_provider()
495
+ {
496
+ return EndpointProvider::defaultProvider();
497
+ }
498
+
499
+ public static function _default_signature_provider()
500
+ {
501
+ return SignatureProvider::defaultProvider();
502
+ }
503
+
504
+ public static function _default_signature_version(array &$args)
505
+ {
506
+ return isset($args['config']['signature_version'])
507
+ ? $args['config']['signature_version']
508
+ : $args['api']->getSignatureVersion();
509
+ }
510
+
511
+ public static function _missing_version(array $args)
512
+ {
513
+ $service = isset($args['service']) ? $args['service'] : '';
514
+ $versions = ApiProvider::defaultProvider()->getVersions($service);
515
+ $versions = implode("\n", array_map(function ($v) {
516
+ return "* \"$v\"";
517
+ }, $versions)) ?: '* (none found)';
518
+
519
+ return <<<EOT
520
+ A "version" configuration value is required. Specifying a version constraint
521
+ ensures that your code will not be affected by a breaking change made to the
522
+ service. For example, when using Amazon S3, you can lock your API version to
523
+ "2006-03-01".
524
+
525
+ Your build of the SDK has the following version(s) of "{$service}": {$versions}
526
+
527
+ You may provide "latest" to the "version" configuration value to utilize the
528
+ most recent available API version that your client's API provider can find.
529
+ Note: Using 'latest' in a production application is not recommended.
530
+
531
+ A list of available API versions can be found on each client's API documentation
532
+ page: http://docs.aws.amazon.com/aws-sdk-php/v3/api/index.html. If you are
533
+ unable to load a specific API version, then you may need to update your copy of
534
+ the SDK.
535
+ EOT;
536
+ }
537
+
538
+ public static function _missing_region(array $args)
539
+ {
540
+ $service = isset($args['service']) ? $args['service'] : '';
541
+
542
+ return <<<EOT
543
+ A "region" configuration value is required for the "{$service}" service
544
+ (e.g., "us-west-2"). A list of available public regions and endpoints can be
545
+ found at http://docs.aws.amazon.com/general/latest/gr/rande.html.
546
+ EOT;
547
+ }
548
+ }
includes/aws/Aws/CloudFront/CloudFrontClient.php ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\CloudFront;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * This client is used to interact with the **Amazon CloudFront** service.
8
+ *
9
+ * @method \Aws\Result createCloudFrontOriginAccessIdentity(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise createCloudFrontOriginAccessIdentityAsync(array $args = [])
11
+ * @method \Aws\Result createDistribution(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise createDistributionAsync(array $args = [])
13
+ * @method \Aws\Result createInvalidation(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise createInvalidationAsync(array $args = [])
15
+ * @method \Aws\Result createStreamingDistribution(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise createStreamingDistributionAsync(array $args = [])
17
+ * @method \Aws\Result deleteCloudFrontOriginAccessIdentity(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise deleteCloudFrontOriginAccessIdentityAsync(array $args = [])
19
+ * @method \Aws\Result deleteDistribution(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise deleteDistributionAsync(array $args = [])
21
+ * @method \Aws\Result deleteStreamingDistribution(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise deleteStreamingDistributionAsync(array $args = [])
23
+ * @method \Aws\Result getCloudFrontOriginAccessIdentity(array $args = [])
24
+ * @method \GuzzleHttp\Promise\Promise getCloudFrontOriginAccessIdentityAsync(array $args = [])
25
+ * @method \Aws\Result getCloudFrontOriginAccessIdentityConfig(array $args = [])
26
+ * @method \GuzzleHttp\Promise\Promise getCloudFrontOriginAccessIdentityConfigAsync(array $args = [])
27
+ * @method \Aws\Result getDistribution(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise getDistributionAsync(array $args = [])
29
+ * @method \Aws\Result getDistributionConfig(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise getDistributionConfigAsync(array $args = [])
31
+ * @method \Aws\Result getInvalidation(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise getInvalidationAsync(array $args = [])
33
+ * @method \Aws\Result getStreamingDistribution(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise getStreamingDistributionAsync(array $args = [])
35
+ * @method \Aws\Result getStreamingDistributionConfig(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise getStreamingDistributionConfigAsync(array $args = [])
37
+ * @method \Aws\Result listCloudFrontOriginAccessIdentities(array $args = [])
38
+ * @method \GuzzleHttp\Promise\Promise listCloudFrontOriginAccessIdentitiesAsync(array $args = [])
39
+ * @method \Aws\Result listDistributions(array $args = [])
40
+ * @method \GuzzleHttp\Promise\Promise listDistributionsAsync(array $args = [])
41
+ * @method \Aws\Result listDistributionsByWebACLId(array $args = [])
42
+ * @method \GuzzleHttp\Promise\Promise listDistributionsByWebACLIdAsync(array $args = [])
43
+ * @method \Aws\Result listInvalidations(array $args = [])
44
+ * @method \GuzzleHttp\Promise\Promise listInvalidationsAsync(array $args = [])
45
+ * @method \Aws\Result listStreamingDistributions(array $args = [])
46
+ * @method \GuzzleHttp\Promise\Promise listStreamingDistributionsAsync(array $args = [])
47
+ * @method \Aws\Result updateCloudFrontOriginAccessIdentity(array $args = [])
48
+ * @method \GuzzleHttp\Promise\Promise updateCloudFrontOriginAccessIdentityAsync(array $args = [])
49
+ * @method \Aws\Result updateDistribution(array $args = [])
50
+ * @method \GuzzleHttp\Promise\Promise updateDistributionAsync(array $args = [])
51
+ * @method \Aws\Result updateStreamingDistribution(array $args = [])
52
+ * @method \GuzzleHttp\Promise\Promise updateStreamingDistributionAsync(array $args = [])
53
+ */
54
+ class CloudFrontClient extends AwsClient
55
+ {
56
+ /**
57
+ * Create a signed Amazon CloudFront URL.
58
+ *
59
+ * This method accepts an array of configuration options:
60
+ *
61
+ * - url: (string) URL of the resource being signed (can include query
62
+ * string and wildcards). For example: rtmp://s5c39gqb8ow64r.cloudfront.net/videos/mp3_name.mp3
63
+ * http://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes
64
+ * - policy: (string) JSON policy. Use this option when creating a signed
65
+ * URL for a custom policy.
66
+ * - expires: (int) UTC Unix timestamp used when signing with a canned
67
+ * policy. Not required when passing a custom 'policy' option.
68
+ * - key_pair_id: (string) The ID of the key pair used to sign CloudFront
69
+ * URLs for private distributions.
70
+ * - private_key: (string) The filepath ot the private key used to sign
71
+ * CloudFront URLs for private distributions.
72
+ *
73
+ * @param array $options Array of configuration options used when signing
74
+ *
75
+ * @return string Signed URL with authentication parameters
76
+ * @throws \InvalidArgumentException if url, key_pair_id, or private_key
77
+ * were not specified.
78
+ * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
79
+ */
80
+ public function getSignedUrl(array $options)
81
+ {
82
+ foreach (['url', 'key_pair_id', 'private_key'] as $required) {
83
+ if (!isset($options[$required])) {
84
+ throw new \InvalidArgumentException("$required is required");
85
+ }
86
+ }
87
+
88
+ $urlSigner = new UrlSigner(
89
+ $options['key_pair_id'],
90
+ $options['private_key']
91
+ );
92
+
93
+ return $urlSigner->getSignedUrl(
94
+ $options['url'],
95
+ isset($options['expires']) ? $options['expires'] : null,
96
+ isset($options['policy']) ? $options['policy'] : null
97
+ );
98
+ }
99
+
100
+ /**
101
+ * Create a signed Amazon CloudFront cookie.
102
+ *
103
+ * This method accepts an array of configuration options:
104
+ *
105
+ * - url: (string) URL of the resource being signed (can include query
106
+ * string and wildcards). For example: http://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes
107
+ * - policy: (string) JSON policy. Use this option when creating a signed
108
+ * URL for a custom policy.
109
+ * - expires: (int) UTC Unix timestamp used when signing with a canned
110
+ * policy. Not required when passing a custom 'policy' option.
111
+ * - key_pair_id: (string) The ID of the key pair used to sign CloudFront
112
+ * URLs for private distributions.
113
+ * - private_key: (string) The filepath ot the private key used to sign
114
+ * CloudFront URLs for private distributions.
115
+ *
116
+ * @param array $options Array of configuration options used when signing
117
+ *
118
+ * @return array Key => value pairs of signed cookies to set
119
+ * @throws \InvalidArgumentException if url, key_pair_id, or private_key
120
+ * were not specified.
121
+ * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
122
+ */
123
+ public function getSignedCookie(array $options)
124
+ {
125
+ foreach (['key_pair_id', 'private_key'] as $required) {
126
+ if (!isset($options[$required])) {
127
+ throw new \InvalidArgumentException("$required is required");
128
+ }
129
+ }
130
+
131
+ $cookieSigner = new CookieSigner(
132
+ $options['key_pair_id'],
133
+ $options['private_key']
134
+ );
135
+
136
+ return $cookieSigner->getSignedCookie(
137
+ isset($options['url']) ? $options['url'] : null,
138
+ isset($options['expires']) ? $options['expires'] : null,
139
+ isset($options['policy']) ? $options['policy'] : null
140
+ );
141
+ }
142
+ }
includes/aws/Aws/CloudFront/CookieSigner.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\CloudFront;
3
+
4
+ class CookieSigner
5
+ {
6
+ /** @var Signer */
7
+ private $signer;
8
+
9
+ private static $schemes = [
10
+ 'http' => true,
11
+ 'https' => true,
12
+ ];
13
+
14
+ /**
15
+ * @param $keyPairId string ID of the key pair
16
+ * @param $privateKey string Path to the private key used for signing
17
+ *
18
+ * @throws \RuntimeException if the openssl extension is missing
19
+ * @throws \InvalidArgumentException if the private key cannot be found.
20
+ */
21
+ public function __construct($keyPairId, $privateKey)
22
+ {
23
+ $this->signer = new Signer($keyPairId, $privateKey);
24
+ }
25
+
26
+ /**
27
+ * Create a signed Amazon CloudFront Cookie.
28
+ *
29
+ * @param string $url URL to sign (can include query string
30
+ * and wildcards). Not required
31
+ * when passing a custom $policy.
32
+ * @param string|integer|null $expires UTC Unix timestamp used when signing
33
+ * with a canned policy. Not required
34
+ * when passing a custom $policy.
35
+ * @param string $policy JSON policy. Use this option when
36
+ * creating a signed cookie for a custom
37
+ * policy.
38
+ *
39
+ * @return array The authenticated cookie parameters
40
+ * @throws \InvalidArgumentException if the URL provided is invalid
41
+ * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html
42
+ */
43
+ public function getSignedCookie($url = null, $expires = null, $policy = null)
44
+ {
45
+ if ($url) {
46
+ $this->validateUrl($url);
47
+ }
48
+
49
+ $cookieParameters = [];
50
+ $signature = $this->signer->getSignature($url, $expires, $policy);
51
+ foreach ($signature as $key => $value) {
52
+ $cookieParameters["CloudFront-$key"] = $value;
53
+ }
54
+
55
+ return $cookieParameters;
56
+ }
57
+
58
+ private function validateUrl($url)
59
+ {
60
+ $scheme = str_replace('*', '', explode('://', $url)[0]);
61
+ if (empty(self::$schemes[strtolower($scheme)])) {
62
+ throw new \InvalidArgumentException('Invalid or missing URI scheme');
63
+ }
64
+ }
65
+ }
includes/aws/Aws/CloudFront/Exception/CloudFrontException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\CloudFront\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the Amazon CloudFront service.
8
+ */
9
+ class CloudFrontException extends AwsException {}
includes/aws/Aws/CloudFront/Signer.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\CloudFront;
3
+
4
+ /**
5
+ * @internal
6
+ */
7
+ class Signer
8
+ {
9
+ private $keyPairId;
10
+ private $pk;
11
+
12
+ /**
13
+ * A signer for creating the signature values used in CloudFront signed URLs
14
+ * and signed cookies.
15
+ *
16
+ * @param $keyPairId string ID of the key pair
17
+ * @param $privateKey string Path to the private key used for signing
18
+ *
19
+ * @throws \RuntimeException if the openssl extension is missing
20
+ * @throws \InvalidArgumentException if the private key cannot be found.
21
+ */
22
+ public function __construct($keyPairId, $privateKey)
23
+ {
24
+ if (!extension_loaded('openssl')) {
25
+ //@codeCoverageIgnoreStart
26
+ throw new \RuntimeException('The openssl extension is required to '
27
+ . 'sign CloudFront urls.');
28
+ //@codeCoverageIgnoreEnd
29
+ }
30
+
31
+ $this->keyPairId = $keyPairId;
32
+
33
+ if (!file_exists($privateKey)) {
34
+ throw new \InvalidArgumentException("PK file not found: $privateKey");
35
+ }
36
+
37
+ $this->pk = file_get_contents($privateKey);
38
+ }
39
+
40
+
41
+ /**
42
+ * Create the values used to construct signed URLs and cookies.
43
+ *
44
+ * @param string $resource The CloudFront resource to which
45
+ * this signature will grant access.
46
+ * Not used when a custom policy is
47
+ * provided.
48
+ * @param string|integer|null $expires UTC Unix timestamp used when
49
+ * signing with a canned policy.
50
+ * Not required when passing a
51
+ * custom $policy.
52
+ * @param string $policy JSON policy. Use this option when
53
+ * creating a signature for a custom
54
+ * policy.
55
+ *
56
+ * @return array The values needed to construct a signed URL or cookie
57
+ * @throws \InvalidArgumentException when not provided either a policy or a
58
+ * resource and a expires
59
+ *
60
+ * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html
61
+ */
62
+ public function getSignature($resource = null, $expires = null, $policy = null)
63
+ {
64
+ $signatureHash = [];
65
+ if ($policy) {
66
+ $policy = preg_replace('/\s/s', '', $policy);
67
+ $signatureHash['Policy'] = $this->encode($policy);
68
+ } elseif ($resource && $expires) {
69
+ $policy = $this->createCannedPolicy($resource, $expires);
70
+ $signatureHash['Expires'] = $expires;
71
+ } else {
72
+ throw new \InvalidArgumentException('Either a policy or a resource'
73
+ . ' and an expiration time must be provided.');
74
+ }
75
+
76
+ $signatureHash['Signature'] = $this->encode($this->sign($policy));
77
+ $signatureHash['Key-Pair-Id'] = $this->keyPairId;
78
+
79
+ return $signatureHash;
80
+ }
81
+
82
+ private function createCannedPolicy($resource, $expiration)
83
+ {
84
+ return json_encode([
85
+ 'Statement' => [
86
+ [
87
+ 'Resource' => $resource,
88
+ 'Condition' => [
89
+ 'DateLessThan' => ['AWS:EpochTime' => $expiration],
90
+ ],
91
+ ],
92
+ ],
93
+ ], JSON_UNESCAPED_SLASHES);
94
+ }
95
+
96
+ private function sign($policy)
97
+ {
98
+ $signature = '';
99
+ openssl_sign($policy, $signature, $this->pk);
100
+
101
+ return $signature;
102
+ }
103
+
104
+ private function encode($policy)
105
+ {
106
+ return strtr(base64_encode($policy), '+=/', '-_~');
107
+ }
108
+ }
includes/aws/Aws/CloudFront/UrlSigner.php ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\CloudFront;
3
+
4
+ use GuzzleHttp\Psr7;
5
+ use GuzzleHttp\Psr7\Uri;
6
+ use Psr\Http\Message\UriInterface;
7
+
8
+ /**
9
+ * Creates signed URLs for Amazon CloudFront resources.
10
+ */
11
+ class UrlSigner
12
+ {
13
+ private $signer;
14
+
15
+ /**
16
+ * @param $keyPairId string ID of the key pair
17
+ * @param $privateKey string Path to the private key used for signing
18
+ *
19
+ * @throws \RuntimeException if the openssl extension is missing
20
+ * @throws \InvalidArgumentException if the private key cannot be found.
21
+ */
22
+ public function __construct($keyPairId, $privateKey)
23
+ {
24
+ $this->signer = new Signer($keyPairId, $privateKey);
25
+ }
26
+
27
+ /**
28
+ * Create a signed Amazon CloudFront URL.
29
+ *
30
+ * Keep in mind that URLs meant for use in media/flash players may have
31
+ * different requirements for URL formats (e.g. some require that the
32
+ * extension be removed, some require the file name to be prefixed
33
+ * - mp4:<path>, some require you to add "/cfx/st" into your URL).
34
+ *
35
+ * @param string $url URL to sign (can include query
36
+ * string string and wildcards)
37
+ * @param string|integer|null $expires UTC Unix timestamp used when signing
38
+ * with a canned policy. Not required
39
+ * when passing a custom $policy.
40
+ * @param string $policy JSON policy. Use this option when
41
+ * creating a signed URL for a custom
42
+ * policy.
43
+ *
44
+ * @return string The file URL with authentication parameters
45
+ * @throws \InvalidArgumentException if the URL provided is invalid
46
+ * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
47
+ */
48
+ public function getSignedUrl($url, $expires = null, $policy = null)
49
+ {
50
+ // Determine the scheme of the url
51
+ $urlSections = explode('://', $url);
52
+
53
+ if (count($urlSections) < 2) {
54
+ throw new \InvalidArgumentException("Invalid URL: {$url}");
55
+ }
56
+
57
+ // Get the real scheme by removing wildcards from the scheme
58
+ $scheme = str_replace('*', '', $urlSections[0]);
59
+ $uri = new Uri($scheme . '://' . $urlSections[1]);
60
+ $query = Psr7\parse_query($uri->getQuery(), PHP_QUERY_RFC3986);
61
+ $signature = $this->signer->getSignature(
62
+ $this->createResource($scheme, (string) $uri),
63
+ $expires,
64
+ $policy
65
+ );
66
+ $uri = $uri->withQuery(
67
+ http_build_query($query + $signature, null, '&', PHP_QUERY_RFC3986)
68
+ );
69
+
70
+ return $scheme === 'rtmp'
71
+ ? $this->createRtmpUrl($uri)
72
+ : (string) $uri;
73
+ }
74
+
75
+ private function createRtmpUrl(UriInterface $uri)
76
+ {
77
+ // Use a relative URL when creating Flash player URLs
78
+ $result = ltrim($uri->getPath(), '/');
79
+
80
+ if ($query = $uri->getQuery()) {
81
+ $result .= '?' . $query;
82
+ }
83
+
84
+ return $result;
85
+ }
86
+
87
+ /**
88
+ * @param $scheme
89
+ * @param $url
90
+ *
91
+ * @return string
92
+ */
93
+ private function createResource($scheme, $url)
94
+ {
95
+ switch ($scheme) {
96
+ case 'http':
97
+ case 'http*':
98
+ case 'https':
99
+ return $url;
100
+ case 'rtmp':
101
+ $parts = parse_url($url);
102
+ $pathParts = pathinfo($parts['path']);
103
+ $resource = ltrim(
104
+ $pathParts['dirname'] . '/' . $pathParts['basename'],
105
+ '/'
106
+ );
107
+
108
+ // Add a query string if present.
109
+ if (isset($parts['query'])) {
110
+ $resource .= "?{$parts['query']}";
111
+ }
112
+
113
+ return $resource;
114
+ }
115
+
116
+ throw new \InvalidArgumentException("Invalid URI scheme: {$scheme}. "
117
+ . "Scheme must be one of: http, https, or rtmp");
118
+ }
119
+ }
includes/aws/Aws/Command.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ /**
5
+ * AWS command object.
6
+ */
7
+ class Command implements CommandInterface
8
+ {
9
+ use HasDataTrait;
10
+
11
+ /** @var string */
12
+ private $name;
13
+
14
+ /** @var HandlerList */
15
+ private $handlerList;
16
+
17
+ /**
18
+ * Accepts an associative array of command options, including:
19
+ *
20
+ * - @http: (array) Associative array of transfer options.
21
+ *
22
+ * @param string $name Name of the command
23
+ * @param array $args Arguments to pass to the command
24
+ * @param HandlerList $list Handler list
25
+ */
26
+ public function __construct($name, array $args = [], HandlerList $list = null)
27
+ {
28
+ $this->name = $name;
29
+ $this->data = $args;
30
+ $this->handlerList = $list ?: new HandlerList();
31
+
32
+ if (!isset($this->data['@http'])) {
33
+ $this->data['@http'] = [];
34
+ }
35
+ }
36
+
37
+ public function getName()
38
+ {
39
+ return $this->name;
40
+ }
41
+
42
+ public function hasParam($name)
43
+ {
44
+ return array_key_exists($name, $this->data);
45
+ }
46
+
47
+ public function getHandlerList()
48
+ {
49
+ return $this->handlerList;
50
+ }
51
+
52
+ /** @deprecated */
53
+ public function get($name)
54
+ {
55
+ return $this[$name];
56
+ }
57
+ }
includes/aws/Aws/CommandInterface.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ /**
5
+ * A command object encapsulates the input parameters used to control the
6
+ * creation of a HTTP request and processing of a HTTP response.
7
+ *
8
+ * Using the toArray() method will return the input parameters of the command
9
+ * as an associative array.
10
+ */
11
+ interface CommandInterface extends \ArrayAccess, \Countable, \IteratorAggregate
12
+ {
13
+ /**
14
+ * Converts the command parameters to an array
15
+ *
16
+ * @return array
17
+ */
18
+ public function toArray();
19
+
20
+ /**
21
+ * Get the name of the command
22
+ *
23
+ * @return string
24
+ */
25
+ public function getName();
26
+
27
+ /**
28
+ * Check if the command has a parameter by name.
29
+ *
30
+ * @param string $name Name of the parameter to check
31
+ *
32
+ * @return bool
33
+ */
34
+ public function hasParam($name);
35
+
36
+ /**
37
+ * Get the handler list used to transfer the command.
38
+ *
39
+ * @return HandlerList
40
+ */
41
+ public function getHandlerList();
42
+ }
includes/aws/Aws/CommandPool.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use GuzzleHttp\Promise\PromisorInterface;
5
+ use GuzzleHttp\Promise\EachPromise;
6
+
7
+ /**
8
+ * Sends and iterator of commands concurrently using a capped pool size.
9
+ *
10
+ * The pool will read command objects from an iterator until it is cancelled or
11
+ * until the iterator is consumed.
12
+ */
13
+ class CommandPool implements PromisorInterface
14
+ {
15
+ /** @var EachPromise */
16
+ private $each;
17
+
18
+ /**
19
+ * The CommandPool constructor accepts a hash of configuration options:
20
+ *
21
+ * - concurrency: (callable|int) Maximum number of commands to execute
22
+ * concurrently. Provide a function to resize the pool dynamically. The
23
+ * function will be provided the current number of pending requests and
24
+ * is expected to return an integer representing the new pool size limit.
25
+ * - before: (callable) function to invoke before sending each command. The
26
+ * before function accepts the command and the key of the iterator of the
27
+ * command. You can mutate the command as needed in the before function
28
+ * before sending the command.
29
+ * - fulfilled: (callable) Function to invoke when a promise is fulfilled.
30
+ * The function is provided the result object, id of the iterator that the
31
+ * result came from, and the aggregate promise that can be resolved/rejected
32
+ * if you need to short-circuit the pool.
33
+ * - rejected: (callable) Function to invoke when a promise is rejected.
34
+ * The function is provided an AwsException object, id of the iterator that
35
+ * the exception came from, and the aggregate promise that can be
36
+ * resolved/rejected if you need to short-circuit the pool.
37
+ *
38
+ * @param AwsClientInterface $client Client used to execute commands.
39
+ * @param array|\Iterator $commands Iterable that yields commands.
40
+ * @param array $config Associative array of options.
41
+ */
42
+ public function __construct(
43
+ AwsClientInterface $client,
44
+ $commands,
45
+ array $config = []
46
+ ) {
47
+ if (!isset($config['concurrency'])) {
48
+ $config['concurrency'] = 25;
49
+ }
50
+
51
+ $before = $this->getBefore($config);
52
+ $mapFn = function ($commands) use ($client, $before) {
53
+ foreach ($commands as $key => $command) {
54
+ if (!($command instanceof CommandInterface)) {
55
+ throw new \InvalidArgumentException('Each value yielded by '
56
+ . 'the iterator must be an Aws\CommandInterface.');
57
+ }
58
+ if ($before) {
59
+ $before($command, $key);
60
+ }
61
+ yield $client->executeAsync($command);
62
+ }
63
+ };
64
+
65
+ $this->each = new EachPromise($mapFn($commands), $config);
66
+ }
67
+
68
+ /**
69
+ * @return \GuzzleHttp\Promise\PromiseInterface
70
+ */
71
+ public function promise()
72
+ {
73
+ return $this->each->promise();
74
+ }
75
+
76
+ /**
77
+ * Executes a pool synchronously and aggregates the results of the pool
78
+ * into an indexed array in the same order as the passed in array.
79
+ *
80
+ * @param AwsClientInterface $client Client used to execute commands.
81
+ * @param mixed $commands Iterable that yields commands.
82
+ * @param array $config Configuration options.
83
+ *
84
+ * @return array
85
+ * @see \Aws\CommandPool::__construct for available configuration options.
86
+ */
87
+ public static function batch(
88
+ AwsClientInterface $client,
89
+ $commands,
90
+ array $config = []
91
+ ) {
92
+ $results = [];
93
+ self::cmpCallback($config, 'fulfilled', $results);
94
+ self::cmpCallback($config, 'rejected', $results);
95
+
96
+ return (new self($client, $commands, $config))
97
+ ->promise()
98
+ ->then(static function () use (&$results) {
99
+ ksort($results);
100
+ return $results;
101
+ })
102
+ ->wait();
103
+ }
104
+
105
+ /**
106
+ * @return callable
107
+ */
108
+ private function getBefore(array $config)
109
+ {
110
+ if (!isset($config['before'])) {
111
+ return null;
112
+ }
113
+
114
+ if (is_callable($config['before'])) {
115
+ return $config['before'];
116
+ }
117
+
118
+ throw new \InvalidArgumentException('before must be callable');
119
+ }
120
+
121
+ /**
122
+ * Adds an onFulfilled or onRejected callback that aggregates results into
123
+ * an array. If a callback is already present, it is replaced with the
124
+ * composed function.
125
+ *
126
+ * @param array $config
127
+ * @param $name
128
+ * @param array $results
129
+ */
130
+ private static function cmpCallback(array &$config, $name, array &$results)
131
+ {
132
+ if (!isset($config[$name])) {
133
+ $config[$name] = function ($v, $k) use (&$results) {
134
+ $results[$k] = $v;
135
+ };
136
+ } else {
137
+ $currentFn = $config[$name];
138
+ $config[$name] = function ($v, $k) use (&$results, $currentFn) {
139
+ $currentFn($v, $k);
140
+ $results[$k] = $v;
141
+ };
142
+ }
143
+ }
144
+ }
includes/aws/Aws/ConfigService/ConfigServiceClient.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\ConfigService;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * This client is used to interact with AWS Config.
8
+ *
9
+ * @method \Aws\Result deleteConfigRule(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise deleteConfigRuleAsync(array $args = [])
11
+ * @method \Aws\Result deleteDeliveryChannel(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise deleteDeliveryChannelAsync(array $args = [])
13
+ * @method \Aws\Result deliverConfigSnapshot(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise deliverConfigSnapshotAsync(array $args = [])
15
+ * @method \Aws\Result describeComplianceByConfigRule(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise describeComplianceByConfigRuleAsync(array $args = [])
17
+ * @method \Aws\Result describeComplianceByResource(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise describeComplianceByResourceAsync(array $args = [])
19
+ * @method \Aws\Result describeConfigRuleEvaluationStatus(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise describeConfigRuleEvaluationStatusAsync(array $args = [])
21
+ * @method \Aws\Result describeConfigRules(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise describeConfigRulesAsync(array $args = [])
23
+ * @method \Aws\Result describeConfigurationRecorderStatus(array $args = [])
24
+ * @method \GuzzleHttp\Promise\Promise describeConfigurationRecorderStatusAsync(array $args = [])
25
+ * @method \Aws\Result describeConfigurationRecorders(array $args = [])
26
+ * @method \GuzzleHttp\Promise\Promise describeConfigurationRecordersAsync(array $args = [])
27
+ * @method \Aws\Result describeDeliveryChannelStatus(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise describeDeliveryChannelStatusAsync(array $args = [])
29
+ * @method \Aws\Result describeDeliveryChannels(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise describeDeliveryChannelsAsync(array $args = [])
31
+ * @method \Aws\Result getComplianceDetailsByConfigRule(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise getComplianceDetailsByConfigRuleAsync(array $args = [])
33
+ * @method \Aws\Result getComplianceDetailsByResource(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise getComplianceDetailsByResourceAsync(array $args = [])
35
+ * @method \Aws\Result getComplianceSummaryByConfigRule(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise getComplianceSummaryByConfigRuleAsync(array $args = [])
37
+ * @method \Aws\Result getComplianceSummaryByResourceType(array $args = [])
38
+ * @method \GuzzleHttp\Promise\Promise getComplianceSummaryByResourceTypeAsync(array $args = [])
39
+ * @method \Aws\Result getResourceConfigHistory(array $args = [])
40
+ * @method \GuzzleHttp\Promise\Promise getResourceConfigHistoryAsync(array $args = [])
41
+ * @method \Aws\Result listDiscoveredResources(array $args = [])
42
+ * @method \GuzzleHttp\Promise\Promise listDiscoveredResourcesAsync(array $args = [])
43
+ * @method \Aws\Result putConfigRule(array $args = [])
44
+ * @method \GuzzleHttp\Promise\Promise putConfigRuleAsync(array $args = [])
45
+ * @method \Aws\Result putConfigurationRecorder(array $args = [])
46
+ * @method \GuzzleHttp\Promise\Promise putConfigurationRecorderAsync(array $args = [])
47
+ * @method \Aws\Result putDeliveryChannel(array $args = [])
48
+ * @method \GuzzleHttp\Promise\Promise putDeliveryChannelAsync(array $args = [])
49
+ * @method \Aws\Result putEvaluations(array $args = [])
50
+ * @method \GuzzleHttp\Promise\Promise putEvaluationsAsync(array $args = [])
51
+ * @method \Aws\Result startConfigurationRecorder(array $args = [])
52
+ * @method \GuzzleHttp\Promise\Promise startConfigurationRecorderAsync(array $args = [])
53
+ * @method \Aws\Result stopConfigurationRecorder(array $args = [])
54
+ * @method \GuzzleHttp\Promise\Promise stopConfigurationRecorderAsync(array $args = [])
55
+ */
56
+ class ConfigServiceClient extends AwsClient {}
includes/aws/Aws/ConfigService/Exception/ConfigServiceException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\ConfigService\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the AWS Config service.
8
+ */
9
+ class ConfigServiceException extends AwsException {}
includes/aws/Aws/Credentials/CredentialProvider.php ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Credentials;
3
+
4
+ use Aws;
5
+ use Aws\CacheInterface;
6
+ use Aws\Exception\CredentialsException;
7
+ use GuzzleHttp\Promise;
8
+
9
+ /**
10
+ * Credential providers are functions that accept no arguments and return a
11
+ * promise that is fulfilled with an {@see \Aws\Credentials\CredentialsInterface}
12
+ * or rejected with an {@see \Aws\Exception\CredentialsException}.
13
+ *
14
+ * <code>
15
+ * use Aws\Credentials\CredentialProvider;
16
+ * $provider = CredentialProvider::defaultProvider();
17
+ * // Returns a CredentialsInterface or throws.
18
+ * $creds = $provider()->wait();
19
+ * </code>
20
+ *
21
+ * Credential providers can be composed to create credentials using conditional
22
+ * logic that can create different credentials in different environments. You
23
+ * can compose multiple providers into a single provider using
24
+ * {@see Aws\Credentials\CredentialProvider::chain}. This function accepts
25
+ * providers as variadic arguments and returns a new function that will invoke
26
+ * each provider until a successful set of credentials is returned.
27
+ *
28
+ * <code>
29
+ * // First try an INI file at this location.
30
+ * $a = CredentialProvider::ini(null, '/path/to/file.ini');
31
+ * // Then try an INI file at this location.
32
+ * $b = CredentialProvider::ini(null, '/path/to/other-file.ini');
33
+ * // Then try loading from envrionment variables.
34
+ * $c = CredentialProvider::env();
35
+ * // Combine the three providers together.
36
+ * $composed = CredentialProvider::chain($a, $b, $c);
37
+ * // Returns a promise that is fulfilled with credentials or throws.
38
+ * $promise = $composed();
39
+ * // Wait on the credentials to resolve.
40
+ * $creds = $promise->wait();
41
+ * </code>
42
+ */
43
+ class CredentialProvider
44
+ {
45
+ const ENV_KEY = 'AWS_ACCESS_KEY_ID';
46
+ const ENV_SECRET = 'AWS_SECRET_ACCESS_KEY';
47
+ const ENV_SESSION = 'AWS_SESSION_TOKEN';
48
+ const ENV_PROFILE = 'AWS_PROFILE';
49
+
50
+ /**
51
+ * Create a default credential provider that first checks for environment
52
+ * variables, then checks for the "default" profile in ~/.aws/credentials,
53
+ * and finally checks for credentials using EC2 instance profile
54
+ * credentials.
55
+ *
56
+ * This provider is automatically wrapped in a memoize function that caches
57
+ * previously provided credentials.
58
+ *
59
+ * @param array $config Optional array of instance profile credentials
60
+ * provider options.
61
+ * @return callable
62
+ */
63
+ public static function defaultProvider(array $config = [])
64
+ {
65
+ $instanceProfileProvider = self::instanceProfile($config);
66
+ if (isset($config['credentials'])
67
+ && $config['credentials'] instanceof CacheInterface
68
+ ) {
69
+ $instanceProfileProvider = self::cache(
70
+ $instanceProfileProvider,
71
+ $config['credentials']
72
+ );
73
+ }
74
+
75
+ return self::memoize(
76
+ self::chain(
77
+ self::env(),
78
+ self::ini(),
79
+ $instanceProfileProvider
80
+ )
81
+ );
82
+ }
83
+
84
+ /**
85
+ * Create a credential provider function from a set of static credentials.
86
+ *
87
+ * @param CredentialsInterface $creds
88
+ *
89
+ * @return callable
90
+ */
91
+ public static function fromCredentials(CredentialsInterface $creds)
92
+ {
93
+ $promise = Promise\promise_for($creds);
94
+
95
+ return function () use ($promise) {
96
+ return $promise;
97
+ };
98
+ }
99
+
100
+ /**
101
+ * Creates an aggregate credentials provider that invokes the provided
102
+ * variadic providers one after the other until a provider returns
103
+ * credentials.
104
+ *
105
+ * @return callable
106
+ */
107
+ public static function chain()
108
+ {
109
+ $links = func_get_args();
110
+ if (empty($links)) {
111
+ throw new \InvalidArgumentException('No providers in chain');
112
+ }
113
+
114
+ return function () use ($links) {
115
+ /** @var callable $parent */
116
+ $parent = array_shift($links);
117
+ $promise = $parent();
118
+ while ($next = array_shift($links)) {
119
+ $promise = $promise->otherwise($next);
120
+ }
121
+ return $promise;
122
+ };
123
+ }
124
+
125
+ /**
126
+ * Wraps a credential provider and caches previously provided credentials.
127
+ *
128
+ * Ensures that cached credentials are refreshed when they expire.
129
+ *
130
+ * @param callable $provider Credentials provider function to wrap.
131
+ *
132
+ * @return callable
133
+ */
134
+ public static function memoize(callable $provider)
135
+ {
136
+ return function () use ($provider) {
137
+ static $result;
138
+ static $isConstant;
139
+
140
+ // Constant credentials will be returned constantly.
141
+ if ($isConstant) {
142
+ return $result;
143
+ }
144
+
145
+ // Create the initial promise that will be used as the cached value
146
+ // until it expires.
147
+ if (null === $result) {
148
+ $result = $provider();
149
+ }
150
+
151
+ // Return credentials that could expire and refresh when needed.
152
+ return $result
153
+ ->then(function (CredentialsInterface $creds) use ($provider, &$isConstant, &$result) {
154
+ // Determine if these are constant credentials.
155
+ if (!$creds->getExpiration()) {
156
+ $isConstant = true;
157
+ return $creds;
158
+ }
159
+
160
+ // Refresh expired credentials.
161
+ if (!$creds->isExpired()) {
162
+ return $creds;
163
+ }
164
+ // Refresh the result and forward the promise.
165
+ return $result = $provider();
166
+ });
167
+ };
168
+ }
169
+
170
+ /**
171
+ * Wraps a credential provider and saves provided credentials in an
172
+ * instance of Aws\CacheInterface. Forwards calls when no credentials found
173
+ * in cache and updates cache with the results.
174
+ *
175
+ * Defaults to using a simple file-based cache when none provided.
176
+ *
177
+ * @param callable $provider Credentials provider function to wrap
178
+ * @param CacheInterface $cache (optional) Cache to store credentials
179
+ * @param string|null $cacheKey (optional) Cache key to use
180
+ *
181
+ * @return callable
182
+ */
183
+ public static function cache(
184
+ callable $provider,
185
+ CacheInterface $cache,
186
+ $cacheKey = null
187
+ ) {
188
+ $cacheKey = $cacheKey ?: 'aws_cached_credentials';
189
+
190
+ return function () use ($provider, $cache, $cacheKey) {
191
+ $found = $cache->get($cacheKey);
192
+ if ($found instanceof CredentialsInterface && !$found->isExpired()) {
193
+ return Promise\promise_for($found);
194
+ }
195
+
196
+ return $provider()
197
+ ->then(function (CredentialsInterface $creds) use (
198
+ $cache,
199
+ $cacheKey
200
+ ) {
201
+ $cache->set(
202
+ $cacheKey,
203
+ $creds,
204
+ null === $creds->getExpiration() ?
205
+ 0 : $creds->getExpiration() - time()
206
+ );
207
+
208
+ return $creds;
209
+ });
210
+ };
211
+ }
212
+
213
+ /**
214
+ * Provider that creates credentials from environment variables
215
+ * AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN.
216
+ *
217
+ * @return callable
218
+ */
219
+ public static function env()
220
+ {
221
+ return function () {
222
+ // Use credentials from environment variables, if available
223
+ $key = getenv(self::ENV_KEY);
224
+ $secret = getenv(self::ENV_SECRET);
225
+ if ($key && $secret) {
226
+ return Promise\promise_for(
227
+ new Credentials($key, $secret, getenv(self::ENV_SESSION))
228
+ );
229
+ }
230
+
231
+ return self::reject('Could not find environment variable '
232
+ . 'credentials in ' . self::ENV_KEY . '/' . self::ENV_SECRET);
233
+ };
234
+ }
235
+
236
+ /**
237
+ * Credential provider that creates credentials using instance profile
238
+ * credentials.
239
+ *
240
+ * @param array $config Array of configuration data.
241
+ *
242
+ * @return InstanceProfileProvider
243
+ * @see Aws\Credentials\InstanceProfileProvider for $config details.
244
+ */
245
+ public static function instanceProfile(array $config = [])
246
+ {
247
+ return new InstanceProfileProvider($config);
248
+ }
249
+
250
+ /**
251
+ * Credentials provider that creates credentials using an ini file stored
252
+ * in the current user's home directory.
253
+ *
254
+ * @param string|null $profile Profile to use. If not specified will use
255
+ * the "default" profile.
256
+ * @param string|null $filename If provided, uses a custom filename rather
257
+ * than looking in the home directory for the
258
+ *
259
+ * @return callable
260
+ */
261
+ public static function ini($profile = null, $filename = null)
262
+ {
263
+ $filename = $filename ?: (self::getHomeDir() . '/.aws/credentials');
264
+ $profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
265
+
266
+ return function () use ($profile, $filename) {
267
+ if (!is_readable($filename)) {
268
+ return self::reject("Cannot read credentials from $filename");
269
+ }
270
+ $data = parse_ini_file($filename, true);
271
+ if ($data === false) {
272
+ return self::reject("Invalid credentials file: $filename");
273
+ }
274
+ if (!isset($data[$profile])) {
275
+ return self::reject("'$profile' not found in credentials file");
276
+ }
277
+ if (!isset($data[$profile]['aws_access_key_id'])
278
+ || !isset($data[$profile]['aws_secret_access_key'])
279
+ ) {
280
+ return self::reject("No credentials present in INI profile "
281
+ . "'$profile' ($filename)");
282
+ }
283
+
284
+ if (empty($data[$profile]['aws_session_token'])) {
285
+ $data[$profile]['aws_session_token']
286
+ = isset($data[$profile]['aws_security_token'])
287
+ ? $data[$profile]['aws_security_token']
288
+ : null;
289
+ }
290
+
291
+ return Promise\promise_for(
292
+ new Credentials(
293
+ $data[$profile]['aws_access_key_id'],
294
+ $data[$profile]['aws_secret_access_key'],
295
+ $data[$profile]['aws_session_token']
296
+ )
297
+ );
298
+ };
299
+ }
300
+
301
+ /**
302
+ * Gets the environment's HOME directory if available.
303
+ *
304
+ * @return null|string
305
+ */
306
+ private static function getHomeDir()
307
+ {
308
+ // On Linux/Unix-like systems, use the HOME environment variable
309
+ if ($homeDir = getenv('HOME')) {
310
+ return $homeDir;
311
+ }
312
+
313
+ // Get the HOMEDRIVE and HOMEPATH values for Windows hosts
314
+ $homeDrive = getenv('HOMEDRIVE');
315
+ $homePath = getenv('HOMEPATH');
316
+
317
+ return ($homeDrive && $homePath) ? $homeDrive . $homePath : null;
318
+ }
319
+
320
+ private static function reject($msg)
321
+ {
322
+ return new Promise\RejectedPromise(new CredentialsException($msg));
323
+ }
324
+ }
includes/aws/Aws/Credentials/Credentials.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Credentials;
3
+
4
+ /**
5
+ * Basic implementation of the AWS Credentials interface that allows callers to
6
+ * pass in the AWS Access Key and AWS Secret Access Key in the constructor.
7
+ */
8
+ class Credentials implements CredentialsInterface, \Serializable
9
+ {
10
+ private $key;
11
+ private $secret;
12
+ private $token;
13
+ private $expires;
14
+
15
+ /**
16
+ * Constructs a new BasicAWSCredentials object, with the specified AWS
17
+ * access key and AWS secret key
18
+ *
19
+ * @param string $key AWS access key ID
20
+ * @param string $secret AWS secret access key
21
+ * @param string $token Security token to use
22
+ * @param int $expires UNIX timestamp for when credentials expire
23
+ */
24
+ public function __construct($key, $secret, $token = null, $expires = null)
25
+ {
26
+ $this->key = trim($key);
27
+ $this->secret = trim($secret);
28
+ $this->token = $token;
29
+ $this->expires = $expires;
30
+ }
31
+
32
+ public static function __set_state(array $state)
33
+ {
34
+ return new self(
35
+ $state['key'],
36
+ $state['secret'],
37
+ $state['token'],
38
+ $state['expires']
39
+ );
40
+ }
41
+
42
+ public function getAccessKeyId()
43
+ {
44
+ return $this->key;
45
+ }
46
+
47
+ public function getSecretKey()
48
+ {
49
+ return $this->secret;
50
+ }
51
+
52
+ public function getSecurityToken()
53
+ {
54
+ return $this->token;
55
+ }
56
+
57
+ public function getExpiration()
58
+ {
59
+ return $this->expires;
60
+ }
61
+
62
+ public function isExpired()
63
+ {
64
+ return $this->expires !== null && time() >= $this->expires;
65
+ }
66
+
67
+ public function toArray()
68
+ {
69
+ return [
70
+ 'key' => $this->key,
71
+ 'secret' => $this->secret,
72
+ 'token' => $this->token,
73
+ 'expires' => $this->expires
74
+ ];
75
+ }
76
+
77
+ public function serialize()
78
+ {
79
+ return json_encode($this->toArray());
80
+ }
81
+
82
+ public function unserialize($serialized)
83
+ {
84
+ $data = json_decode($serialized, true);
85
+
86
+ $this->key = $data['key'];
87
+ $this->secret = $data['secret'];
88
+ $this->token = $data['token'];
89
+ $this->expires = $data['expires'];
90
+ }
91
+ }
includes/aws/Aws/Credentials/CredentialsInterface.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Credentials;
3
+
4
+ /**
5
+ * Provides access to the AWS credentials used for accessing AWS services: AWS
6
+ * access key ID, secret access key, and security token. These credentials are
7
+ * used to securely sign requests to AWS services.
8
+ */
9
+ interface CredentialsInterface
10
+ {
11
+ /**
12
+ * Returns the AWS access key ID for this credentials object.
13
+ *
14
+ * @return string
15
+ */
16
+ public function getAccessKeyId();
17
+
18
+ /**
19
+ * Returns the AWS secret access key for this credentials object.
20
+ *
21
+ * @return string
22
+ */
23
+ public function getSecretKey();
24
+
25
+ /**
26
+ * Get the associated security token if available
27
+ *
28
+ * @return string|null
29
+ */
30
+ public function getSecurityToken();
31
+
32
+ /**
33
+ * Get the UNIX timestamp in which the credentials will expire
34
+ *
35
+ * @return int|null
36
+ */
37
+ public function getExpiration();
38
+
39
+ /**
40
+ * Check if the credentials are expired
41
+ *
42
+ * @return bool
43
+ */
44
+ public function isExpired();
45
+
46
+ /**
47
+ * Converts the credentials to an associative array.
48
+ *
49
+ * @return array
50
+ */
51
+ public function toArray();
52
+ }
includes/aws/Aws/Credentials/InstanceProfileProvider.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Credentials;
3
+
4
+ use Aws\Exception\CredentialsException;
5
+ use GuzzleHttp\Promise;
6
+ use GuzzleHttp\Psr7\Request;
7
+ use GuzzleHttp\Promise\PromiseInterface;
8
+ use Psr\Http\Message\ResponseInterface;
9
+
10
+ /**
11
+ * Credential provider that provides credentials from the EC2 metadata server.
12
+ */
13
+ class InstanceProfileProvider
14
+ {
15
+ const SERVER_URI = 'http://169.254.169.254/latest/';
16
+ const CRED_PATH = 'meta-data/iam/security-credentials/';
17
+
18
+ /** @var string */
19
+ private $profile;
20
+
21
+ /** @var callable */
22
+ private $client;
23
+
24
+ /**
25
+ * The constructor accepts the following options:
26
+ *
27
+ * - timeout: Connection timeout, in seconds.
28
+ * - profile: Optional EC2 profile name, if known.
29
+ *
30
+ * @param array $config Configuration options.
31
+ */
32
+ public function __construct(array $config = [])
33
+ {
34
+ $this->timeout = isset($config['timeout']) ? $config['timeout'] : 1.0;
35
+ $this->profile = isset($config['profile']) ? $config['profile'] : null;
36
+ $this->client = isset($config['client'])
37
+ ? $config['client'] // internal use only
38
+ : \Aws\default_http_handler();
39
+ }
40
+
41
+ /**
42
+ * Loads instance profile credentials.
43
+ *
44
+ * @return PromiseInterface
45
+ */
46
+ public function __invoke()
47
+ {
48
+ return Promise\coroutine(function () {
49
+ if (!$this->profile) {
50
+ $this->profile = (yield $this->request(self::CRED_PATH));
51
+ }
52
+ $json = (yield $this->request(self::CRED_PATH . $this->profile));
53
+ $result = $this->decodeResult($json);
54
+ yield new Credentials(
55
+ $result['AccessKeyId'],
56
+ $result['SecretAccessKey'],
57
+ $result['Token'],
58
+ strtotime($result['Expiration'])
59
+ );
60
+ });
61
+ }
62
+
63
+ /**
64
+ * @param string $url
65
+ * @return PromiseInterface Returns a promise that is fulfilled with the
66
+ * body of the response as a string.
67
+ */
68
+ private function request($url)
69
+ {
70
+ $fn = $this->client;
71
+ $request = new Request('GET', self::SERVER_URI . $url);
72
+
73
+ return $fn($request, ['timeout' => $this->timeout])
74
+ ->then(function (ResponseInterface $response) {
75
+ return (string) $response->getBody();
76
+ })->otherwise(function (array $reason) {
77
+ $reason = $reason['exception'];
78
+ $msg = $reason->getMessage();
79
+ throw new CredentialsException(
80
+ $this->createErrorMessage($msg, 0, $reason)
81
+ );
82
+ });
83
+ }
84
+
85
+ private function createErrorMessage($previous)
86
+ {
87
+ return "Error retrieving credentials from the instance profile "
88
+ . "metadata server. ({$previous})";
89
+ }
90
+
91
+ private function decodeResult($response)
92
+ {
93
+ $result = json_decode($response, true);
94
+
95
+ if ($result['Code'] !== 'Success') {
96
+ throw new CredentialsException('Unexpected instance profile '
97
+ . 'response code: ' . $result['Code']);
98
+ }
99
+
100
+ return $result;
101
+ }
102
+ }
includes/aws/Aws/DataPipeline/DataPipelineClient.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\DataPipeline;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * This client is used to interact with the **AWS Data Pipeline** service.
8
+ *
9
+ * @method \Aws\Result activatePipeline(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise activatePipelineAsync(array $args = [])
11
+ * @method \Aws\Result addTags(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise addTagsAsync(array $args = [])
13
+ * @method \Aws\Result createPipeline(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise createPipelineAsync(array $args = [])
15
+ * @method \Aws\Result deactivatePipeline(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise deactivatePipelineAsync(array $args = [])
17
+ * @method \Aws\Result deletePipeline(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise deletePipelineAsync(array $args = [])
19
+ * @method \Aws\Result describeObjects(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise describeObjectsAsync(array $args = [])
21
+ * @method \Aws\Result describePipelines(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise describePipelinesAsync(array $args = [])
23
+ * @method \Aws\Result evaluateExpression(array $args = [])
24
+ * @method \GuzzleHttp\Promise\Promise evaluateExpressionAsync(array $args = [])
25
+ * @method \Aws\Result getPipelineDefinition(array $args = [])
26
+ * @method \GuzzleHttp\Promise\Promise getPipelineDefinitionAsync(array $args = [])
27
+ * @method \Aws\Result listPipelines(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise listPipelinesAsync(array $args = [])
29
+ * @method \Aws\Result pollForTask(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise pollForTaskAsync(array $args = [])
31
+ * @method \Aws\Result putPipelineDefinition(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise putPipelineDefinitionAsync(array $args = [])
33
+ * @method \Aws\Result queryObjects(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise queryObjectsAsync(array $args = [])
35
+ * @method \Aws\Result removeTags(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise removeTagsAsync(array $args = [])
37
+ * @method \Aws\Result reportTaskProgress(array $args = [])
38
+ * @method \GuzzleHttp\Promise\Promise reportTaskProgressAsync(array $args = [])
39
+ * @method \Aws\Result reportTaskRunnerHeartbeat(array $args = [])
40
+ * @method \GuzzleHttp\Promise\Promise reportTaskRunnerHeartbeatAsync(array $args = [])
41
+ * @method \Aws\Result setStatus(array $args = [])
42
+ * @method \GuzzleHttp\Promise\Promise setStatusAsync(array $args = [])
43
+ * @method \Aws\Result setTaskStatus(array $args = [])
44
+ * @method \GuzzleHttp\Promise\Promise setTaskStatusAsync(array $args = [])
45
+ * @method \Aws\Result validatePipelineDefinition(array $args = [])
46
+ * @method \GuzzleHttp\Promise\Promise validatePipelineDefinitionAsync(array $args = [])
47
+ */
48
+ class DataPipelineClient extends AwsClient {}
includes/aws/Aws/DataPipeline/Exception/DataPipelineException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\DataPipeline\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the AWS Data Pipeline service.
8
+ */
9
+ class DataPipelineException extends AwsException {}
includes/aws/Aws/DirectConnect/DirectConnectClient.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\DirectConnect;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * This client is used to interact with the **AWS Direct Connect** service.
8
+ *
9
+ * @method \Aws\Result allocateConnectionOnInterconnect(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise allocateConnectionOnInterconnectAsync(array $args = [])
11
+ * @method \Aws\Result allocatePrivateVirtualInterface(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise allocatePrivateVirtualInterfaceAsync(array $args = [])
13
+ * @method \Aws\Result allocatePublicVirtualInterface(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise allocatePublicVirtualInterfaceAsync(array $args = [])
15
+ * @method \Aws\Result confirmConnection(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise confirmConnectionAsync(array $args = [])
17
+ * @method \Aws\Result confirmPrivateVirtualInterface(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise confirmPrivateVirtualInterfaceAsync(array $args = [])
19
+ * @method \Aws\Result confirmPublicVirtualInterface(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise confirmPublicVirtualInterfaceAsync(array $args = [])
21
+ * @method \Aws\Result createConnection(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise createConnectionAsync(array $args = [])
23
+ * @method \Aws\Result createInterconnect(array $args = [])
24
+ * @method \GuzzleHttp\Promise\Promise createInterconnectAsync(array $args = [])
25
+ * @method \Aws\Result createPrivateVirtualInterface(array $args = [])
26
+ * @method \GuzzleHttp\Promise\Promise createPrivateVirtualInterfaceAsync(array $args = [])
27
+ * @method \Aws\Result createPublicVirtualInterface(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise createPublicVirtualInterfaceAsync(array $args = [])
29
+ * @method \Aws\Result deleteConnection(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise deleteConnectionAsync(array $args = [])
31
+ * @method \Aws\Result deleteInterconnect(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise deleteInterconnectAsync(array $args = [])
33
+ * @method \Aws\Result deleteVirtualInterface(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise deleteVirtualInterfaceAsync(array $args = [])
35
+ * @method \Aws\Result describeConnections(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise describeConnectionsAsync(array $args = [])
37
+ * @method \Aws\Result describeConnectionsOnInterconnect(array $args = [])
38
+ * @method \GuzzleHttp\Promise\Promise describeConnectionsOnInterconnectAsync(array $args = [])
39
+ * @method \Aws\Result describeInterconnects(array $args = [])
40
+ * @method \GuzzleHttp\Promise\Promise describeInterconnectsAsync(array $args = [])
41
+ * @method \Aws\Result describeLocations(array $args = [])
42
+ * @method \GuzzleHttp\Promise\Promise describeLocationsAsync(array $args = [])
43
+ * @method \Aws\Result describeVirtualGateways(array $args = [])
44
+ * @method \GuzzleHttp\Promise\Promise describeVirtualGatewaysAsync(array $args = [])
45
+ * @method \Aws\Result describeVirtualInterfaces(array $args = [])
46
+ * @method \GuzzleHttp\Promise\Promise describeVirtualInterfacesAsync(array $args = [])
47
+ */
48
+ class DirectConnectClient extends AwsClient {}
includes/aws/Aws/DirectConnect/Exception/DirectConnectException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\DirectConnect\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the AWS Direct Connect service.
8
+ */
9
+ class DirectConnectException extends AwsException {}
includes/aws/Aws/DirectoryService/DirectoryServiceClient.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\DirectoryService;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * AWS Directory Service client
8
+ *
9
+ * @method \Aws\Result connectDirectory(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise connectDirectoryAsync(array $args = [])
11
+ * @method \Aws\Result createAlias(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise createAliasAsync(array $args = [])
13
+ * @method \Aws\Result createComputer(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise createComputerAsync(array $args = [])
15
+ * @method \Aws\Result createDirectory(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise createDirectoryAsync(array $args = [])
17
+ * @method \Aws\Result createMicrosoftAD(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise createMicrosoftADAsync(array $args = [])
19
+ * @method \Aws\Result createSnapshot(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise createSnapshotAsync(array $args = [])
21
+ * @method \Aws\Result createTrust(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise createTrustAsync(array $args = [])
23
+ * @method \Aws\Result deleteDirectory(array $args = [])
24
+ * @method \GuzzleHttp\Promise\Promise deleteDirectoryAsync(array $args = [])
25
+ * @method \Aws\Result deleteSnapshot(array $args = [])
26
+ * @method \GuzzleHttp\Promise\Promise deleteSnapshotAsync(array $args = [])
27
+ * @method \Aws\Result deleteTrust(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise deleteTrustAsync(array $args = [])
29
+ * @method \Aws\Result describeDirectories(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise describeDirectoriesAsync(array $args = [])
31
+ * @method \Aws\Result describeSnapshots(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise describeSnapshotsAsync(array $args = [])
33
+ * @method \Aws\Result describeTrusts(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise describeTrustsAsync(array $args = [])
35
+ * @method \Aws\Result disableRadius(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise disableRadiusAsync(array $args = [])
37
+ * @method \Aws\Result disableSso(array $args = [])
38
+ * @method \GuzzleHttp\Promise\Promise disableSsoAsync(array $args = [])
39
+ * @method \Aws\Result enableRadius(array $args = [])
40
+ * @method \GuzzleHttp\Promise\Promise enableRadiusAsync(array $args = [])
41
+ * @method \Aws\Result enableSso(array $args = [])
42
+ * @method \GuzzleHttp\Promise\Promise enableSsoAsync(array $args = [])
43
+ * @method \Aws\Result getDirectoryLimits(array $args = [])
44
+ * @method \GuzzleHttp\Promise\Promise getDirectoryLimitsAsync(array $args = [])
45
+ * @method \Aws\Result getSnapshotLimits(array $args = [])
46
+ * @method \GuzzleHttp\Promise\Promise getSnapshotLimitsAsync(array $args = [])
47
+ * @method \Aws\Result restoreFromSnapshot(array $args = [])
48
+ * @method \GuzzleHttp\Promise\Promise restoreFromSnapshotAsync(array $args = [])
49
+ * @method \Aws\Result updateRadius(array $args = [])
50
+ * @method \GuzzleHttp\Promise\Promise updateRadiusAsync(array $args = [])
51
+ * @method \Aws\Result verifyTrust(array $args = [])
52
+ * @method \GuzzleHttp\Promise\Promise verifyTrustAsync(array $args = [])
53
+ */
54
+ class DirectoryServiceClient extends AwsClient {}
includes/aws/Aws/DirectoryService/Exception/DirectoryServiceException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\DirectoryService\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * AWS Directory Service Exception
8
+ */
9
+ class DirectoryServiceException extends AwsException {}
includes/aws/Aws/DoctrineCacheAdapter.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Doctrine\Common\Cache\Cache;
5
+
6
+ class DoctrineCacheAdapter implements CacheInterface, Cache
7
+ {
8
+ /** @var Cache */
9
+ private $cache;
10
+
11
+ public function __construct(Cache $cache)
12
+ {
13
+ $this->cache = $cache;
14
+ }
15
+
16
+ public function get($key)
17
+ {
18
+ return $this->cache->fetch($key);
19
+ }
20
+
21
+ public function fetch($key)
22
+ {
23
+ return $this->get($key);
24
+ }
25
+
26
+ public function set($key, $value, $ttl = 0)
27
+ {
28
+ return $this->cache->save($key, $value, $ttl);
29
+ }
30
+
31
+ public function save($key, $value, $ttl = 0)
32
+ {
33
+ return $this->set($key, $value, $ttl);
34
+ }
35
+
36
+ public function remove($key)
37
+ {
38
+ return $this->cache->delete($key);
39
+ }
40
+
41
+ public function delete($key)
42
+ {
43
+ return $this->remove($key);
44
+ }
45
+
46
+ public function contains($key)
47
+ {
48
+ return $this->cache->contains($key);
49
+ }
50
+
51
+ public function getStats()
52
+ {
53
+ return $this->cache->getStats();
54
+ }
55
+ }
includes/aws/Aws/Endpoint/EndpointProvider.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Endpoint;
3
+
4
+ use Aws\Exception\UnresolvedEndpointException;
5
+
6
+ /**
7
+ * Endpoint providers.
8
+ *
9
+ * An endpoint provider is a function that accepts a hash of endpoint options,
10
+ * including but not limited to "service" and "region" key value pairs. The
11
+ * endpoint provider function returns a hash of endpoint data, which MUST
12
+ * include an "endpoint" key value pair that represents the resolved endpoint
13
+ * or NULL if an endpoint cannot be determined.
14
+ *
15
+ * You can wrap your calls to an endpoint provider with the
16
+ * {@see EndpointProvider::resolve} function to ensure that an endpoint hash is
17
+ * created. If an endpoint hash is not created, then the resolve() function
18
+ * will throw an {@see Aws\Exception\UnresolvedEndpointException}.
19
+ *
20
+ * use Aws\Endpoint\EndpointProvider;
21
+ * $provider = EndpointProvider::defaultProvider();
22
+ * // Returns an array or NULL.
23
+ * $endpoint = $provider(['service' => 'ec2', 'region' => 'us-west-2']);
24
+ * // Returns an endpoint array or throws.
25
+ * $endpoint = EndpointProvider::resolve($provider, [
26
+ * 'service' => 'ec2',
27
+ * 'region' => 'us-west-2'
28
+ * ]);
29
+ *
30
+ * You can compose multiple providers into a single provider using
31
+ * {@see Aws\or_chain}. This function accepts providers as arguments and
32
+ * returns a new function that will invoke each provider until a non-null value
33
+ * is returned.
34
+ *
35
+ * $a = function (array $args) {
36
+ * if ($args['region'] === 'my-test-region') {
37
+ * return ['endpoint' => 'http://localhost:123/api'];
38
+ * }
39
+ * };
40
+ * $b = EndpointProvider::defaultProvider();
41
+ * $c = \Aws\or_chain($a, $b);
42
+ * $config = ['service' => 'ec2', 'region' => 'my-test-region'];
43
+ * $res = $c($config); // $a handles this.
44
+ * $config['region'] = 'us-west-2';
45
+ * $res = $c($config); // $b handles this.
46
+ */
47
+ class EndpointProvider
48
+ {
49
+ /**
50
+ * Resolves and endpoint provider and ensures a non-null return value.
51
+ *
52
+ * @param callable $provider Provider function to invoke.
53
+ * @param array $args Endpoint arguments to pass to the provider.
54
+ *
55
+ * @return array
56
+ * @throws UnresolvedEndpointException
57
+ */
58
+ public static function resolve(callable $provider, array $args = [])
59
+ {
60
+ $result = $provider($args);
61
+ if (is_array($result)) {
62
+ return $result;
63
+ }
64
+
65
+ throw new UnresolvedEndpointException(
66
+ 'Unable to resolve an endpoint using the provider arguments: '
67
+ . json_encode($args) . '. Note: you can provide an "endpoint" '
68
+ . 'option to a client constructor to bypass invoking an endpoint '
69
+ . 'provider.');
70
+ }
71
+
72
+ /**
73
+ * Creates and returns the default SDK endpoint provider.
74
+ *
75
+ * @return callable
76
+ */
77
+ public static function defaultProvider()
78
+ {
79
+ $data = \Aws\load_compiled_json(__DIR__ . '/../data/endpoints.json');
80
+
81
+ return new PatternEndpointProvider($data['endpoints']);
82
+ }
83
+
84
+ /**
85
+ * Creates and returns an endpoint provider that uses patterns from an
86
+ * array.
87
+ *
88
+ * @param array $patterns Endpoint patterns
89
+ *
90
+ * @return callable
91
+ */
92
+ public static function patterns(array $patterns)
93
+ {
94
+ return new PatternEndpointProvider($patterns);
95
+ }
96
+ }
includes/aws/Aws/Endpoint/PatternEndpointProvider.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Endpoint;
3
+
4
+ /**
5
+ * Provides endpoints based on an endpoint pattern configuration array.
6
+ */
7
+ class PatternEndpointProvider
8
+ {
9
+ /** @var array */
10
+ private $patterns;
11
+
12
+ /**
13
+ * @param array $patterns Hash of endpoint patterns mapping to endpoint
14
+ * configurations.
15
+ */
16
+ public function __construct(array $patterns)
17
+ {
18
+ $this->patterns = $patterns;
19
+ }
20
+
21
+ public function __invoke(array $args = [])
22
+ {
23
+ $service = isset($args['service']) ? $args['service'] : '';
24
+ $region = isset($args['region']) ? $args['region'] : '';
25
+ $keys = ["{$region}/{$service}", "{$region}/*", "*/{$service}", "*/*"];
26
+
27
+ foreach ($keys as $key) {
28
+ if (isset($this->patterns[$key])) {
29
+ return $this->expand(
30
+ $this->patterns[$key],
31
+ isset($args['scheme']) ? $args['scheme'] : 'https',
32
+ $service,
33
+ $region
34
+ );
35
+ }
36
+ }
37
+
38
+ return null;
39
+ }
40
+
41
+ private function expand(array $config, $scheme, $service, $region)
42
+ {
43
+ $config['endpoint'] = $scheme . '://'
44
+ . strtr($config['endpoint'], [
45
+ '{service}' => $service,
46
+ '{region}' => $region
47
+ ]);
48
+
49
+ return $config;
50
+ }
51
+ }
includes/aws/Aws/Exception/AwsException.php ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Exception;
3
+
4
+ use Psr\Http\Message\ResponseInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use Aws\CommandInterface;
7
+ use Aws\ResultInterface;
8
+
9
+ /**
10
+ * Represents an AWS exception that is thrown when a command fails.
11
+ */
12
+ class AwsException extends \RuntimeException
13
+ {
14
+ /** @var ResponseInterface */
15
+ private $response;
16
+ private $request;
17
+ private $result;
18
+ private $command;
19
+ private $requestId;
20
+ private $errorType;
21
+ private $errorCode;
22
+ private $connectionError;
23
+
24
+ /**
25
+ * @param string $message Exception message
26
+ * @param CommandInterface $command
27
+ * @param array $context Exception context
28
+ * @param \Exception $previous Previous exception (if any)
29
+ */
30
+ public function __construct(
31
+ $message,
32
+ CommandInterface $command,
33
+ array $context = [],
34
+ \Exception $previous = null
35
+ ) {
36
+ $this->command = $command;
37
+ $this->response = isset($context['response']) ? $context['response'] : null;
38
+ $this->request = isset($context['request']) ? $context['request'] : null;
39
+ $this->requestId = isset($context['request_id'])
40
+ ? $context['request_id']
41
+ : null;
42
+ $this->errorType = isset($context['type']) ? $context['type'] : null;
43
+ $this->errorCode = isset($context['code']) ? $context['code'] : null;
44
+ $this->connectionError = !empty($context['connection_error']);
45
+ $this->result = isset($context['result']) ? $context['result'] : null;
46
+ parent::__construct($message, 0, $previous);
47
+ }
48
+
49
+ public function __toString()
50
+ {
51
+ if (!$this->getPrevious()) {
52
+ return parent::__toString();
53
+ }
54
+
55
+ // PHP strangely shows the innermost exception first before the outer
56
+ // exception message. It also has a default character limit for
57
+ // exception message strings such that the "next" exception (this one)
58
+ // might not even get shown, causing developers to attempt to catch
59
+ // the inner exception instead of the actual exception because they
60
+ // can't see the outer exception's __toString output.
61
+ return sprintf(
62
+ "exception '%s' with message '%s'\n\n%s",
63
+ get_class($this),
64
+ $this->getMessage(),
65
+ parent::__toString()
66
+ );
67
+ }
68
+
69
+ /**
70
+ * Get the command that was executed.
71
+ *
72
+ * @return CommandInterface
73
+ */
74
+ public function getCommand()
75
+ {
76
+ return $this->command;
77
+ }
78
+
79
+ /**
80
+ * Get the sent HTTP request if any.
81
+ *
82
+ * @return RequestInterface|null
83
+ */
84
+ public function getRequest()
85
+ {
86
+ return $this->request;
87
+ }
88
+
89
+ /**
90
+ * Get the received HTTP response if any.
91
+ *
92
+ * @return ResponseInterface|null
93
+ */
94
+ public function getResponse()
95
+ {
96
+ return $this->response;
97
+ }
98
+
99
+ /**
100
+ * Get the result of the exception if available
101
+ *
102
+ * @return ResultInterface|null
103
+ */
104
+ public function getResult()
105
+ {
106
+ return $this->result;
107
+ }
108
+
109
+ /**
110
+ * Returns true if this is a connection error.
111
+ *
112
+ * @return bool
113
+ */
114
+ public function isConnectionError()
115
+ {
116
+ return $this->connectionError;
117
+ }
118
+
119
+ /**
120
+ * If available, gets the HTTP status code of the corresponding response
121
+ *
122
+ * @return int|null
123
+ */
124
+ public function getStatusCode()
125
+ {
126
+ return $this->response ? $this->response->getStatusCode() : null;
127
+ }
128
+
129
+ /**
130
+ * Get the request ID of the error. This value is only present if a
131
+ * response was received and is not present in the event of a networking
132
+ * error.
133
+ *
134
+ * @return string|null Returns null if no response was received
135
+ */
136
+ public function getAwsRequestId()
137
+ {
138
+ return $this->requestId;
139
+ }
140
+
141
+ /**
142
+ * Get the AWS error type.
143
+ *
144
+ * @return string|null Returns null if no response was received
145
+ */
146
+ public function getAwsErrorType()
147
+ {
148
+ return $this->errorType;
149
+ }
150
+
151
+ /**
152
+ * Get the AWS error code.
153
+ *
154
+ * @return string|null Returns null if no response was received
155
+ */
156
+ public function getAwsErrorCode()
157
+ {
158
+ return $this->errorCode;
159
+ }
160
+ }
includes/aws/Aws/Exception/CouldNotCreateChecksumException.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Exception;
3
+
4
+ class CouldNotCreateChecksumException extends \RuntimeException
5
+ {
6
+ public function __construct($algorithm, \Exception $previous = null)
7
+ {
8
+ $prefix = $algorithm === 'md5' ? "An" : "A";
9
+ parent::__construct("{$prefix} {$algorithm} checksum could not be "
10
+ . "calculated for the provided upload body, because it was not "
11
+ . "seekable. To prevent this error you can either 1) include the "
12
+ . "ContentMD5 or ContentSHA256 parameters with your request, 2) "
13
+ . "use a seekable stream for the body, or 3) wrap the non-seekable "
14
+ . "stream in a GuzzleHttp\\Psr7\\CachingStream object. You "
15
+ . "should be careful though and remember that the CachingStream "
16
+ . "utilizes PHP temp streams. This means that the stream will be "
17
+ . "temporarily stored on the local disk.", 0, $previous);
18
+ }
19
+ }
includes/aws/Aws/Exception/CredentialsException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace Aws\Exception;
3
+
4
+ class CredentialsException extends \RuntimeException {}
includes/aws/Aws/Exception/MultipartUploadException.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Exception;
3
+
4
+ use Aws\Multipart\UploadState;
5
+
6
+ class MultipartUploadException extends \RuntimeException
7
+ {
8
+ /** @var UploadState State of the erroneous transfer */
9
+ private $state;
10
+
11
+ /**
12
+ * @param UploadState $state Upload state at time of the exception.
13
+ * @param \Exception|array $prev Exception being thrown.
14
+ */
15
+ public function __construct(UploadState $state, $prev = null) {
16
+ $msg = 'An exception occurred while performing a multipart upload.';
17
+
18
+ if (is_array($prev)) {
19
+ $msg = strtr($msg, ['performing' => 'uploading parts to']);
20
+ $msg .= " The following parts had errors:\n";
21
+ /** @var $error AwsException */
22
+ foreach ($prev as $part => $error) {
23
+ $msg .= "- Part {$part}: " . $error->getMessage(). "\n";
24
+ }
25
+ } elseif ($prev instanceof AwsException) {
26
+ switch ($prev->getCommand()->getName()) {
27
+ case 'CreateMultipartUpload':
28
+ case 'InitiateMultipartUpload':
29
+ $action = 'initiating';
30
+ break;
31
+ case 'CompleteMultipartUpload':
32
+ $action = 'completing';
33
+ break;
34
+ }
35
+ if (isset($action)) {
36
+ $msg = strtr($msg, ['performing' => $action]);
37
+ }
38
+ }
39
+
40
+ if (!$prev instanceof \Exception) {
41
+ $prev = null;
42
+ }
43
+
44
+ parent::__construct($msg, 0, $prev);
45
+ $this->state = $state;
46
+ }
47
+
48
+ /**
49
+ * Get the state of the transfer
50
+ *
51
+ * @return UploadState
52
+ */
53
+ public function getState()
54
+ {
55
+ return $this->state;
56
+ }
57
+ }
includes/aws/Aws/Exception/UnresolvedApiException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace Aws\Exception;
3
+
4
+ class UnresolvedApiException extends \RuntimeException {}
includes/aws/Aws/Exception/UnresolvedEndpointException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace Aws\Exception;
3
+
4
+ class UnresolvedEndpointException extends \RuntimeException {}
includes/aws/Aws/Exception/UnresolvedSignatureException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace Aws\Exception;
3
+
4
+ class UnresolvedSignatureException extends \RuntimeException {}
includes/aws/Aws/Firehose/Exception/FirehoseException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Firehose\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the **Amazon Kinesis Firehose** service.
8
+ */
9
+ class FirehoseException extends AwsException {}
includes/aws/Aws/Firehose/FirehoseClient.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Firehose;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * This client is used to interact with the **Amazon Kinesis Firehose** service.
8
+ *
9
+ * @method \Aws\Result createDeliveryStream(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise createDeliveryStreamAsync(array $args = [])
11
+ * @method \Aws\Result deleteDeliveryStream(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise deleteDeliveryStreamAsync(array $args = [])
13
+ * @method \Aws\Result describeDeliveryStream(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise describeDeliveryStreamAsync(array $args = [])
15
+ * @method \Aws\Result listDeliveryStreams(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise listDeliveryStreamsAsync(array $args = [])
17
+ * @method \Aws\Result putRecord(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise putRecordAsync(array $args = [])
19
+ * @method \Aws\Result putRecordBatch(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise putRecordBatchAsync(array $args = [])
21
+ * @method \Aws\Result updateDestination(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise updateDestinationAsync(array $args = [])
23
+ */
24
+ class FirehoseClient extends AwsClient {}
includes/aws/Aws/Glacier/Exception/GlacierException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Glacier\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the Amazon Glacier service.
8
+ */
9
+ class GlacierException extends AwsException {}
includes/aws/Aws/Glacier/GlacierClient.php ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Glacier;
3
+
4
+ use Aws\Api\ApiProvider;
5
+ use Aws\Api\DocModel;
6
+ use Aws\Api\Service;
7
+ use Aws\AwsClient;
8
+ use Aws\CommandInterface;
9
+ use Aws\Exception\CouldNotCreateChecksumException;
10
+ use Aws\HashingStream;
11
+ use Aws\Middleware;
12
+ use Aws\PhpHash;
13
+ use Psr\Http\Message\RequestInterface;
14
+
15
+ /**
16
+ * This client is used to interact with the **Amazon Glacier** service.
17
+ *
18
+ * @method \Aws\Result abortMultipartUpload(array $args = [])
19
+ * @method \GuzzleHttp\Promise\Promise abortMultipartUploadAsync(array $args = [])
20
+ * @method \Aws\Result abortVaultLock(array $args = [])
21
+ * @method \GuzzleHttp\Promise\Promise abortVaultLockAsync(array $args = [])
22
+ * @method \Aws\Result addTagsToVault(array $args = [])
23
+ * @method \GuzzleHttp\Promise\Promise addTagsToVaultAsync(array $args = [])
24
+ * @method \Aws\Result completeMultipartUpload(array $args = [])
25
+ * @method \GuzzleHttp\Promise\Promise completeMultipartUploadAsync(array $args = [])
26
+ * @method \Aws\Result completeVaultLock(array $args = [])
27
+ * @method \GuzzleHttp\Promise\Promise completeVaultLockAsync(array $args = [])
28
+ * @method \Aws\Result createVault(array $args = [])
29
+ * @method \GuzzleHttp\Promise\Promise createVaultAsync(array $args = [])
30
+ * @method \Aws\Result deleteArchive(array $args = [])
31
+ * @method \GuzzleHttp\Promise\Promise deleteArchiveAsync(array $args = [])
32
+ * @method \Aws\Result deleteVault(array $args = [])
33
+ * @method \GuzzleHttp\Promise\Promise deleteVaultAsync(array $args = [])
34
+ * @method \Aws\Result deleteVaultAccessPolicy(array $args = [])
35
+ * @method \GuzzleHttp\Promise\Promise deleteVaultAccessPolicyAsync(array $args = [])
36
+ * @method \Aws\Result deleteVaultNotifications(array $args = [])
37
+ * @method \GuzzleHttp\Promise\Promise deleteVaultNotificationsAsync(array $args = [])
38
+ * @method \Aws\Result describeJob(array $args = [])
39
+ * @method \GuzzleHttp\Promise\Promise describeJobAsync(array $args = [])
40
+ * @method \Aws\Result describeVault(array $args = [])
41
+ * @method \GuzzleHttp\Promise\Promise describeVaultAsync(array $args = [])
42
+ * @method \Aws\Result getDataRetrievalPolicy(array $args = [])
43
+ * @method \GuzzleHttp\Promise\Promise getDataRetrievalPolicyAsync(array $args = [])
44
+ * @method \Aws\Result getJobOutput(array $args = [])
45
+ * @method \GuzzleHttp\Promise\Promise getJobOutputAsync(array $args = [])
46
+ * @method \Aws\Result getVaultAccessPolicy(array $args = [])
47
+ * @method \GuzzleHttp\Promise\Promise getVaultAccessPolicyAsync(array $args = [])
48
+ * @method \Aws\Result getVaultLock(array $args = [])
49
+ * @method \GuzzleHttp\Promise\Promise getVaultLockAsync(array $args = [])
50
+ * @method \Aws\Result getVaultNotifications(array $args = [])
51
+ * @method \GuzzleHttp\Promise\Promise getVaultNotificationsAsync(array $args = [])
52
+ * @method \Aws\Result initiateJob(array $args = [])
53
+ * @method \GuzzleHttp\Promise\Promise initiateJobAsync(array $args = [])
54
+ * @method \Aws\Result initiateMultipartUpload(array $args = [])
55
+ * @method \GuzzleHttp\Promise\Promise initiateMultipartUploadAsync(array $args = [])
56
+ * @method \Aws\Result initiateVaultLock(array $args = [])
57
+ * @method \GuzzleHttp\Promise\Promise initiateVaultLockAsync(array $args = [])
58
+ * @method \Aws\Result listJobs(array $args = [])
59
+ * @method \GuzzleHttp\Promise\Promise listJobsAsync(array $args = [])
60
+ * @method \Aws\Result listMultipartUploads(array $args = [])
61
+ * @method \GuzzleHttp\Promise\Promise listMultipartUploadsAsync(array $args = [])
62
+ * @method \Aws\Result listParts(array $args = [])
63
+ * @method \GuzzleHttp\Promise\Promise listPartsAsync(array $args = [])
64
+ * @method \Aws\Result listTagsForVault(array $args = [])
65
+ * @method \GuzzleHttp\Promise\Promise listTagsForVaultAsync(array $args = [])
66
+ * @method \Aws\Result listVaults(array $args = [])
67
+ * @method \GuzzleHttp\Promise\Promise listVaultsAsync(array $args = [])
68
+ * @method \Aws\Result removeTagsFromVault(array $args = [])
69
+ * @method \GuzzleHttp\Promise\Promise removeTagsFromVaultAsync(array $args = [])
70
+ * @method \Aws\Result setDataRetrievalPolicy(array $args = [])
71
+ * @method \GuzzleHttp\Promise\Promise setDataRetrievalPolicyAsync(array $args = [])
72
+ * @method \Aws\Result setVaultAccessPolicy(array $args = [])
73
+ * @method \GuzzleHttp\Promise\Promise setVaultAccessPolicyAsync(array $args = [])
74
+ * @method \Aws\Result setVaultNotifications(array $args = [])
75
+ * @method \GuzzleHttp\Promise\Promise setVaultNotificationsAsync(array $args = [])
76
+ * @method \Aws\Result uploadArchive(array $args = [])
77
+ * @method \GuzzleHttp\Promise\Promise uploadArchiveAsync(array $args = [])
78
+ * @method \Aws\Result uploadMultipartPart(array $args = [])
79
+ * @method \GuzzleHttp\Promise\Promise uploadMultipartPartAsync(array $args = [])
80
+ */
81
+ class GlacierClient extends AwsClient
82
+ {
83
+ public function __construct(array $args)
84
+ {
85
+ parent::__construct($args);
86
+
87
+ // Setup middleware.
88
+ $stack = $this->getHandlerList();
89
+ $stack->appendBuild($this->getApiVersionMiddleware(), 'glacier.api_version');
90
+ $stack->appendBuild($this->getChecksumsMiddleware(), 'glacier.checksum');
91
+ $stack->appendBuild(
92
+ Middleware::contentType(['UploadArchive', 'UploadPart']),
93
+ 'glacier.content_type'
94
+ );
95
+ $stack->appendInit(
96
+ Middleware::sourceFile($this->getApi(), 'body', 'sourceFile'),
97
+ 'glacier.source_file'
98
+ );
99
+ }
100
+
101
+ /**
102
+ * {@inheritdoc}
103
+ *
104
+ * Sets the default accountId to "-" for all operations.
105
+ */
106
+ public function getCommand($name, array $args = [])
107
+ {
108
+ return parent::getCommand($name, $args + ['accountId' => '-']);
109
+ }
110
+
111
+ /**
112
+ * Creates a middleware that updates a command with the content and tree
113
+ * hash headers for upload operations.
114
+ *
115
+ * @return callable
116
+ * @throws CouldNotCreateChecksumException if the body is not seekable.
117
+ */
118
+ private function getChecksumsMiddleware()
119
+ {
120
+ return function (callable $handler) {
121
+ return function (
122
+ CommandInterface $command,
123
+ RequestInterface $request = null
124
+ ) use ($handler) {
125
+ // Accept "ContentSHA256" with a lowercase "c" to match other Glacier params.
126
+ if (!$command['ContentSHA256'] && $command['contentSHA256']) {
127
+ $command['ContentSHA256'] = $command['contentSHA256'];
128
+ unset($command['contentSHA256']);
129
+ }
130
+
131
+ // If uploading, then make sure checksums are added.
132
+ $name = $command->getName();
133
+ if (($name === 'UploadArchive' || $name === 'UploadMultipartPart')
134
+ && (!$command['checksum'] || !$command['ContentSHA256'])
135
+ ) {
136
+ $body = $request->getBody();
137
+ if (!$body->isSeekable()) {
138
+ throw new CouldNotCreateChecksumException('sha256');
139
+ }
140
+
141
+ // Add a tree hash if not provided.
142
+ if (!$command['checksum']) {
143
+ $body = new HashingStream(
144
+ $body, new TreeHash(),
145
+ function ($result) use ($command, &$request) {
146
+ $request = $request->withHeader(
147
+ 'x-amz-sha256-tree-hash',
148
+ bin2hex($result)
149
+ );
150
+ }
151
+ );
152
+ }
153
+
154
+ // Add a linear content hash if not provided.
155
+ if (!$command['ContentSHA256']) {
156
+ $body = new HashingStream(
157
+ $body, new PhpHash('sha256'),
158
+ function ($result) use ($command) {
159
+ $command['ContentSHA256'] = bin2hex($result);
160
+ }
161
+ );
162
+ }
163
+
164
+ // Read the stream in order to calculate the hashes.
165
+ while (!$body->eof()) {
166
+ $body->read(1048576);
167
+ }
168
+ $body->seek(0);
169
+ }
170
+
171
+ // Set the content hash header if a value is in the command.
172
+ if ($command['ContentSHA256']) {
173
+ $request = $request->withHeader(
174
+ 'x-amz-content-sha256',
175
+ $command['ContentSHA256']
176
+ );
177
+ }
178
+
179
+ return $handler($command, $request);
180
+ };
181
+ };
182
+ }
183
+
184
+ /**
185
+ * Creates a middleware that adds the API version header for all requests.
186
+ *
187
+ * @return callable
188
+ */
189
+ private function getApiVersionMiddleware()
190
+ {
191
+ return function (callable $handler) {
192
+ return function (
193
+ CommandInterface $command,
194
+ RequestInterface $request = null
195
+ ) use ($handler) {
196
+ return $handler($command, $request->withHeader(
197
+ 'x-amz-glacier-version',
198
+ $this->getApi()->getMetadata('apiVersion')
199
+ ));
200
+ };
201
+ };
202
+ }
203
+
204
+ /**
205
+ * @internal
206
+ * @codeCoverageIgnore
207
+ */
208
+ public static function applyDocFilters(array $api, array $docs)
209
+ {
210
+ // Add the SourceFile parameter.
211
+ $docs['shapes']['SourceFile']['base'] = 'The path to a file on disk to use instead of the body parameter.';
212
+ $api['shapes']['SourceFile'] = ['type' => 'string'];
213
+ $api['shapes']['UploadArchiveInput']['members']['sourceFile'] = ['shape' => 'SourceFile'];
214
+ $api['shapes']['UploadMultipartPartInput']['members']['sourceFile'] = ['shape' => 'SourceFile'];
215
+
216
+ // Add the ContentSHA256 parameter.
217
+ $docs['shapes']['ContentSHA256']['base'] = 'A SHA256 hash of the content of the request body';
218
+ $api['shapes']['ContentSHA256'] = ['type' => 'string'];
219
+ $api['shapes']['UploadArchiveInput']['members']['contentSHA256'] = ['shape' => 'ContentSHA256'];
220
+ $api['shapes']['UploadMultipartPartInput']['members']['contentSHA256'] = ['shape' => 'ContentSHA256'];
221
+
222
+ // Add information about "checksum" and "ContentSHA256" being optional.
223
+ $optional = '<div class="alert alert-info">The SDK will compute this value '
224
+ . 'for you on your behalf if it is not supplied.</div>';
225
+ $docs['shapes']['checksum']['append'] = $optional;
226
+ $docs['shapes']['ContentSHA256']['append'] = $optional;
227
+
228
+ // Make "accountId" optional for all operations.
229
+ foreach ($api['operations'] as $operation) {
230
+ $inputShape =& $api['shapes'][$operation['input']['shape']];
231
+ $accountIdIndex = array_search('accountId', $inputShape['required']);
232
+ unset($inputShape['required'][$accountIdIndex]);
233
+ }
234
+ // Add information about the default value for "accountId".
235
+ $optional = '<div class="alert alert-info">The SDK will set this value to "-" by default.</div>';
236
+ foreach ($docs['shapes']['string']['refs'] as $name => &$ref) {
237
+ if (strpos($name, 'accountId')) {
238
+ $ref .= $optional;
239
+ }
240
+ }
241
+
242
+ return [
243
+ new Service($api, ApiProvider::defaultProvider()),
244
+ new DocModel($docs)
245
+ ];
246
+ }
247
+ }
includes/aws/Aws/Glacier/MultipartUploader.php ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Glacier;
3
+
4
+ use Aws\CommandInterface;
5
+ use Aws\HashingStream;
6
+ use Aws\Multipart\AbstractUploader;
7
+ use Aws\Multipart\UploadState;
8
+ use Aws\PhpHash;
9
+ use Aws\ResultInterface;
10
+ use GuzzleHttp\Psr7;
11
+ use Psr\Http\Message\StreamInterface as Stream;
12
+
13
+ /**
14
+ * Encapsulates the execution of a multipart upload to Glacier.
15
+ */
16
+ class MultipartUploader extends AbstractUploader
17
+ {
18
+ const PART_MIN_SIZE = 1048576;
19
+
20
+ private static $validPartSizes = [
21
+ 1048576, // 1 MB
22
+ 2097152, // 2 MB
23
+ 4194304, // 4 MB
24
+ 8388608, // 8 MB
25
+ 16777216, // 16 MB
26
+ 33554432, // 32 MB
27
+ 67108864, // 64 MB
28
+ 134217728, // 128 MB
29
+ 268435456, // 256 MB
30
+ 536870912, // 512 MB
31
+ 1073741824, // 1 GB
32
+ 2147483648, // 2 GB
33
+ 4294967296, // 4 GB
34
+ ];
35
+
36
+ /**
37
+ * Creates an UploadState object for a multipart upload by querying the
38
+ * service for the specified upload's information.
39
+ *
40
+ * @param GlacierClient $client GlacierClient object to use.
41
+ * @param string $vaultName Vault name for the multipart upload.
42
+ * @param string $uploadId Upload ID for the multipart upload.
43
+ * @param string $accountId Account ID for the multipart upload.
44
+ *
45
+ * @return UploadState
46
+ */
47
+ public static function getStateFromService(
48
+ GlacierClient $client,
49
+ $vaultName,
50
+ $uploadId,
51
+ $accountId = '-'
52
+ ) {
53
+ $state = new UploadState([
54
+ 'accountId' => $accountId,
55
+ 'vaultName' => $vaultName,
56
+ 'uploadId' => $uploadId,
57
+ ]);
58
+
59
+ foreach ($client->getPaginator('ListParts', $state->getId()) as $result) {
60
+ // Get the part size from the first part in the first result.
61
+ if (!$state->getPartSize()) {
62
+ $state->setPartSize($result['PartSizeInBytes']);
63
+ }
64
+ // Mark all the parts returned by ListParts as uploaded.
65
+ foreach ($result['Parts'] as $part) {
66
+ list($rangeIndex, $rangeSize) = self::parseRange(
67
+ $part['RangeInBytes'],
68
+ $state->getPartSize()
69
+ );
70
+ $state->markPartAsUploaded($rangeIndex, [
71
+ 'size' => $rangeSize,
72
+ 'checksum' => $part['SHA256TreeHash'],
73
+ ]);
74
+ }
75
+ }
76
+
77
+ $state->setStatus(UploadState::INITIATED);
78
+
79
+ return $state;
80
+ }
81
+
82
+ /**
83
+ * Creates a multipart upload for a Glacier archive.
84
+ *
85
+ * The valid configuration options are as follows:
86
+ *
87
+ * - account_id: (string, default=string('-')) Account ID for the archive
88
+ * being uploaded, if different from the account making the request.
89
+ * - archive_description: (string) Description of the archive.
90
+ * - before_complete: (callable) Callback to invoke before the
91
+ * `CompleteMultipartUpload` operation. The callback should have a
92
+ * function signature like `function (Aws\Command $command) {...}`.
93
+ * - before_initiate: (callable) Callback to invoke before the
94
+ * `InitiateMultipartUpload` operation. The callback should have a
95
+ * function signature like `function (Aws\Command $command) {...}`.
96
+ * - before_upload: (callable) Callback to invoke before any
97
+ * `UploadMultipartPart` operations. The callback should have a function
98
+ * signature like `function (Aws\Command $command) {...}`.
99
+ * - concurrency: (int, default=int(3)) Maximum number of concurrent
100
+ * `UploadMultipartPart` operations allowed during the multipart upload.
101
+ * - part_size: (int, default=int(1048576)) Part size, in bytes, to use when
102
+ * doing a multipart upload. This must between 1 MB and 4 GB, and must be
103
+ * a power of 2 (in megabytes).
104
+ * - state: (Aws\Multipart\UploadState) An object that represents the state
105
+ * of the multipart upload and that is used to resume a previous upload.
106
+ * When this options is provided, the `account_id`, `key`, and `part_size`
107
+ * options are ignored.
108
+ * - vault_name: (string, required) Vault name to use for the archive being
109
+ * uploaded.
110
+ *
111
+ * @param GlacierClient $client Client used for the upload.
112
+ * @param mixed $source Source of the data to upload.
113
+ * @param array $config Configuration used to perform the upload.
114
+ */
115
+ public function __construct(GlacierClient $client, $source, array $config = [])
116
+ {
117
+ parent::__construct($client, $source, $config + [
118
+ 'account_id' => '-',
119
+ 'vault_name' => null,
120
+ ]);
121
+ }
122
+
123
+ protected function loadUploadWorkflowInfo()
124
+ {
125
+ return [
126
+ 'command' => [
127
+ 'initiate' => 'InitiateMultipartUpload',
128
+ 'upload' => 'UploadMultipartPart',
129
+ 'complete' => 'CompleteMultipartUpload',
130
+ ],
131
+ 'id' => [
132
+ 'account_id' => 'accountId',
133
+ 'vault_name' => 'vaultName',
134
+ 'upload_id' => 'uploadId',
135
+ ],
136
+ 'part_num' => 'range',
137
+ ];
138
+ }
139
+
140
+ protected function determinePartSize()
141
+ {
142
+ // Make sure the part size is set.
143
+ $partSize = $this->config['part_size'] ?: self::PART_MIN_SIZE;
144
+
145
+ // Ensure that the part size is valid.
146
+ if (!in_array($partSize, self::$validPartSizes)) {
147
+ throw new \InvalidArgumentException('The part_size must be a power '
148
+ . 'of 2, in megabytes, such that 1 MB <= PART_SIZE <= 4 GB.');
149
+ }
150
+
151
+ return $partSize;
152
+ }
153
+
154
+ protected function createPart($seekable, $number)
155
+ {
156
+ $data = [];
157
+ $firstByte = $this->source->tell();
158
+
159
+ // Read from the source to create the body stream. This also
160
+ // calculates the linear and tree hashes as the data is read.
161
+ if ($seekable) {
162
+ // Case 1: Stream is seekable, can make stream from new handle.
163
+ $body = Psr7\try_fopen($this->source->getMetadata('uri'), 'r');
164
+ $body = $this->limitPartStream(Psr7\stream_for($body));
165
+ // Create another stream decorated with hashing streams and read
166
+ // through it, so we can get the hash values for the part.
167
+ $decoratedBody = $this->decorateWithHashes($body, $data);
168
+ while (!$decoratedBody->eof()) $decoratedBody->read(1048576);
169
+ // Seek the original source forward to the end of the range.
170
+ $this->source->seek($this->source->tell() + $body->getSize());
171
+ } else {
172
+ // Case 2: Stream is not seekable, must store part in temp stream.
173
+ $source = $this->limitPartStream($this->source);
174
+ $source = $this->decorateWithHashes($source, $data);
175
+ $body = Psr7\stream_for();
176
+ Psr7\copy_to_stream($source, $body);
177
+ }
178
+
179
+ // Do not create a part if the body size is zero.
180
+ if ($body->getSize() === 0) {
181
+ return false;
182
+ }
183
+
184
+ $body->seek(0);
185
+ $data['body'] = $body;
186
+ $lastByte = $this->source->tell() - 1;
187
+ $data['range'] = "bytes {$firstByte}-{$lastByte}/*";
188
+
189
+ return $data;
190
+ }
191
+
192
+ protected function handleResult(CommandInterface $command, ResultInterface $result)
193
+ {
194
+ list($rangeIndex, $rangeSize) = $this->parseRange(
195
+ $command['range'],
196
+ $this->state->getPartSize()
197
+ );
198
+
199
+ $this->state->markPartAsUploaded($rangeIndex, [
200
+ 'size' => $rangeSize,
201
+ 'checksum' => $command['checksum']
202
+ ]);
203
+ }
204
+
205
+ protected function getInitiateParams()
206
+ {
207
+ $params = ['partSize' => $this->state->getPartSize()];
208
+ if (isset($this->config['archive_description'])) {
209
+ $params['archiveDescription'] = $this->config['archive_description'];
210
+ }
211
+
212
+ return $params;
213
+ }
214
+
215
+ protected function getCompleteParams()
216
+ {
217
+ $treeHash = new TreeHash();
218
+ $archiveSize = 0;
219
+ foreach ($this->state->getUploadedParts() as $part) {
220
+ $archiveSize += $part['size'];
221
+ $treeHash->addChecksum($part['checksum']);
222
+ }
223
+
224
+ return [
225
+ 'archiveSize' => $archiveSize,
226
+ 'checksum' => bin2hex($treeHash->complete()),
227
+ ];
228
+ }
229
+
230
+ /**
231
+ * Decorates a stream with a tree AND linear sha256 hashing stream.
232
+ *
233
+ * @param Stream $stream Stream to decorate.
234
+ * @param array $data Data bag that results are injected into.
235
+ *
236
+ * @return Stream
237
+ */
238
+ private function decorateWithHashes(Stream $stream, array &$data)
239
+ {
240
+ // Make sure that a tree hash is calculated.
241
+ $stream = new HashingStream($stream, new TreeHash(),
242
+ function ($result) use (&$data) {
243
+ $data['checksum'] = bin2hex($result);
244
+ }
245
+ );
246
+
247
+ // Make sure that a linear SHA256 hash is calculated.
248
+ $stream = new HashingStream($stream, new PhpHash('sha256'),
249
+ function ($result) use (&$data) {
250
+ $data['ContentSHA256'] = bin2hex($result);
251
+ }
252
+ );
253
+
254
+ return $stream;
255
+ }
256
+
257
+ /**
258
+ * Parses a Glacier range string into a size and part number.
259
+ *
260
+ * @param string $range Glacier range string (e.g., "bytes 5-5000/*")
261
+ * @param int $partSize The chosen part size
262
+ *
263
+ * @return array
264
+ */
265
+ private static function parseRange($range, $partSize)
266
+ {
267
+ // Strip away the prefix and suffix.
268
+ if (strpos($range, 'bytes') !== false) {
269
+ $range = substr($range, 6, -2);
270
+ }
271
+
272
+ // Split that range into it's parts.
273
+ list($firstByte, $lastByte) = explode('-', $range);
274
+
275
+ // Calculate and return range index and range size
276
+ return [
277
+ intval($firstByte / $partSize) + 1,
278
+ $lastByte - $firstByte + 1,
279
+ ];
280
+ }
281
+ }
includes/aws/Aws/Glacier/TreeHash.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Glacier;
3
+
4
+ use Aws\HashInterface;
5
+
6
+ /**
7
+ * Encapsulates the creation of a tree hash from streamed data
8
+ */
9
+ class TreeHash implements HashInterface
10
+ {
11
+ const MB = 1048576;
12
+ const EMPTY_HASH = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
13
+
14
+ /** @var string Algorithm used for hashing. */
15
+ private $algorithm;
16
+
17
+ /** @var string Buffered data that has not yet been hashed. */
18
+ private $buffer;
19
+
20
+ /** @var array Binary checksums from which the tree hash is derived. */
21
+ private $checksums = [];
22
+
23
+ /** @var string Resulting hash in binary form. */
24
+ private $hash;
25
+
26
+ public function __construct($algorithm = 'sha256')
27
+ {
28
+ $this->algorithm = $algorithm;
29
+ $this->reset();
30
+ }
31
+
32
+ /**
33
+ * {@inheritdoc}
34
+ * @throws \LogicException if the root tree hash is already calculated
35
+ */
36
+ public function update($data)
37
+ {
38
+ // Error if hash is already calculated.
39
+ if ($this->hash) {
40
+ throw new \LogicException('You may not add more data to a '
41
+ . 'complete tree hash.');
42
+ }
43
+
44
+ // Buffer incoming data.
45
+ $this->buffer .= $data;
46
+
47
+ // When there is more than a MB of data, create a checksum.
48
+ while (strlen($this->buffer) >= self::MB) {
49
+ $data = substr($this->buffer, 0, self::MB);
50
+ $this->buffer = substr($this->buffer, self::MB) ?: '';
51
+ $this->checksums[] = hash($this->algorithm, $data, true);
52
+ }
53
+
54
+ return $this;
55
+ }
56
+
57
+ /**
58
+ * Add a checksum to the tree hash directly
59
+ *
60
+ * @param string $checksum The checksum to add
61
+ * @param bool $inBinaryForm TRUE if checksum is in binary form
62
+ *
63
+ * @return self
64
+ * @throws \LogicException if the root tree hash is already calculated
65
+ */
66
+ public function addChecksum($checksum, $inBinaryForm = false)
67
+ {
68
+ // Error if hash is already calculated
69
+ if ($this->hash) {
70
+ throw new \LogicException('You may not add more checksums to a '
71
+ . 'complete tree hash.');
72
+ }
73
+
74
+ // Convert the checksum to binary form if necessary
75
+ $this->checksums[] = $inBinaryForm ? $checksum : hex2bin($checksum);
76
+
77
+ return $this;
78
+ }
79
+
80
+ public function complete()
81
+ {
82
+ if (!$this->hash) {
83
+ // Clear out the remaining buffer.
84
+ if ($this->buffer) {
85
+ $this->checksums[] = hash($this->algorithm, $this->buffer, true);
86
+ $this->buffer = '';
87
+ }
88
+
89
+ // If no hashes, add the EMPTY_HASH.
90
+ if (!$this->checksums) {
91
+ $this->checksums[] = hex2bin(self::EMPTY_HASH);
92
+ }
93
+
94
+ // Perform hashes up the tree to arrive at the root checksum.
95
+ $hashes = $this->checksums;
96
+ while (count($hashes) > 1) {
97
+ $sets = array_chunk($hashes, 2);
98
+ $hashes = array();
99
+ foreach ($sets as $set) {
100
+ $hashes[] = (count($set) === 1)
101
+ ? $set[0]
102
+ : hash($this->algorithm, $set[0] . $set[1], true);
103
+ }
104
+ }
105
+
106
+ $this->hash = $hashes[0];
107
+ }
108
+
109
+ return $this->hash;
110
+ }
111
+
112
+ public function reset()
113
+ {
114
+ $this->hash = null;
115
+ $this->checksums = [];
116
+ $this->buffer = '';
117
+ }
118
+ }
includes/aws/Aws/Handler/GuzzleV5/GuzzleHandler.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Handler\GuzzleV5;
3
+
4
+ use Aws\Sdk;
5
+ use Exception;
6
+ use GuzzleHttp\Client;
7
+ use GuzzleHttp\ClientInterface;
8
+ use GuzzleHttp\Exception\ConnectException;
9
+ use GuzzleHttp\Exception\RequestException;
10
+ use GuzzleHttp\Message\ResponseInterface as GuzzleResponse;
11
+ use GuzzleHttp\Promise;
12
+ use GuzzleHttp\Psr7\Response as Psr7Response;
13
+ use Psr\Http\Message\RequestInterface as Psr7Request;
14
+ use Psr\Http\Message\StreamInterface as Psr7StreamInterface;
15
+
16
+ /**
17
+ * A request handler that sends PSR-7-compatible requests with Guzzle 5.
18
+ *
19
+ * The handler accepts a PSR-7 Request object and an array of transfer options
20
+ * and returns a Guzzle 6 Promise. The promise is either resolved with a
21
+ * PSR-7 Response object or rejected with an array of error data.
22
+ *
23
+ * @codeCoverageIgnore
24
+ */
25
+ class GuzzleHandler
26
+ {
27
+ private static $validOptions = [
28
+ 'proxy' => true,
29
+ 'verify' => true,
30
+ 'timeout' => true,
31
+ 'debug' => true,
32
+ 'connect_timeout' => true,
33
+ 'stream' => true,
34
+ 'delay' => true,
35
+ 'sink' => true,
36
+ ];
37
+
38
+ /** @var ClientInterface */
39
+ private $client;
40
+
41
+ /**
42
+ * @param ClientInterface $client
43
+ */
44
+ public function __construct(ClientInterface $client = null)
45
+ {
46
+ $this->client = $client ?: new Client();
47
+ }
48
+
49
+ /**
50
+ * @param Psr7Request $request
51
+ * @param array $options
52
+ *
53
+ * @return Promise\Promise
54
+ */
55
+ public function __invoke(Psr7Request $request, array $options = [])
56
+ {
57
+ // Create and send a Guzzle 5 request
58
+ $guzzlePromise = $this->client->send(
59
+ $this->createGuzzleRequest($request, $options)
60
+ );
61
+
62
+ $promise = new Promise\Promise(
63
+ function () use ($guzzlePromise) {
64
+ try {
65
+ $guzzlePromise->wait();
66
+ } catch (\Exception $e) {
67
+ // The promise is already delivered when the exception is
68
+ // thrown, so don't rethrow it.
69
+ }
70
+ },
71
+ [$guzzlePromise, 'cancel']
72
+ );
73
+
74
+ $guzzlePromise->then([$promise, 'resolve'], [$promise, 'reject']);
75
+
76
+ return $promise->then(
77
+ function (GuzzleResponse $response) {
78
+ // Adapt the Guzzle 5 Future to a Guzzle 6 ResponsePromise.
79
+ return $this->createPsr7Response($response);
80
+ },
81
+ function (Exception $exception) {
82
+ // Reject with information about the error.
83
+ return new Promise\RejectedPromise($this->prepareErrorData($exception));
84
+ }
85
+ );
86
+ }
87
+
88
+ private function createGuzzleRequest(Psr7Request $psrRequest, array $options)
89
+ {
90
+ $ringConfig = [];
91
+
92
+ // Remove unsupported options.
93
+ foreach (array_keys($options) as $key) {
94
+ if (!isset(self::$validOptions[$key])) {
95
+ unset($options[$key]);
96
+ }
97
+ }
98
+
99
+ // Handle delay option.
100
+ if (isset($options['delay'])) {
101
+ $ringConfig['delay'] = $options['delay'];
102
+ unset($options['delay']);
103
+ }
104
+
105
+ // Prepare sink option.
106
+ if (isset($options['sink'])) {
107
+ $ringConfig['save_to'] = ($options['sink'] instanceof Psr7StreamInterface)
108
+ ? new GuzzleStream($options['sink'])
109
+ : $options['sink'];
110
+ unset($options['sink']);
111
+ }
112
+
113
+ // Ensure that all requests are async and lazy like Guzzle 6.
114
+ $options['future'] = 'lazy';
115
+
116
+ // Create the Guzzle 5 request from the provided PSR7 request.
117
+ $request = $this->client->createRequest(
118
+ $psrRequest->getMethod(),
119
+ $psrRequest->getUri(),
120
+ $options
121
+ );
122
+
123
+ // For the request body, adapt the PSR stream to a Guzzle stream.
124
+ $body = $psrRequest->getBody();
125
+ if ($body->getSize() === 0) {
126
+ $request->setBody(null);
127
+ } else {
128
+ $request->setBody(new GuzzleStream($body));
129
+ }
130
+
131
+ $request->setHeaders($psrRequest->getHeaders());
132
+
133
+ $request->setHeader(
134
+ 'User-Agent',
135
+ $request->getHeader('User-Agent')
136
+ . ' ' . Client::getDefaultUserAgent()
137
+ );
138
+
139
+ // Make sure the delay is configured, if provided.
140
+ if ($ringConfig) {
141
+ foreach ($ringConfig as $k => $v) {
142
+ $request->getConfig()->set($k, $v);
143
+ }
144
+ }
145
+
146
+ return $request;
147
+ }
148
+
149
+ private function createPsr7Response(GuzzleResponse $response)
150
+ {
151
+ if ($body = $response->getBody()) {
152
+ $body = new PsrStream($body);
153
+ }
154
+
155
+ return new Psr7Response(
156
+ $response->getStatusCode(),
157
+ $response->getHeaders(),
158
+ $body,
159
+ $response->getReasonPhrase()
160
+ );
161
+ }
162
+
163
+ private function prepareErrorData(Exception $e)
164
+ {
165
+ $error = [
166
+ 'exception' => $e,
167
+ 'connection_error' => false,
168
+ 'response' => null,
169
+ ];
170
+
171
+ if ($e instanceof ConnectException) {
172
+ $error['connection_error'] = true;
173
+ }
174
+
175
+ if ($e instanceof RequestException && $e->getResponse()) {
176
+ $error['response'] = $this->createPsr7Response($e->getResponse());
177
+ }
178
+
179
+ return $error;
180
+ }
181
+ }
includes/aws/Aws/Handler/GuzzleV5/GuzzleStream.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Handler\GuzzleV5;
3
+
4
+ use GuzzleHttp\Stream\StreamDecoratorTrait;
5
+ use GuzzleHttp\Stream\StreamInterface as GuzzleStreamInterface;
6
+ use Psr\Http\Message\StreamInterface as Psr7StreamInterface;
7
+
8
+ /**
9
+ * Adapts a PSR-7 Stream to a Guzzle 5 Stream.
10
+ *
11
+ * @codeCoverageIgnore
12
+ */
13
+ class GuzzleStream implements GuzzleStreamInterface
14
+ {
15
+ use StreamDecoratorTrait;
16
+
17
+ /** @var Psr7StreamInterface */
18
+ private $stream;
19
+
20
+ public function __construct(Psr7StreamInterface $stream)
21
+ {
22
+ $this->stream = $stream;
23
+ }
24
+ }
includes/aws/Aws/Handler/GuzzleV5/PsrStream.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Handler\GuzzleV5;
3
+
4
+ use GuzzleHttp\Stream\StreamDecoratorTrait;
5
+ use GuzzleHttp\Stream\StreamInterface as GuzzleStreamInterface;
6
+ use Psr\Http\Message\StreamInterface as Psr7StreamInterface;
7
+
8
+ /**
9
+ * Adapts a Guzzle 5 Stream to a PSR-7 Stream.
10
+ *
11
+ * @codeCoverageIgnore
12
+ */
13
+ class PsrStream implements Psr7StreamInterface
14
+ {
15
+ use StreamDecoratorTrait;
16
+
17
+ /** @var GuzzleStreamInterface */
18
+ private $stream;
19
+
20
+ public function __construct(GuzzleStreamInterface $stream)
21
+ {
22
+ $this->stream = $stream;
23
+ }
24
+
25
+ public function rewind()
26
+ {
27
+ $this->stream->seek(0);
28
+ }
29
+
30
+ public function getContents()
31
+ {
32
+ return $this->stream->getContents();
33
+ }
34
+ }
includes/aws/Aws/Handler/GuzzleV6/GuzzleHandler.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Handler\GuzzleV6;
3
+
4
+ use Aws\Sdk;
5
+ use Exception;
6
+ use GuzzleHttp\Exception\ConnectException;
7
+ use GuzzleHttp\Exception\RequestException;
8
+ use GuzzleHttp\Promise;
9
+ use GuzzleHttp\Client;
10
+ use GuzzleHttp\ClientInterface;
11
+ use Psr\Http\Message\RequestInterface as Psr7Request;
12
+
13
+ /**
14
+ * A request handler that sends PSR-7-compatible requests with Guzzle 6.
15
+ */
16
+ class GuzzleHandler
17
+ {
18
+ /** @var ClientInterface */
19
+ private $client;
20
+
21
+ /**
22
+ * @param ClientInterface $client
23
+ */
24
+ public function __construct(ClientInterface $client = null)
25
+ {
26
+ $this->client = $client ?: new Client();
27
+ }
28
+
29
+ /**
30
+ * @param Psr7Request $request
31
+ * @param array $options
32
+ *
33
+ * @return Promise\Promise
34
+ */
35
+ public function __invoke(Psr7Request $request, array $options = [])
36
+ {
37
+ $request = $request->withHeader(
38
+ 'User-Agent',
39
+ $request->getHeaderLine('User-Agent')
40
+ . ' ' . \GuzzleHttp\default_user_agent()
41
+ );
42
+
43
+ return $this->client->sendAsync($request, $options)->otherwise(
44
+ static function (\Exception $e) {
45
+ $error = [
46
+ 'exception' => $e,
47
+ 'connection_error' => $e instanceof ConnectException,
48
+ 'response' => null,
49
+ ];
50
+
51
+ if ($e instanceof RequestException && $e->getResponse()) {
52
+ $error['response'] = $e->getResponse();
53
+ }
54
+
55
+ return new Promise\RejectedPromise($error);
56
+ }
57
+ );
58
+ }
59
+ }
includes/aws/Aws/HandlerList.php ADDED
@@ -0,0 +1,424 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ /**
5
+ * Builds a single handler function from zero or more middleware functions and
6
+ * a handler. The handler function is then used to send command objects and
7
+ * return a promise that is resolved with an AWS result object.
8
+ *
9
+ * The "front" of the list is invoked before the "end" of the list. You can add
10
+ * middleware to the front of the list using one of the "prepend" method, and
11
+ * the end of the list using one of the "append" method. The last function
12
+ * invoked in a handler list is the handler (a function that does not accept a
13
+ * next handler but rather is responsible for returning a promise that is
14
+ * fulfilled with an Aws\ResultInterface object).
15
+ *
16
+ * Handlers are ordered using a "step" that describes the step at which the
17
+ * SDK is when sending a command. The available steps are:
18
+ *
19
+ * - init: The command is being initialized, allowing you to do things like add
20
+ * default options.
21
+ * - validate: The command is being validated before it is serialized
22
+ * - build: The command is being serialized into an HTTP request. A middleware
23
+ * in this step MUST serialize an HTTP request and populate the "@request"
24
+ * parameter of a command with the request such that it is available to
25
+ * subsequent middleware.
26
+ * - sign: The request is being signed and prepared to be sent over the wire.
27
+ *
28
+ * Middleware can be registered with a name to allow you to easily add a
29
+ * middleware before or after another middleware by name. This also allows you
30
+ * to remove a middleware by name (in addition to removing by instance).
31
+ */
32
+ class HandlerList implements \Countable
33
+ {
34
+ const INIT = 'init';
35
+ const VALIDATE = 'validate';
36
+ const BUILD = 'build';
37
+ const SIGN = 'sign';
38
+
39
+ /** @var callable */
40
+ private $handler;
41
+
42
+ /** @var array */
43
+ private $named = [];
44
+
45
+ /** @var array */
46
+ private $sorted;
47
+
48
+ /** @var callable|null */
49
+ private $interposeFn;
50
+
51
+ /** @var array Steps (in reverse order) */
52
+ private $steps = [
53
+ self::SIGN => [],
54
+ self::BUILD => [],
55
+ self::VALIDATE => [],
56
+ self::INIT => [],
57
+ ];
58
+
59
+ /**
60
+ * @param callable $handler HTTP handler.
61
+ */
62
+ public function __construct(callable $handler = null)
63
+ {
64
+ $this->handler = $handler;
65
+ }
66
+
67
+ /**
68
+ * Dumps a string representation of the list.
69
+ *
70
+ * @return string
71
+ */
72
+ public function __toString()
73
+ {
74
+ $str = '';
75
+ $i = 0;
76
+
77
+ foreach (array_reverse($this->steps) as $k => $step) {
78
+ foreach (array_reverse($step) as $j => $tuple) {
79
+ $str .= "{$i}) Step: {$k}, ";
80
+ if ($tuple[1]) {
81
+ $str .= "Name: {$tuple[1]}, ";
82
+ }
83
+ $str .= "Function: " . $this->debugCallable($tuple[0]) . "\n";
84
+ $i++;
85
+ }
86
+ }
87
+
88
+ if ($this->handler) {
89
+ $str .= "{$i}) Handler: " . $this->debugCallable($this->handler) . "\n";
90
+ }
91
+
92
+ return $str;
93
+ }
94
+
95
+ /**
96
+ * Set the HTTP handler that actually returns a response.
97
+ *
98
+ * @param callable $handler Function that accepts a request and array of
99
+ * options and returns a Promise.
100
+ */
101
+ public function setHandler(callable $handler)
102
+ {
103
+ $this->handler = $handler;
104
+ }
105
+
106
+ /**
107
+ * Returns true if the builder has a handler.
108
+ *
109
+ * @return bool
110
+ */
111
+ public function hasHandler()
112
+ {
113
+ return (bool) $this->handler;
114
+ }
115
+
116
+ /**
117
+ * Append a middleware to the init step.
118
+ *
119
+ * @param callable $middleware Middleware function to add.
120
+ * @param string $name Name of the middleware.
121
+ */
122
+ public function appendInit(callable $middleware, $name = null)
123
+ {
124
+ $this->add(self::INIT, $name, $middleware);
125
+ }
126
+
127
+ /**
128
+ * Prepend a middleware to the init step.
129
+ *
130
+ * @param callable $middleware Middleware function to add.
131
+ * @param string $name Name of the middleware.
132
+ */
133
+ public function prependInit(callable $middleware, $name = null)
134
+ {
135
+ $this->add(self::INIT, $name, $middleware, true);
136
+ }
137
+
138
+ /**
139
+ * Append a middleware to the validate step.
140
+ *
141
+ * @param callable $middleware Middleware function to add.
142
+ * @param string $name Name of the middleware.
143
+ */
144
+ public function appendValidate(callable $middleware, $name = null)
145
+ {
146
+ $this->add(self::VALIDATE, $name, $middleware);
147
+ }
148
+
149
+ /**
150
+ * Prepend a middleware to the validate step.
151
+ *
152
+ * @param callable $middleware Middleware function to add.
153
+ * @param string $name Name of the middleware.
154
+ */
155
+ public function prependValidate(callable $middleware, $name = null)
156
+ {
157
+ $this->add(self::VALIDATE, $name, $middleware, true);
158
+ }
159
+
160
+ /**
161
+ * Append a middleware to the build step.
162
+ *
163
+ * @param callable $middleware Middleware function to add.
164
+ * @param string $name Name of the middleware.
165
+ */
166
+ public function appendBuild(callable $middleware, $name = null)
167
+ {
168
+ $this->add(self::BUILD, $name, $middleware);
169
+ }
170
+
171
+ /**
172
+ * Prepend a middleware to the build step.
173
+ *
174
+ * @param callable $middleware Middleware function to add.
175
+ * @param string $name Name of the middleware.
176
+ */
177
+ public function prependBuild(callable $middleware, $name = null)
178
+ {
179
+ $this->add(self::BUILD, $name, $middleware, true);
180
+ }
181
+
182
+ /**
183
+ * Append a middleware to the sign step.
184
+ *
185
+ * @param callable $middleware Middleware function to add.
186
+ * @param string $name Name of the middleware.
187
+ */
188
+ public function appendSign(callable $middleware, $name = null)
189
+ {
190
+ $this->add(self::SIGN, $name, $middleware);
191
+ }
192
+
193
+ /**
194
+ * Prepend a middleware to the sign step.
195
+ *
196
+ * @param callable $middleware Middleware function to add.
197
+ * @param string $name Name of the middleware.
198
+ */
199
+ public function prependSign(callable $middleware, $name = null)
200
+ {
201
+ $this->add(self::SIGN, $name, $middleware, true);
202
+ }
203
+
204
+ /**
205
+ * Add a middleware before the given middleware by name.
206
+ *
207
+ * @param string|callable $findName Add before this
208
+ * @param string $withName Optional name to give the middleware
209
+ * @param callable $middleware Middleware to add.
210
+ */
211
+ public function before($findName, $withName, callable $middleware)
212
+ {
213
+ $this->splice($findName, $withName, $middleware, true);
214
+ }
215
+
216
+ /**
217
+ * Add a middleware after the given middleware by name.
218
+ *
219
+ * @param string|callable $findName Add after this
220
+ * @param string $withName Optional name to give the middleware
221
+ * @param callable $middleware Middleware to add.
222
+ */
223
+ public function after($findName, $withName, callable $middleware)
224
+ {
225
+ $this->splice($findName, $withName, $middleware, false);
226
+ }
227
+
228
+ /**
229
+ * Remove a middleware by name or by instance from the list.
230
+ *
231
+ * @param string|callable $nameOrInstance Middleware to remove.
232
+ */
233
+ public function remove($nameOrInstance)
234
+ {
235
+ if (is_callable($nameOrInstance)) {
236
+ $this->removeByInstance($nameOrInstance);
237
+ } elseif (is_string($nameOrInstance)) {
238
+ $this->removeByName($nameOrInstance);
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Interpose a function between each middleware (e.g., allowing for a trace
244
+ * through the middleware layers).
245
+ *
246
+ * The interpose function is a function that accepts a "step" argument as a
247
+ * string and a "name" argument string. This function must then return a
248
+ * function that accepts the next handler in the list. This function must
249
+ * then return a function that accepts a CommandInterface and optional
250
+ * RequestInterface and returns a promise that is fulfilled with an
251
+ * Aws\ResultInterface or rejected with an Aws\Exception\AwsException
252
+ * object.
253
+ *
254
+ * @param callable|null $fn Pass null to remove any previously set function
255
+ */
256
+ public function interpose(callable $fn = null)
257
+ {
258
+ $this->sorted = null;
259
+ $this->interposeFn = $fn;
260
+ }
261
+
262
+ /**
263
+ * Compose the middleware and handler into a single callable function.
264
+ *
265
+ * @return callable
266
+ */
267
+ public function resolve()
268
+ {
269
+ if (!($prev = $this->handler)) {
270
+ throw new \LogicException('No handler has been specified');
271
+ }
272
+
273
+ if ($this->sorted === null) {
274
+ $this->sortMiddleware();
275
+ }
276
+
277
+ foreach ($this->sorted as $fn) {
278
+ $prev = $fn($prev);
279
+ }
280
+
281
+ return $prev;
282
+ }
283
+
284
+ public function count()
285
+ {
286
+ return count($this->steps[self::INIT])
287
+ + count($this->steps[self::VALIDATE])
288
+ + count($this->steps[self::BUILD])
289
+ + count($this->steps[self::SIGN]);
290
+ }
291
+
292
+ /**
293
+ * Splices a function into the middleware list at a specific position.
294
+ *
295
+ * @param $findName
296
+ * @param $withName
297
+ * @param callable $middleware
298
+ * @param $before
299
+ */
300
+ private function splice($findName, $withName, callable $middleware, $before)
301
+ {
302
+ if (!isset($this->named[$findName])) {
303
+ throw new \InvalidArgumentException("$findName not found");
304
+ }
305
+
306
+ $idx = $this->sorted = null;
307
+ $step = $this->named[$findName];
308
+
309
+ if ($withName) {
310
+ $this->named[$withName] = $step;
311
+ }
312
+
313
+ foreach ($this->steps[$step] as $i => $tuple) {
314
+ if ($tuple[1] === $findName) {
315
+ $idx = $i;
316
+ break;
317
+ }
318
+ }
319
+
320
+ $replacement = $before
321
+ ? [$this->steps[$step][$idx], [$middleware, $withName]]
322
+ : [[$middleware, $withName], $this->steps[$step][$idx]];
323
+ array_splice($this->steps[$step], $idx, 1, $replacement);
324
+ }
325
+
326
+ /**
327
+ * Provides a debug string for a given callable.
328
+ *
329
+ * @param array|callable $fn Function to write as a string.
330
+ *
331
+ * @return string
332
+ */
333
+ private function debugCallable($fn)
334
+ {
335
+ if (is_string($fn)) {
336
+ return "callable({$fn})";
337
+ } elseif (is_array($fn)) {
338
+ $ele = is_string($fn[0]) ? $fn[0] : get_class($fn[0]);
339
+ return "callable(['{$ele}', '{$fn[1]}'])";
340
+ } else {
341
+ return 'callable(' . spl_object_hash($fn) . ')';
342
+ }
343
+ }
344
+
345
+ /**
346
+ * Sort the middleware, and interpose if needed in the sorted list.
347
+ */
348
+ private function sortMiddleware()
349
+ {
350
+ $this->sorted = [];
351
+
352
+ if (!$this->interposeFn) {
353
+ foreach ($this->steps as $step) {
354
+ foreach ($step as $fn) {
355
+ $this->sorted[] = $fn[0];
356
+ }
357
+ }
358
+ return;
359
+ }
360
+
361
+ $ifn = $this->interposeFn;
362
+ // Interpose the interposeFn into the handler stack.
363
+ foreach ($this->steps as $stepName => $step) {
364
+ foreach ($step as $fn) {
365
+ $this->sorted[] = $ifn($stepName, $fn[1]);
366
+ $this->sorted[] = $fn[0];
367
+ }
368
+ }
369
+ }
370
+
371
+ private function removeByName($name)
372
+ {
373
+ if (!isset($this->named[$name])) {
374
+ return;
375
+ }
376
+
377
+ $this->sorted = null;
378
+ $step = $this->named[$name];
379
+ $this->steps[$step] = array_values(
380
+ array_filter(
381
+ $this->steps[$step],
382
+ function ($tuple) use ($name) {
383
+ return $tuple[1] !== $name;
384
+ }
385
+ )
386
+ );
387
+ }
388
+
389
+ private function removeByInstance(callable $fn)
390
+ {
391
+ foreach ($this->steps as $k => $step) {
392
+ foreach ($step as $j => $tuple) {
393
+ if ($tuple[0] === $fn) {
394
+ $this->sorted = null;
395
+ unset($this->named[$this->steps[$k][$j][1]]);
396
+ unset($this->steps[$k][$j]);
397
+ }
398
+ }
399
+ }
400
+ }
401
+
402
+ /**
403
+ * Add a middleware to a step.
404
+ *
405
+ * @param string $step Middleware step.
406
+ * @param string $name Middleware name.
407
+ * @param callable $middleware Middleware function to add.
408
+ * @param bool $prepend Prepend instead of append.
409
+ */
410
+ private function add($step, $name, callable $middleware, $prepend = false)
411
+ {
412
+ $this->sorted = null;
413
+
414
+ if ($prepend) {
415
+ $this->steps[$step][] = [$middleware, $name];
416
+ } else {
417
+ array_unshift($this->steps[$step], [$middleware, $name]);
418
+ }
419
+
420
+ if ($name) {
421
+ $this->named[$name] = $step;
422
+ }
423
+ }
424
+ }
includes/aws/Aws/HasDataTrait.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ /**
5
+ * Trait implementing ToArrayInterface, \ArrayAccess, \Countable, and
6
+ * \IteratorAggregate
7
+ */
8
+ trait HasDataTrait
9
+ {
10
+ /** @var array */
11
+ private $data = [];
12
+
13
+ public function getIterator()
14
+ {
15
+ return new \ArrayIterator($this->data);
16
+ }
17
+
18
+ /**
19
+ * This method returns a reference to the variable to allow for indirect
20
+ * array modification (e.g., $foo['bar']['baz'] = 'qux').
21
+ *
22
+ * @param $offset
23
+ *
24
+ * @return mixed|null
25
+ */
26
+ public function & offsetGet($offset)
27
+ {
28
+ if (isset($this->data[$offset])) {
29
+ return $this->data[$offset];
30
+ }
31
+
32
+ $value = null;
33
+ return $value;
34
+ }
35
+
36
+ public function offsetSet($offset, $value)
37
+ {
38
+ $this->data[$offset] = $value;
39
+ }
40
+
41
+ public function offsetExists($offset)
42
+ {
43
+ return isset($this->data[$offset]);
44
+ }
45
+
46
+ public function offsetUnset($offset)
47
+ {
48
+ unset($this->data[$offset]);
49
+ }
50
+
51
+ public function toArray()
52
+ {
53
+ return $this->data;
54
+ }
55
+
56
+ public function count()
57
+ {
58
+ return count($this->data);
59
+ }
60
+ }
includes/aws/Aws/HashInterface.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ /**
5
+ * Interface that allows implementing various incremental hashes.
6
+ */
7
+ interface HashInterface
8
+ {
9
+ /**
10
+ * Adds data to the hash.
11
+ *
12
+ * @param string $data Data to add to the hash
13
+ */
14
+ public function update($data);
15
+
16
+ /**
17
+ * Finalizes the incremental hash and returns the resulting digest.
18
+ *
19
+ * @return string
20
+ */
21
+ public function complete();
22
+
23
+ /**
24
+ * Removes all data from the hash, effectively starting a new hash.
25
+ */
26
+ public function reset();
27
+ }
includes/aws/Aws/HashingStream.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use GuzzleHttp\Psr7\StreamDecoratorTrait;
5
+ use Psr\Http\Message\StreamInterface;
6
+
7
+ /**
8
+ * Stream decorator that calculates a rolling hash of the stream as it is read.
9
+ */
10
+ class HashingStream implements StreamInterface
11
+ {
12
+ use StreamDecoratorTrait;
13
+
14
+ /** @var HashInterface */
15
+ private $hash;
16
+
17
+ /** @var callable|null */
18
+ private $callback;
19
+
20
+ /**
21
+ * @param StreamInterface $stream Stream that is being read.
22
+ * @param HashInterface $hash Hash used to calculate checksum.
23
+ * @param callable $onComplete Optional function invoked when the
24
+ * hash calculation is completed.
25
+ */
26
+ public function __construct(
27
+ StreamInterface $stream,
28
+ HashInterface $hash,
29
+ callable $onComplete = null
30
+ ) {
31
+ $this->stream = $stream;
32
+ $this->hash = $hash;
33
+ $this->callback = $onComplete;
34
+ }
35
+
36
+ public function read($length)
37
+ {
38
+ $data = $this->stream->read($length);
39
+ $this->hash->update($data);
40
+ if ($this->eof()) {
41
+ $result = $this->hash->complete();
42
+ if ($this->callback) {
43
+ call_user_func($this->callback, $result);
44
+ }
45
+ }
46
+
47
+ return $data;
48
+ }
49
+
50
+ public function seek($offset, $whence = SEEK_SET)
51
+ {
52
+ if ($offset === 0) {
53
+ $this->hash->reset();
54
+ return $this->stream->seek($offset);
55
+ } else {
56
+ // Seeking arbitrarily is not supported.
57
+ return false;
58
+ }
59
+ }
60
+ }
includes/aws/Aws/History.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+ use Aws\Exception\AwsException;
6
+
7
+ /**
8
+ * Represents a history container that is required when using the history
9
+ * middleware.
10
+ */
11
+ class History implements \Countable, \IteratorAggregate
12
+ {
13
+ private $maxEntries;
14
+ private $entries;
15
+
16
+ /**
17
+ * @param int $maxEntries Maximum number of entries to store.
18
+ */
19
+ public function __construct($maxEntries = 10)
20
+ {
21
+ $this->maxEntries = $maxEntries;
22
+ }
23
+
24
+ public function count()
25
+ {
26
+ return count($this->entries);
27
+ }
28
+
29
+ public function getIterator()
30
+ {
31
+ return new \ArrayIterator(array_values($this->entries));
32
+ }
33
+
34
+ /**
35
+ * Get the last finished command seen by the history container.
36
+ *
37
+ * @return CommandInterface
38
+ * @throws \LogicException if no commands have been seen.
39
+ */
40
+ public function getLastCommand()
41
+ {
42
+ if (!$this->entries) {
43
+ throw new \LogicException('No commands received');
44
+ }
45
+
46
+ return end($this->entries)['command'];
47
+ }
48
+
49
+ /**
50
+ * Get the last finished request seen by the history container.
51
+ *
52
+ * @return RequestInterface
53
+ * @throws \LogicException if no requests have been seen.
54
+ */
55
+ public function getLastRequest()
56
+ {
57
+ if (!$this->entries) {
58
+ throw new \LogicException('No requests received');
59
+ }
60
+
61
+ return end($this->entries)['request'];
62
+ }
63
+
64
+ /**
65
+ * Get the last received result or exception.
66
+ *
67
+ * @return ResultInterface|AwsException
68
+ * @throws \LogicException if no return values have been received.
69
+ */
70
+ public function getLastReturn()
71
+ {
72
+ if (!$this->entries) {
73
+ throw new \LogicException('No entries');
74
+ }
75
+
76
+ $last = end($this->entries);
77
+
78
+ if (isset($last['result'])) {
79
+ return $last['result'];
80
+ } elseif (isset($last['exception'])) {
81
+ return $last['exception'];
82
+ } else {
83
+ throw new \LogicException('No return value for last entry.');
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Initiate an entry being added to the history.
89
+ *
90
+ * @param CommandInterface $cmd Command be executed.
91
+ * @param RequestInterface $req Request being sent.
92
+ *
93
+ * @return string Returns the ticket used to finish the entry.
94
+ */
95
+ public function start(CommandInterface $cmd, RequestInterface $req)
96
+ {
97
+ $ticket = uniqid();
98
+ $this->entries[$ticket] = [
99
+ 'command' => $cmd,
100
+ 'request' => $req,
101
+ 'result' => null,
102
+ 'exception' => null,
103
+ ];
104
+
105
+ return $ticket;
106
+ }
107
+
108
+ /**
109
+ * Finish adding an entry to the history container.
110
+ *
111
+ * @param string $ticket Ticket returned from the start call.
112
+ * @param mixed $result The result (an exception or AwsResult).
113
+ */
114
+ public function finish($ticket, $result)
115
+ {
116
+ if (!isset($this->entries[$ticket])) {
117
+ throw new \InvalidArgumentException('Invalid history ticket');
118
+ } elseif (isset($this->entries[$ticket]['result'])
119
+ || isset($this->entries[$ticket]['exception'])
120
+ ) {
121
+ throw new \LogicException('History entry is already finished');
122
+ }
123
+
124
+ if ($result instanceof \Exception) {
125
+ $this->entries[$ticket]['exception'] = $result;
126
+ } else {
127
+ $this->entries[$ticket]['result'] = $result;
128
+ }
129
+
130
+ if (count($this->entries) >= $this->maxEntries) {
131
+ $this->entries = array_slice($this->entries, -$this->maxEntries, null, true);
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Flush the history
137
+ */
138
+ public function clear()
139
+ {
140
+ $this->entries = [];
141
+ }
142
+
143
+ /**
144
+ * Converts the history to an array.
145
+ *
146
+ * @return array
147
+ */
148
+ public function toArray()
149
+ {
150
+ return array_values($this->entries);
151
+ }
152
+ }
includes/aws/Aws/Iam/Exception/IamException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Iam\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the AWS Identity and Access Management service.
8
+ */
9
+ class IamException extends AwsException {}
includes/aws/Aws/Iam/IamClient.php ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Iam;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * This client is used to interact with the **AWS Identity and Access Management (AWS IAM)** service.
8
+ *
9
+ * @method \Aws\Result addClientIDToOpenIDConnectProvider(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise addClientIDToOpenIDConnectProviderAsync(array $args = [])
11
+ * @method \Aws\Result addRoleToInstanceProfile(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise addRoleToInstanceProfileAsync(array $args = [])
13
+ * @method \Aws\Result addUserToGroup(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise addUserToGroupAsync(array $args = [])
15
+ * @method \Aws\Result attachGroupPolicy(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise attachGroupPolicyAsync(array $args = [])
17
+ * @method \Aws\Result attachRolePolicy(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise attachRolePolicyAsync(array $args = [])
19
+ * @method \Aws\Result attachUserPolicy(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise attachUserPolicyAsync(array $args = [])
21
+ * @method \Aws\Result changePassword(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise changePasswordAsync(array $args = [])
23
+ * @method \Aws\Result createAccessKey(array $args = [])
24
+ * @method \GuzzleHttp\Promise\Promise createAccessKeyAsync(array $args = [])
25
+ * @method \Aws\Result createAccountAlias(array $args = [])
26
+ * @method \GuzzleHttp\Promise\Promise createAccountAliasAsync(array $args = [])
27
+ * @method \Aws\Result createGroup(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise createGroupAsync(array $args = [])
29
+ * @method \Aws\Result createInstanceProfile(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise createInstanceProfileAsync(array $args = [])
31
+ * @method \Aws\Result createLoginProfile(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise createLoginProfileAsync(array $args = [])
33
+ * @method \Aws\Result createOpenIDConnectProvider(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise createOpenIDConnectProviderAsync(array $args = [])
35
+ * @method \Aws\Result createPolicy(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise createPolicyAsync(array $args = [])
37
+ * @method \Aws\Result createPolicyVersion(array $args = [])
38
+ * @method \GuzzleHttp\Promise\Promise createPolicyVersionAsync(array $args = [])
39
+ * @method \Aws\Result createRole(array $args = [])
40
+ * @method \GuzzleHttp\Promise\Promise createRoleAsync(array $args = [])
41
+ * @method \Aws\Result createSAMLProvider(array $args = [])
42
+ * @method \GuzzleHttp\Promise\Promise createSAMLProviderAsync(array $args = [])
43
+ * @method \Aws\Result createUser(array $args = [])
44
+ * @method \GuzzleHttp\Promise\Promise createUserAsync(array $args = [])
45
+ * @method \Aws\Result createVirtualMFADevice(array $args = [])
46
+ * @method \GuzzleHttp\Promise\Promise createVirtualMFADeviceAsync(array $args = [])
47
+ * @method \Aws\Result deactivateMFADevice(array $args = [])
48
+ * @method \GuzzleHttp\Promise\Promise deactivateMFADeviceAsync(array $args = [])
49
+ * @method \Aws\Result deleteAccessKey(array $args = [])
50
+ * @method \GuzzleHttp\Promise\Promise deleteAccessKeyAsync(array $args = [])
51
+ * @method \Aws\Result deleteAccountAlias(array $args = [])
52
+ * @method \GuzzleHttp\Promise\Promise deleteAccountAliasAsync(array $args = [])
53
+ * @method \Aws\Result deleteAccountPasswordPolicy(array $args = [])
54
+ * @method \GuzzleHttp\Promise\Promise deleteAccountPasswordPolicyAsync(array $args = [])
55
+ * @method \Aws\Result deleteGroup(array $args = [])
56
+ * @method \GuzzleHttp\Promise\Promise deleteGroupAsync(array $args = [])
57
+ * @method \Aws\Result deleteGroupPolicy(array $args = [])
58
+ * @method \GuzzleHttp\Promise\Promise deleteGroupPolicyAsync(array $args = [])
59
+ * @method \Aws\Result deleteInstanceProfile(array $args = [])
60
+ * @method \GuzzleHttp\Promise\Promise deleteInstanceProfileAsync(array $args = [])
61
+ * @method \Aws\Result deleteLoginProfile(array $args = [])
62
+ * @method \GuzzleHttp\Promise\Promise deleteLoginProfileAsync(array $args = [])
63
+ * @method \Aws\Result deleteOpenIDConnectProvider(array $args = [])
64
+ * @method \GuzzleHttp\Promise\Promise deleteOpenIDConnectProviderAsync(array $args = [])
65
+ * @method \Aws\Result deletePolicy(array $args = [])
66
+ * @method \GuzzleHttp\Promise\Promise deletePolicyAsync(array $args = [])
67
+ * @method \Aws\Result deletePolicyVersion(array $args = [])
68
+ * @method \GuzzleHttp\Promise\Promise deletePolicyVersionAsync(array $args = [])
69
+ * @method \Aws\Result deleteRole(array $args = [])
70
+ * @method \GuzzleHttp\Promise\Promise deleteRoleAsync(array $args = [])
71
+ * @method \Aws\Result deleteRolePolicy(array $args = [])
72
+ * @method \GuzzleHttp\Promise\Promise deleteRolePolicyAsync(array $args = [])
73
+ * @method \Aws\Result deleteSAMLProvider(array $args = [])
74
+ * @method \GuzzleHttp\Promise\Promise deleteSAMLProviderAsync(array $args = [])
75
+ * @method \Aws\Result deleteSSHPublicKey(array $args = [])
76
+ * @method \GuzzleHttp\Promise\Promise deleteSSHPublicKeyAsync(array $args = [])
77
+ * @method \Aws\Result deleteServerCertificate(array $args = [])
78
+ * @method \GuzzleHttp\Promise\Promise deleteServerCertificateAsync(array $args = [])
79
+ * @method \Aws\Result deleteSigningCertificate(array $args = [])
80
+ * @method \GuzzleHttp\Promise\Promise deleteSigningCertificateAsync(array $args = [])
81
+ * @method \Aws\Result deleteUser(array $args = [])
82
+ * @method \GuzzleHttp\Promise\Promise deleteUserAsync(array $args = [])
83
+ * @method \Aws\Result deleteUserPolicy(array $args = [])
84
+ * @method \GuzzleHttp\Promise\Promise deleteUserPolicyAsync(array $args = [])
85
+ * @method \Aws\Result deleteVirtualMFADevice(array $args = [])
86
+ * @method \GuzzleHttp\Promise\Promise deleteVirtualMFADeviceAsync(array $args = [])
87
+ * @method \Aws\Result detachGroupPolicy(array $args = [])
88
+ * @method \GuzzleHttp\Promise\Promise detachGroupPolicyAsync(array $args = [])
89
+ * @method \Aws\Result detachRolePolicy(array $args = [])
90
+ * @method \GuzzleHttp\Promise\Promise detachRolePolicyAsync(array $args = [])
91
+ * @method \Aws\Result detachUserPolicy(array $args = [])
92
+ * @method \GuzzleHttp\Promise\Promise detachUserPolicyAsync(array $args = [])
93
+ * @method \Aws\Result enableMFADevice(array $args = [])
94
+ * @method \GuzzleHttp\Promise\Promise enableMFADeviceAsync(array $args = [])
95
+ * @method \Aws\Result generateCredentialReport(array $args = [])
96
+ * @method \GuzzleHttp\Promise\Promise generateCredentialReportAsync(array $args = [])
97
+ * @method \Aws\Result getAccessKeyLastUsed(array $args = [])
98
+ * @method \GuzzleHttp\Promise\Promise getAccessKeyLastUsedAsync(array $args = [])
99
+ * @method \Aws\Result getAccountAuthorizationDetails(array $args = [])
100
+ * @method \GuzzleHttp\Promise\Promise getAccountAuthorizationDetailsAsync(array $args = [])
101
+ * @method \Aws\Result getAccountPasswordPolicy(array $args = [])
102
+ * @method \GuzzleHttp\Promise\Promise getAccountPasswordPolicyAsync(array $args = [])
103
+ * @method \Aws\Result getAccountSummary(array $args = [])
104
+ * @method \GuzzleHttp\Promise\Promise getAccountSummaryAsync(array $args = [])
105
+ * @method \Aws\Result getContextKeysForCustomPolicy(array $args = [])
106
+ * @method \GuzzleHttp\Promise\Promise getContextKeysForCustomPolicyAsync(array $args = [])
107
+ * @method \Aws\Result getContextKeysForPrincipalPolicy(array $args = [])
108
+ * @method \GuzzleHttp\Promise\Promise getContextKeysForPrincipalPolicyAsync(array $args = [])
109
+ * @method \Aws\Result getCredentialReport(array $args = [])
110
+ * @method \GuzzleHttp\Promise\Promise getCredentialReportAsync(array $args = [])
111
+ * @method \Aws\Result getGroup(array $args = [])
112
+ * @method \GuzzleHttp\Promise\Promise getGroupAsync(array $args = [])
113
+ * @method \Aws\Result getGroupPolicy(array $args = [])
114
+ * @method \GuzzleHttp\Promise\Promise getGroupPolicyAsync(array $args = [])
115
+ * @method \Aws\Result getInstanceProfile(array $args = [])
116
+ * @method \GuzzleHttp\Promise\Promise getInstanceProfileAsync(array $args = [])
117
+ * @method \Aws\Result getLoginProfile(array $args = [])
118
+ * @method \GuzzleHttp\Promise\Promise getLoginProfileAsync(array $args = [])
119
+ * @method \Aws\Result getOpenIDConnectProvider(array $args = [])
120
+ * @method \GuzzleHttp\Promise\Promise getOpenIDConnectProviderAsync(array $args = [])
121
+ * @method \Aws\Result getPolicy(array $args = [])
122
+ * @method \GuzzleHttp\Promise\Promise getPolicyAsync(array $args = [])
123
+ * @method \Aws\Result getPolicyVersion(array $args = [])
124
+ * @method \GuzzleHttp\Promise\Promise getPolicyVersionAsync(array $args = [])
125
+ * @method \Aws\Result getRole(array $args = [])
126
+ * @method \GuzzleHttp\Promise\Promise getRoleAsync(array $args = [])
127
+ * @method \Aws\Result getRolePolicy(array $args = [])
128
+ * @method \GuzzleHttp\Promise\Promise getRolePolicyAsync(array $args = [])
129
+ * @method \Aws\Result getSAMLProvider(array $args = [])
130
+ * @method \GuzzleHttp\Promise\Promise getSAMLProviderAsync(array $args = [])
131
+ * @method \Aws\Result getSSHPublicKey(array $args = [])
132
+ * @method \GuzzleHttp\Promise\Promise getSSHPublicKeyAsync(array $args = [])
133
+ * @method \Aws\Result getServerCertificate(array $args = [])
134
+ * @method \GuzzleHttp\Promise\Promise getServerCertificateAsync(array $args = [])
135
+ * @method \Aws\Result getUser(array $args = [])
136
+ * @method \GuzzleHttp\Promise\Promise getUserAsync(array $args = [])
137
+ * @method \Aws\Result getUserPolicy(array $args = [])
138
+ * @method \GuzzleHttp\Promise\Promise getUserPolicyAsync(array $args = [])
139
+ * @method \Aws\Result listAccessKeys(array $args = [])
140
+ * @method \GuzzleHttp\Promise\Promise listAccessKeysAsync(array $args = [])
141
+ * @method \Aws\Result listAccountAliases(array $args = [])
142
+ * @method \GuzzleHttp\Promise\Promise listAccountAliasesAsync(array $args = [])
143
+ * @method \Aws\Result listAttachedGroupPolicies(array $args = [])
144
+ * @method \GuzzleHttp\Promise\Promise listAttachedGroupPoliciesAsync(array $args = [])
145
+ * @method \Aws\Result listAttachedRolePolicies(array $args = [])
146
+ * @method \GuzzleHttp\Promise\Promise listAttachedRolePoliciesAsync(array $args = [])
147
+ * @method \Aws\Result listAttachedUserPolicies(array $args = [])
148
+ * @method \GuzzleHttp\Promise\Promise listAttachedUserPoliciesAsync(array $args = [])
149
+ * @method \Aws\Result listEntitiesForPolicy(array $args = [])
150
+ * @method \GuzzleHttp\Promise\Promise listEntitiesForPolicyAsync(array $args = [])
151
+ * @method \Aws\Result listGroupPolicies(array $args = [])
152
+ * @method \GuzzleHttp\Promise\Promise listGroupPoliciesAsync(array $args = [])
153
+ * @method \Aws\Result listGroups(array $args = [])
154
+ * @method \GuzzleHttp\Promise\Promise listGroupsAsync(array $args = [])
155
+ * @method \Aws\Result listGroupsForUser(array $args = [])
156
+ * @method \GuzzleHttp\Promise\Promise listGroupsForUserAsync(array $args = [])
157
+ * @method \Aws\Result listInstanceProfiles(array $args = [])
158
+ * @method \GuzzleHttp\Promise\Promise listInstanceProfilesAsync(array $args = [])
159
+ * @method \Aws\Result listInstanceProfilesForRole(array $args = [])
160
+ * @method \GuzzleHttp\Promise\Promise listInstanceProfilesForRoleAsync(array $args = [])
161
+ * @method \Aws\Result listMFADevices(array $args = [])
162
+ * @method \GuzzleHttp\Promise\Promise listMFADevicesAsync(array $args = [])
163
+ * @method \Aws\Result listOpenIDConnectProviders(array $args = [])
164
+ * @method \GuzzleHttp\Promise\Promise listOpenIDConnectProvidersAsync(array $args = [])
165
+ * @method \Aws\Result listPolicies(array $args = [])
166
+ * @method \GuzzleHttp\Promise\Promise listPoliciesAsync(array $args = [])
167
+ * @method \Aws\Result listPolicyVersions(array $args = [])
168
+ * @method \GuzzleHttp\Promise\Promise listPolicyVersionsAsync(array $args = [])
169
+ * @method \Aws\Result listRolePolicies(array $args = [])
170
+ * @method \GuzzleHttp\Promise\Promise listRolePoliciesAsync(array $args = [])
171
+ * @method \Aws\Result listRoles(array $args = [])
172
+ * @method \GuzzleHttp\Promise\Promise listRolesAsync(array $args = [])
173
+ * @method \Aws\Result listSAMLProviders(array $args = [])
174
+ * @method \GuzzleHttp\Promise\Promise listSAMLProvidersAsync(array $args = [])
175
+ * @method \Aws\Result listSSHPublicKeys(array $args = [])
176
+ * @method \GuzzleHttp\Promise\Promise listSSHPublicKeysAsync(array $args = [])
177
+ * @method \Aws\Result listServerCertificates(array $args = [])
178
+ * @method \GuzzleHttp\Promise\Promise listServerCertificatesAsync(array $args = [])
179
+ * @method \Aws\Result listSigningCertificates(array $args = [])
180
+ * @method \GuzzleHttp\Promise\Promise listSigningCertificatesAsync(array $args = [])
181
+ * @method \Aws\Result listUserPolicies(array $args = [])
182
+ * @method \GuzzleHttp\Promise\Promise listUserPoliciesAsync(array $args = [])
183
+ * @method \Aws\Result listUsers(array $args = [])
184
+ * @method \GuzzleHttp\Promise\Promise listUsersAsync(array $args = [])
185
+ * @method \Aws\Result listVirtualMFADevices(array $args = [])
186
+ * @method \GuzzleHttp\Promise\Promise listVirtualMFADevicesAsync(array $args = [])
187
+ * @method \Aws\Result putGroupPolicy(array $args = [])
188
+ * @method \GuzzleHttp\Promise\Promise putGroupPolicyAsync(array $args = [])
189
+ * @method \Aws\Result putRolePolicy(array $args = [])
190
+ * @method \GuzzleHttp\Promise\Promise putRolePolicyAsync(array $args = [])
191
+ * @method \Aws\Result putUserPolicy(array $args = [])
192
+ * @method \GuzzleHttp\Promise\Promise putUserPolicyAsync(array $args = [])
193
+ * @method \Aws\Result removeClientIDFromOpenIDConnectProvider(array $args = [])
194
+ * @method \GuzzleHttp\Promise\Promise removeClientIDFromOpenIDConnectProviderAsync(array $args = [])
195
+ * @method \Aws\Result removeRoleFromInstanceProfile(array $args = [])
196
+ * @method \GuzzleHttp\Promise\Promise removeRoleFromInstanceProfileAsync(array $args = [])
197
+ * @method \Aws\Result removeUserFromGroup(array $args = [])
198
+ * @method \GuzzleHttp\Promise\Promise removeUserFromGroupAsync(array $args = [])
199
+ * @method \Aws\Result resyncMFADevice(array $args = [])
200
+ * @method \GuzzleHttp\Promise\Promise resyncMFADeviceAsync(array $args = [])
201
+ * @method \Aws\Result setDefaultPolicyVersion(array $args = [])
202
+ * @method \GuzzleHttp\Promise\Promise setDefaultPolicyVersionAsync(array $args = [])
203
+ * @method \Aws\Result simulateCustomPolicy(array $args = [])
204
+ * @method \GuzzleHttp\Promise\Promise simulateCustomPolicyAsync(array $args = [])
205
+ * @method \Aws\Result simulatePrincipalPolicy(array $args = [])
206
+ * @method \GuzzleHttp\Promise\Promise simulatePrincipalPolicyAsync(array $args = [])
207
+ * @method \Aws\Result updateAccessKey(array $args = [])
208
+ * @method \GuzzleHttp\Promise\Promise updateAccessKeyAsync(array $args = [])
209
+ * @method \Aws\Result updateAccountPasswordPolicy(array $args = [])
210
+ * @method \GuzzleHttp\Promise\Promise updateAccountPasswordPolicyAsync(array $args = [])
211
+ * @method \Aws\Result updateAssumeRolePolicy(array $args = [])
212
+ * @method \GuzzleHttp\Promise\Promise updateAssumeRolePolicyAsync(array $args = [])
213
+ * @method \Aws\Result updateGroup(array $args = [])
214
+ * @method \GuzzleHttp\Promise\Promise updateGroupAsync(array $args = [])
215
+ * @method \Aws\Result updateLoginProfile(array $args = [])
216
+ * @method \GuzzleHttp\Promise\Promise updateLoginProfileAsync(array $args = [])
217
+ * @method \Aws\Result updateOpenIDConnectProviderThumbprint(array $args = [])
218
+ * @method \GuzzleHttp\Promise\Promise updateOpenIDConnectProviderThumbprintAsync(array $args = [])
219
+ * @method \Aws\Result updateSAMLProvider(array $args = [])
220
+ * @method \GuzzleHttp\Promise\Promise updateSAMLProviderAsync(array $args = [])
221
+ * @method \Aws\Result updateSSHPublicKey(array $args = [])
222
+ * @method \GuzzleHttp\Promise\Promise updateSSHPublicKeyAsync(array $args = [])
223
+ * @method \Aws\Result updateServerCertificate(array $args = [])
224
+ * @method \GuzzleHttp\Promise\Promise updateServerCertificateAsync(array $args = [])
225
+ * @method \Aws\Result updateSigningCertificate(array $args = [])
226
+ * @method \GuzzleHttp\Promise\Promise updateSigningCertificateAsync(array $args = [])
227
+ * @method \Aws\Result updateUser(array $args = [])
228
+ * @method \GuzzleHttp\Promise\Promise updateUserAsync(array $args = [])
229
+ * @method \Aws\Result uploadSSHPublicKey(array $args = [])
230
+ * @method \GuzzleHttp\Promise\Promise uploadSSHPublicKeyAsync(array $args = [])
231
+ * @method \Aws\Result uploadServerCertificate(array $args = [])
232
+ * @method \GuzzleHttp\Promise\Promise uploadServerCertificateAsync(array $args = [])
233
+ * @method \Aws\Result uploadSigningCertificate(array $args = [])
234
+ * @method \GuzzleHttp\Promise\Promise uploadSigningCertificateAsync(array $args = [])
235
+ */
236
+ class IamClient extends AwsClient {}
includes/aws/Aws/Inspector/Exception/InspectorException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Inspector\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the **Amazon Inspector** service.
8
+ */
9
+ class InspectorException extends AwsException {}
includes/aws/Aws/Inspector/InspectorClient.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Inspector;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * This client is used to interact with the **Amazon Inspector** service.
8
+ *
9
+ * @method \Aws\Result addAttributesToFindings(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise addAttributesToFindingsAsync(array $args = [])
11
+ * @method \Aws\Result attachAssessmentAndRulesPackage(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise attachAssessmentAndRulesPackageAsync(array $args = [])
13
+ * @method \Aws\Result createApplication(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise createApplicationAsync(array $args = [])
15
+ * @method \Aws\Result createAssessment(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise createAssessmentAsync(array $args = [])
17
+ * @method \Aws\Result createResourceGroup(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise createResourceGroupAsync(array $args = [])
19
+ * @method \Aws\Result deleteApplication(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise deleteApplicationAsync(array $args = [])
21
+ * @method \Aws\Result deleteAssessment(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise deleteAssessmentAsync(array $args = [])
23
+ * @method \Aws\Result deleteRun(array $args = [])
24
+ * @method \GuzzleHttp\Promise\Promise deleteRunAsync(array $args = [])
25
+ * @method \Aws\Result describeApplication(array $args = [])
26
+ * @method \GuzzleHttp\Promise\Promise describeApplicationAsync(array $args = [])
27
+ * @method \Aws\Result describeAssessment(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise describeAssessmentAsync(array $args = [])
29
+ * @method \Aws\Result describeCrossAccountAccessRole(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise describeCrossAccountAccessRoleAsync(array $args = [])
31
+ * @method \Aws\Result describeFinding(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise describeFindingAsync(array $args = [])
33
+ * @method \Aws\Result describeResourceGroup(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise describeResourceGroupAsync(array $args = [])
35
+ * @method \Aws\Result describeRulesPackage(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise describeRulesPackageAsync(array $args = [])
37
+ * @method \Aws\Result describeRun(array $args = [])
38
+ * @method \GuzzleHttp\Promise\Promise describeRunAsync(array $args = [])
39
+ * @method \Aws\Result detachAssessmentAndRulesPackage(array $args = [])
40
+ * @method \GuzzleHttp\Promise\Promise detachAssessmentAndRulesPackageAsync(array $args = [])
41
+ * @method \Aws\Result getAssessmentTelemetry(array $args = [])
42
+ * @method \GuzzleHttp\Promise\Promise getAssessmentTelemetryAsync(array $args = [])
43
+ * @method \Aws\Result listApplications(array $args = [])
44
+ * @method \GuzzleHttp\Promise\Promise listApplicationsAsync(array $args = [])
45
+ * @method \Aws\Result listAssessmentAgents(array $args = [])
46
+ * @method \GuzzleHttp\Promise\Promise listAssessmentAgentsAsync(array $args = [])
47
+ * @method \Aws\Result listAssessments(array $args = [])
48
+ * @method \GuzzleHttp\Promise\Promise listAssessmentsAsync(array $args = [])
49
+ * @method \Aws\Result listAttachedAssessments(array $args = [])
50
+ * @method \GuzzleHttp\Promise\Promise listAttachedAssessmentsAsync(array $args = [])
51
+ * @method \Aws\Result listAttachedRulesPackages(array $args = [])
52
+ * @method \GuzzleHttp\Promise\Promise listAttachedRulesPackagesAsync(array $args = [])
53
+ * @method \Aws\Result listFindings(array $args = [])
54
+ * @method \GuzzleHttp\Promise\Promise listFindingsAsync(array $args = [])
55
+ * @method \Aws\Result listRulesPackages(array $args = [])
56
+ * @method \GuzzleHttp\Promise\Promise listRulesPackagesAsync(array $args = [])
57
+ * @method \Aws\Result listRuns(array $args = [])
58
+ * @method \GuzzleHttp\Promise\Promise listRunsAsync(array $args = [])
59
+ * @method \Aws\Result listTagsForResource(array $args = [])
60
+ * @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = [])
61
+ * @method \Aws\Result localizeText(array $args = [])
62
+ * @method \GuzzleHttp\Promise\Promise localizeTextAsync(array $args = [])
63
+ * @method \Aws\Result previewAgentsForResourceGroup(array $args = [])
64
+ * @method \GuzzleHttp\Promise\Promise previewAgentsForResourceGroupAsync(array $args = [])
65
+ * @method \Aws\Result registerCrossAccountAccessRole(array $args = [])
66
+ * @method \GuzzleHttp\Promise\Promise registerCrossAccountAccessRoleAsync(array $args = [])
67
+ * @method \Aws\Result removeAttributesFromFindings(array $args = [])
68
+ * @method \GuzzleHttp\Promise\Promise removeAttributesFromFindingsAsync(array $args = [])
69
+ * @method \Aws\Result runAssessment(array $args = [])
70
+ * @method \GuzzleHttp\Promise\Promise runAssessmentAsync(array $args = [])
71
+ * @method \Aws\Result setTagsForResource(array $args = [])
72
+ * @method \GuzzleHttp\Promise\Promise setTagsForResourceAsync(array $args = [])
73
+ * @method \Aws\Result startDataCollection(array $args = [])
74
+ * @method \GuzzleHttp\Promise\Promise startDataCollectionAsync(array $args = [])
75
+ * @method \Aws\Result stopDataCollection(array $args = [])
76
+ * @method \GuzzleHttp\Promise\Promise stopDataCollectionAsync(array $args = [])
77
+ * @method \Aws\Result updateApplication(array $args = [])
78
+ * @method \GuzzleHttp\Promise\Promise updateApplicationAsync(array $args = [])
79
+ * @method \Aws\Result updateAssessment(array $args = [])
80
+ * @method \GuzzleHttp\Promise\Promise updateAssessmentAsync(array $args = [])
81
+ */
82
+ class InspectorClient extends AwsClient {}
includes/aws/Aws/Iot/Exception/IotException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Iot\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the **AWS IoT** service.
8
+ */
9
+ class IotException extends AwsException {}
includes/aws/Aws/Iot/IotClient.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Iot;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * This client is used to interact with the **AWS IoT** service.
8
+ *
9
+ * @method \Aws\Result acceptCertificateTransfer(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise acceptCertificateTransferAsync(array $args = [])
11
+ * @method \Aws\Result attachPrincipalPolicy(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise attachPrincipalPolicyAsync(array $args = [])
13
+ * @method \Aws\Result attachThingPrincipal(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise attachThingPrincipalAsync(array $args = [])
15
+ * @method \Aws\Result cancelCertificateTransfer(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise cancelCertificateTransferAsync(array $args = [])
17
+ * @method \Aws\Result createCertificateFromCsr(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise createCertificateFromCsrAsync(array $args = [])
19
+ * @method \Aws\Result createKeysAndCertificate(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise createKeysAndCertificateAsync(array $args = [])
21
+ * @method \Aws\Result createPolicy(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise createPolicyAsync(array $args = [])
23
+ * @method \Aws\Result createPolicyVersion(array $args = [])
24
+ * @method \GuzzleHttp\Promise\Promise createPolicyVersionAsync(array $args = [])
25
+ * @method \Aws\Result createThing(array $args = [])
26
+ * @method \GuzzleHttp\Promise\Promise createThingAsync(array $args = [])
27
+ * @method \Aws\Result createTopicRule(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise createTopicRuleAsync(array $args = [])
29
+ * @method \Aws\Result deleteCertificate(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise deleteCertificateAsync(array $args = [])
31
+ * @method \Aws\Result deletePolicy(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise deletePolicyAsync(array $args = [])
33
+ * @method \Aws\Result deletePolicyVersion(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise deletePolicyVersionAsync(array $args = [])
35
+ * @method \Aws\Result deleteThing(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise deleteThingAsync(array $args = [])
37
+ * @method \Aws\Result deleteTopicRule(array $args = [])
38
+ * @method \GuzzleHttp\Promise\Promise deleteTopicRuleAsync(array $args = [])
39
+ * @method \Aws\Result describeCertificate(array $args = [])
40
+ * @method \GuzzleHttp\Promise\Promise describeCertificateAsync(array $args = [])
41
+ * @method \Aws\Result describeEndpoint(array $args = [])
42
+ * @method \GuzzleHttp\Promise\Promise describeEndpointAsync(array $args = [])
43
+ * @method \Aws\Result describeThing(array $args = [])
44
+ * @method \GuzzleHttp\Promise\Promise describeThingAsync(array $args = [])
45
+ * @method \Aws\Result detachPrincipalPolicy(array $args = [])
46
+ * @method \GuzzleHttp\Promise\Promise detachPrincipalPolicyAsync(array $args = [])
47
+ * @method \Aws\Result detachThingPrincipal(array $args = [])
48
+ * @method \GuzzleHttp\Promise\Promise detachThingPrincipalAsync(array $args = [])
49
+ * @method \Aws\Result getLoggingOptions(array $args = [])
50
+ * @method \GuzzleHttp\Promise\Promise getLoggingOptionsAsync(array $args = [])
51
+ * @method \Aws\Result getPolicy(array $args = [])
52
+ * @method \GuzzleHttp\Promise\Promise getPolicyAsync(array $args = [])
53
+ * @method \Aws\Result getPolicyVersion(array $args = [])
54
+ * @method \GuzzleHttp\Promise\Promise getPolicyVersionAsync(array $args = [])
55
+ * @method \Aws\Result getTopicRule(array $args = [])
56
+ * @method \GuzzleHttp\Promise\Promise getTopicRuleAsync(array $args = [])
57
+ * @method \Aws\Result listCertificates(array $args = [])
58
+ * @method \GuzzleHttp\Promise\Promise listCertificatesAsync(array $args = [])
59
+ * @method \Aws\Result listPolicies(array $args = [])
60
+ * @method \GuzzleHttp\Promise\Promise listPoliciesAsync(array $args = [])
61
+ * @method \Aws\Result listPolicyVersions(array $args = [])
62
+ * @method \GuzzleHttp\Promise\Promise listPolicyVersionsAsync(array $args = [])
63
+ * @method \Aws\Result listPrincipalPolicies(array $args = [])
64
+ * @method \GuzzleHttp\Promise\Promise listPrincipalPoliciesAsync(array $args = [])
65
+ * @method \Aws\Result listPrincipalThings(array $args = [])
66
+ * @method \GuzzleHttp\Promise\Promise listPrincipalThingsAsync(array $args = [])
67
+ * @method \Aws\Result listThingPrincipals(array $args = [])
68
+ * @method \GuzzleHttp\Promise\Promise listThingPrincipalsAsync(array $args = [])
69
+ * @method \Aws\Result listThings(array $args = [])
70
+ * @method \GuzzleHttp\Promise\Promise listThingsAsync(array $args = [])
71
+ * @method \Aws\Result listTopicRules(array $args = [])
72
+ * @method \GuzzleHttp\Promise\Promise listTopicRulesAsync(array $args = [])
73
+ * @method \Aws\Result rejectCertificateTransfer(array $args = [])
74
+ * @method \GuzzleHttp\Promise\Promise rejectCertificateTransferAsync(array $args = [])
75
+ * @method \Aws\Result replaceTopicRule(array $args = [])
76
+ * @method \GuzzleHttp\Promise\Promise replaceTopicRuleAsync(array $args = [])
77
+ * @method \Aws\Result setDefaultPolicyVersion(array $args = [])
78
+ * @method \GuzzleHttp\Promise\Promise setDefaultPolicyVersionAsync(array $args = [])
79
+ * @method \Aws\Result setLoggingOptions(array $args = [])
80
+ * @method \GuzzleHttp\Promise\Promise setLoggingOptionsAsync(array $args = [])
81
+ * @method \Aws\Result transferCertificate(array $args = [])
82
+ * @method \GuzzleHttp\Promise\Promise transferCertificateAsync(array $args = [])
83
+ * @method \Aws\Result updateCertificate(array $args = [])
84
+ * @method \GuzzleHttp\Promise\Promise updateCertificateAsync(array $args = [])
85
+ * @method \Aws\Result updateThing(array $args = [])
86
+ * @method \GuzzleHttp\Promise\Promise updateThingAsync(array $args = [])
87
+ */
88
+ class IotClient extends AwsClient {}
includes/aws/Aws/IotDataPlane/Exception/IotDataPlaneException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\IotDataPlane\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the **AWS IoT Data Plane** service.
8
+ */
9
+ class IotDataPlaneException extends AwsException {}
includes/aws/Aws/IotDataPlane/IotDataPlaneClient.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\IotDataPlane;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * This client is used to interact with the **AWS IoT Data Plane** service.
8
+ *
9
+ * @method \Aws\Result deleteThingShadow(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise deleteThingShadowAsync(array $args = [])
11
+ * @method \Aws\Result getThingShadow(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise getThingShadowAsync(array $args = [])
13
+ * @method \Aws\Result publish(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise publishAsync(array $args = [])
15
+ * @method \Aws\Result updateThingShadow(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise updateThingShadowAsync(array $args = [])
17
+ */
18
+ class IotDataPlaneClient extends AwsClient {}
includes/aws/Aws/JsonCompiler.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ /**
5
+ * Loads JSON files and compiles them into PHP arrays.
6
+ *
7
+ * @internal Please use json_decode instead.
8
+ * @deprecated
9
+ */
10
+ class JsonCompiler
11
+ {
12
+ const CACHE_ENV = 'AWS_PHP_CACHE_DIR';
13
+
14
+ /**
15
+ * Loads a JSON file from cache or from the JSON file directly.
16
+ *
17
+ * @param string $path Path to the JSON file to load.
18
+ *
19
+ * @return mixed
20
+ */
21
+ public function load($path)
22
+ {
23
+ return load_compiled_json($path);
24
+ }
25
+ }
includes/aws/Aws/LruArrayCache.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ /**
5
+ * Simple in-memory LRU cache that limits the number of cached entries.
6
+ *
7
+ * The LRU cache is implemented using PHP's ordered associative array. When
8
+ * accessing an element, the element is removed from the hash and re-added to
9
+ * ensure that recently used items are always at the end of the list while
10
+ * least recently used are at the beginning. When a value is added to the
11
+ * cache, if the number of cached items exceeds the allowed number, the first
12
+ * N number of items are removed from the array.
13
+ */
14
+ class LruArrayCache implements CacheInterface
15
+ {
16
+ /** @var int */
17
+ private $maxItems;
18
+
19
+ /** @var array */
20
+ private $items;
21
+
22
+ /**
23
+ * @param int $maxItems Maximum number of allowed cache items.
24
+ */
25
+ public function __construct($maxItems = 1000)
26
+ {
27
+ $this->maxItems = $maxItems;
28
+ }
29
+
30
+ public function get($key)
31
+ {
32
+ if (!isset($this->items[$key])) {
33
+ return null;
34
+ }
35
+
36
+ $entry = $this->items[$key];
37
+
38
+ // Ensure the item is not expired.
39
+ if (!$entry[1] || time() < $entry[1]) {
40
+ // LRU: remove the item and push it to the end of the array.
41
+ unset($this->items[$key]);
42
+ $this->items[$key] = $entry;
43
+ return $entry[0];
44
+ }
45
+
46
+ unset($this->items[$key]);
47
+ return null;
48
+ }
49
+
50
+ public function set($key, $value, $ttl = 0)
51
+ {
52
+ // Only call time() if the TTL is not 0/false/null
53
+ $ttl = $ttl ? time() + $ttl : 0;
54
+ $this->items[$key] = [$value, $ttl];
55
+
56
+ // Determine if there are more items in the cache than allowed.
57
+ $diff = count($this->items) - $this->maxItems;
58
+
59
+ // Clear out least recently used items.
60
+ if ($diff > 0) {
61
+ // Reset to the beginning of the array and begin unsetting.
62
+ reset($this->items);
63
+ for ($i = 0; $i < $diff; $i++) {
64
+ unset($this->items[key($this->items)]);
65
+ next($this->items);
66
+ }
67
+ }
68
+ }
69
+
70
+ public function remove($key)
71
+ {
72
+ unset($this->items[$key]);
73
+ }
74
+ }
includes/aws/Aws/Middleware.php ADDED
@@ -0,0 +1,308 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Aws\Api\Service;
5
+ use Aws\Api\Validator;
6
+ use Aws\Credentials\CredentialsInterface;
7
+ use GuzzleHttp\Promise;
8
+ use GuzzleHttp\Psr7;
9
+ use GuzzleHttp\Psr7\LazyOpenStream;
10
+ use Psr\Http\Message\RequestInterface;
11
+
12
+ final class Middleware
13
+ {
14
+ /**
15
+ * Middleware used to allow a command parameter (e.g., "SourceFile") to
16
+ * be used to specify the source of data for an upload operation.
17
+ *
18
+ * @param Service $api
19
+ * @param string $bodyParameter
20
+ * @param string $sourceParameter
21
+ *
22
+ * @return callable
23
+ */
24
+ public static function sourceFile(
25
+ Service $api,
26
+ $bodyParameter = 'Body',
27
+ $sourceParameter = 'SourceFile'
28
+ ) {
29
+ return function (callable $handler) use (
30
+ $api,
31
+ $bodyParameter,
32
+ $sourceParameter
33
+ ) {
34
+ return function (
35
+ CommandInterface $command,
36
+ RequestInterface $request = null)
37
+ use (
38
+ $handler,
39
+ $api,
40
+ $bodyParameter,
41
+ $sourceParameter
42
+ ) {
43
+ $operation = $api->getOperation($command->getName());
44
+ $source = $command[$sourceParameter];
45
+
46
+ if ($source !== null
47
+ && $operation->getInput()->hasMember($bodyParameter)
48
+ ) {
49
+ $command[$bodyParameter] = new LazyOpenStream($source, 'r');
50
+ unset($command[$sourceParameter]);
51
+ }
52
+
53
+ return $handler($command, $request);
54
+ };
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Adds a middleware that uses client-side validation.
60
+ *
61
+ * @param Service $api API being accessed.
62
+ *
63
+ * @return callable
64
+ */
65
+ public static function validation(Service $api)
66
+ {
67
+ $validator = new Validator();
68
+ return function (callable $handler) use ($api, $validator) {
69
+ return function (
70
+ CommandInterface $command,
71
+ RequestInterface $request = null
72
+ ) use ($api, $validator, $handler) {
73
+ $operation = $api->getOperation($command->getName());
74
+ $validator->validate(
75
+ $command->getName(),
76
+ $operation->getInput(),
77
+ $command->toArray()
78
+ );
79
+ return $handler($command, $request);
80
+ };
81
+ };
82
+ }
83
+
84
+ /**
85
+ * Builds an HTTP request for a command.
86
+ *
87
+ * @param callable $serializer Function used to serialize a request for a
88
+ * command.
89
+ * @return callable
90
+ */
91
+ public static function requestBuilder(callable $serializer)
92
+ {
93
+ return function (callable $handler) use ($serializer) {
94
+ return function (CommandInterface $command) use ($serializer, $handler) {
95
+ return $handler($command, $serializer($command));
96
+ };
97
+ };
98
+ }
99
+
100
+ /**
101
+ * Creates a middleware that signs requests for a command.
102
+ *
103
+ * @param callable $credProvider Credentials provider function that
104
+ * returns a promise that is resolved
105
+ * with a CredentialsInterface object.
106
+ * @param callable $signatureFunction Function that accepts a Command
107
+ * object and returns a
108
+ * SignatureInterface.
109
+ *
110
+ * @return callable
111
+ */
112
+ public static function signer(callable $credProvider, callable $signatureFunction)
113
+ {
114
+ return function (callable $handler) use ($signatureFunction, $credProvider) {
115
+ return function (
116
+ CommandInterface $command,
117
+ RequestInterface $request
118
+ ) use ($handler, $signatureFunction, $credProvider) {
119
+ $signer = $signatureFunction($command);
120
+ return $credProvider()->then(
121
+ function (CredentialsInterface $creds)
122
+ use ($handler, $command, $signer, $request) {
123
+ return $handler(
124
+ $command,
125
+ $signer->signRequest($request, $creds)
126
+ );
127
+ }
128
+ );
129
+ };
130
+ };
131
+ }
132
+
133
+ /**
134
+ * Creates a middleware that invokes a callback at a given step.
135
+ *
136
+ * The tap callback accepts a CommandInterface and RequestInterface as
137
+ * arguments but is not expected to return a new value or proxy to
138
+ * downstream middleware. It's simply a way to "tap" into the handler chain
139
+ * to debug or get an intermediate value.
140
+ *
141
+ * @param callable $fn Tap function
142
+ *
143
+ * @return callable
144
+ */
145
+ public static function tap(callable $fn)
146
+ {
147
+ return function (callable $handler) use ($fn) {
148
+ return function (
149
+ CommandInterface $command,
150
+ RequestInterface $request = null
151
+ ) use ($handler, $fn) {
152
+ $fn($command, $request);
153
+ return $handler($command, $request);
154
+ };
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Middleware wrapper function that retries requests based on the boolean
160
+ * result of invoking the provided "decider" function.
161
+ *
162
+ * If no delay function is provided, a simple implementation of exponential
163
+ * backoff will be utilized.
164
+ *
165
+ * @param callable $decider Function that accepts the number of retries,
166
+ * a request, [result], and [exception] and
167
+ * returns true if the command is to be retried.
168
+ * @param callable $delay Function that accepts the number of retries and
169
+ * returns the number of milliseconds to delay.
170
+ *
171
+ * @return callable
172
+ */
173
+ public static function retry(callable $decider = null, callable $delay = null)
174
+ {
175
+ $decider = $decider ?: RetryMiddleware::createDefaultDecider();
176
+ $delay = $delay ?: [RetryMiddleware::class, 'exponentialDelay'];
177
+
178
+ return function (callable $handler) use ($decider, $delay) {
179
+ return new RetryMiddleware($decider, $delay, $handler);
180
+ };
181
+ }
182
+
183
+ /**
184
+ * Middleware wrapper function that adds a Content-Type header to requests.
185
+ * This is only done when the Content-Type has not already been set, and the
186
+ * request body's URI is available. It then checks the file extension of the
187
+ * URI to determine the mime-type.
188
+ *
189
+ * @param array $operations Operations that Content-Type should be added to.
190
+ *
191
+ * @return callable
192
+ */
193
+ public static function contentType(array $operations)
194
+ {
195
+ return function (callable $handler) use ($operations) {
196
+ return function (
197
+ CommandInterface $command,
198
+ RequestInterface $request = null
199
+ ) use ($handler, $operations) {
200
+ if (!$request->hasHeader('Content-Type')
201
+ && in_array($command->getName(), $operations, true)
202
+ && ($uri = $request->getBody()->getMetadata('uri'))
203
+ ) {
204
+ $request = $request->withHeader(
205
+ 'Content-Type',
206
+ Psr7\mimetype_from_filename($uri) ?: 'application/octet-stream'
207
+ );
208
+ }
209
+
210
+ return $handler($command, $request);
211
+ };
212
+ };
213
+ }
214
+
215
+ /**
216
+ * Tracks command and request history using a history container.
217
+ *
218
+ * This is useful for testing.
219
+ *
220
+ * @param History $history History container to store entries.
221
+ *
222
+ * @return callable
223
+ */
224
+ public static function history(History $history)
225
+ {
226
+ return function (callable $handler) use ($history) {
227
+ return function (
228
+ CommandInterface $command,
229
+ RequestInterface $request = null
230
+ ) use ($handler, $history) {
231
+ $ticket = $history->start($command, $request);
232
+ return $handler($command, $request)
233
+ ->then(
234
+ function ($result) use ($history, $ticket) {
235
+ $history->finish($ticket, $result);
236
+ return $result;
237
+ },
238
+ function ($reason) use ($history, $ticket) {
239
+ $history->finish($ticket, $reason);
240
+ return Promise\rejection_for($reason);
241
+ }
242
+ );
243
+ };
244
+ };
245
+ }
246
+
247
+ /**
248
+ * Creates a middleware that applies a map function to requests as they
249
+ * pass through the middleware.
250
+ *
251
+ * @param callable $f Map function that accepts a RequestInterface and
252
+ * returns a RequestInterface.
253
+ *
254
+ * @return callable
255
+ */
256
+ public static function mapRequest(callable $f)
257
+ {
258
+ return function (callable $handler) use ($f) {
259
+ return function (
260
+ CommandInterface $command,
261
+ RequestInterface $request = null
262
+ ) use ($handler, $f) {
263
+ return $handler($command, $f($request));
264
+ };
265
+ };
266
+ }
267
+
268
+ /**
269
+ * Creates a middleware that applies a map function to commands as they
270
+ * pass through the middleware.
271
+ *
272
+ * @param callable $f Map function that accepts a command and returns a
273
+ * command.
274
+ *
275
+ * @return callable
276
+ */
277
+ public static function mapCommand(callable $f)
278
+ {
279
+ return function (callable $handler) use ($f) {
280
+ return function (
281
+ CommandInterface $command,
282
+ RequestInterface $request = null
283
+ ) use ($handler, $f) {
284
+ return $handler($f($command), $request);
285
+ };
286
+ };
287
+ }
288
+
289
+ /**
290
+ * Creates a middleware that applies a map function to results.
291
+ *
292
+ * @param callable $f Map function that accepts an Aws\ResultInterface and
293
+ * returns an Aws\ResultInterface.
294
+ *
295
+ * @return callable
296
+ */
297
+ public static function mapResult(callable $f)
298
+ {
299
+ return function (callable $handler) use ($f) {
300
+ return function (
301
+ CommandInterface $command,
302
+ RequestInterface $request = null
303
+ ) use ($handler, $f) {
304
+ return $handler($command, $request)->then($f);
305
+ };
306
+ };
307
+ }
308
+ }
includes/aws/Aws/MockHandler.php ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Aws\Exception\AwsException;
5
+ use GuzzleHttp\Promise;
6
+ use GuzzleHttp\Promise\RejectedPromise;
7
+ use Psr\Http\Message\RequestInterface;
8
+
9
+ /**
10
+ * Returns promises that are rejected or fulfilled using a queue of
11
+ * Aws\ResultInterface and Aws\Exception\AwsException objects.
12
+ */
13
+ class MockHandler implements \Countable
14
+ {
15
+ private $queue;
16
+ private $lastCommand;
17
+ private $lastRequest;
18
+ private $onFulfilled;
19
+ private $onRejected;
20
+
21
+ /**
22
+ * The passed in value must be an array of {@see Aws\ResultInterface} or
23
+ * {@see AwsException} objects that acts as a queue of results or
24
+ * exceptions to return each time the handler is invoked.
25
+ *
26
+ * @param array $resultOrQueue
27
+ * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
28
+ * @param callable $onRejected Callback to invoke when the return value is rejected.
29
+ */
30
+ public function __construct(
31
+ array $resultOrQueue = [],
32
+ callable $onFulfilled = null,
33
+ callable $onRejected = null
34
+ ) {
35
+ $this->onFulfilled = $onFulfilled;
36
+ $this->onRejected = $onRejected;
37
+
38
+ if ($resultOrQueue) {
39
+ call_user_func_array([$this, 'append'], $resultOrQueue);
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Adds one or more variadic ResultInterface or AwsException objects to the
45
+ * queue.
46
+ */
47
+ public function append()
48
+ {
49
+ foreach (func_get_args() as $value) {
50
+ if ($value instanceof ResultInterface
51
+ || $value instanceof AwsException
52
+ || is_callable($value)
53
+ ) {
54
+ $this->queue[] = $value;
55
+ } else {
56
+ throw new \InvalidArgumentException('Expected an Aws\ResultInterface or Aws\Exception\AwsException.');
57
+ }
58
+ }
59
+ }
60
+
61
+ public function __invoke(
62
+ CommandInterface $command,
63
+ RequestInterface $request
64
+ ) {
65
+ if (!$this->queue) {
66
+ $last = $this->lastCommand
67
+ ? ' The last command sent was ' . $this->lastCommand->getName() . '.'
68
+ : '';
69
+ throw new \RuntimeException('Mock queue is empty. Trying to send a '
70
+ . $command->getName() . ' command failed.' . $last);
71
+ }
72
+
73
+ $this->lastCommand = $command;
74
+ $this->lastRequest = $request;
75
+
76
+ $result = array_shift($this->queue);
77
+
78
+ if (is_callable($result)) {
79
+ $result = $result($command, $request);
80
+ }
81
+
82
+ if ($result instanceof \Exception) {
83
+ $result = new RejectedPromise($result);
84
+ } else {
85
+ // Add an effective URI and statusCode if not present.
86
+ $meta = $result['@metadata'];
87
+ if (!isset($meta['effectiveUri'])) {
88
+ $meta['effectiveUri'] = (string) $request->getUri();
89
+ }
90
+ if (!isset($meta['statusCode'])) {
91
+ $meta['statusCode'] = 200;
92
+ }
93
+ $result['@metadata'] = $meta;
94
+ $result = Promise\promise_for($result);
95
+ }
96
+
97
+ $result->then($this->onFulfilled, $this->onRejected);
98
+
99
+ return $result;
100
+ }
101
+
102
+ /**
103
+ * Get the last received request.
104
+ *
105
+ * @return RequestInterface
106
+ */
107
+ public function getLastRequest()
108
+ {
109
+ return $this->lastRequest;
110
+ }
111
+
112
+ /**
113
+ * Get the last received command.
114
+ *
115
+ * @return CommandInterface
116
+ */
117
+ public function getLastCommand()
118
+ {
119
+ return $this->lastCommand;
120
+ }
121
+
122
+ /**
123
+ * Returns the number of remaining items in the queue.
124
+ *
125
+ * @return int
126
+ */
127
+ public function count()
128
+ {
129
+ return count($this->queue);
130
+ }
131
+ }
includes/aws/Aws/Multipart/AbstractUploadManager.php ADDED
@@ -0,0 +1,297 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Multipart;
3
+
4
+ use Aws\AwsClientInterface as Client;
5
+ use Aws\CommandInterface;
6
+ use Aws\CommandPool;
7
+ use Aws\Exception\AwsException;
8
+ use Aws\Exception\MultipartUploadException;
9
+ use Aws\Result;
10
+ use Aws\ResultInterface;
11
+ use GuzzleHttp\Promise;
12
+ use GuzzleHttp\Promise\PromiseInterface;
13
+ use GuzzleHttp\Psr7;
14
+ use InvalidArgumentException as IAE;
15
+ use Psr\Http\Message\RequestInterface;
16
+
17
+ /**
18
+ * Encapsulates the execution of a multipart upload to S3 or Glacier.
19
+ *
20
+ * @internal
21
+ */
22
+ abstract class AbstractUploadManager implements Promise\PromisorInterface
23
+ {
24
+ const DEFAULT_CONCURRENCY = 5;
25
+
26
+ /** @var array Default values for base multipart configuration */
27
+ private static $defaultConfig = [
28
+ 'part_size' => null,
29
+ 'state' => null,
30
+ 'concurrency' => self::DEFAULT_CONCURRENCY,
31
+ 'before_initiate' => null,
32
+ 'before_upload' => null,
33
+ 'before_complete' => null,
34
+ ];
35
+
36
+ /** @var Client Client used for the upload. */
37
+ protected $client;
38
+
39
+ /** @var array Configuration used to perform the upload. */
40
+ protected $config;
41
+
42
+ /** @var array Service-specific information about the upload workflow. */
43
+ protected $info;
44
+
45
+ /** @var PromiseInterface Promise that represents the multipart upload. */
46
+ protected $promise;
47
+
48
+ /** @var UploadState State used to manage the upload. */
49
+ protected $state;
50
+
51
+ /**
52
+ * @param Client $client
53
+ * @param array $config
54
+ */
55
+ public function __construct(Client $client, array $config = [])
56
+ {
57
+ $this->client = $client;
58
+ $this->info = $this->loadUploadWorkflowInfo();
59
+ $this->config = $config + self::$defaultConfig;
60
+ $this->state = $this->determineState();
61
+ }
62
+
63
+ /**
64
+ * Returns the current state of the upload
65
+ *
66
+ * @return UploadState
67
+ */
68
+ public function getState()
69
+ {
70
+ return $this->state;
71
+ }
72
+
73
+ /**
74
+ * Upload the source using multipart upload operations.
75
+ *
76
+ * @return Result The result of the CompleteMultipartUpload operation.
77
+ * @throws \LogicException if the upload is already complete or aborted.
78
+ * @throws MultipartUploadException if an upload operation fails.
79
+ */
80
+ public function upload()
81
+ {
82
+ return $this->promise()->wait();
83
+ }
84
+
85
+ /**
86
+ * Upload the source asynchronously using multipart upload operations.
87
+ *
88
+ * @return PromiseInterface
89
+ */
90
+ public function promise()
91
+ {
92
+ if ($this->promise) {
93
+ return $this->promise;
94
+ }
95
+
96
+ return $this->promise = Promise\coroutine(function () {
97
+ // Initiate the upload.
98
+ if ($this->state->isCompleted()) {
99
+ throw new \LogicException('This multipart upload has already '
100
+ . 'been completed or aborted.'
101
+ );
102
+ } elseif (!$this->state->isInitiated()) {
103
+ $result = (yield $this->execCommand('initiate', $this->getInitiateParams()));
104
+ $this->state->setUploadId(
105
+ $this->info['id']['upload_id'],
106
+ $result[$this->info['id']['upload_id']]
107
+ );
108
+ $this->state->setStatus(UploadState::INITIATED);
109
+ }
110
+
111
+ // Create a command pool from a generator that yields UploadPart
112
+ // commands for each upload part.
113
+ $resultHandler = $this->getResultHandler($errors);
114
+ $commands = new CommandPool(
115
+ $this->client,
116
+ $this->getUploadCommands($resultHandler),
117
+ [
118
+ 'concurrency' => $this->config['concurrency'],
119
+ 'before' => $this->config['before_upload'],
120
+ ]
121
+ );
122
+
123
+ // Execute the pool of commands concurrently, and process errors.
124
+ yield $commands->promise();
125
+ if ($errors) {
126
+ throw new MultipartUploadException($this->state, $errors);
127
+ }
128
+
129
+ // Complete the multipart upload.
130
+ yield $this->execCommand('complete', $this->getCompleteParams());
131
+ $this->state->setStatus(UploadState::COMPLETED);
132
+ })->otherwise(function (\Exception $e) {
133
+ // Throw errors from the operations as a specific Multipart error.
134
+ if ($e instanceof AwsException) {
135
+ $e = new MultipartUploadException($this->state, $e);
136
+ }
137
+ throw $e;
138
+ });
139
+ }
140
+
141
+ protected function getConfig()
142
+ {
143
+ return $this->config;
144
+ }
145
+
146
+ /**
147
+ * Provides service-specific information about the multipart upload
148
+ * workflow.
149
+ *
150
+ * This array of data should include the keys: 'command', 'id', and 'part_num'.
151
+ *
152
+ * @return array
153
+ */
154
+ abstract protected function loadUploadWorkflowInfo();
155
+
156
+ /**
157
+ * Determines the part size to use for upload parts.
158
+ *
159
+ * Examines the provided partSize value and the source to determine the
160
+ * best possible part size.
161
+ *
162
+ * @throws \InvalidArgumentException if the part size is invalid.
163
+ *
164
+ * @return int
165
+ */
166
+ abstract protected function determinePartSize();
167
+
168
+ /**
169
+ * Uses information from the Command and Result to determine which part was
170
+ * uploaded and mark it as uploaded in the upload's state.
171
+ *
172
+ * @param CommandInterface $command
173
+ * @param ResultInterface $result
174
+ */
175
+ abstract protected function handleResult(
176
+ CommandInterface $command,
177
+ ResultInterface $result
178
+ );
179
+
180
+ /**
181
+ * Gets the service-specific parameters used to initiate the upload.
182
+ *
183
+ * @return array
184
+ */
185
+ abstract protected function getInitiateParams();
186
+
187
+ /**
188
+ * Gets the service-specific parameters used to complete the upload.
189
+ *
190
+ * @return array
191
+ */
192
+ abstract protected function getCompleteParams();
193
+
194
+ /**
195
+ * Based on the config and service-specific workflow info, creates a
196
+ * `Promise` for an `UploadState` object.
197
+ *
198
+ * @return PromiseInterface A `Promise` that resolves to an `UploadState`.
199
+ */
200
+ private function determineState()
201
+ {
202
+ // If the state was provided via config, then just use it.
203
+ if ($this->config['state'] instanceof UploadState) {
204
+ return $this->config['state'];
205
+ }
206
+
207
+ // Otherwise, construct a new state from the provided identifiers.
208
+ $required = $this->info['id'];
209
+ $id = [$required['upload_id'] => null];
210
+ unset($required['upload_id']);
211
+ foreach ($required as $key => $param) {
212
+ if (!$this->config[$key]) {
213
+ throw new IAE('You must provide a value for "' . $key . '" in '
214
+ . 'your config for the MultipartUploader for '
215
+ . $this->client->getApi()->getServiceFullName() . '.');
216
+ }
217
+ $id[$param] = $this->config[$key];
218
+ }
219
+ $state = new UploadState($id);
220
+ $state->setPartSize($this->determinePartSize());
221
+
222
+ return $state;
223
+ }
224
+
225
+ /**
226
+ * Executes a MUP command with all of the parameters for the operation.
227
+ *
228
+ * @param string $operation Name of the operation.
229
+ * @param array $params Service-specific params for the operation.
230
+ *
231
+ * @return PromiseInterface
232
+ */
233
+ private function execCommand($operation, array $params)
234
+ {
235
+ // Create the command.
236
+ $command = $this->client->getCommand(
237
+ $this->info['command'][$operation],
238
+ $params + $this->state->getId()
239
+ );
240
+
241
+ // Execute the before callback.
242
+ if (is_callable($this->config["before_{$operation}"])) {
243
+ $this->config["before_{$operation}"]($command);
244
+ }
245
+
246
+ // Execute the command asynchronously and return the promise.
247
+ return $this->client->executeAsync($command);
248
+ }
249
+
250
+ /**
251
+ * Returns a middleware for processing responses of part upload operations.
252
+ *
253
+ * - Adds an onFulfilled callback that calls the service-specific
254
+ * handleResult method on the Result of the operation.
255
+ * - Adds an onRejected callback that adds the error to an array of errors.
256
+ * - Has a passedByRef $errors arg that the exceptions get added to. The
257
+ * caller should use that &$errors array to do error handling.
258
+ *
259
+ * @param array $errors Errors from upload operations are added to this.
260
+ *
261
+ * @return callable
262
+ */
263
+ private function getResultHandler(&$errors = [])
264
+ {
265
+ return function (callable $handler) use (&$errors) {
266
+ return function (
267
+ CommandInterface $command,
268
+ RequestInterface $request = null
269
+ ) use ($handler, &$errors) {
270
+ return $handler($command, $request)->then(
271
+ function (ResultInterface $result) use ($command) {
272
+ $this->handleResult($command, $result);
273
+ return $result;
274
+ },
275
+ function (AwsException $e) use (&$errors) {
276
+ $errors[$e->getCommand()[$this->info['part_num']]] = $e;
277
+ return new Result();
278
+ }
279
+ );
280
+ };
281
+ };
282
+ }
283
+
284
+ /**
285
+ * Creates a generator that yields part data for the upload's source.
286
+ *
287
+ * Yields associative arrays of parameters that are ultimately merged in
288
+ * with others to form the complete parameters of a command. This can
289
+ * include the Body parameter, which is a limited stream (i.e., a Stream
290
+ * object, decorated with a LimitStream).
291
+ *
292
+ * @param callable $resultHandler
293
+ *
294
+ * @return \Generator
295
+ */
296
+ abstract protected function getUploadCommands(callable $resultHandler);
297
+ }
includes/aws/Aws/Multipart/AbstractUploader.php ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Multipart;
3
+
4
+ use Aws\AwsClientInterface as Client;
5
+ use GuzzleHttp\Psr7;
6
+ use InvalidArgumentException as IAE;
7
+ use Psr\Http\Message\StreamInterface as Stream;
8
+
9
+ abstract class AbstractUploader extends AbstractUploadManager
10
+ {
11
+ /** @var Stream Source of the data to be uploaded. */
12
+ protected $source;
13
+
14
+ /**
15
+ * @param Client $client
16
+ * @param mixed $source
17
+ * @param array $config
18
+ */
19
+ public function __construct(Client $client, $source, array $config = [])
20
+ {
21
+ $this->source = $this->determineSource($source);
22
+ parent::__construct($client, $config);
23
+ }
24
+
25
+ /**
26
+ * Create a stream for a part that starts at the current position and
27
+ * has a length of the upload part size (or less with the final part).
28
+ *
29
+ * @param Stream $stream
30
+ *
31
+ * @return Psr7\LimitStream
32
+ */
33
+ protected function limitPartStream(Stream $stream)
34
+ {
35
+ // Limit what is read from the stream to the part size.
36
+ return new Psr7\LimitStream(
37
+ $stream,
38
+ $this->state->getPartSize(),
39
+ $this->source->tell()
40
+ );
41
+ }
42
+
43
+ protected function getUploadCommands(callable $resultHandler)
44
+ {
45
+ // Determine if the source can be seeked.
46
+ $seekable = $this->source->isSeekable()
47
+ && $this->source->getMetadata('wrapper_type') === 'plainfile';
48
+
49
+ for ($partNumber = 1; $this->isEof($seekable); $partNumber++) {
50
+ // If we haven't already uploaded this part, yield a new part.
51
+ if (!$this->state->hasPartBeenUploaded($partNumber)) {
52
+ $partStartPos = $this->source->tell();
53
+ if (!($data = $this->createPart($seekable, $partNumber))) {
54
+ break;
55
+ }
56
+ $command = $this->client->getCommand(
57
+ $this->info['command']['upload'],
58
+ $data + $this->state->getId()
59
+ );
60
+ $command->getHandlerList()->appendSign($resultHandler, 'mup');
61
+ yield $command;
62
+ if ($this->source->tell() > $partStartPos) {
63
+ continue;
64
+ }
65
+ }
66
+
67
+ // Advance the source's offset if not already advanced.
68
+ if ($seekable) {
69
+ $this->source->seek(min(
70
+ $this->source->tell() + $this->state->getPartSize(),
71
+ $this->source->getSize()
72
+ ));
73
+ } else {
74
+ $this->source->read($this->state->getPartSize());
75
+ }
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Generates the parameters for an upload part by analyzing a range of the
81
+ * source starting from the current offset up to the part size.
82
+ *
83
+ * @param bool $seekable
84
+ * @param int $number
85
+ *
86
+ * @return array|null
87
+ */
88
+ abstract protected function createPart($seekable, $number);
89
+
90
+ /**
91
+ * Checks if the source is at EOF.
92
+ *
93
+ * @param bool $seekable
94
+ *
95
+ * @return bool
96
+ */
97
+ private function isEof($seekable)
98
+ {
99
+ return $seekable
100
+ ? $this->source->tell() < $this->source->getSize()
101
+ : !$this->source->eof();
102
+ }
103
+
104
+ /**
105
+ * Turns the provided source into a stream and stores it.
106
+ *
107
+ * If a string is provided, it is assumed to be a filename, otherwise, it
108
+ * passes the value directly to `Psr7\stream_for()`.
109
+ *
110
+ * @param mixed $source
111
+ *
112
+ * @return Stream
113
+ */
114
+ private function determineSource($source)
115
+ {
116
+ // Use the contents of a file as the data source.
117
+ if (is_string($source)) {
118
+ $source = Psr7\try_fopen($source, 'r');
119
+ }
120
+
121
+ // Create a source stream.
122
+ $stream = Psr7\stream_for($source);
123
+ if (!$stream->isReadable()) {
124
+ throw new IAE('Source stream must be readable.');
125
+ }
126
+
127
+ return $stream;
128
+ }
129
+ }
includes/aws/Aws/Multipart/UploadState.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Multipart;
3
+
4
+ /**
5
+ * Representation of the multipart upload.
6
+ *
7
+ * This object keeps track of the state of the upload, including the status and
8
+ * which parts have been uploaded.
9
+ */
10
+ class UploadState
11
+ {
12
+ const CREATED = 0;
13
+ const INITIATED = 1;
14
+ const COMPLETED = 2;
15
+
16
+ /** @var array Params used to identity the upload. */
17
+ private $id;
18
+
19
+ /** @var int Part size being used by the upload. */
20
+ private $partSize;
21
+
22
+ /** @var array Parts that have been uploaded. */
23
+ private $uploadedParts = [];
24
+
25
+ /** @var int Identifies the status the upload. */
26
+ private $status = self::CREATED;
27
+
28
+ /**
29
+ * @param array $id Params used to identity the upload.
30
+ */
31
+ public function __construct(array $id)
32
+ {
33
+ $this->id = $id;
34
+ }
35
+
36
+ /**
37
+ * Get the upload's ID, which is a tuple of parameters that can uniquely
38
+ * identify the upload.
39
+ *
40
+ * @return array
41
+ */
42
+ public function getId()
43
+ {
44
+ return $this->id;
45
+ }
46
+
47
+ /**
48
+ * Set's the "upload_id", or 3rd part of the upload's ID. This typically
49
+ * only needs to be done after initiating an upload.
50
+ *
51
+ * @param string $key The param key of the upload_id.
52
+ * @param string $value The param value of the upload_id.
53
+ */
54
+ public function setUploadId($key, $value)
55
+ {
56
+ $this->id[$key] = $value;
57
+ }
58
+
59
+ /**
60
+ * Get the part size.
61
+ *
62
+ * @return int
63
+ */
64
+ public function getPartSize()
65
+ {
66
+ return $this->partSize;
67
+ }
68
+
69
+ /**
70
+ * Set the part size.
71
+ *
72
+ * @param $partSize int Size of upload parts.
73
+ */
74
+ public function setPartSize($partSize)
75
+ {
76
+ $this->partSize = $partSize;
77
+ }
78
+
79
+ /**
80
+ * Marks a part as being uploaded.
81
+ *
82
+ * @param int $partNumber The part number.
83
+ * @param array $partData Data from the upload operation that needs to be
84
+ * recalled during the complete operation.
85
+ */
86
+ public function markPartAsUploaded($partNumber, array $partData = [])
87
+ {
88
+ $this->uploadedParts[$partNumber] = $partData;
89
+ }
90
+
91
+ /**
92
+ * Returns whether a part has been uploaded.
93
+ *
94
+ * @param int $partNumber The part number.
95
+ *
96
+ * @return bool
97
+ */
98
+ public function hasPartBeenUploaded($partNumber)
99
+ {
100
+ return isset($this->uploadedParts[$partNumber]);
101
+ }
102
+
103
+ /**
104
+ * Returns a sorted list of all the uploaded parts.
105
+ *
106
+ * @return array
107
+ */
108
+ public function getUploadedParts()
109
+ {
110
+ ksort($this->uploadedParts);
111
+
112
+ return $this->uploadedParts;
113
+ }
114
+
115
+ /**
116
+ * Set the status of the upload.
117
+ *
118
+ * @param int $status Status is an integer code defined by the constants
119
+ * CREATED, INITIATED, and COMPLETED on this class.
120
+ */
121
+ public function setStatus($status)
122
+ {
123
+ $this->status = $status;
124
+ }
125
+
126
+ /**
127
+ * Determines whether the upload state is in the INITIATED status.
128
+ *
129
+ * @return bool
130
+ */
131
+ public function isInitiated()
132
+ {
133
+ return $this->status === self::INITIATED;
134
+ }
135
+
136
+ /**
137
+ * Determines whether the upload state is in the COMPLETED status.
138
+ *
139
+ * @return bool
140
+ */
141
+ public function isCompleted()
142
+ {
143
+ return $this->status === self::COMPLETED;
144
+ }
145
+ }
includes/aws/Aws/PhpHash.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ /**
5
+ * Incremental hashing using PHP's hash functions.
6
+ */
7
+ class PhpHash implements HashInterface
8
+ {
9
+ /** @var resource */
10
+ private $context;
11
+
12
+ /** @var string */
13
+ private $algo;
14
+
15
+ /** @var array */
16
+ private $options;
17
+
18
+ /** @var string */
19
+ private $hash;
20
+
21
+ /**
22
+ * @param string $algo Hashing algorithm. One of PHP's hash_algos()
23
+ * return values (e.g. md5, sha1, etc...).
24
+ * @param array $options Associative array of hashing options:
25
+ * - key: Secret key used with the hashing algorithm.
26
+ * - base64: Set to true to base64 encode the value when complete.
27
+ */
28
+ public function __construct($algo, array $options = [])
29
+ {
30
+ $this->algo = $algo;
31
+ $this->options = $options;
32
+ }
33
+
34
+ public function update($data)
35
+ {
36
+ if ($this->hash !== null) {
37
+ $this->reset();
38
+ }
39
+
40
+ hash_update($this->getContext(), $data);
41
+ }
42
+
43
+ public function complete()
44
+ {
45
+ if ($this->hash) {
46
+ return $this->hash;
47
+ }
48
+
49
+ $this->hash = hash_final($this->getContext(), true);
50
+
51
+ if (isset($this->options['base64']) && $this->options['base64']) {
52
+ $this->hash = base64_encode($this->hash);
53
+ }
54
+
55
+ return $this->hash;
56
+ }
57
+
58
+ public function reset()
59
+ {
60
+ $this->context = $this->hash = null;
61
+ }
62
+
63
+ /**
64
+ * Get a hash context or create one if needed
65
+ *
66
+ * @return resource
67
+ */
68
+ private function getContext()
69
+ {
70
+ if (!$this->context) {
71
+ $key = isset($this->options['key']) ? $this->options['key'] : null;
72
+ $this->context = hash_init(
73
+ $this->algo,
74
+ $key ? HASH_HMAC : 0,
75
+ $key
76
+ );
77
+ }
78
+
79
+ return $this->context;
80
+ }
81
+ }
includes/aws/Aws/Result.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use JmesPath\Env as JmesPath;
5
+
6
+ /**
7
+ * AWS result.
8
+ */
9
+ class Result implements ResultInterface
10
+ {
11
+ use HasDataTrait;
12
+
13
+ public function __construct(array $data = [])
14
+ {
15
+ $this->data = $data;
16
+ }
17
+
18
+ public function hasKey($name)
19
+ {
20
+ return isset($this->data[$name]);
21
+ }
22
+
23
+ public function get($key)
24
+ {
25
+ return $this[$key];
26
+ }
27
+
28
+ public function search($expression)
29
+ {
30
+ return JmesPath::search($expression, $this->toArray());
31
+ }
32
+
33
+ public function __toString()
34
+ {
35
+ $jsonData = json_encode($this->toArray(), JSON_PRETTY_PRINT);
36
+ return <<<EOT
37
+ Model Data
38
+ ----------
39
+ Data can be retrieved from the model object using the get() method of the
40
+ model (e.g., `\$result->get(\$key)`) or "accessing the result like an
41
+ associative array (e.g. `\$result['key']`). You can also execute JMESPath
42
+ expressions on the result data using the search() method.
43
+
44
+ {$jsonData}
45
+
46
+ EOT;
47
+ }
48
+
49
+ /**
50
+ * @deprecated
51
+ */
52
+ public function getPath($path)
53
+ {
54
+ return $this->search(str_replace('/', '.', $path));
55
+ }
56
+ }
includes/aws/Aws/ResultInterface.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ /**
5
+ * Represents an AWS result object that is returned from executing an operation.
6
+ */
7
+ interface ResultInterface extends \ArrayAccess, \IteratorAggregate, \Countable
8
+ {
9
+ /**
10
+ * Provides debug information about the result object
11
+ *
12
+ * @return string
13
+ */
14
+ public function __toString();
15
+
16
+ /**
17
+ * Convert the result to an array.
18
+ *
19
+ * @return array
20
+ */
21
+ public function toArray();
22
+
23
+ /**
24
+ * Check if the model contains a key by name
25
+ *
26
+ * @param string $name Name of the key to retrieve
27
+ *
28
+ * @return bool
29
+ */
30
+ public function hasKey($name);
31
+
32
+ /**
33
+ * Get a specific key value from the result model.
34
+ *
35
+ * @param string $key Key to retrieve.
36
+ *
37
+ * @return mixed|null Value of the key or NULL if not found.
38
+ */
39
+ public function get($key);
40
+
41
+ /**
42
+ * Returns the result of executing a JMESPath expression on the contents
43
+ * of the Result model.
44
+ *
45
+ * $result = $client->execute($command);
46
+ * $jpResult = $result->search('foo.*.bar[?baz > `10`]');
47
+ *
48
+ * @param string $expression JMESPath expression to execute
49
+ *
50
+ * @return mixed Returns the result of the JMESPath expression.
51
+ * @link http://jmespath.readthedocs.org/en/latest/ JMESPath documentation
52
+ */
53
+ public function search($expression);
54
+ };
includes/aws/Aws/ResultPaginator.php ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use GuzzleHttp\Promise;
5
+
6
+ /**
7
+ * Iterator that yields each page of results of a pageable operation.
8
+ */
9
+ class ResultPaginator implements \Iterator
10
+ {
11
+ /** @var AwsClientInterface Client performing operations. */
12
+ private $client;
13
+
14
+ /** @var string Name of the operation being paginated. */
15
+ private $operation;
16
+
17
+ /** @var array Args for the operation. */
18
+ private $args;
19
+
20
+ /** @var array Configuration for the paginator. */
21
+ private $config;
22
+
23
+ /** @var Result Most recent result from the client. */
24
+ private $result;
25
+
26
+ /** @var string|array Next token to use for pagination. */
27
+ private $nextToken;
28
+
29
+ /** @var int Number of operations/requests performed. */
30
+ private $requestCount = 0;
31
+
32
+ /**
33
+ * @param AwsClientInterface $client
34
+ * @param string $operation
35
+ * @param array $args
36
+ * @param array $config
37
+ */
38
+ public function __construct(
39
+ AwsClientInterface $client,
40
+ $operation,
41
+ array $args,
42
+ array $config
43
+ ) {
44
+ $this->client = $client;
45
+ $this->operation = $operation;
46
+ $this->args = $args;
47
+ $this->config = $config;
48
+ }
49
+
50
+ /**
51
+ * Runs a paginator asynchronously and uses a callback to handle results.
52
+ *
53
+ * The callback should have the signature: function (Aws\Result $result).
54
+ * A non-null return value from the callback will be yielded by the
55
+ * promise. This means that you can return promises from the callback that
56
+ * will need to be resolved before continuing iteration over the remaining
57
+ * items, essentially merging in other promises to the iteration. The last
58
+ * non-null value returned by the callback will be the result that fulfills
59
+ * the promise to any downstream promises.
60
+ *
61
+ * @param callable $handleResult Callback for handling each page of results.
62
+ * The callback accepts the result that was
63
+ * yielded as a single argument. If the
64
+ * callback returns a promise, the promise
65
+ * will be merged into the coroutine.
66
+ *
67
+ * @return Promise\Promise
68
+ */
69
+ public function each(callable $handleResult)
70
+ {
71
+ return Promise\coroutine(function () use ($handleResult) {
72
+ $nextToken = null;
73
+ do {
74
+ $command = $this->createNextCommand($this->args, $nextToken);
75
+ $result = (yield $this->client->executeAsync($command));
76
+ $nextToken = $this->determineNextToken($result);
77
+ $retVal = $handleResult($result);
78
+ if ($retVal !== null) {
79
+ yield Promise\promise_for($retVal);
80
+ }
81
+ } while ($nextToken);
82
+ });
83
+ }
84
+
85
+ /**
86
+ * Returns an iterator that iterates over the values of applying a JMESPath
87
+ * search to each result yielded by the iterator as a flat sequence.
88
+ *
89
+ * @param string $expression JMESPath expression to apply to each result.
90
+ *
91
+ * @return \Iterator
92
+ */
93
+ public function search($expression)
94
+ {
95
+ // Apply JMESPath expression on each result, but as a flat sequence.
96
+ return flatmap($this, function (Result $result) use ($expression) {
97
+ return (array) $result->search($expression);
98
+ });
99
+ }
100
+
101
+ /**
102
+ * @return Result
103
+ */
104
+ public function current()
105
+ {
106
+ return $this->valid() ? $this->result : false;
107
+ }
108
+
109
+ public function key()
110
+ {
111
+ return $this->valid() ? $this->requestCount - 1 : null;
112
+ }
113
+
114
+ public function next()
115
+ {
116
+ $this->result = null;
117
+ }
118
+
119
+ public function valid()
120
+ {
121
+ if ($this->result) {
122
+ return true;
123
+ }
124
+
125
+ if ($this->nextToken || !$this->requestCount) {
126
+ $this->result = $this->client->execute(
127
+ $this->createNextCommand($this->args, $this->nextToken)
128
+ );
129
+ $this->nextToken = $this->determineNextToken($this->result);
130
+ $this->requestCount++;
131
+ return true;
132
+ }
133
+
134
+ return false;
135
+ }
136
+
137
+ public function rewind()
138
+ {
139
+ $this->requestCount = 0;
140
+ $this->nextToken = null;
141
+ $this->result = null;
142
+ }
143
+
144
+ private function createNextCommand(array $args, $nextToken)
145
+ {
146
+ // Prepare arguments
147
+ if ($nextToken) {
148
+ $inputArg = $this->config['input_token'];
149
+ if (is_array($nextToken) && is_array($inputArg)) {
150
+ foreach ($inputArg as $index => $key) {
151
+ $args[$key] = $nextToken[$index];
152
+ }
153
+ } else {
154
+ $args[$inputArg] = $nextToken;
155
+ }
156
+ }
157
+
158
+ return $this->client->getCommand($this->operation, $args);
159
+ }
160
+
161
+ private function determineNextToken(Result $result)
162
+ {
163
+ if (!$this->config['output_token']) {
164
+ return null;
165
+ }
166
+
167
+ if ($this->config['more_results']
168
+ && !$result->search($this->config['more_results'])
169
+ ) {
170
+ return null;
171
+ }
172
+
173
+ $nextToken = is_array($this->config['output_token'])
174
+ ? array_filter($result->search(json_encode($this->config['output_token'])))
175
+ : $result->search($this->config['output_token']);
176
+
177
+ return $nextToken;
178
+ }
179
+ }
includes/aws/Aws/RetryMiddleware.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Aws\Exception\AwsException;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use GuzzleHttp\Promise\PromiseInterface;
7
+ use GuzzleHttp\Psr7;
8
+
9
+ /**
10
+ * @internal Middleware that retries failures.
11
+ */
12
+ class RetryMiddleware
13
+ {
14
+ private static $retryStatusCodes = [
15
+ 500 => true,
16
+ 503 => true
17
+ ];
18
+
19
+ private static $retryCodes = [
20
+ 'RequestLimitExceeded' => true,
21
+ 'Throttling' => true,
22
+ 'ThrottlingException' => true,
23
+ 'ProvisionedThroughputExceededException' => true,
24
+ 'RequestThrottled' => true,
25
+ ];
26
+
27
+ private $decider;
28
+ private $delay;
29
+ private $nextHandler;
30
+
31
+ public function __construct(
32
+ callable $decider,
33
+ callable $delay,
34
+ callable $nextHandler
35
+ ) {
36
+ $this->decider = $decider;
37
+ $this->delay = $delay;
38
+ $this->nextHandler = $nextHandler;
39
+ }
40
+
41
+ /**
42
+ * Creates a default AWS retry decider function.
43
+ *
44
+ * @param int $maxRetries
45
+ *
46
+ * @return callable
47
+ */
48
+ public static function createDefaultDecider($maxRetries = 3)
49
+ {
50
+ return function (
51
+ $retries,
52
+ CommandInterface $command,
53
+ RequestInterface $request,
54
+ ResultInterface $result = null,
55
+ $error = null
56
+ ) use ($maxRetries) {
57
+ // Allow command-level options to override this value
58
+ $maxRetries = null !== $command['@retries'] ?
59
+ $command['@retries']
60
+ : $maxRetries;
61
+
62
+ if ($retries >= $maxRetries) {
63
+ return false;
64
+ } elseif (!$error) {
65
+ return isset(self::$retryStatusCodes[$result['@metadata']['statusCode']]);
66
+ } elseif (!($error instanceof AwsException)) {
67
+ return false;
68
+ } elseif ($error->isConnectionError()) {
69
+ return true;
70
+ } elseif (isset(self::$retryCodes[$error->getAwsErrorCode()])) {
71
+ return true;
72
+ } elseif (isset(self::$retryStatusCodes[$error->getStatusCode()])) {
73
+ return true;
74
+ } else {
75
+ return false;
76
+ }
77
+ };
78
+ }
79
+
80
+ /**
81
+ * Delay function that calculates an exponential delay.
82
+ *
83
+ * @param $retries
84
+ *
85
+ * @return int
86
+ */
87
+ public static function exponentialDelay($retries)
88
+ {
89
+ return mt_rand(0, (int) pow(2, $retries - 1) * 100);
90
+ }
91
+
92
+ /**
93
+ * @param CommandInterface $command
94
+ * @param RequestInterface $request
95
+ *
96
+ * @return PromiseInterface
97
+ */
98
+ public function __invoke(
99
+ CommandInterface $command,
100
+ RequestInterface $request = null
101
+ ) {
102
+ $retries = 0;
103
+ $handler = $this->nextHandler;
104
+ $decider = $this->decider;
105
+ $delay = $this->delay;
106
+
107
+ $g = function ($value) use ($handler, $decider, $delay, $command, $request, &$retries, &$g) {
108
+ if ($value instanceof \Exception) {
109
+ if (!$decider($retries, $command, $request, null, $value)) {
110
+ return \GuzzleHttp\Promise\rejection_for($value);
111
+ }
112
+ } elseif ($value instanceof ResultInterface
113
+ && !$decider($retries, $command, $request, $value, null)
114
+ ) {
115
+ return $value;
116
+ }
117
+
118
+ // Delay fn is called with 0, 1, ... so increment after the call.
119
+ $command['@http']['delay'] = $delay($retries++);
120
+ return $handler($command, $request)->then($g, $g);
121
+ };
122
+
123
+ return $handler($command, $request)->then($g, $g);
124
+ }
125
+ }
includes/aws/Aws/S3/AmbiguousSuccessParser.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\Api\Parser\AbstractParser;
5
+ use Aws\CommandInterface;
6
+ use Aws\Exception\AwsException;
7
+ use Psr\Http\Message\ResponseInterface;
8
+
9
+ /**
10
+ * Converts errors returned with a status code of 200 to a retryable error type.
11
+ *
12
+ * @internal
13
+ */
14
+ class AmbiguousSuccessParser extends AbstractParser
15
+ {
16
+ private static $ambiguousSuccesses = [
17
+ 'UploadPartCopy' => true,
18
+ 'CopyObject' => true,
19
+ 'CompleteMultipartUpload' => true,
20
+ ];
21
+
22
+ /** @var callable */
23
+ private $parser;
24
+ /** @var callable */
25
+ private $errorParser;
26
+ /** @var string */
27
+ private $exceptionClass;
28
+
29
+ public function __construct(
30
+ callable $parser,
31
+ callable $errorParser,
32
+ $exceptionClass = AwsException::class
33
+ ) {
34
+ $this->parser = $parser;
35
+ $this->errorParser = $errorParser;
36
+ $this->exceptionClass = $exceptionClass;
37
+ }
38
+
39
+ public function __invoke(
40
+ CommandInterface $command,
41
+ ResponseInterface $response
42
+ ) {
43
+ if (200 === $response->getStatusCode()
44
+ && isset(self::$ambiguousSuccesses[$command->getName()])
45
+ ) {
46
+ $errorParser = $this->errorParser;
47
+ $parsed = $errorParser($response);
48
+ if (isset($parsed['code']) && isset($parsed['message'])) {
49
+ throw new $this->exceptionClass(
50
+ $parsed['message'],
51
+ $command,
52
+ ['connection_error' => true]
53
+ );
54
+ }
55
+ }
56
+
57
+ $fn = $this->parser;
58
+ return $fn($command, $response);
59
+ }
60
+ }
includes/aws/Aws/S3/ApplyChecksumMiddleware.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\CommandInterface;
5
+ use GuzzleHttp\Psr7;
6
+ use Psr\Http\Message\RequestInterface;
7
+
8
+ /**
9
+ * Apply required or optional MD5s to requests before sending.
10
+ *
11
+ * IMPORTANT: This middleware must be added after the "build" step.
12
+ *
13
+ * @internal
14
+ */
15
+ class ApplyChecksumMiddleware
16
+ {
17
+ private static $md5 = [
18
+ 'DeleteObjects',
19
+ 'PutBucketCors',
20
+ 'PutBucketLifecycle',
21
+ 'PutBucketLifecycleConfiguration',
22
+ 'PutBucketPolicy',
23
+ 'PutBucketTagging',
24
+ ];
25
+
26
+ private static $sha256 = [
27
+ 'PutObject',
28
+ 'UploadPart',
29
+ ];
30
+
31
+ private $nextHandler;
32
+
33
+ /**
34
+ * Create a middleware wrapper function.
35
+ *
36
+ * @return callable
37
+ */
38
+ public static function wrap()
39
+ {
40
+ return function (callable $handler) {
41
+ return new self($handler);
42
+ };
43
+ }
44
+
45
+ public function __construct(callable $nextHandler)
46
+ {
47
+ $this->nextHandler = $nextHandler;
48
+ }
49
+
50
+ public function __invoke(
51
+ CommandInterface $command,
52
+ RequestInterface $request
53
+ ) {
54
+ $next = $this->nextHandler;
55
+ $name = $command->getName();
56
+ $body = $request->getBody();
57
+
58
+ if (in_array($name, self::$md5) && !$request->hasHeader('Content-MD5')) {
59
+ // Set the content MD5 header for operations that require it.
60
+ $request = $request->withHeader(
61
+ 'Content-MD5',
62
+ base64_encode(Psr7\hash($body, 'md5', true))
63
+ );
64
+ } elseif (in_array($name, self::$sha256) && $command['ContentSHA256']) {
65
+ // Set the content hash header if provided in the parameters.
66
+ $request = $request->withHeader(
67
+ 'X-Amz-Content-Sha256',
68
+ $command['ContentSHA256']
69
+ );
70
+ }
71
+
72
+ return $next($command, $request);
73
+ }
74
+ }
includes/aws/Aws/S3/BatchDelete.php ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\AwsClientInterface;
5
+ use Aws\S3\Exception\DeleteMultipleObjectsException;
6
+ use GuzzleHttp\Promise;
7
+ use GuzzleHttp\Promise\PromisorInterface;
8
+ use GuzzleHttp\Promise\PromiseInterface;
9
+
10
+ /**
11
+ * Efficiently deletes many objects from a single Amazon S3 bucket using an
12
+ * iterator that yields keys. Deletes are made using the DeleteObjects API
13
+ * operation.
14
+ *
15
+ * $s3 = new Aws\S3\Client([
16
+ * 'region' => 'us-west-2',
17
+ * 'version' => 'latest'
18
+ * ]);
19
+ *
20
+ * $listObjectsParams = ['Bucket' => 'foo', 'Prefix' => 'starts/with/'];
21
+ * $delete = Aws\S3\BatchDelete::fromListObjects($s3, $listObjectsParams);
22
+ * // Asynchronously delete
23
+ * $promise = $delete->promise();
24
+ * // Force synchronous completion
25
+ * $delete->delete();
26
+ *
27
+ * When using one of the batch delete creational static methods, you can supply
28
+ * an associative array of options:
29
+ *
30
+ * - before: Function invoked before executing a command. The function is
31
+ * passed the command that is about to be executed. This can be useful
32
+ * for logging, adding custom request headers, etc.
33
+ * - batch_size: The size of each delete batch. Defaults to 1000.
34
+ *
35
+ * @link http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
36
+ */
37
+ class BatchDelete implements PromisorInterface
38
+ {
39
+ private $bucket;
40
+ /** @var AwsClientInterface */
41
+ private $client;
42
+ /** @var callable */
43
+ private $before;
44
+ /** @var PromiseInterface */
45
+ private $cachedPromise;
46
+ /** @var callable */
47
+ private $promiseCreator;
48
+ private $batchSize = 1000;
49
+ private $queue = [];
50
+
51
+ /**
52
+ * Creates a BatchDelete object from all of the paginated results of a
53
+ * ListObjects operation. Each result that is returned by the ListObjects
54
+ * operation will be deleted.
55
+ *
56
+ * @param AwsClientInterface $client AWS Client to use.
57
+ * @param array $listObjectsParams ListObjects API parameters
58
+ * @param array $options BatchDelete options.
59
+ *
60
+ * @return BatchDelete
61
+ */
62
+ public static function fromListObjects(
63
+ AwsClientInterface $client,
64
+ array $listObjectsParams,
65
+ array $options = []
66
+ ) {
67
+ $iter = $client->getPaginator('ListObjects', $listObjectsParams);
68
+ $bucket = $listObjectsParams['Bucket'];
69
+ $fn = function (BatchDelete $that) use ($iter) {
70
+ return $iter->each(function ($result) use ($that) {
71
+ $promises = [];
72
+ if (is_array($result['Contents'])) {
73
+ foreach ($result['Contents'] as $object) {
74
+ if ($promise = $that->enqueue($object)) {
75
+ $promises[] = $promise;
76
+ }
77
+ }
78
+ }
79
+ return $promises ? Promise\all($promises) : null;
80
+ });
81
+ };
82
+
83
+ return new self($client, $bucket, $fn, $options);
84
+ }
85
+
86
+ /**
87
+ * Creates a BatchDelete object from an iterator that yields results.
88
+ *
89
+ * @param AwsClientInterface $client AWS Client to use to execute commands
90
+ * @param string $bucket Bucket where the objects are stored
91
+ * @param \Iterator $iter Iterator that yields assoc arrays
92
+ * @param array $options BatchDelete options
93
+ *
94
+ * @return BatchDelete
95
+ */
96
+ public static function fromIterator(
97
+ AwsClientInterface $client,
98
+ $bucket,
99
+ \Iterator $iter,
100
+ array $options = []
101
+ ) {
102
+ $fn = function (BatchDelete $that) use ($iter) {
103
+ return \GuzzleHttp\Promise\coroutine(function () use ($that, $iter) {
104
+ foreach ($iter as $obj) {
105
+ if ($promise = $that->enqueue($obj)) {
106
+ yield $promise;
107
+ }
108
+ }
109
+ });
110
+ };
111
+
112
+ return new self($client, $bucket, $fn, $options);
113
+ }
114
+
115
+ public function promise()
116
+ {
117
+ if (!$this->cachedPromise) {
118
+ $this->cachedPromise = $this->createPromise();
119
+ }
120
+
121
+ return $this->cachedPromise;
122
+ }
123
+
124
+ /**
125
+ * Synchronously deletes all of the objects.
126
+ *
127
+ * @throws DeleteMultipleObjectsException on error.
128
+ */
129
+ public function delete()
130
+ {
131
+ $this->promise()->wait();
132
+ }
133
+
134
+ /**
135
+ * @param AwsClientInterface $client Client used to transfer the requests
136
+ * @param string $bucket Bucket to delete from.
137
+ * @param callable $promiseFn Creates a promise.
138
+ * @param array $options Hash of options used with the batch
139
+ *
140
+ * @throws \InvalidArgumentException if the provided batch_size is <= 0
141
+ */
142
+ private function __construct(
143
+ AwsClientInterface $client,
144
+ $bucket,
145
+ callable $promiseFn,
146
+ array $options = []
147
+ ) {
148
+ $this->client = $client;
149
+ $this->bucket = $bucket;
150
+ $this->promiseCreator = $promiseFn;
151
+
152
+ if (isset($options['before'])) {
153
+ if (!is_callable($options['before'])) {
154
+ throw new \InvalidArgumentException('before must be callable');
155
+ }
156
+ $this->before = $options['before'];
157
+ }
158
+
159
+ if (isset($options['batch_size'])) {
160
+ if ($options['batch_size'] <= 0) {
161
+ throw new \InvalidArgumentException('batch_size is not > 0');
162
+ }
163
+ $this->batchSize = min($options['batch_size'], 1000);
164
+ }
165
+ }
166
+
167
+ private function enqueue(array $obj)
168
+ {
169
+ $this->queue[] = $obj;
170
+ return count($this->queue) >= $this->batchSize
171
+ ? $this->flushQueue()
172
+ : null;
173
+ }
174
+
175
+ private function flushQueue()
176
+ {
177
+ static $validKeys = ['Key' => true, 'VersionId' => true];
178
+
179
+ if (count($this->queue) === 0) {
180
+ return null;
181
+ }
182
+
183
+ $batch = [];
184
+ while ($obj = array_shift($this->queue)) {
185
+ $batch[] = array_intersect_key($obj, $validKeys);
186
+ }
187
+
188
+ $command = $this->client->getCommand('DeleteObjects', [
189
+ 'Bucket' => $this->bucket,
190
+ 'Delete' => ['Objects' => $batch]
191
+ ]);
192
+
193
+ if ($this->before) {
194
+ call_user_func($this->before, $command);
195
+ }
196
+
197
+ return $this->client->executeAsync($command)
198
+ ->then(function ($result) {
199
+ if (!empty($result['Errors'])) {
200
+ throw new DeleteMultipleObjectsException(
201
+ $result['Deleted'] ?: [],
202
+ $result['Errors']
203
+ );
204
+ }
205
+ return $result;
206
+ });
207
+ }
208
+
209
+ /**
210
+ * Returns a promise that will clean up any references when it completes.
211
+ *
212
+ * @return PromiseInterface
213
+ */
214
+ private function createPromise()
215
+ {
216
+ // Create the promise
217
+ $promise = call_user_func($this->promiseCreator, $this);
218
+ $this->promiseCreator = null;
219
+
220
+ // Cleans up the promise state and references.
221
+ $cleanup = function () {
222
+ $this->before = $this->client = $this->queue = null;
223
+ };
224
+
225
+ // When done, ensure cleanup and that any remaining are processed.
226
+ return $promise->then(
227
+ function () use ($cleanup) {
228
+ return Promise\promise_for($this->flushQueue())
229
+ ->then($cleanup);
230
+ },
231
+ function ($reason) use ($cleanup) {
232
+ $cleanup();
233
+ return Promise\rejection_for($reason);
234
+ }
235
+ );
236
+ }
237
+ }
includes/aws/Aws/S3/BucketEndpointMiddleware.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\CommandInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+
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
+ /**
21
+ * Create a middleware wrapper function.
22
+ *
23
+ * @return callable
24
+ */
25
+ public static function wrap()
26
+ {
27
+ return function (callable $handler) {
28
+ return new self($handler);
29
+ };
30
+ }
31
+
32
+ public function __construct(callable $nextHandler)
33
+ {
34
+ $this->nextHandler = $nextHandler;
35
+ }
36
+
37
+ public function __invoke(CommandInterface $command, RequestInterface $request)
38
+ {
39
+ $nextHandler = $this->nextHandler;
40
+ $bucket = $command['Bucket'];
41
+
42
+ if ($bucket && !isset(self::$exclusions[$command->getName()])) {
43
+ $request = $this->modifyRequest($request, $command);
44
+ }
45
+
46
+ return $nextHandler($command, $request);
47
+ }
48
+
49
+ private function removeBucketFromPath($path, $bucket)
50
+ {
51
+ $len = strlen($bucket) + 1;
52
+ if (substr($path, 0, $len) === "/{$bucket}") {
53
+ $path = substr($path, $len);
54
+ }
55
+
56
+ return $path ?: '/';
57
+ }
58
+
59
+ private function modifyRequest(
60
+ RequestInterface $request,
61
+ CommandInterface $command
62
+ ) {
63
+ $uri = $request->getUri();
64
+ $path = $uri->getPath();
65
+ $bucket = $command['Bucket'];
66
+ $path = $this->removeBucketFromPath($path, $bucket);
67
+
68
+ // Modify the Key to make sure the key is encoded, but slashes are not.
69
+ if ($command['Key']) {
70
+ $path = S3Client::encodeKey(rawurldecode($path));
71
+ }
72
+
73
+ return $request->withUri($uri->withPath($path));
74
+ }
75
+ }
includes/aws/Aws/S3/Exception/DeleteMultipleObjectsException.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3\Exception;
3
+
4
+ /**
5
+ * Exception thrown when errors occur while deleting objects using a
6
+ * {@see S3\BatchDelete} object.
7
+ */
8
+ class DeleteMultipleObjectsException extends \Exception
9
+ {
10
+ private $deleted = [];
11
+ private $errors = [];
12
+
13
+ /**
14
+ * @param array $deleted Array of successfully deleted keys
15
+ * @param array $errors Array of errors that were encountered
16
+ */
17
+ public function __construct(array $deleted, array $errors)
18
+ {
19
+ $this->deleted = array_values($deleted);
20
+ $this->errors = array_values($errors);
21
+ parent::__construct('Unable to delete certain keys when executing a'
22
+ . ' DeleteMultipleObjects request: '
23
+ . self::createMessageFromErrors($errors));
24
+ }
25
+
26
+ /**
27
+ * Create a single error message from multiple errors.
28
+ *
29
+ * @param array $errors Errors encountered
30
+ *
31
+ * @return string
32
+ */
33
+ public static function createMessageFromErrors(array $errors)
34
+ {
35
+ return "\n- " . implode("\n- ", array_map(function ($key) {
36
+ return json_encode($key);
37
+ }, $errors));
38
+ }
39
+
40
+ /**
41
+ * Get the errored objects
42
+ *
43
+ * @return array Returns an array of associative arrays, each containing
44
+ * a 'Code', 'Message', and 'Key' key.
45
+ */
46
+ public function getErrors()
47
+ {
48
+ return $this->errors;
49
+ }
50
+
51
+ /**
52
+ * Get the successfully deleted objects
53
+ *
54
+ * @return array Returns an array of associative arrays, each containing
55
+ * a 'Key' and optionally 'DeleteMarker' and
56
+ * 'DeleterMarkerVersionId'
57
+ */
58
+ public function getDeleted()
59
+ {
60
+ return $this->deleted;
61
+ }
62
+ }
includes/aws/Aws/S3/Exception/PermanentRedirectException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3\Exception;
3
+
4
+ class PermanentRedirectException extends S3Exception {}
includes/aws/Aws/S3/Exception/S3Exception.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the Amazon Simple Storage Service.
8
+ */
9
+ class S3Exception extends AwsException {}
includes/aws/Aws/S3/GetBucketLocationParser.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\Api\Parser\AbstractParser;
5
+ use Aws\CommandInterface;
6
+ use Psr\Http\Message\ResponseInterface;
7
+
8
+ /**
9
+ * @internal Decorates a parser for the S3 service to correctly handle the
10
+ * GetBucketLocation operation.
11
+ */
12
+ class GetBucketLocationParser extends AbstractParser
13
+ {
14
+ /** @var callable */
15
+ private $parser;
16
+
17
+ /**
18
+ * @param callable $parser Parser to wrap.
19
+ */
20
+ public function __construct(callable $parser)
21
+ {
22
+ $this->parser = $parser;
23
+ }
24
+
25
+ public function __invoke(
26
+ CommandInterface $command,
27
+ ResponseInterface $response
28
+ ) {
29
+ $fn = $this->parser;
30
+ $result = $fn($command, $response);
31
+
32
+ if ($command->getName() === 'GetBucketLocation') {
33
+ $location = 'us-east-1';
34
+ if (preg_match('/>(.+?)<\/LocationConstraint>/', $response->getBody(), $matches)) {
35
+ $location = $matches[1] === 'EU' ? 'eu-west-1' : $matches[1];
36
+ }
37
+ $result['LocationConstraint'] = $location;
38
+ }
39
+
40
+ return $result;
41
+ }
42
+ }
includes/aws/Aws/S3/MultipartCopy.php ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\Multipart\AbstractUploadManager;
5
+ use Aws\ResultInterface;
6
+ use GuzzleHttp\Psr7;
7
+
8
+ class MultipartCopy extends AbstractUploadManager
9
+ {
10
+ use MultipartUploadingTrait;
11
+
12
+ /** @var string */
13
+ private $source;
14
+ /** @var ResultInterface */
15
+ private $sourceMetadata;
16
+
17
+ /**
18
+ * Creates a multipart upload for copying an S3 object.
19
+ *
20
+ * The valid configuration options are as follows:
21
+ *
22
+ * - acl: (string) ACL to set on the object being upload. Objects are
23
+ * private by default.
24
+ * - before_complete: (callable) Callback to invoke before the
25
+ * `CompleteMultipartUpload` operation. The callback should have a
26
+ * function signature like `function (Aws\Command $command) {...}`.
27
+ * - before_initiate: (callable) Callback to invoke before the
28
+ * `CreateMultipartUpload` operation. The callback should have a function
29
+ * signature like `function (Aws\Command $command) {...}`.
30
+ * - before_upload: (callable) Callback to invoke before `UploadPartCopy`
31
+ * operations. The callback should have a function signature like
32
+ * `function (Aws\Command $command) {...}`.
33
+ * - bucket: (string, required) Name of the bucket to which the object is
34
+ * being uploaded.
35
+ * - concurrency: (int, default=int(5)) Maximum number of concurrent
36
+ * `UploadPart` operations allowed during the multipart upload.
37
+ * - key: (string, required) Key to use for the object being uploaded.
38
+ * - part_size: (int, default=int(5242880)) Part size, in bytes, to use when
39
+ * doing a multipart upload. This must between 5 MB and 5 GB, inclusive.
40
+ * - state: (Aws\Multipart\UploadState) An object that represents the state
41
+ * of the multipart upload and that is used to resume a previous upload.
42
+ * When this option is provided, the `bucket`, `key`, and `part_size`
43
+ * options are ignored.
44
+ * - source_metadata: (Aws\ResultInterface) An object that represents the
45
+ * result of executing a HeadObject command on the copy source.
46
+ *
47
+ * @param S3Client $client Client used for the upload.
48
+ * @param string $source Location of the data to be copied
49
+ * (in the form /<bucket>/<key>).
50
+ * @param array $config Configuration used to perform the upload.
51
+ */
52
+ public function __construct(S3Client $client, $source, array $config = [])
53
+ {
54
+ $this->source = '/' . ltrim($source, '/');
55
+ parent::__construct($client, array_change_key_case($config) + [
56
+ 'source_metadata' => null
57
+ ]);
58
+ }
59
+
60
+ /**
61
+ * An alias of the self::upload method.
62
+ *
63
+ * @see self::upload
64
+ */
65
+ public function copy()
66
+ {
67
+ return $this->upload();
68
+ }
69
+
70
+ protected function loadUploadWorkflowInfo()
71
+ {
72
+ return [
73
+ 'command' => [
74
+ 'initiate' => 'CreateMultipartUpload',
75
+ 'upload' => 'UploadPartCopy',
76
+ 'complete' => 'CompleteMultipartUpload',
77
+ ],
78
+ 'id' => [
79
+ 'bucket' => 'Bucket',
80
+ 'key' => 'Key',
81
+ 'upload_id' => 'UploadId',
82
+ ],
83
+ 'part_num' => 'PartNumber',
84
+ ];
85
+ }
86
+
87
+ protected function getUploadCommands(callable $resultHandler)
88
+ {
89
+ $parts = ceil($this->getSourceSize() / $this->determinePartSize());
90
+
91
+ for ($partNumber = 1; $partNumber <= $parts; $partNumber++) {
92
+ // If we haven't already uploaded this part, yield a new part.
93
+ if (!$this->state->hasPartBeenUploaded($partNumber)) {
94
+ $command = $this->client->getCommand(
95
+ $this->info['command']['upload'],
96
+ $this->createPart($partNumber, $parts)
97
+ + $this->getState()->getId()
98
+ );
99
+ $command->getHandlerList()->appendSign($resultHandler, 'mup');
100
+ yield $command;
101
+ }
102
+ }
103
+ }
104
+
105
+ private function createPart($partNumber, $partsCount)
106
+ {
107
+ $defaultPartSize = $this->determinePartSize();
108
+ $startByte = $defaultPartSize * ($partNumber - 1);
109
+ $partSize = $partNumber < $partsCount
110
+ ? $defaultPartSize
111
+ : $this->getSourceSize() - ($defaultPartSize * ($partsCount - 1));
112
+ $endByte = $startByte + $partSize - 1;
113
+
114
+ return [
115
+ 'ContentLength' => $partSize,
116
+ 'CopySource' => $this->source,
117
+ 'CopySourceRange' => "bytes=$startByte-$endByte",
118
+ 'PartNumber' => $partNumber,
119
+ ];
120
+ }
121
+
122
+ protected function extractETag(ResultInterface $result)
123
+ {
124
+ return $result->search('CopyPartResult.ETag');
125
+ }
126
+
127
+ protected function getSourceMimeType()
128
+ {
129
+ return $this->getSourceMetadata()['ContentType'];
130
+ }
131
+
132
+ protected function getSourceSize()
133
+ {
134
+ return $this->getSourceMetadata()['ContentLength'];
135
+ }
136
+
137
+ private function getSourceMetadata()
138
+ {
139
+ if (empty($this->sourceMetadata)) {
140
+ $this->sourceMetadata = $this->fetchSourceMetadata();
141
+ }
142
+
143
+ return $this->sourceMetadata;
144
+ }
145
+
146
+ private function fetchSourceMetadata()
147
+ {
148
+ if ($this->config['source_metadata'] instanceof ResultInterface) {
149
+ return $this->config['source_metadata'];
150
+ }
151
+
152
+ list($bucket, $key) = explode('/', ltrim($this->source, '/'), 2);
153
+ $headParams = [
154
+ 'Bucket' => $bucket,
155
+ 'Key' => $key,
156
+ ];
157
+ if (strpos($key, '?')) {
158
+ list($key, $query) = explode('?', $key, 2);
159
+ $headParams['Key'] = $key;
160
+ $query = Psr7\parse_query($query, false);
161
+ if (isset($query['versionId'])) {
162
+ $headParams['VersionId'] = $query['versionId'];
163
+ }
164
+ }
165
+ return $this->client->headObject($headParams);
166
+ }
167
+ }
includes/aws/Aws/S3/MultipartUploader.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\HashingStream;
5
+ use Aws\Multipart\AbstractUploader;
6
+ use Aws\PhpHash;
7
+ use Aws\ResultInterface;
8
+ use GuzzleHttp\Psr7;
9
+ use Psr\Http\Message\StreamInterface as Stream;
10
+
11
+ /**
12
+ * Encapsulates the execution of a multipart upload to S3 or Glacier.
13
+ */
14
+ class MultipartUploader extends AbstractUploader
15
+ {
16
+ use MultipartUploadingTrait;
17
+
18
+ const PART_MIN_SIZE = 5242880;
19
+ const PART_MAX_SIZE = 5368709120;
20
+ const PART_MAX_NUM = 10000;
21
+
22
+ /**
23
+ * Creates a multipart upload for an S3 object.
24
+ *
25
+ * The valid configuration options are as follows:
26
+ *
27
+ * - acl: (string) ACL to set on the object being upload. Objects are
28
+ * private by default.
29
+ * - before_complete: (callable) Callback to invoke before the
30
+ * `CompleteMultipartUpload` operation. The callback should have a
31
+ * function signature like `function (Aws\Command $command) {...}`.
32
+ * - before_initiate: (callable) Callback to invoke before the
33
+ * `CreateMultipartUpload` operation. The callback should have a function
34
+ * signature like `function (Aws\Command $command) {...}`.
35
+ * - before_upload: (callable) Callback to invoke before any `UploadPart`
36
+ * operations. The callback should have a function signature like
37
+ * `function (Aws\Command $command) {...}`.
38
+ * - bucket: (string, required) Name of the bucket to which the object is
39
+ * being uploaded.
40
+ * - concurrency: (int, default=int(5)) Maximum number of concurrent
41
+ * `UploadPart` operations allowed during the multipart upload.
42
+ * - key: (string, required) Key to use for the object being uploaded.
43
+ * - part_size: (int, default=int(5242880)) Part size, in bytes, to use when
44
+ * doing a multipart upload. This must between 5 MB and 5 GB, inclusive.
45
+ * - state: (Aws\Multipart\UploadState) An object that represents the state
46
+ * of the multipart upload and that is used to resume a previous upload.
47
+ * When this option is provided, the `bucket`, `key`, and `part_size`
48
+ * options are ignored.
49
+ *
50
+ * @param S3Client $client Client used for the upload.
51
+ * @param mixed $source Source of the data to upload.
52
+ * @param array $config Configuration used to perform the upload.
53
+ */
54
+ public function __construct(S3Client $client, $source, array $config = [])
55
+ {
56
+ parent::__construct($client, $source, array_change_key_case($config) + [
57
+ 'bucket' => null,
58
+ 'key' => null,
59
+ ]);
60
+ }
61
+
62
+ protected function loadUploadWorkflowInfo()
63
+ {
64
+ return [
65
+ 'command' => [
66
+ 'initiate' => 'CreateMultipartUpload',
67
+ 'upload' => 'UploadPart',
68
+ 'complete' => 'CompleteMultipartUpload',
69
+ ],
70
+ 'id' => [
71
+ 'bucket' => 'Bucket',
72
+ 'key' => 'Key',
73
+ 'upload_id' => 'UploadId',
74
+ ],
75
+ 'part_num' => 'PartNumber',
76
+ ];
77
+ }
78
+
79
+ protected function createPart($seekable, $number)
80
+ {
81
+ // Initialize the array of part data that will be returned.
82
+ $data = ['PartNumber' => $number];
83
+
84
+ // Read from the source to create the body stream.
85
+ if ($seekable) {
86
+ // Case 1: Source is seekable, use lazy stream to defer work.
87
+ $body = $this->limitPartStream(
88
+ new Psr7\LazyOpenStream($this->source->getMetadata('uri'), 'r')
89
+ );
90
+ } else {
91
+ // Case 2: Stream is not seekable; must store in temp stream.
92
+ $source = $this->limitPartStream($this->source);
93
+ $source = $this->decorateWithHashes($source, $data);
94
+ $body = Psr7\stream_for();
95
+ Psr7\copy_to_stream($source, $body);
96
+ $data['ContentLength'] = $body->getSize();
97
+ }
98
+
99
+ // Do not create a part if the body size is zero.
100
+ if ($body->getSize() === 0) {
101
+ return false;
102
+ }
103
+
104
+ $body->seek(0);
105
+ $data['Body'] = $body;
106
+
107
+ return $data;
108
+ }
109
+
110
+ protected function extractETag(ResultInterface $result)
111
+ {
112
+ return $result['ETag'];
113
+ }
114
+
115
+ protected function getSourceMimeType()
116
+ {
117
+ if ($uri = $this->source->getMetadata('uri')) {
118
+ return Psr7\mimetype_from_filename($uri)
119
+ ?: 'application/octet-stream';
120
+ }
121
+ }
122
+
123
+ protected function getSourceSize()
124
+ {
125
+ return $this->source->getSize();
126
+ }
127
+
128
+ /**
129
+ * Decorates a stream with a sha256 linear hashing stream.
130
+ *
131
+ * @param Stream $stream Stream to decorate.
132
+ * @param array $data Part data to augment with the hash result.
133
+ *
134
+ * @return Stream
135
+ */
136
+ private function decorateWithHashes(Stream $stream, array &$data)
137
+ {
138
+ // Decorate source with a hashing stream
139
+ $hash = new PhpHash('sha256');
140
+ return new HashingStream($stream, $hash, function ($result) use (&$data) {
141
+ $data['ContentSHA256'] = bin2hex($result);
142
+ });
143
+ }
144
+ }
includes/aws/Aws/S3/MultipartUploadingTrait.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\CommandInterface;
5
+ use Aws\Multipart\UploadState;
6
+ use Aws\ResultInterface;
7
+
8
+ trait MultipartUploadingTrait
9
+ {
10
+ /**
11
+ * Creates an UploadState object for a multipart upload by querying the
12
+ * service for the specified upload's information.
13
+ *
14
+ * @param S3Client $client S3Client used for the upload.
15
+ * @param string $bucket Bucket for the multipart upload.
16
+ * @param string $key Object key for the multipart upload.
17
+ * @param string $uploadId Upload ID for the multipart upload.
18
+ *
19
+ * @return UploadState
20
+ */
21
+ public static function getStateFromService(
22
+ S3Client $client,
23
+ $bucket,
24
+ $key,
25
+ $uploadId
26
+ ) {
27
+ $state = new UploadState([
28
+ 'Bucket' => $bucket,
29
+ 'Key' => $key,
30
+ 'UploadId' => $uploadId,
31
+ ]);
32
+
33
+ foreach ($client->getPaginator('ListParts', $state->getId()) as $result) {
34
+ // Get the part size from the first part in the first result.
35
+ if (!$state->getPartSize()) {
36
+ $state->setPartSize($result->search('Parts[0].Size'));
37
+ }
38
+ // Mark all the parts returned by ListParts as uploaded.
39
+ foreach ($result['Parts'] as $part) {
40
+ $state->markPartAsUploaded($part['PartNumber'], [
41
+ 'PartNumber' => $part['PartNumber'],
42
+ 'ETag' => $part['ETag']
43
+ ]);
44
+ }
45
+ }
46
+
47
+ $state->setStatus(UploadState::INITIATED);
48
+
49
+ return $state;
50
+ }
51
+
52
+ protected function handleResult(CommandInterface $command, ResultInterface $result)
53
+ {
54
+ $this->getState()->markPartAsUploaded($command['PartNumber'], [
55
+ 'PartNumber' => $command['PartNumber'],
56
+ 'ETag' => $this->extractETag($result),
57
+ ]);
58
+ }
59
+
60
+ abstract protected function extractETag(ResultInterface $result);
61
+
62
+ protected function getCompleteParams()
63
+ {
64
+ return ['MultipartUpload' => [
65
+ 'Parts' => $this->getState()->getUploadedParts()
66
+ ]];
67
+ }
68
+
69
+ protected function determinePartSize()
70
+ {
71
+ // Make sure the part size is set.
72
+ $partSize = $this->getConfig()['part_size'] ?: MultipartUploader::PART_MIN_SIZE;
73
+
74
+ // Adjust the part size to be larger for known, x-large uploads.
75
+ if ($sourceSize = $this->getSourceSize()) {
76
+ $partSize = (int) max(
77
+ $partSize,
78
+ ceil($sourceSize / MultipartUploader::PART_MAX_NUM)
79
+ );
80
+ }
81
+
82
+ // Ensure that the part size follows the rules: 5 MB <= size <= 5 GB.
83
+ if ($partSize < MultipartUploader::PART_MIN_SIZE || $partSize > MultipartUploader::PART_MAX_SIZE) {
84
+ throw new \InvalidArgumentException('The part size must be no less '
85
+ . 'than 5 MB and no greater than 5 GB.');
86
+ }
87
+
88
+ return $partSize;
89
+ }
90
+
91
+ protected function getInitiateParams()
92
+ {
93
+ $params = [];
94
+
95
+ if (isset($this->getConfig()['acl'])) {
96
+ $params['ACL'] = $this->getConfig()['acl'];
97
+ }
98
+
99
+ // Set the content type
100
+ if ($type = $this->getSourceMimeType()) {
101
+ $params['ContentType'] = $type;
102
+ }
103
+
104
+ return $params;
105
+ }
106
+
107
+ /**
108
+ * @return UploadState
109
+ */
110
+ abstract protected function getState();
111
+
112
+ /**
113
+ * @return array
114
+ */
115
+ abstract protected function getConfig();
116
+
117
+ /**
118
+ * @return int
119
+ */
120
+ abstract protected function getSourceSize();
121
+
122
+ /**
123
+ * @return string|null
124
+ */
125
+ abstract protected function getSourceMimeType();
126
+ }
includes/aws/Aws/S3/PermanentRedirectMiddleware.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\CommandInterface;
5
+ use Aws\ResultInterface;
6
+ use Aws\S3\Exception\PermanentRedirectException;
7
+ use Psr\Http\Message\RequestInterface;
8
+
9
+ /**
10
+ * Throws a PermanentRedirectException exception when a 301 redirect is
11
+ * encountered.
12
+ *
13
+ * @internal
14
+ */
15
+ class PermanentRedirectMiddleware
16
+ {
17
+ /** @var callable */
18
+ private $nextHandler;
19
+
20
+ /**
21
+ * Create a middleware wrapper function.
22
+ *
23
+ * @return callable
24
+ */
25
+ public static function wrap()
26
+ {
27
+ return function (callable $handler) {
28
+ return new self($handler);
29
+ };
30
+ }
31
+
32
+ /**
33
+ * @param callable $nextHandler Next handler to invoke.
34
+ */
35
+ public function __construct(callable $nextHandler)
36
+ {
37
+ $this->nextHandler = $nextHandler;
38
+ }
39
+
40
+ public function __invoke(CommandInterface $command, RequestInterface $request = null)
41
+ {
42
+ $next = $this->nextHandler;
43
+ return $next($command, $request)->then(
44
+ function (ResultInterface $result) use ($command) {
45
+ $status = isset($result['@metadata']['statusCode'])
46
+ ? $result['@metadata']['statusCode']
47
+ : null;
48
+ if ($status == 301) {
49
+ throw new PermanentRedirectException(
50
+ 'Encountered a permanent redirect while requesting '
51
+ . $result->search('"@metadata".effectiveUri') . '. '
52
+ . 'Are you sure you are using the correct region for '
53
+ . 'this bucket?',
54
+ $command,
55
+ ['result' => $result]
56
+ );
57
+ }
58
+ return $result;
59
+ }
60
+ );
61
+ }
62
+ }
includes/aws/Aws/S3/PostObject.php ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\Credentials\CredentialsInterface;
5
+ use GuzzleHttp\Psr7\Uri;
6
+
7
+ /**
8
+ * Encapsulates the logic for getting the data for an S3 object POST upload form
9
+ *
10
+ * @link http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html
11
+ */
12
+ class PostObject
13
+ {
14
+ private $client;
15
+ private $bucket;
16
+ private $formAttributes;
17
+ private $formInputs;
18
+ private $jsonPolicy;
19
+
20
+ /**
21
+ * Constructs the PostObject.
22
+ *
23
+ * @param S3Client $client Client used with the POST object
24
+ * @param string $bucket Bucket to use
25
+ * @param array $formInputs Associative array of form input fields.
26
+ * @param string|array $jsonPolicy JSON encoded POST policy document. The
27
+ * policy will be base64 encoded and applied
28
+ * to the form on your behalf.
29
+ */
30
+ public function __construct(
31
+ S3Client $client,
32
+ $bucket,
33
+ array $formInputs,
34
+ $jsonPolicy
35
+ ) {
36
+ $this->client = $client;
37
+ $this->bucket = $bucket;
38
+
39
+ if (is_array($jsonPolicy)) {
40
+ $jsonPolicy = json_encode($jsonPolicy);
41
+ }
42
+
43
+ $this->jsonPolicy = $jsonPolicy;
44
+ $this->formAttributes = [
45
+ 'action' => $this->generateUri(),
46
+ 'method' => 'POST',
47
+ 'enctype' => 'multipart/form-data'
48
+ ];
49
+
50
+ $this->formInputs = $formInputs + ['key' => '${filename}'];
51
+ $credentials = $client->getCredentials()->wait();
52
+ $this->formInputs += $this->getPolicyAndSignature($credentials);
53
+ }
54
+
55
+ /**
56
+ * Gets the S3 client.
57
+ *
58
+ * @return S3Client
59
+ */
60
+ public function getClient()
61
+ {
62
+ return $this->client;
63
+ }
64
+
65
+ /**
66
+ * Gets the bucket name.
67
+ *
68
+ * @return string
69
+ */
70
+ public function getBucket()
71
+ {
72
+ return $this->bucket;
73
+ }
74
+
75
+ /**
76
+ * Gets the form attributes as an array.
77
+ *
78
+ * @return array
79
+ */
80
+ public function getFormAttributes()
81
+ {
82
+ return $this->formAttributes;
83
+ }
84
+
85
+ /**
86
+ * Set a form attribute.
87
+ *
88
+ * @param string $attribute Form attribute to set.
89
+ * @param string $value Value to set.
90
+ */
91
+ public function setFormAttribute($attribute, $value)
92
+ {
93
+ $this->formAttributes[$attribute] = $value;
94
+ }
95
+
96
+ /**
97
+ * Gets the form inputs as an array.
98
+ *
99
+ * @return array
100
+ */
101
+ public function getFormInputs()
102
+ {
103
+ return $this->formInputs;
104
+ }
105
+
106
+ /**
107
+ * Set a form input.
108
+ *
109
+ * @param string $field Field name to set
110
+ * @param string $value Value to set.
111
+ */
112
+ public function setFormInput($field, $value)
113
+ {
114
+ $this->formInputs[$field] = $value;
115
+ }
116
+
117
+ /**
118
+ * Gets the raw JSON policy.
119
+ *
120
+ * @return string
121
+ */
122
+ public function getJsonPolicy()
123
+ {
124
+ return $this->jsonPolicy;
125
+ }
126
+
127
+ private function generateUri()
128
+ {
129
+ $uri = new Uri($this->client->getEndpoint());
130
+
131
+ if ($uri->getScheme() === 'https'
132
+ && strpos($this->bucket, '.') !== false
133
+ ) {
134
+ // Use path-style URLs
135
+ $uri = $uri->withPath($this->bucket);
136
+ } else {
137
+ // Use virtual-style URLs
138
+ $uri = $uri->withHost($this->bucket . '.' . $uri->getHost());
139
+ }
140
+
141
+ return (string) $uri;
142
+ }
143
+
144
+ protected function getPolicyAndSignature(CredentialsInterface $creds)
145
+ {
146
+ $jsonPolicy64 = base64_encode($this->jsonPolicy);
147
+
148
+ return [
149
+ 'AWSAccessKeyId' => $creds->getAccessKeyId(),
150
+ 'policy' => $jsonPolicy64,
151
+ 'signature' => base64_encode(hash_hmac(
152
+ 'sha1',
153
+ $jsonPolicy64,
154
+ $creds->getSecretKey(),
155
+ true
156
+ ))
157
+ ];
158
+ }
159
+ }
includes/aws/Aws/S3/PutObjectUrlMiddleware.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\CommandInterface;
5
+ use Aws\ResultInterface;
6
+ use Psr\Http\Message\RequestInterface;
7
+
8
+ /**
9
+ * Injects ObjectURL into the result of the PutObject operation.
10
+ *
11
+ * @internal
12
+ */
13
+ class PutObjectUrlMiddleware
14
+ {
15
+ /** @var callable */
16
+ private $nextHandler;
17
+
18
+ /**
19
+ * Create a middleware wrapper function.
20
+ *
21
+ * @return callable
22
+ */
23
+ public static function wrap()
24
+ {
25
+ return function (callable $handler) {
26
+ return new self($handler);
27
+ };
28
+ }
29
+
30
+ /**
31
+ * @param callable $nextHandler Next handler to invoke.
32
+ */
33
+ public function __construct(callable $nextHandler)
34
+ {
35
+ $this->nextHandler = $nextHandler;
36
+ }
37
+
38
+ public function __invoke(CommandInterface $command, RequestInterface $request = null)
39
+ {
40
+ $next = $this->nextHandler;
41
+ return $next($command, $request)->then(
42
+ function (ResultInterface $result) use ($command) {
43
+ $name = $command->getName();
44
+ switch ($name) {
45
+ case 'PutObject':
46
+ case 'CopyObject':
47
+ $result['ObjectURL'] = $result['@metadata']['effectiveUri'];
48
+ break;
49
+ case 'CompleteMultipartUpload':
50
+ $result['ObjectURL'] = $result['Location'];
51
+ break;
52
+ }
53
+ return $result;
54
+ }
55
+ );
56
+ }
57
+ }
includes/aws/Aws/S3/RetryableMalformedResponseParser.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\Api\Parser\AbstractParser;
5
+ use Aws\Api\Parser\Exception\ParserException;
6
+ use Aws\CommandInterface;
7
+ use Aws\Exception\AwsException;
8
+ use Psr\Http\Message\ResponseInterface;
9
+
10
+ /**
11
+ * Converts malformed responses to a retryable error type.
12
+ *
13
+ * @internal
14
+ */
15
+ class RetryableMalformedResponseParser extends AbstractParser
16
+ {
17
+ /** @var callable */
18
+ private $parser;
19
+ /** @var string */
20
+ private $exceptionClass;
21
+
22
+ public function __construct(
23
+ callable $parser,
24
+ $exceptionClass = AwsException::class
25
+ ) {
26
+ $this->parser = $parser;
27
+ $this->exceptionClass = $exceptionClass;
28
+ }
29
+
30
+ public function __invoke(
31
+ CommandInterface $command,
32
+ ResponseInterface $response
33
+ ) {
34
+ $fn = $this->parser;
35
+
36
+ try {
37
+ return $fn($command, $response);
38
+ } catch (ParserException $e) {
39
+ throw new $this->exceptionClass(
40
+ "Error parsing response for {$command->getName()}:"
41
+ . " AWS parsing error: {$e->getMessage()}",
42
+ $command,
43
+ ['connection_error' => true, 'exception' => $e],
44
+ $e
45
+ );
46
+ }
47
+ }
48
+ }
includes/aws/Aws/S3/S3Client.php ADDED
@@ -0,0 +1,855 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\Api\ApiProvider;
5
+ use Aws\Api\DocModel;
6
+ use Aws\Api\Service;
7
+ use Aws\AwsClient;
8
+ use Aws\ClientResolver;
9
+ use Aws\Command;
10
+ use Aws\Exception\AwsException;
11
+ use Aws\HandlerList;
12
+ use Aws\Middleware;
13
+ use Aws\RetryMiddleware;
14
+ use Aws\S3\Exception\S3Exception;
15
+ use Aws\ResultInterface;
16
+ use Aws\CommandInterface;
17
+ use GuzzleHttp\Exception\RequestException;
18
+ use GuzzleHttp\Promise;
19
+ use GuzzleHttp\Promise\PromiseInterface;
20
+ use GuzzleHttp\Psr7;
21
+ use Psr\Http\Message\RequestInterface;
22
+ use Psr\Http\Message\StreamInterface;
23
+
24
+ /**
25
+ * Client used to interact with **Amazon Simple Storage Service (Amazon S3)**.
26
+ *
27
+ * @method \Aws\Result abortMultipartUpload(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise abortMultipartUploadAsync(array $args = [])
29
+ * @method \Aws\Result completeMultipartUpload(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise completeMultipartUploadAsync(array $args = [])
31
+ * @method \Aws\Result copyObject(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise copyObjectAsync(array $args = [])
33
+ * @method \Aws\Result createBucket(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise createBucketAsync(array $args = [])
35
+ * @method \Aws\Result createMultipartUpload(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise createMultipartUploadAsync(array $args = [])
37
+ * @method \Aws\Result deleteBucket(array $args = [])
38
+ * @method \GuzzleHttp\Promise\Promise deleteBucketAsync(array $args = [])
39
+ * @method \Aws\Result deleteBucketCors(array $args = [])
40
+ * @method \GuzzleHttp\Promise\Promise deleteBucketCorsAsync(array $args = [])
41
+ * @method \Aws\Result deleteBucketLifecycle(array $args = [])
42
+ * @method \GuzzleHttp\Promise\Promise deleteBucketLifecycleAsync(array $args = [])
43
+ * @method \Aws\Result deleteBucketPolicy(array $args = [])
44
+ * @method \GuzzleHttp\Promise\Promise deleteBucketPolicyAsync(array $args = [])
45
+ * @method \Aws\Result deleteBucketReplication(array $args = [])
46
+ * @method \GuzzleHttp\Promise\Promise deleteBucketReplicationAsync(array $args = [])
47
+ * @method \Aws\Result deleteBucketTagging(array $args = [])
48
+ * @method \GuzzleHttp\Promise\Promise deleteBucketTaggingAsync(array $args = [])
49
+ * @method \Aws\Result deleteBucketWebsite(array $args = [])
50
+ * @method \GuzzleHttp\Promise\Promise deleteBucketWebsiteAsync(array $args = [])
51
+ * @method \Aws\Result deleteObject(array $args = [])
52
+ * @method \GuzzleHttp\Promise\Promise deleteObjectAsync(array $args = [])
53
+ * @method \Aws\Result deleteObjects(array $args = [])
54
+ * @method \GuzzleHttp\Promise\Promise deleteObjectsAsync(array $args = [])
55
+ * @method \Aws\Result getBucketAcl(array $args = [])
56
+ * @method \GuzzleHttp\Promise\Promise getBucketAclAsync(array $args = [])
57
+ * @method \Aws\Result getBucketCors(array $args = [])
58
+ * @method \GuzzleHttp\Promise\Promise getBucketCorsAsync(array $args = [])
59
+ * @method \Aws\Result getBucketLifecycle(array $args = [])
60
+ * @method \GuzzleHttp\Promise\Promise getBucketLifecycleAsync(array $args = [])
61
+ * @method \Aws\Result getBucketLifecycleConfiguration(array $args = [])
62
+ * @method \GuzzleHttp\Promise\Promise getBucketLifecycleConfigurationAsync(array $args = [])
63
+ * @method \Aws\Result getBucketLocation(array $args = [])
64
+ * @method \GuzzleHttp\Promise\Promise getBucketLocationAsync(array $args = [])
65
+ * @method \Aws\Result getBucketLogging(array $args = [])
66
+ * @method \GuzzleHttp\Promise\Promise getBucketLoggingAsync(array $args = [])
67
+ * @method \Aws\Result getBucketNotification(array $args = [])
68
+ * @method \GuzzleHttp\Promise\Promise getBucketNotificationAsync(array $args = [])
69
+ * @method \Aws\Result getBucketNotificationConfiguration(array $args = [])
70
+ * @method \GuzzleHttp\Promise\Promise getBucketNotificationConfigurationAsync(array $args = [])
71
+ * @method \Aws\Result getBucketPolicy(array $args = [])
72
+ * @method \GuzzleHttp\Promise\Promise getBucketPolicyAsync(array $args = [])
73
+ * @method \Aws\Result getBucketReplication(array $args = [])
74
+ * @method \GuzzleHttp\Promise\Promise getBucketReplicationAsync(array $args = [])
75
+ * @method \Aws\Result getBucketRequestPayment(array $args = [])
76
+ * @method \GuzzleHttp\Promise\Promise getBucketRequestPaymentAsync(array $args = [])
77
+ * @method \Aws\Result getBucketTagging(array $args = [])
78
+ * @method \GuzzleHttp\Promise\Promise getBucketTaggingAsync(array $args = [])
79
+ * @method \Aws\Result getBucketVersioning(array $args = [])
80
+ * @method \GuzzleHttp\Promise\Promise getBucketVersioningAsync(array $args = [])
81
+ * @method \Aws\Result getBucketWebsite(array $args = [])
82
+ * @method \GuzzleHttp\Promise\Promise getBucketWebsiteAsync(array $args = [])
83
+ * @method \Aws\Result getObject(array $args = [])
84
+ * @method \GuzzleHttp\Promise\Promise getObjectAsync(array $args = [])
85
+ * @method \Aws\Result getObjectAcl(array $args = [])
86
+ * @method \GuzzleHttp\Promise\Promise getObjectAclAsync(array $args = [])
87
+ * @method \Aws\Result getObjectTorrent(array $args = [])
88
+ * @method \GuzzleHttp\Promise\Promise getObjectTorrentAsync(array $args = [])
89
+ * @method \Aws\Result headBucket(array $args = [])
90
+ * @method \GuzzleHttp\Promise\Promise headBucketAsync(array $args = [])
91
+ * @method \Aws\Result headObject(array $args = [])
92
+ * @method \GuzzleHttp\Promise\Promise headObjectAsync(array $args = [])
93
+ * @method \Aws\Result listBuckets(array $args = [])
94
+ * @method \GuzzleHttp\Promise\Promise listBucketsAsync(array $args = [])
95
+ * @method \Aws\Result listMultipartUploads(array $args = [])
96
+ * @method \GuzzleHttp\Promise\Promise listMultipartUploadsAsync(array $args = [])
97
+ * @method \Aws\Result listObjectVersions(array $args = [])
98
+ * @method \GuzzleHttp\Promise\Promise listObjectVersionsAsync(array $args = [])
99
+ * @method \Aws\Result listObjects(array $args = [])
100
+ * @method \GuzzleHttp\Promise\Promise listObjectsAsync(array $args = [])
101
+ * @method \Aws\Result listParts(array $args = [])
102
+ * @method \GuzzleHttp\Promise\Promise listPartsAsync(array $args = [])
103
+ * @method \Aws\Result putBucketAcl(array $args = [])
104
+ * @method \GuzzleHttp\Promise\Promise putBucketAclAsync(array $args = [])
105
+ * @method \Aws\Result putBucketCors(array $args = [])
106
+ * @method \GuzzleHttp\Promise\Promise putBucketCorsAsync(array $args = [])
107
+ * @method \Aws\Result putBucketLifecycle(array $args = [])
108
+ * @method \GuzzleHttp\Promise\Promise putBucketLifecycleAsync(array $args = [])
109
+ * @method \Aws\Result putBucketLifecycleConfiguration(array $args = [])
110
+ * @method \GuzzleHttp\Promise\Promise putBucketLifecycleConfigurationAsync(array $args = [])
111
+ * @method \Aws\Result putBucketLogging(array $args = [])
112
+ * @method \GuzzleHttp\Promise\Promise putBucketLoggingAsync(array $args = [])
113
+ * @method \Aws\Result putBucketNotification(array $args = [])
114
+ * @method \GuzzleHttp\Promise\Promise putBucketNotificationAsync(array $args = [])
115
+ * @method \Aws\Result putBucketNotificationConfiguration(array $args = [])
116
+ * @method \GuzzleHttp\Promise\Promise putBucketNotificationConfigurationAsync(array $args = [])
117
+ * @method \Aws\Result putBucketPolicy(array $args = [])
118
+ * @method \GuzzleHttp\Promise\Promise putBucketPolicyAsync(array $args = [])
119
+ * @method \Aws\Result putBucketReplication(array $args = [])
120
+ * @method \GuzzleHttp\Promise\Promise putBucketReplicationAsync(array $args = [])
121
+ * @method \Aws\Result putBucketRequestPayment(array $args = [])
122
+ * @method \GuzzleHttp\Promise\Promise putBucketRequestPaymentAsync(array $args = [])
123
+ * @method \Aws\Result putBucketTagging(array $args = [])
124
+ * @method \GuzzleHttp\Promise\Promise putBucketTaggingAsync(array $args = [])
125
+ * @method \Aws\Result putBucketVersioning(array $args = [])
126
+ * @method \GuzzleHttp\Promise\Promise putBucketVersioningAsync(array $args = [])
127
+ * @method \Aws\Result putBucketWebsite(array $args = [])
128
+ * @method \GuzzleHttp\Promise\Promise putBucketWebsiteAsync(array $args = [])
129
+ * @method \Aws\Result putObject(array $args = [])
130
+ * @method \GuzzleHttp\Promise\Promise putObjectAsync(array $args = [])
131
+ * @method \Aws\Result putObjectAcl(array $args = [])
132
+ * @method \GuzzleHttp\Promise\Promise putObjectAclAsync(array $args = [])
133
+ * @method \Aws\Result restoreObject(array $args = [])
134
+ * @method \GuzzleHttp\Promise\Promise restoreObjectAsync(array $args = [])
135
+ * @method \Aws\Result uploadPart(array $args = [])
136
+ * @method \GuzzleHttp\Promise\Promise uploadPartAsync(array $args = [])
137
+ * @method \Aws\Result uploadPartCopy(array $args = [])
138
+ * @method \GuzzleHttp\Promise\Promise uploadPartCopyAsync(array $args = [])
139
+ */
140
+ class S3Client extends AwsClient
141
+ {
142
+ public static function getArguments()
143
+ {
144
+ $args = parent::getArguments();
145
+ $args['retries']['fn'] = [__CLASS__, '_applyRetryConfig'];
146
+ $args['api_provider']['fn'] = [__CLASS__, '_applyApiProvider'];
147
+
148
+ return $args + [
149
+ 'bucket_endpoint' => [
150
+ 'type' => 'config',
151
+ 'valid' => ['bool'],
152
+ 'doc' => 'Set to true to send requests to a hardcoded '
153
+ . 'bucket endpoint rather than create an endpoint as a '
154
+ . 'result of injecting the bucket into the URL. This '
155
+ . 'option is useful for interacting with CNAME endpoints.',
156
+ ],
157
+ ];
158
+ }
159
+
160
+ /**
161
+ * {@inheritdoc}
162
+ *
163
+ * In addition to the options available to
164
+ * {@see Aws\AwsClient::__construct}, S3Client accepts the following
165
+ * options:
166
+ *
167
+ * - bucket_endpoint: (bool) Set to true to send requests to a
168
+ * hardcoded bucket endpoint rather than create an endpoint as a result
169
+ * of injecting the bucket into the URL. This option is useful for
170
+ * interacting with CNAME endpoints.
171
+ * - calculate_md5: (bool) Set to false to disable calculating an MD5
172
+ * for all Amazon S3 signed uploads.
173
+ *
174
+ * @param array $args
175
+ */
176
+ public function __construct(array $args)
177
+ {
178
+ parent::__construct($args);
179
+ $stack = $this->getHandlerList();
180
+ $stack->appendInit(SSECMiddleware::wrap($this->getEndpoint()->getScheme()), 's3.ssec');
181
+ $stack->appendBuild(ApplyChecksumMiddleware::wrap(), 's3.checksum');
182
+ $stack->appendBuild(
183
+ Middleware::contentType(['PutObject', 'UploadPart']),
184
+ 's3.content_type'
185
+ );
186
+
187
+ // Use the bucket style middleware when using a "bucket_endpoint" (for cnames)
188
+ if ($this->getConfig('bucket_endpoint')) {
189
+ $stack->appendBuild(BucketEndpointMiddleware::wrap(), 's3.bucket_endpoint');
190
+ }
191
+
192
+ $stack->appendSign(PutObjectUrlMiddleware::wrap(), 's3.put_object_url');
193
+ $stack->appendSign(PermanentRedirectMiddleware::wrap(), 's3.permanent_redirect');
194
+ $stack->appendInit(Middleware::sourceFile($this->getApi()), 's3.source_file');
195
+ $stack->appendInit($this->getSaveAsParameter(), 's3.save_as');
196
+ $stack->appendInit($this->getLocationConstraintMiddleware(), 's3.location');
197
+ }
198
+
199
+ /**
200
+ * Determine if a string is a valid name for a DNS compatible Amazon S3
201
+ * bucket.
202
+ *
203
+ * DNS compatible bucket names can be used as a subdomain in a URL (e.g.,
204
+ * "<bucket>.s3.amazonaws.com").
205
+ *
206
+ * @param string $bucket Bucket name to check.
207
+ *
208
+ * @return bool
209
+ */
210
+ public static function isBucketDnsCompatible($bucket)
211
+ {
212
+ $bucketLen = strlen($bucket);
213
+
214
+ return ($bucketLen >= 3 && $bucketLen <= 63) &&
215
+ // Cannot look like an IP address
216
+ !filter_var($bucket, FILTER_VALIDATE_IP) &&
217
+ preg_match('/^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$/', $bucket);
218
+ }
219
+
220
+ /**
221
+ * Create a pre-signed URL for the given S3 command object.
222
+ *
223
+ * @param CommandInterface $command Command to create a pre-signed
224
+ * URL for.
225
+ * @param int|string|\DateTime $expires The time at which the URL should
226
+ * expire. This can be a Unix
227
+ * timestamp, a PHP DateTime object,
228
+ * or a string that can be evaluated
229
+ * by strtotime().
230
+ *
231
+ * @return RequestInterface
232
+ */
233
+ public function createPresignedRequest(CommandInterface $command, $expires)
234
+ {
235
+ /** @var \Aws\Signature\SignatureInterface $signer */
236
+ $signer = call_user_func(
237
+ $this->getSignatureProvider(),
238
+ $this->getConfig('signature_version'),
239
+ $this->getApi()->getSigningName(),
240
+ $this->getRegion()
241
+ );
242
+
243
+ return $signer->presign(
244
+ \Aws\serialize($command),
245
+ $this->getCredentials()->wait(),
246
+ $expires
247
+ );
248
+ }
249
+
250
+ /**
251
+ * Returns the URL to an object identified by its bucket and key.
252
+ *
253
+ * The URL returned by this method is not signed nor does it ensure the the
254
+ * bucket and key given to the method exist. If you need a signed URL, then
255
+ * use the {@see \Aws\S3\S3Client::createPresignedRequest} method and get
256
+ * the URI of the signed request.
257
+ *
258
+ * @param string $bucket The name of the bucket where the object is located
259
+ * @param string $key The key of the object
260
+ *
261
+ * @return string The URL to the object
262
+ */
263
+ public function getObjectUrl($bucket, $key)
264
+ {
265
+ $command = $this->getCommand('GetObject', [
266
+ 'Bucket' => $bucket,
267
+ 'Key' => $key
268
+ ]);
269
+
270
+ return (string) \Aws\serialize($command)->getUri();
271
+ }
272
+
273
+ /**
274
+ * Determines whether or not a bucket exists by name.
275
+ *
276
+ * @param string $bucket The name of the bucket
277
+ *
278
+ * @return bool
279
+ */
280
+ public function doesBucketExist($bucket)
281
+ {
282
+ return $this->checkExistenceWithCommand(
283
+ $this->getCommand('HeadBucket', ['Bucket' => $bucket])
284
+ );
285
+ }
286
+
287
+ /**
288
+ * Determines whether or not an object exists by name.
289
+ *
290
+ * @param string $bucket The name of the bucket
291
+ * @param string $key The key of the object
292
+ * @param array $options Additional options available in the HeadObject
293
+ * operation (e.g., VersionId).
294
+ *
295
+ * @return bool
296
+ */
297
+ public function doesObjectExist($bucket, $key, array $options = [])
298
+ {
299
+ return $this->checkExistenceWithCommand(
300
+ $this->getCommand('HeadObject', [
301
+ 'Bucket' => $bucket,
302
+ 'Key' => $key
303
+ ] + $options)
304
+ );
305
+ }
306
+
307
+ /**
308
+ * Raw URL encode a key and allow for '/' characters
309
+ *
310
+ * @param string $key Key to encode
311
+ *
312
+ * @return string Returns the encoded key
313
+ */
314
+ public static function encodeKey($key)
315
+ {
316
+ return str_replace('%2F', '/', rawurlencode($key));
317
+ }
318
+
319
+ /**
320
+ * Register the Amazon S3 stream wrapper with this client instance.
321
+ */
322
+ public function registerStreamWrapper()
323
+ {
324
+ StreamWrapper::register($this);
325
+ }
326
+
327
+ /**
328
+ * Deletes objects from Amazon S3 that match the result of a ListObjects
329
+ * operation. For example, this allows you to do things like delete all
330
+ * objects that match a specific key prefix.
331
+ *
332
+ * @param string $bucket Bucket that contains the object keys
333
+ * @param string $prefix Optionally delete only objects under this key prefix
334
+ * @param string $regex Delete only objects that match this regex
335
+ * @param array $options Aws\S3\BatchDelete options array.
336
+ *
337
+ * @see Aws\S3\S3Client::listObjects
338
+ * @throws \RuntimeException if no prefix and no regex is given
339
+ */
340
+ public function deleteMatchingObjects(
341
+ $bucket,
342
+ $prefix = '',
343
+ $regex = '',
344
+ array $options = []
345
+ ) {
346
+ if (!$prefix && !$regex) {
347
+ throw new \RuntimeException('A prefix or regex is required.');
348
+ }
349
+
350
+ $params = ['Bucket' => $bucket, 'Prefix' => $prefix];
351
+ $iter = $this->getIterator('ListObjects', $params);
352
+
353
+ if ($regex) {
354
+ $iter = \Aws\filter($iter, function ($c) use ($regex) {
355
+ return preg_match($regex, $c['Key']);
356
+ });
357
+ }
358
+
359
+ BatchDelete::fromIterator($this, $bucket, $iter, $options)->delete();
360
+ }
361
+
362
+ /**
363
+ * Upload a file, stream, or string to a bucket.
364
+ *
365
+ * If the upload size exceeds the specified threshold, the upload will be
366
+ * performed using concurrent multipart uploads.
367
+ *
368
+ * The options array accepts the following options:
369
+ *
370
+ * - before_upload: (callable) Callback to invoke before any upload
371
+ * operations during the upload process. The callback should have a
372
+ * function signature like `function (Aws\Command $command) {...}`.
373
+ * - concurrency: (int, default=int(3)) Maximum number of concurrent
374
+ * `UploadPart` operations allowed during a multipart upload.
375
+ * - mup_threshold: (int, default=int(16777216)) The size, in bytes, allowed
376
+ * before the upload must be sent via a multipart upload. Default: 16 MB.
377
+ * - params: (array, default=array([])) Custom parameters to use with the
378
+ * upload. For single uploads, they must correspond to those used for the
379
+ * `PutObject` operation. For multipart uploads, they correspond to the
380
+ * parameters of the `CreateMultipartUpload` operation.
381
+ * - part_size: (int) Part size to use when doing a multipart upload.
382
+ *
383
+ * @param string $bucket Bucket to upload the object.
384
+ * @param string $key Key of the object.
385
+ * @param mixed $body Object data to upload. Can be a
386
+ * StreamInterface, PHP stream resource, or a
387
+ * string of data to upload.
388
+ * @param string $acl ACL to apply to the object (default: private).
389
+ * @param array $options Options used to configure the upload process.
390
+ *
391
+ * @see Aws\S3\MultipartUploader for more info about multipart uploads.
392
+ * @return ResultInterface Returns the result of the upload.
393
+ */
394
+ public function upload(
395
+ $bucket,
396
+ $key,
397
+ $body,
398
+ $acl = 'private',
399
+ array $options = []
400
+ ) {
401
+ return $this
402
+ ->uploadAsync($bucket, $key, $body, $acl, $options)
403
+ ->wait();
404
+ }
405
+
406
+ /**
407
+ * Upload a file, stream, or string to a bucket asynchronously.
408
+ *
409
+ * @param string $bucket Bucket to upload the object.
410
+ * @param string $key Key of the object.
411
+ * @param mixed $body Object data to upload. Can be a
412
+ * StreamInterface, PHP stream resource, or a
413
+ * string of data to upload.
414
+ * @param string $acl ACL to apply to the object (default: private).
415
+ * @param array $options Options used to configure the upload process.
416
+ *
417
+ * @see self::upload
418
+ * @return PromiseInterface Returns a promise that will be fulfilled
419
+ * with the result of the upload.
420
+ */
421
+ public function uploadAsync(
422
+ $bucket,
423
+ $key,
424
+ $body,
425
+ $acl = 'private',
426
+ array $options = []
427
+ ) {
428
+ // Prepare the options.
429
+ static $defaults = [
430
+ 'before_upload' => null,
431
+ 'concurrency' => 3,
432
+ 'mup_threshold' => 16777216,
433
+ 'params' => [],
434
+ 'part_size' => null,
435
+ ];
436
+ $options = array_intersect_key($options + $defaults, $defaults);
437
+
438
+ // Perform the required operations to upload the S3 Object.
439
+ $body = Psr7\stream_for($body);
440
+ if ($this->requiresMultipart($body, $options['mup_threshold'])) {
441
+ // Perform a multipart upload.
442
+ $options['before_initiate'] = function ($command) use ($options) {
443
+ foreach ($options['params'] as $k => $v) {
444
+ $command[$k] = $v;
445
+ }
446
+ };
447
+ return (new MultipartUploader($this, $body, [
448
+ 'bucket' => $bucket,
449
+ 'key' => $key,
450
+ 'acl' => $acl
451
+ ] + $options))->promise();
452
+ } else {
453
+ // Perform a regular PutObject operation.
454
+ $command = $this->getCommand('PutObject', [
455
+ 'Bucket' => $bucket,
456
+ 'Key' => $key,
457
+ 'Body' => $body,
458
+ 'ACL' => $acl,
459
+ ] + $options['params']);
460
+ if (is_callable($options['before_upload'])) {
461
+ $options['before_upload']($command);
462
+ }
463
+ return $this->executeAsync($command);
464
+ }
465
+ }
466
+
467
+ /**
468
+ * Copy an object of any size to a different location.
469
+ *
470
+ * If the upload size exceeds the maximum allowable size for direct S3
471
+ * copying, a multipart copy will be used.
472
+ *
473
+ * The options array accepts the following options:
474
+ *
475
+ * - before_upload: (callable) Callback to invoke before any upload
476
+ * operations during the upload process. The callback should have a
477
+ * function signature like `function (Aws\Command $command) {...}`.
478
+ * - concurrency: (int, default=int(5)) Maximum number of concurrent
479
+ * `UploadPart` operations allowed during a multipart upload.
480
+ * - params: (array, default=array([])) Custom parameters to use with the
481
+ * upload. For single uploads, they must correspond to those used for the
482
+ * `CopyObject` operation. For multipart uploads, they correspond to the
483
+ * parameters of the `CreateMultipartUpload` operation.
484
+ * - part_size: (int) Part size to use when doing a multipart upload.
485
+ *
486
+ * @param string $fromBucket Bucket where the copy source resides.
487
+ * @param string $fromKey Key of the copy source.
488
+ * @param string $destBucket Bucket to which to copy the object.
489
+ * @param string $destKey Key to which to copy the object.
490
+ * @param string $acl ACL to apply to the copy (default: private).
491
+ * @param array $options Options used to configure the upload process.
492
+ *
493
+ * @see Aws\S3\MultipartCopy for more info about multipart uploads.
494
+ * @return ResultInterface Returns the result of the copy.
495
+ */
496
+ public function copy(
497
+ $fromBucket,
498
+ $fromKey,
499
+ $destBucket,
500
+ $destKey,
501
+ $acl = 'private',
502
+ array $options = []
503
+ ) {
504
+ return $this
505
+ ->copyAsync($fromBucket, $fromKey, $destBucket, $destKey, $acl, $options)
506
+ ->wait();
507
+ }
508
+
509
+ /**
510
+ * Copy an object of any size to a different location asynchronously.
511
+ *
512
+ * @param string $fromBucket Bucket where the copy source resides.
513
+ * @param string $fromKey Key of the copy source.
514
+ * @param string $destBucket Bucket to which to copy the object.
515
+ * @param string $destKey Key to which to copy the object.
516
+ * @param string $acl ACL to apply to the copy (default: private).
517
+ * @param array $options Options used to configure the upload process.
518
+ *
519
+ * @see self::copy for more info about the parameters above.
520
+ * @return PromiseInterface Returns a promise that will be fulfilled
521
+ * with the result of the copy.
522
+ */
523
+ public function copyAsync(
524
+ $fromBucket,
525
+ $fromKey,
526
+ $destBucket,
527
+ $destKey,
528
+ $acl = 'private',
529
+ array $options = []
530
+ ) {
531
+ // Prepare the options.
532
+ static $defaults = [
533
+ 'before_upload' => null,
534
+ 'concurrency' => 5,
535
+ 'mup_threshold' => MultipartUploader::PART_MAX_SIZE,
536
+ 'params' => [],
537
+ 'part_size' => null,
538
+ 'version_id' => null,
539
+ ];
540
+
541
+ return Promise\coroutine($this->doCopyAsync(
542
+ ['Bucket' => $fromBucket, 'Key' => $fromKey],
543
+ ['Bucket' => $destBucket, 'Key' => $destKey],
544
+ $acl,
545
+ $options + $defaults
546
+ ));
547
+ }
548
+
549
+ private function doCopyAsync(
550
+ array $source,
551
+ array $destination,
552
+ $acl,
553
+ array $options
554
+ ) {
555
+ return function () use ($source, $destination, $acl, $options) {
556
+ $sourcePath = '/' . $source['Bucket'] . '/' . rawurlencode($source['Key']);
557
+ if ($options['version_id']) {
558
+ $sourcePath .= "?versionId={$options['version_id']}";
559
+ $source['VersionId'] = $options['version_id'];
560
+ }
561
+
562
+ $objectStats = (yield $this->headObjectAsync($source));
563
+
564
+ if ($objectStats['ContentLength'] > $options['mup_threshold']) {
565
+ $mup = new MultipartCopy($this, $sourcePath, $destination + [
566
+ 'source_metadata' => $objectStats,
567
+ 'acl' => $acl,
568
+ ] + $options);
569
+
570
+ yield $mup->promise();
571
+ } else {
572
+ yield $this->copyObjectAsync($options + $destination + [
573
+ 'ACL' => $acl,
574
+ 'MetadataDirective' => 'COPY',
575
+ 'CopySource' => $sourcePath,
576
+ ] + $options['params']);
577
+ }
578
+ };
579
+ }
580
+
581
+ /**
582
+ * Recursively uploads all files in a given directory to a given bucket.
583
+ *
584
+ * @param string $directory Full path to a directory to upload
585
+ * @param string $bucket Name of the bucket
586
+ * @param string $keyPrefix Virtual directory key prefix to add to each upload
587
+ * @param array $options Options available in Aws\S3\Transfer::__construct
588
+ *
589
+ * @see Aws\S3\Transfer for more options and customization
590
+ */
591
+ public function uploadDirectory(
592
+ $directory,
593
+ $bucket,
594
+ $keyPrefix = null,
595
+ array $options = []
596
+ ) {
597
+ $d = "s3://$bucket" . ($keyPrefix ? '/' . ltrim($keyPrefix, '/') : '');
598
+ (new Transfer($this, $directory, $d, $options))->transfer();
599
+ }
600
+
601
+ /**
602
+ * Downloads a bucket to the local filesystem
603
+ *
604
+ * @param string $directory Directory to download to
605
+ * @param string $bucket Bucket to download from
606
+ * @param string $keyPrefix Only download objects that use this key prefix
607
+ * @param array $options Options available in Aws\S3\Transfer::__construct
608
+ */
609
+ public function downloadBucket(
610
+ $directory,
611
+ $bucket,
612
+ $keyPrefix = '',
613
+ array $options = []
614
+ ) {
615
+ $s = "s3://$bucket" . ($keyPrefix ? '/' . ltrim($keyPrefix, '/') : '');
616
+ (new Transfer($this, $s, $directory, $options))->transfer();
617
+ }
618
+
619
+ /**
620
+ * Determines if the body should be uploaded using PutObject or the
621
+ * Multipart Upload System. It also modifies the passed-in $body as needed
622
+ * to support the upload.
623
+ *
624
+ * @param StreamInterface $body Stream representing the body.
625
+ * @param integer $threshold Minimum bytes before using Multipart.
626
+ *
627
+ * @return bool
628
+ */
629
+ private function requiresMultipart(StreamInterface &$body, $threshold)
630
+ {
631
+ // If body size known, compare to threshold to determine if Multipart.
632
+ if ($body->getSize() !== null) {
633
+ return $body->getSize() >= $threshold;
634
+ }
635
+
636
+ // Handle the situation where the body size is unknown.
637
+ // Read up to 5MB into a buffer to determine how to upload the body.
638
+ $buffer = Psr7\stream_for();
639
+ Psr7\copy_to_stream($body, $buffer, MultipartUploader::PART_MIN_SIZE);
640
+
641
+ // If body < 5MB, use PutObject with the buffer.
642
+ if ($buffer->getSize() < MultipartUploader::PART_MIN_SIZE) {
643
+ $buffer->seek(0);
644
+ $body = $buffer;
645
+ return false;
646
+ }
647
+
648
+ // If body >= 5 MB, then use multipart. [YES]
649
+ if ($body->isSeekable()) {
650
+ // If the body is seekable, just rewind the body.
651
+ $body->seek(0);
652
+ } else {
653
+ // If the body is non-seekable, stitch the rewind the buffer and
654
+ // the partially read body together into one stream. This avoids
655
+ // unnecessary disc usage and does not require seeking on the
656
+ // original stream.
657
+ $buffer->seek(0);
658
+ $body = new Psr7\AppendStream([$buffer, $body]);
659
+ }
660
+
661
+ return true;
662
+ }
663
+
664
+ /**
665
+ * Determines whether or not a resource exists using a command
666
+ *
667
+ * @param CommandInterface $command Command used to poll for the resource
668
+ *
669
+ * @return bool
670
+ * @throws S3Exception|\Exception if there is an unhandled exception
671
+ */
672
+ private function checkExistenceWithCommand(CommandInterface $command)
673
+ {
674
+ try {
675
+ $this->execute($command);
676
+ return true;
677
+ } catch (S3Exception $e) {
678
+ if ($e->getAwsErrorCode() == 'AccessDenied') {
679
+ return true;
680
+ }
681
+ if ($e->getStatusCode() >= 500) {
682
+ throw $e;
683
+ }
684
+ return false;
685
+ }
686
+ }
687
+
688
+ /**
689
+ * Provides a middleware that removes the need to specify LocationConstraint on CreateBucket.
690
+ *
691
+ * @return \Closure
692
+ */
693
+ private function getLocationConstraintMiddleware()
694
+ {
695
+ $region = $this->getRegion();
696
+ return static function (callable $handler) use ($region) {
697
+ return function (Command $command, $request = null) use ($handler, $region) {
698
+ if ($command->getName() === 'CreateBucket') {
699
+ $locationConstraint = isset($command['CreateBucketConfiguration']['LocationConstraint'])
700
+ ? $command['CreateBucketConfiguration']['LocationConstraint']
701
+ : null;
702
+
703
+ if ($locationConstraint === 'us-east-1') {
704
+ unset($command['CreateBucketConfiguration']);
705
+ } elseif ('us-east-1' !== $region && empty($locationConstraint)) {
706
+ $command['CreateBucketConfiguration'] = ['LocationConstraint' => $region];
707
+ }
708
+ }
709
+
710
+ return $handler($command, $request);
711
+ };
712
+ };
713
+ }
714
+
715
+ /**
716
+ * Provides a middleware that supports the `SaveAs` parameter.
717
+ *
718
+ * @return \Closure
719
+ */
720
+ private function getSaveAsParameter()
721
+ {
722
+ return static function (callable $handler) {
723
+ return function (Command $command, $request = null) use ($handler) {
724
+ if ($command->getName() === 'GetObject' && isset($command['SaveAs'])) {
725
+ $command['@http']['sink'] = $command['SaveAs'];
726
+ unset($command['SaveAs']);
727
+ }
728
+
729
+ return $handler($command, $request);
730
+ };
731
+ };
732
+ }
733
+
734
+ /** @internal */
735
+ public static function _applyRetryConfig($value, $_, HandlerList $list)
736
+ {
737
+ if (!$value) {
738
+ return;
739
+ }
740
+
741
+ $decider = RetryMiddleware::createDefaultDecider($value);
742
+ $decider = function ($retries, $command, $request, $result, $error) use ($decider, $value) {
743
+ $maxRetries = null !== $command['@retries']
744
+ ? $command['@retries']
745
+ : $value;
746
+
747
+ if ($decider($retries, $command, $request, $result, $error)) {
748
+ return true;
749
+ } elseif ($error instanceof AwsException
750
+ && $retries < $maxRetries
751
+ ) {
752
+ if (
753
+ $error->getResponse()
754
+ && $error->getResponse()->getStatusCode() >= 400
755
+ ) {
756
+ return strpos(
757
+ $error->getResponse()->getBody(),
758
+ 'Your socket connection to the server'
759
+ ) !== false;
760
+ } elseif ($error->getPrevious() instanceof RequestException) {
761
+ // All commands except CompleteMultipartUpload are
762
+ // idempotent and may be retried without worry if a
763
+ // networking error has occurred.
764
+ return $command->getName() !== 'CompleteMultipartUpload';
765
+ }
766
+ }
767
+ return false;
768
+ };
769
+
770
+ $delay = [RetryMiddleware::class, 'exponentialDelay'];
771
+ $list->appendSign(Middleware::retry($decider, $delay), 'retry');
772
+ }
773
+
774
+ /** @internal */
775
+ public static function _applyApiProvider($value, array &$args, HandlerList $list)
776
+ {
777
+ ClientResolver::_apply_api_provider($value, $args, $list);
778
+ $args['parser'] = new GetBucketLocationParser(
779
+ new AmbiguousSuccessParser(
780
+ new RetryableMalformedResponseParser(
781
+ $args['parser'],
782
+ $args['exception_class']
783
+ ),
784
+ $args['error_parser'],
785
+ $args['exception_class']
786
+ )
787
+ );
788
+ }
789
+
790
+ /**
791
+ * @internal
792
+ * @codeCoverageIgnore
793
+ */
794
+ public static function applyDocFilters(array $api, array $docs)
795
+ {
796
+ $b64 = '<div class="alert alert-info">This value will be base64 encoded on your behalf.</div>';
797
+ $opt = '<div class="alert alert-info">This value will be computed for you it is not supplied.</div>';
798
+
799
+ // Add the SourceFile parameter.
800
+ $docs['shapes']['SourceFile']['base'] = 'The path to a file on disk to use instead of the Body parameter.';
801
+ $api['shapes']['SourceFile'] = ['type' => 'string'];
802
+ $api['shapes']['PutObjectRequest']['members']['SourceFile'] = ['shape' => 'SourceFile'];
803
+ $api['shapes']['UploadPartRequest']['members']['SourceFile'] = ['shape' => 'SourceFile'];
804
+
805
+ // Add the ContentSHA256 parameter.
806
+ $docs['shapes']['ContentSHA256']['base'] = 'A SHA256 hash of the body content of the request.';
807
+ $api['shapes']['ContentSHA256'] = ['type' => 'string'];
808
+ $api['shapes']['PutObjectRequest']['members']['ContentSHA256'] = ['shape' => 'ContentSHA256'];
809
+ $api['shapes']['UploadPartRequest']['members']['ContentSHA256'] = ['shape' => 'ContentSHA256'];
810
+ unset($api['shapes']['PutObjectRequest']['members']['ContentMD5']);
811
+ unset($api['shapes']['UploadPartRequest']['members']['ContentMD5']);
812
+ $docs['shapes']['ContentSHA256']['append'] = $opt;
813
+
814
+ // Add the SaveAs parameter.
815
+ $docs['shapes']['SaveAs']['base'] = 'The path to a file on disk to save the object data.';
816
+ $api['shapes']['SaveAs'] = ['type' => 'string'];
817
+ $api['shapes']['GetObjectRequest']['members']['SaveAs'] = ['shape' => 'SaveAs'];
818
+
819
+ // Several SSECustomerKey documentation updates.
820
+ $docs['shapes']['SSECustomerKey']['append'] = $b64;
821
+ $docs['shapes']['CopySourceSSECustomerKey']['append'] = $b64;
822
+ $docs['shapes']['SSECustomerKeyMd5']['append'] = $opt;
823
+
824
+ // Add the ObjectURL to various output shapes and documentation.
825
+ $docs['shapes']['ObjectURL']['base'] = 'The URI of the created object.';
826
+ $api['shapes']['ObjectURL'] = ['type' => 'string'];
827
+ $api['shapes']['PutObjectOutput']['members']['ObjectURL'] = ['shape' => 'ObjectURL'];
828
+ $api['shapes']['CopyObjectOutput']['members']['ObjectURL'] = ['shape' => 'ObjectURL'];
829
+ $api['shapes']['CompleteMultipartUploadOutput']['members']['ObjectURL'] = ['shape' => 'ObjectURL'];
830
+
831
+ // Fix references to Location Constraint.
832
+ unset($api['shapes']['CreateBucketRequest']['payload']);
833
+ $api['shapes']['BucketLocationConstraint']['enum'] = [
834
+ "ap-northeast-1",
835
+ "ap-southeast-2",
836
+ "ap-southeast-1",
837
+ "cn-north-1",
838
+ "eu-central-1",
839
+ "eu-west-1",
840
+ "us-east-1",
841
+ "us-west-1",
842
+ "us-west-2",
843
+ "sa-east-1",
844
+ ];
845
+
846
+ // Add a note that the ContentMD5 is optional.
847
+ $docs['shapes']['ContentMD5']['append'] = '<div class="alert alert-info">The value will be computed on '
848
+ . 'your behalf.</div>';
849
+
850
+ return [
851
+ new Service($api, ApiProvider::defaultProvider()),
852
+ new DocModel($docs)
853
+ ];
854
+ }
855
+ }
includes/aws/Aws/S3/S3UriParser.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use GuzzleHttp\Psr7;
5
+ use Psr\Http\Message\UriInterface;
6
+
7
+ /**
8
+ * Extracts a region, bucket, key, and and if a URI is in path-style
9
+ */
10
+ class S3UriParser
11
+ {
12
+ private $pattern = '/^(.+\\.)?s3[.-]([A-Za-z0-9-]+)\\./';
13
+
14
+ private static $defaultResult = [
15
+ 'path_style' => true,
16
+ 'bucket' => null,
17
+ 'key' => null,
18
+ 'region' => null
19
+ ];
20
+
21
+ /**
22
+ * Parses a URL into an associative array of Amazon S3 data including:
23
+ *
24
+ * - bucket: The Amazon S3 bucket (null if none)
25
+ * - key: The Amazon S3 key (null if none)
26
+ * - path_style: Set to true if using path style, or false if not
27
+ * - region: Set to a string if a non-class endpoint is used or null.
28
+ *
29
+ * @param string|UriInterface $uri
30
+ *
31
+ * @return array
32
+ * @throws \InvalidArgumentException
33
+ */
34
+ public function parse($uri)
35
+ {
36
+ $url = Psr7\uri_for($uri);
37
+ if (!$url->getHost()) {
38
+ throw new \InvalidArgumentException('No hostname found in URI: '
39
+ . $uri);
40
+ }
41
+
42
+ if (!preg_match($this->pattern, $url->getHost(), $matches)) {
43
+ return $this->parseCustomEndpoint($url);
44
+ }
45
+
46
+ // Parse the URI based on the matched format (path / virtual)
47
+ $result = empty($matches[1])
48
+ ? $this->parsePathStyle($url)
49
+ : $this->parseVirtualHosted($url, $matches);
50
+
51
+ // Add the region if one was found and not the classic endpoint
52
+ $result['region'] = $matches[2] == 'amazonaws' ? null : $matches[2];
53
+
54
+ return $result;
55
+ }
56
+
57
+ private function parseCustomEndpoint(UriInterface $url)
58
+ {
59
+ $result = $result = self::$defaultResult;
60
+ $path = ltrim($url->getPath(), '/ ');
61
+ $segments = explode('/', $path, 2);
62
+
63
+ if (isset($segments[0])) {
64
+ $result['bucket'] = $segments[0];
65
+ if (isset($segments[1])) {
66
+ $result['key'] = $segments[1];
67
+ }
68
+ }
69
+
70
+ return $result;
71
+ }
72
+
73
+ private function parsePathStyle(UriInterface $url)
74
+ {
75
+ $result = self::$defaultResult;
76
+
77
+ if ($url->getPath() != '/') {
78
+ $path = ltrim($url->getPath(), '/');
79
+ if ($path) {
80
+ $pathPos = strpos($path, '/');
81
+ if ($pathPos === false) {
82
+ // https://s3.amazonaws.com/bucket
83
+ $result['bucket'] = $path;
84
+ } elseif ($pathPos == strlen($path) - 1) {
85
+ // https://s3.amazonaws.com/bucket/
86
+ $result['bucket'] = substr($path, 0, -1);
87
+ } else {
88
+ // https://s3.amazonaws.com/bucket/key
89
+ $result['bucket'] = substr($path, 0, $pathPos);
90
+ $result['key'] = substr($path, $pathPos + 1) ?: null;
91
+ }
92
+ }
93
+ }
94
+
95
+ return $result;
96
+ }
97
+
98
+ private function parseVirtualHosted(UriInterface $url, array $matches)
99
+ {
100
+ $result = self::$defaultResult;
101
+ $result['path_style'] = false;
102
+ // Remove trailing "." from the prefix to get the bucket
103
+ $result['bucket'] = substr($matches[1], 0, -1);
104
+ $path = $url->getPath();
105
+ // Check if a key was present, and if so, removing the leading "/"
106
+ $result['key'] = !$path || $path == '/' ? null : substr($path, 1);
107
+
108
+ return $result;
109
+ }
110
+ }
includes/aws/Aws/S3/SSECMiddleware.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\CommandInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+
7
+ /**
8
+ * Simplifies the SSE-C process by encoding and hashing the key.
9
+ * @internal
10
+ */
11
+ class SSECMiddleware
12
+ {
13
+ private $endpointScheme;
14
+ private $nextHandler;
15
+
16
+ /**
17
+ * Provide the URI scheme of the client sending requests.
18
+ *
19
+ * @param string $endpointScheme URI scheme (http/https).
20
+ *
21
+ * @return callable
22
+ */
23
+ public static function wrap($endpointScheme)
24
+ {
25
+ return function (callable $handler) use ($endpointScheme) {
26
+ return new self($endpointScheme, $handler);
27
+ };
28
+ }
29
+
30
+ public function __construct($endpointScheme, callable $nextHandler)
31
+ {
32
+ $this->nextHandler = $nextHandler;
33
+ $this->endpointScheme = $endpointScheme;
34
+ }
35
+
36
+ public function __invoke(
37
+ CommandInterface $command,
38
+ RequestInterface $request = null
39
+ ) {
40
+ // Allows only HTTPS connections when using SSE-C
41
+ if (($command['SSECustomerKey'] || $command['CopySourceSSECustomerKey'])
42
+ && $this->endpointScheme !== 'https'
43
+ ) {
44
+ throw new \RuntimeException('You must configure your S3 client to '
45
+ . 'use HTTPS in order to use the SSE-C features.');
46
+ }
47
+
48
+ // Prepare the normal SSE-CPK headers
49
+ if ($command['SSECustomerKey']) {
50
+ $this->prepareSseParams($command);
51
+ }
52
+
53
+ // If it's a copy operation, prepare the SSE-CPK headers for the source.
54
+ if ($command['CopySourceSSECustomerKey']) {
55
+ $this->prepareSseParams($command, 'CopySource');
56
+ }
57
+
58
+ $f = $this->nextHandler;
59
+ return $f($command, $request);
60
+ }
61
+
62
+ private function prepareSseParams(CommandInterface $command, $prefix = '')
63
+ {
64
+ // Base64 encode the provided key
65
+ $key = $command[$prefix . 'SSECustomerKey'];
66
+ $command[$prefix . 'SSECustomerKey'] = base64_encode($key);
67
+
68
+ // Base64 the provided MD5 or, generate an MD5 if not provided
69
+ if ($md5 = $command[$prefix . 'SSECustomerKeyMD5']) {
70
+ $command[$prefix . 'SSECustomerKeyMD5'] = base64_encode($md5);
71
+ } else {
72
+ $command[$prefix . 'SSECustomerKeyMD5'] = base64_encode(md5($key, true));
73
+ }
74
+ }
75
+ }
includes/aws/Aws/S3/StreamWrapper.php ADDED
@@ -0,0 +1,949 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws\CacheInterface;
5
+ use Aws\LruArrayCache;
6
+ use Aws\Result;
7
+ use Aws\S3\Exception\S3Exception;
8
+ use GuzzleHttp\Psr7;
9
+ use GuzzleHttp\Psr7\Stream;
10
+ use GuzzleHttp\Psr7\CachingStream;
11
+ use Psr\Http\Message\StreamInterface;
12
+
13
+ /**
14
+ * Amazon S3 stream wrapper to use "s3://<bucket>/<key>" files with PHP
15
+ * streams, supporting "r", "w", "a", "x".
16
+ *
17
+ * # Opening "r" (read only) streams:
18
+ *
19
+ * Read only streams are truly streaming by default and will not allow you to
20
+ * seek. This is because data read from the stream is not kept in memory or on
21
+ * the local filesystem. You can force a "r" stream to be seekable by setting
22
+ * the "seekable" stream context option true. This will allow true streaming of
23
+ * data from Amazon S3, but will maintain a buffer of previously read bytes in
24
+ * a 'php://temp' stream to allow seeking to previously read bytes from the
25
+ * stream.
26
+ *
27
+ * You may pass any GetObject parameters as 's3' stream context options. These
28
+ * options will affect how the data is downloaded from Amazon S3.
29
+ *
30
+ * # Opening "w" and "x" (write only) streams:
31
+ *
32
+ * Because Amazon S3 requires a Content-Length header, write only streams will
33
+ * maintain a 'php://temp' stream to buffer data written to the stream until
34
+ * the stream is flushed (usually by closing the stream with fclose).
35
+ *
36
+ * You may pass any PutObject parameters as 's3' stream context options. These
37
+ * options will affect how the data is uploaded to Amazon S3.
38
+ *
39
+ * When opening an "x" stream, the file must exist on Amazon S3 for the stream
40
+ * to open successfully.
41
+ *
42
+ * # Opening "a" (write only append) streams:
43
+ *
44
+ * Similar to "w" streams, opening append streams requires that the data be
45
+ * buffered in a "php://temp" stream. Append streams will attempt to download
46
+ * the contents of an object in Amazon S3, seek to the end of the object, then
47
+ * allow you to append to the contents of the object. The data will then be
48
+ * uploaded using a PutObject operation when the stream is flushed (usually
49
+ * with fclose).
50
+ *
51
+ * You may pass any GetObject and/or PutObject parameters as 's3' stream
52
+ * context options. These options will affect how the data is downloaded and
53
+ * uploaded from Amazon S3.
54
+ *
55
+ * Stream context options:
56
+ *
57
+ * - "seekable": Set to true to create a seekable "r" (read only) stream by
58
+ * using a php://temp stream buffer
59
+ * - For "unlink" only: Any option that can be passed to the DeleteObject
60
+ * operation
61
+ */
62
+ class StreamWrapper
63
+ {
64
+ /** @var resource|null Stream context (this is set by PHP) */
65
+ public $context;
66
+
67
+ /** @var StreamInterface Underlying stream resource */
68
+ private $body;
69
+
70
+ /** @var int Size of the body that is opened */
71
+ private $size;
72
+
73
+ /** @var array Hash of opened stream parameters */
74
+ private $params = [];
75
+
76
+ /** @var string Mode in which the stream was opened */
77
+ private $mode;
78
+
79
+ /** @var \Iterator Iterator used with opendir() related calls */
80
+ private $objectIterator;
81
+
82
+ /** @var string The bucket that was opened when opendir() was called */
83
+ private $openedBucket;
84
+
85
+ /** @var string The prefix of the bucket that was opened with opendir() */
86
+ private $openedBucketPrefix;
87
+
88
+ /** @var string Opened bucket path */
89
+ private $openedPath;
90
+
91
+ /** @var CacheInterface Cache for object and dir lookups */
92
+ private $cache;
93
+
94
+ /** @var string The opened protocol (e.g., "s3") */
95
+ private $protocol = 's3';
96
+
97
+ /**
98
+ * Register the 's3://' stream wrapper
99
+ *
100
+ * @param S3Client $client Client to use with the stream wrapper
101
+ * @param string $protocol Protocol to register as.
102
+ * @param CacheInterface $cache Default cache for the protocol.
103
+ */
104
+ public static function register(
105
+ S3Client $client,
106
+ $protocol = 's3',
107
+ CacheInterface $cache = null
108
+ ) {
109
+ if (in_array($protocol, stream_get_wrappers())) {
110
+ stream_wrapper_unregister($protocol);
111
+ }
112
+
113
+ // Set the client passed in as the default stream context client
114
+ stream_wrapper_register($protocol, get_called_class(), STREAM_IS_URL);
115
+ $default = stream_context_get_options(stream_context_get_default());
116
+ $default[$protocol]['client'] = $client;
117
+
118
+ if ($cache) {
119
+ $default[$protocol]['cache'] = $cache;
120
+ } elseif (!isset($default[$protocol]['cache'])) {
121
+ // Set a default cache adapter.
122
+ $default[$protocol]['cache'] = new LruArrayCache();
123
+ }
124
+
125
+ stream_context_set_default($default);
126
+ }
127
+
128
+ public function stream_close()
129
+ {
130
+ $this->body = $this->cache = null;
131
+ }
132
+
133
+ public function stream_open($path, $mode, $options, &$opened_path)
134
+ {
135
+ $this->initProtocol($path);
136
+ $this->params = $this->getBucketKey($path);
137
+ $this->mode = rtrim($mode, 'bt');
138
+
139
+ if ($errors = $this->validate($path, $this->mode)) {
140
+ return $this->triggerError($errors);
141
+ }
142
+
143
+ return $this->boolCall(function() use ($path) {
144
+ switch ($this->mode) {
145
+ case 'r': return $this->openReadStream($path);
146
+ case 'a': return $this->openAppendStream($path);
147
+ default: return $this->openWriteStream($path);
148
+ }
149
+ });
150
+ }
151
+
152
+ public function stream_eof()
153
+ {
154
+ return $this->body->eof();
155
+ }
156
+
157
+ public function stream_flush()
158
+ {
159
+ if ($this->mode == 'r') {
160
+ return false;
161
+ }
162
+
163
+ if ($this->body->isSeekable()) {
164
+ $this->body->seek(0);
165
+ }
166
+ $params = $this->getOptions(true);
167
+ $params['Body'] = $this->body;
168
+
169
+ // Attempt to guess the ContentType of the upload based on the
170
+ // file extension of the key
171
+ if (!isset($params['ContentType']) &&
172
+ ($type = Psr7\mimetype_from_filename($params['Key']))
173
+ ) {
174
+ $params['ContentType'] = $type;
175
+ }
176
+
177
+ return $this->boolCall(function () use ($params) {
178
+ return (bool) $this->getClient()->putObject($params);
179
+ });
180
+ }
181
+
182
+ public function stream_read($count)
183
+ {
184
+ return $this->body->read($count);
185
+ }
186
+
187
+ public function stream_seek($offset, $whence = SEEK_SET)
188
+ {
189
+ return !$this->body->isSeekable()
190
+ ? false
191
+ : $this->boolCall(function () use ($offset, $whence) {
192
+ $this->body->seek($offset, $whence);
193
+ return true;
194
+ });
195
+ }
196
+
197
+ public function stream_tell()
198
+ {
199
+ return $this->boolCall(function() { return $this->body->tell(); });
200
+ }
201
+
202
+ public function stream_write($data)
203
+ {
204
+ return $this->body->write($data);
205
+ }
206
+
207
+ public function unlink($path)
208
+ {
209
+ $this->initProtocol($path);
210
+
211
+ return $this->boolCall(function () use ($path) {
212
+ $this->clearCacheKey($path);
213
+ $this->getClient()->deleteObject($this->withPath($path));
214
+ return true;
215
+ });
216
+ }
217
+
218
+ public function stream_stat()
219
+ {
220
+ $stat = $this->getStatTemplate();
221
+ $stat[7] = $stat['size'] = $this->getSize();
222
+ $stat[2] = $stat['mode'] = $this->mode;
223
+
224
+ return $stat;
225
+ }
226
+
227
+ /**
228
+ * Provides information for is_dir, is_file, filesize, etc. Works on
229
+ * buckets, keys, and prefixes.
230
+ * @link http://www.php.net/manual/en/streamwrapper.url-stat.php
231
+ */
232
+ public function url_stat($path, $flags)
233
+ {
234
+ $this->initProtocol($path);
235
+
236
+ // Some paths come through as S3:// for some reason.
237
+ $split = explode('://', $path);
238
+ $path = strtolower($split[0]) . '://' . $split[1];
239
+
240
+ // Check if this path is in the url_stat cache
241
+ if ($value = $this->getCacheStorage()->get($path)) {
242
+ return $value;
243
+ }
244
+
245
+ $stat = $this->createStat($path, $flags);
246
+
247
+ if (is_array($stat)) {
248
+ $this->getCacheStorage()->set($path, $stat);
249
+ }
250
+
251
+ return $stat;
252
+ }
253
+
254
+ /**
255
+ * Parse the protocol out of the given path.
256
+ *
257
+ * @param $path
258
+ */
259
+ private function initProtocol($path)
260
+ {
261
+ $parts = explode('://', $path, 2);
262
+ $this->protocol = $parts[0] ?: 's3';
263
+ }
264
+
265
+ private function createStat($path, $flags)
266
+ {
267
+ $this->initProtocol($path);
268
+ $parts = $this->withPath($path);
269
+
270
+ if (!$parts['Key']) {
271
+ return $this->statDirectory($parts, $path, $flags);
272
+ }
273
+
274
+ return $this->boolCall(function () use ($parts, $path) {
275
+ try {
276
+ $result = $this->getClient()->headObject($parts);
277
+ if (substr($parts['Key'], -1, 1) == '/' &&
278
+ $result['ContentLength'] == 0
279
+ ) {
280
+ // Return as if it is a bucket to account for console
281
+ // bucket objects (e.g., zero-byte object "foo/")
282
+ return $this->formatUrlStat($path);
283
+ } else {
284
+ // Attempt to stat and cache regular object
285
+ return $this->formatUrlStat($result->toArray());
286
+ }
287
+ } catch (S3Exception $e) {
288
+ // Maybe this isn't an actual key, but a prefix. Do a prefix
289
+ // listing of objects to determine.
290
+ $result = $this->getClient()->listObjects([
291
+ 'Bucket' => $parts['Bucket'],
292
+ 'Prefix' => rtrim($parts['Key'], '/') . '/',
293
+ 'MaxKeys' => 1
294
+ ]);
295
+ if (!$result['Contents'] && !$result['CommonPrefixes']) {
296
+ throw new \Exception("File or directory not found: $path");
297
+ }
298
+ return $this->formatUrlStat($path);
299
+ }
300
+ }, $flags);
301
+ }
302
+
303
+ private function statDirectory($parts, $path, $flags)
304
+ {
305
+ // Stat "directories": buckets, or "s3://"
306
+ if (!$parts['Bucket'] ||
307
+ $this->getClient()->doesBucketExist($parts['Bucket'])
308
+ ) {
309
+ return $this->formatUrlStat($path);
310
+ }
311
+
312
+ return $this->triggerError("File or directory not found: $path", $flags);
313
+ }
314
+
315
+ /**
316
+ * Support for mkdir().
317
+ *
318
+ * @param string $path Directory which should be created.
319
+ * @param int $mode Permissions. 700-range permissions map to
320
+ * ACL_PUBLIC. 600-range permissions map to
321
+ * ACL_AUTH_READ. All other permissions map to
322
+ * ACL_PRIVATE. Expects octal form.
323
+ * @param int $options A bitwise mask of values, such as
324
+ * STREAM_MKDIR_RECURSIVE.
325
+ *
326
+ * @return bool
327
+ * @link http://www.php.net/manual/en/streamwrapper.mkdir.php
328
+ */
329
+ public function mkdir($path, $mode, $options)
330
+ {
331
+ $this->initProtocol($path);
332
+ $params = $this->withPath($path);
333
+ $this->clearCacheKey($path);
334
+ if (!$params['Bucket']) {
335
+ return false;
336
+ }
337
+
338
+ if (!isset($params['ACL'])) {
339
+ $params['ACL'] = $this->determineAcl($mode);
340
+ }
341
+
342
+ return empty($params['Key'])
343
+ ? $this->createBucket($path, $params)
344
+ : $this->createSubfolder($path, $params);
345
+ }
346
+
347
+ public function rmdir($path, $options)
348
+ {
349
+ $this->initProtocol($path);
350
+ $this->clearCacheKey($path);
351
+ $params = $this->withPath($path);
352
+ $client = $this->getClient();
353
+
354
+ if (!$params['Bucket']) {
355
+ return $this->triggerError('You must specify a bucket');
356
+ }
357
+
358
+ return $this->boolCall(function () use ($params, $path, $client) {
359
+ if (!$params['Key']) {
360
+ $client->deleteBucket(['Bucket' => $params['Bucket']]);
361
+ return true;
362
+ }
363
+ return $this->deleteSubfolder($path, $params);
364
+ });
365
+ }
366
+
367
+ /**
368
+ * Support for opendir().
369
+ *
370
+ * The opendir() method of the Amazon S3 stream wrapper supports a stream
371
+ * context option of "listFilter". listFilter must be a callable that
372
+ * accepts an associative array of object data and returns true if the
373
+ * object should be yielded when iterating the keys in a bucket.
374
+ *
375
+ * @param string $path The path to the directory
376
+ * (e.g. "s3://dir[</prefix>]")
377
+ * @param string $options Unused option variable
378
+ *
379
+ * @return bool true on success
380
+ * @see http://www.php.net/manual/en/function.opendir.php
381
+ */
382
+ public function dir_opendir($path, $options)
383
+ {
384
+ $this->initProtocol($path);
385
+ $this->openedPath = $path;
386
+ $params = $this->withPath($path);
387
+ $delimiter = $this->getOption('delimiter');
388
+ /** @var callable $filterFn */
389
+ $filterFn = $this->getOption('listFilter');
390
+ $op = ['Bucket' => $params['Bucket']];
391
+ $this->openedBucket = $params['Bucket'];
392
+
393
+ if ($delimiter === null) {
394
+ $delimiter = '/';
395
+ }
396
+
397
+ if ($delimiter) {
398
+ $op['Delimiter'] = $delimiter;
399
+ }
400
+
401
+ if ($params['Key']) {
402
+ $params['Key'] = rtrim($params['Key'], $delimiter) . $delimiter;
403
+ $op['Prefix'] = $params['Key'];
404
+ }
405
+
406
+ $this->openedBucketPrefix = $params['Key'];
407
+
408
+ // Filter our "/" keys added by the console as directories, and ensure
409
+ // that if a filter function is provided that it passes the filter.
410
+ $this->objectIterator = \Aws\flatmap(
411
+ $this->getClient()->getPaginator('ListObjects', $op),
412
+ function (Result $result) use ($filterFn) {
413
+ $contentsAndPrefixes = $result->search('[Contents[], CommonPrefixes[]][]');
414
+ // Filter out dir place holder keys and use the filter fn.
415
+ return array_filter(
416
+ $contentsAndPrefixes,
417
+ function ($key) use ($filterFn) {
418
+ return (!$filterFn || call_user_func($filterFn, $key))
419
+ && (!isset($key['Key']) || substr($key['Key'], -1, 1) !== '/');
420
+ }
421
+ );
422
+ }
423
+ );
424
+
425
+ return true;
426
+ }
427
+
428
+ /**
429
+ * Close the directory listing handles
430
+ *
431
+ * @return bool true on success
432
+ */
433
+ public function dir_closedir()
434
+ {
435
+ $this->objectIterator = null;
436
+ gc_collect_cycles();
437
+
438
+ return true;
439
+ }
440
+
441
+ /**
442
+ * This method is called in response to rewinddir()
443
+ *
444
+ * @return boolean true on success
445
+ */
446
+ public function dir_rewinddir()
447
+ {
448
+ $this->boolCall(function() {
449
+ $this->objectIterator = null;
450
+ $this->dir_opendir($this->openedPath, null);
451
+ return true;
452
+ });
453
+ }
454
+
455
+ /**
456
+ * This method is called in response to readdir()
457
+ *
458
+ * @return string Should return a string representing the next filename, or
459
+ * false if there is no next file.
460
+ * @link http://www.php.net/manual/en/function.readdir.php
461
+ */
462
+ public function dir_readdir()
463
+ {
464
+ // Skip empty result keys
465
+ if (!$this->objectIterator->valid()) {
466
+ return false;
467
+ }
468
+
469
+ // First we need to create a cache key. This key is the full path to
470
+ // then object in s3: protocol://bucket/key.
471
+ // Next we need to create a result value. The result value is the
472
+ // current value of the iterator without the opened bucket prefix to
473
+ // emulate how readdir() works on directories.
474
+ // The cache key and result value will depend on if this is a prefix
475
+ // or a key.
476
+ $cur = $this->objectIterator->current();
477
+ if (isset($cur['Prefix'])) {
478
+ // Include "directories". Be sure to strip a trailing "/"
479
+ // on prefixes.
480
+ $result = rtrim($cur['Prefix'], '/');
481
+ $key = $this->formatKey($result);
482
+ $stat = $this->formatUrlStat($key);
483
+ } else {
484
+ $result = $cur['Key'];
485
+ $key = $this->formatKey($cur['Key']);
486
+ $stat = $this->formatUrlStat($cur);
487
+ }
488
+
489
+ // Cache the object data for quick url_stat lookups used with
490
+ // RecursiveDirectoryIterator.
491
+ $this->getCacheStorage()->set($key, $stat);
492
+ $this->objectIterator->next();
493
+
494
+ // Remove the prefix from the result to emulate other stream wrappers.
495
+ return $this->openedBucketPrefix
496
+ ? substr($result, strlen($this->openedBucketPrefix))
497
+ : $result;
498
+ }
499
+
500
+ private function formatKey($key)
501
+ {
502
+ $protocol = explode('://', $this->openedPath)[0];
503
+ return "{$protocol}://{$this->openedBucket}/{$key}";
504
+ }
505
+
506
+ /**
507
+ * Called in response to rename() to rename a file or directory. Currently
508
+ * only supports renaming objects.
509
+ *
510
+ * @param string $path_from the path to the file to rename
511
+ * @param string $path_to the new path to the file
512
+ *
513
+ * @return bool true if file was successfully renamed
514
+ * @link http://www.php.net/manual/en/function.rename.php
515
+ */
516
+ public function rename($path_from, $path_to)
517
+ {
518
+ // PHP will not allow rename across wrapper types, so we can safely
519
+ // assume $path_from and $path_to have the same protocol
520
+ $this->initProtocol($path_from);
521
+ $partsFrom = $this->withPath($path_from);
522
+ $partsTo = $this->withPath($path_to);
523
+ $this->clearCacheKey($path_from);
524
+ $this->clearCacheKey($path_to);
525
+
526
+ if (!$partsFrom['Key'] || !$partsTo['Key']) {
527
+ return $this->triggerError('The Amazon S3 stream wrapper only '
528
+ . 'supports copying objects');
529
+ }
530
+
531
+ return $this->boolCall(function () use ($partsFrom, $partsTo) {
532
+ $options = $this->getOptions(true);
533
+ // Copy the object and allow overriding default parameters if
534
+ // desired, but by default copy metadata
535
+ $this->getClient()->copy(
536
+ $partsFrom['Bucket'],
537
+ $partsFrom['Key'],
538
+ $partsTo['Bucket'],
539
+ $partsTo['Key'],
540
+ isset($options['acl']) ? $options['acl'] : 'private',
541
+ $options
542
+ );
543
+ // Delete the original object
544
+ $this->getClient()->deleteObject([
545
+ 'Bucket' => $partsFrom['Bucket'],
546
+ 'Key' => $partsFrom['Key']
547
+ ] + $options);
548
+ return true;
549
+ });
550
+ }
551
+
552
+ public function stream_cast($cast_as)
553
+ {
554
+ return false;
555
+ }
556
+
557
+ /**
558
+ * Validates the provided stream arguments for fopen and returns an array
559
+ * of errors.
560
+ */
561
+ private function validate($path, $mode)
562
+ {
563
+ $errors = [];
564
+
565
+ if (!$this->getOption('Key')) {
566
+ $errors[] = 'Cannot open a bucket. You must specify a path in the '
567
+ . 'form of s3://bucket/key';
568
+ }
569
+
570
+ if (!in_array($mode, ['r', 'w', 'a', 'x'])) {
571
+ $errors[] = "Mode not supported: {$mode}. "
572
+ . "Use one 'r', 'w', 'a', or 'x'.";
573
+ }
574
+
575
+ // When using mode "x" validate if the file exists before attempting
576
+ // to read
577
+ if ($mode == 'x' &&
578
+ $this->getClient()->doesObjectExist(
579
+ $this->getOption('Bucket'),
580
+ $this->getOption('Key'),
581
+ $this->getOptions(true)
582
+ )
583
+ ) {
584
+ $errors[] = "{$path} already exists on Amazon S3";
585
+ }
586
+
587
+ return $errors;
588
+ }
589
+
590
+ /**
591
+ * Get the stream context options available to the current stream
592
+ *
593
+ * @param bool $removeContextData Set to true to remove contextual kvp's
594
+ * like 'client' from the result.
595
+ *
596
+ * @return array
597
+ */
598
+ private function getOptions($removeContextData = false)
599
+ {
600
+ // Context is not set when doing things like stat
601
+ if ($this->context === null) {
602
+ $options = [];
603
+ } else {
604
+ $options = stream_context_get_options($this->context);
605
+ $options = isset($options[$this->protocol])
606
+ ? $options[$this->protocol]
607
+ : [];
608
+ }
609
+
610
+ $default = stream_context_get_options(stream_context_get_default());
611
+ $default = isset($default[$this->protocol])
612
+ ? $default[$this->protocol]
613
+ : [];
614
+ $result = $this->params + $options + $default;
615
+
616
+ if ($removeContextData) {
617
+ unset($result['client'], $result['seekable'], $result['cache']);
618
+ }
619
+
620
+ return $result;
621
+ }
622
+
623
+ /**
624
+ * Get a specific stream context option
625
+ *
626
+ * @param string $name Name of the option to retrieve
627
+ *
628
+ * @return mixed|null
629
+ */
630
+ private function getOption($name)
631
+ {
632
+ $options = $this->getOptions();
633
+
634
+ return isset($options[$name]) ? $options[$name] : null;
635
+ }
636
+
637
+ /**
638
+ * Gets the client from the stream context
639
+ *
640
+ * @return S3Client
641
+ * @throws \RuntimeException if no client has been configured
642
+ */
643
+ private function getClient()
644
+ {
645
+ if (!$client = $this->getOption('client')) {
646
+ throw new \RuntimeException('No client in stream context');
647
+ }
648
+
649
+ return $client;
650
+ }
651
+
652
+ private function getBucketKey($path)
653
+ {
654
+ // Remove the protocol
655
+ $parts = explode('://', $path);
656
+ // Get the bucket, key
657
+ $parts = explode('/', $parts[1], 2);
658
+
659
+ return [
660
+ 'Bucket' => $parts[0],
661
+ 'Key' => isset($parts[1]) ? $parts[1] : null
662
+ ];
663
+ }
664
+
665
+ /**
666
+ * Get the bucket and key from the passed path (e.g. s3://bucket/key)
667
+ *
668
+ * @param string $path Path passed to the stream wrapper
669
+ *
670
+ * @return array Hash of 'Bucket', 'Key', and custom params from the context
671
+ */
672
+ private function withPath($path)
673
+ {
674
+ $params = $this->getOptions(true);
675
+
676
+ return $this->getBucketKey($path) + $params;
677
+ }
678
+
679
+ private function openReadStream()
680
+ {
681
+ $client = $this->getClient();
682
+ $command = $client->getCommand('GetObject', $this->getOptions(true));
683
+ $command['@http']['stream'] = true;
684
+ $result = $client->execute($command);
685
+ $this->size = $result['ContentLength'];
686
+ $this->body = $result['Body'];
687
+
688
+ // Wrap the body in a caching entity body if seeking is allowed
689
+ if ($this->getOption('seekable') && !$this->body->isSeekable()) {
690
+ $this->body = new CachingStream($this->body);
691
+ }
692
+
693
+ return true;
694
+ }
695
+
696
+ private function openWriteStream()
697
+ {
698
+ $this->body = new Stream(fopen('php://temp', 'r+'));
699
+ return true;
700
+ }
701
+
702
+ private function openAppendStream()
703
+ {
704
+ try {
705
+ // Get the body of the object and seek to the end of the stream
706
+ $client = $this->getClient();
707
+ $this->body = $client->getObject($this->getOptions(true))['Body'];
708
+ $this->body->seek(0, SEEK_END);
709
+ return true;
710
+ } catch (S3Exception $e) {
711
+ // The object does not exist, so use a simple write stream
712
+ return $this->openWriteStream();
713
+ }
714
+ }
715
+
716
+ /**
717
+ * Trigger one or more errors
718
+ *
719
+ * @param string|array $errors Errors to trigger
720
+ * @param mixed $flags If set to STREAM_URL_STAT_QUIET, then no
721
+ * error or exception occurs
722
+ *
723
+ * @return bool Returns false
724
+ * @throws \RuntimeException if throw_errors is true
725
+ */
726
+ private function triggerError($errors, $flags = null)
727
+ {
728
+ // This is triggered with things like file_exists()
729
+ if ($flags & STREAM_URL_STAT_QUIET) {
730
+ return $flags & STREAM_URL_STAT_LINK
731
+ // This is triggered for things like is_link()
732
+ ? $this->formatUrlStat(false)
733
+ : false;
734
+ }
735
+
736
+ // This is triggered when doing things like lstat() or stat()
737
+ trigger_error(implode("\n", (array) $errors), E_USER_WARNING);
738
+
739
+ return false;
740
+ }
741
+
742
+ /**
743
+ * Prepare a url_stat result array
744
+ *
745
+ * @param string|array $result Data to add
746
+ *
747
+ * @return array Returns the modified url_stat result
748
+ */
749
+ private function formatUrlStat($result = null)
750
+ {
751
+ $stat = $this->getStatTemplate();
752
+ switch (gettype($result)) {
753
+ case 'NULL':
754
+ case 'string':
755
+ // Directory with 0777 access - see "man 2 stat".
756
+ $stat['mode'] = $stat[2] = 0040777;
757
+ break;
758
+ case 'array':
759
+ // Regular file with 0777 access - see "man 2 stat".
760
+ $stat['mode'] = $stat[2] = 0100777;
761
+ // Pluck the content-length if available.
762
+ if (isset($result['ContentLength'])) {
763
+ $stat['size'] = $stat[7] = $result['ContentLength'];
764
+ } elseif (isset($result['Size'])) {
765
+ $stat['size'] = $stat[7] = $result['Size'];
766
+ }
767
+ if (isset($result['LastModified'])) {
768
+ // ListObjects or HeadObject result
769
+ $stat['mtime'] = $stat[9] = $stat['ctime'] = $stat[10]
770
+ = strtotime($result['LastModified']);
771
+ }
772
+ }
773
+
774
+ return $stat;
775
+ }
776
+
777
+ /**
778
+ * Creates a bucket for the given parameters.
779
+ *
780
+ * @param string $path Stream wrapper path
781
+ * @param array $params A result of StreamWrapper::withPath()
782
+ *
783
+ * @return bool Returns true on success or false on failure
784
+ */
785
+ private function createBucket($path, array $params)
786
+ {
787
+ if ($this->getClient()->doesBucketExist($params['Bucket'])) {
788
+ return $this->triggerError("Bucket already exists: {$path}");
789
+ }
790
+
791
+ return $this->boolCall(function () use ($params, $path) {
792
+ $this->getClient()->createBucket($params);
793
+ $this->clearCacheKey($path);
794
+ return true;
795
+ });
796
+ }
797
+
798
+ /**
799
+ * Creates a pseudo-folder by creating an empty "/" suffixed key
800
+ *
801
+ * @param string $path Stream wrapper path
802
+ * @param array $params A result of StreamWrapper::withPath()
803
+ *
804
+ * @return bool
805
+ */
806
+ private function createSubfolder($path, array $params)
807
+ {
808
+ // Ensure the path ends in "/" and the body is empty.
809
+ $params['Key'] = rtrim($params['Key'], '/') . '/';
810
+ $params['Body'] = '';
811
+
812
+ // Fail if this pseudo directory key already exists
813
+ if ($this->getClient()->doesObjectExist(
814
+ $params['Bucket'],
815
+ $params['Key'])
816
+ ) {
817
+ return $this->triggerError("Subfolder already exists: {$path}");
818
+ }
819
+
820
+ return $this->boolCall(function () use ($params, $path) {
821
+ $this->getClient()->putObject($params);
822
+ $this->clearCacheKey($path);
823
+ return true;
824
+ });
825
+ }
826
+
827
+ /**
828
+ * Deletes a nested subfolder if it is empty.
829
+ *
830
+ * @param string $path Path that is being deleted (e.g., 's3://a/b/c')
831
+ * @param array $params A result of StreamWrapper::withPath()
832
+ *
833
+ * @return bool
834
+ */
835
+ private function deleteSubfolder($path, $params)
836
+ {
837
+ // Use a key that adds a trailing slash if needed.
838
+ $prefix = rtrim($params['Key'], '/') . '/';
839
+ $result = $this->getClient()->listObjects([
840
+ 'Bucket' => $params['Bucket'],
841
+ 'Prefix' => $prefix,
842
+ 'MaxKeys' => 1
843
+ ]);
844
+
845
+ // Check if the bucket contains keys other than the placeholder
846
+ if ($contents = $result['Contents']) {
847
+ return (count($contents) > 1 || $contents[0]['Key'] != $prefix)
848
+ ? $this->triggerError('Subfolder is not empty')
849
+ : $this->unlink(rtrim($path, '/') . '/');
850
+ }
851
+
852
+ return $result['CommonPrefixes']
853
+ ? $this->triggerError('Subfolder contains nested folders')
854
+ : true;
855
+ }
856
+
857
+ /**
858
+ * Determine the most appropriate ACL based on a file mode.
859
+ *
860
+ * @param int $mode File mode
861
+ *
862
+ * @return string
863
+ */
864
+ private function determineAcl($mode)
865
+ {
866
+ switch (substr(decoct($mode), 0, 1)) {
867
+ case '7': return 'public-read';
868
+ case '6': return 'authenticated-read';
869
+ default: return 'private';
870
+ }
871
+ }
872
+
873
+ /**
874
+ * Gets a URL stat template with default values
875
+ *
876
+ * @return array
877
+ */
878
+ private function getStatTemplate()
879
+ {
880
+ return [
881
+ 0 => 0, 'dev' => 0,
882
+ 1 => 0, 'ino' => 0,
883
+ 2 => 0, 'mode' => 0,
884
+ 3 => 0, 'nlink' => 0,
885
+ 4 => 0, 'uid' => 0,
886
+ 5 => 0, 'gid' => 0,
887
+ 6 => -1, 'rdev' => -1,
888
+ 7 => 0, 'size' => 0,
889
+ 8 => 0, 'atime' => 0,
890
+ 9 => 0, 'mtime' => 0,
891
+ 10 => 0, 'ctime' => 0,
892
+ 11 => -1, 'blksize' => -1,
893
+ 12 => -1, 'blocks' => -1,
894
+ ];
895
+ }
896
+
897
+ /**
898
+ * Invokes a callable and triggers an error if an exception occurs while
899
+ * calling the function.
900
+ *
901
+ * @param callable $fn
902
+ * @param int $flags
903
+ *
904
+ * @return bool
905
+ */
906
+ private function boolCall(callable $fn, $flags = null)
907
+ {
908
+ try {
909
+ return $fn();
910
+ } catch (\Exception $e) {
911
+ return $this->triggerError($e->getMessage(), $flags);
912
+ }
913
+ }
914
+
915
+ /**
916
+ * @return LruArrayCache
917
+ */
918
+ private function getCacheStorage()
919
+ {
920
+ if (!$this->cache) {
921
+ $this->cache = $this->getOption('cache') ?: new LruArrayCache();
922
+ }
923
+
924
+ return $this->cache;
925
+ }
926
+
927
+ /**
928
+ * Clears a specific stat cache value from the stat cache and LRU cache.
929
+ *
930
+ * @param string $key S3 path (s3://bucket/key).
931
+ */
932
+ private function clearCacheKey($key)
933
+ {
934
+ clearstatcache(true, $key);
935
+ $this->getCacheStorage()->remove($key);
936
+ }
937
+
938
+ /**
939
+ * Returns the size of the opened object body.
940
+ *
941
+ * @return int|null
942
+ */
943
+ private function getSize()
944
+ {
945
+ $size = $this->body->getSize();
946
+
947
+ return $size !== null ? $size : $this->size;
948
+ }
949
+ }
includes/aws/Aws/S3/Transfer.php ADDED
@@ -0,0 +1,379 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\S3;
3
+
4
+ use Aws;
5
+ use Aws\CommandInterface;
6
+ use Aws\ResultInterface;
7
+ use GuzzleHttp\Promise;
8
+ use GuzzleHttp\Psr7;
9
+ use GuzzleHttp\Promise\PromisorInterface;
10
+
11
+ /**
12
+ * Transfers files from the local filesystem to S3 or from S3 to the local
13
+ * filesystem.
14
+ *
15
+ * This class does not support copying from the local filesystem to somewhere
16
+ * else on the local filesystem or from one S3 bucket to another.
17
+ */
18
+ class Transfer implements PromisorInterface
19
+ {
20
+ private $client;
21
+ private $promise;
22
+ private $source;
23
+ private $destination;
24
+ private $concurrency;
25
+ private $mupThreshold;
26
+ private $before;
27
+ private $s3Args = [];
28
+
29
+ /**
30
+ * When providing the $source argument, you may provide a string referencing
31
+ * the path to a directory on disk to upload, an s3 scheme URI that contains
32
+ * the bucket and key (e.g., "s3://bucket/key"), or an \Iterator object
33
+ * that yields strings containing filenames that are the path to a file on
34
+ * disk or an s3 scheme URI. The "/key" portion of an s3 URI is optional.
35
+ *
36
+ * When providing an iterator for the $source argument, you must also
37
+ * provide a 'base_dir' key value pair in the $options argument.
38
+ *
39
+ * The $dest argument can be the path to a directory on disk or an s3
40
+ * scheme URI (e.g., "s3://bucket/key").
41
+ *
42
+ * The options array can contain the following key value pairs:
43
+ *
44
+ * - base_dir: (string) Base directory of the source, if $source is an
45
+ * iterator. If the $source option is not an array, then this option is
46
+ * ignored.
47
+ * - before: (callable) A callback to invoke before each transfer. The
48
+ * callback accepts the following positional arguments: string $source,
49
+ * string $dest, Aws\CommandInterface $command. The provided command will
50
+ * be either a GetObject, PutObject, InitiateMultipartUpload, or
51
+ * UploadPart command.
52
+ * - mup_threshold: (int) Size in bytes in which a multipart upload should
53
+ * be used instead of PutObject. Defaults to 20971520 (20 MB).
54
+ * - concurrency: (int, default=5) Number of files to upload concurrently.
55
+ * The ideal concurrency value will vary based on the number of files
56
+ * being uploaded and the average size of each file. Generally speaking,
57
+ * smaller files benefit from a higher concurrency while larger files
58
+ * will not.
59
+ * - debug: (bool) Set to true to print out debug information for
60
+ * transfers. Set to an fopen() resource to write to a specific stream
61
+ * rather than writing to STDOUT.
62
+ *
63
+ * @param S3Client $client Client used for transfers.
64
+ * @param string|\Iterator $source Where the files are transferred from.
65
+ * @param string $dest Where the files are transferred to.
66
+ * @param array $options Hash of options.
67
+ */
68
+ public function __construct(
69
+ S3Client $client,
70
+ $source,
71
+ $dest,
72
+ array $options = []
73
+ ) {
74
+ $this->client = $client;
75
+
76
+ // Prepare the destination.
77
+ $this->destination = $this->prepareTarget($dest);
78
+ if ($this->destination['scheme'] === 's3') {
79
+ $this->s3Args = $this->getS3Args($this->destination['path']);
80
+ }
81
+
82
+ // Prepare the source.
83
+ if (is_string($source)) {
84
+ $this->source = $this->prepareTarget($source);
85
+ } elseif ($source instanceof \Iterator) {
86
+ if (isset($options['base_dir'])) {
87
+ $this->source = $this->prepareTarget($options['base_dir']);
88
+ } else {
89
+ throw new \InvalidArgumentException('You must provide the source'
90
+ . ' argument as a string or provide the "base_dir" option.');
91
+ }
92
+ } else {
93
+ throw new \InvalidArgumentException('source must be the path to a '
94
+ . 'directory or an iterator that yields file names.');
95
+ }
96
+
97
+ // Validate schemes.
98
+ if ($this->source['scheme'] === $this->destination['scheme']) {
99
+ throw new \InvalidArgumentException("You cannot copy from "
100
+ . "{$this->source['scheme']} to {$this->destination['scheme']}."
101
+ );
102
+ }
103
+
104
+ // Handle multipart-related options.
105
+ $this->concurrency = isset($options['concurrency'])
106
+ ? $options['concurrency']
107
+ : MultipartUploader::DEFAULT_CONCURRENCY;
108
+ $this->mupThreshold = isset($options['mup_threshold'])
109
+ ? $options['mup_threshold']
110
+ : 16777216;
111
+ if ($this->mupThreshold < MultipartUploader::PART_MIN_SIZE) {
112
+ throw new \InvalidArgumentException('mup_threshold must be >= 5MB');
113
+ }
114
+
115
+ // Handle "before" callback option.
116
+ if (isset($options['before'])) {
117
+ $this->before = $options['before'];
118
+ if (!is_callable($this->before)) {
119
+ throw new \InvalidArgumentException('before must be a callable.');
120
+ }
121
+ }
122
+
123
+ // Handle "debug" option.
124
+ if (isset($options['debug'])) {
125
+ if ($options['debug'] === true) {
126
+ $options['debug'] = fopen('php://output', 'w');
127
+ }
128
+ $this->addDebugToBefore($options['debug']);
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Transfers the files.
134
+ */
135
+ public function promise()
136
+ {
137
+ // If the promise has been created, just return it.
138
+ if (!$this->promise) {
139
+ // Create an upload/download promise for the transfer.
140
+ $this->promise = $this->source['scheme'] === 'file'
141
+ ? $this->createUploadPromise()
142
+ : $this->createDownloadPromise();
143
+ }
144
+
145
+ return $this->promise;
146
+ }
147
+
148
+ /**
149
+ * Transfers the files synchronously.
150
+ */
151
+ public function transfer()
152
+ {
153
+ $this->promise()->wait();
154
+ }
155
+
156
+ private function prepareTarget($targetPath)
157
+ {
158
+ $target = [
159
+ 'path' => $this->normalizePath($targetPath),
160
+ 'scheme' => $this->determineScheme($targetPath),
161
+ ];
162
+
163
+ if ($target['scheme'] !== 's3' && $target['scheme'] !== 'file') {
164
+ throw new \InvalidArgumentException('Scheme must be "s3" or "file".');
165
+ }
166
+
167
+ return $target;
168
+ }
169
+
170
+ /**
171
+ * Creates an array that contains Bucket and Key by parsing the filename.
172
+ *
173
+ * @param string $path Path to parse.
174
+ *
175
+ * @return array
176
+ */
177
+ private function getS3Args($path)
178
+ {
179
+ $parts = explode('/', str_replace('s3://', '', $path), 2);
180
+ $args = ['Bucket' => $parts[0]];
181
+ if (isset($parts[1])) {
182
+ $args['Key'] = $parts[1];
183
+ }
184
+
185
+ return $args;
186
+ }
187
+
188
+ /**
189
+ * Parses the scheme from a filename.
190
+ *
191
+ * @param string $path Path to parse.
192
+ *
193
+ * @return string
194
+ */
195
+ private function determineScheme($path)
196
+ {
197
+ return !strpos($path, '://') ? 'file' : explode('://', $path)[0];
198
+ }
199
+
200
+ /**
201
+ * Normalize a path so that it has UNIX-style directory separators and no trailing /
202
+ *
203
+ * @param string $path
204
+ *
205
+ * @return string
206
+ */
207
+ private function normalizePath($path)
208
+ {
209
+ return rtrim(str_replace('\\', '/', $path), '/');
210
+ }
211
+
212
+ private function createDownloadPromise()
213
+ {
214
+ // Prepare args for ListObjects.
215
+ $listArgs = $this->getS3Args($this->source['path']);
216
+ if (isset($listArgs['Key'])) {
217
+ $listArgs['Prefix'] = $listArgs['Key'] . '/';
218
+ unset($listArgs['Key']);
219
+ }
220
+
221
+ // Get the Paginator for ListObjects
222
+ $objects = $this->client->getPaginator('ListObjects', $listArgs);
223
+
224
+ // Asynchronously execute the paginator, building command pools to
225
+ // download the objects.
226
+ return $objects->each(function (
227
+ ResultInterface $result
228
+ ) use ($listArgs) {
229
+ $commands = [];
230
+ $prefix = isset($listArgs['Prefix']) ? $listArgs['Prefix'] : null;
231
+ foreach ($result->search('Contents[].Key') as $key) {
232
+ // Skip files on S3 that just mark the existence of a folder.
233
+ if (substr($key, -1, 1) === '/') {
234
+ continue;
235
+ }
236
+
237
+ // Prepare the sink.
238
+ $localKey = $key;
239
+ if ($prefix && strpos($localKey, $prefix) === 0) {
240
+ $localKey = substr($key, strlen($prefix));
241
+ }
242
+ $sink = $this->destination['path'] . '/' . $localKey;
243
+
244
+ // Create the directory if needed.
245
+ $dir = dirname($sink);
246
+ if (!is_dir($dir) && !mkdir($dir, 0777, true)) {
247
+ return Promise\rejection_for(
248
+ new \RuntimeException("Could not create dir: {$dir}")
249
+ );
250
+ }
251
+
252
+ // Create the command.
253
+ $commands[] = $this->client->getCommand('GetObject', [
254
+ 'Bucket' => $listArgs['Bucket'],
255
+ 'Key' => $key,
256
+ '@http' => ['sink' => $sink],
257
+ ]);
258
+ }
259
+
260
+ // Create a GetObject command pool and return the promise.
261
+ return (new Aws\CommandPool($this->client, $commands, [
262
+ 'concurrency' => $this->concurrency,
263
+ 'before' => $this->before,
264
+ 'rejected' => function ($reason, $idx, Promise\PromiseInterface $p) {
265
+ $p->reject($reason);
266
+ }
267
+ ]))->promise();
268
+ });
269
+ }
270
+
271
+ private function createUploadPromise()
272
+ {
273
+ // Creates an iterator that yields promises for either upload or
274
+ // multipart upload operations for each file in the source directory.
275
+ $files = Aws\recursive_dir_iterator($this->source['path']);
276
+ // Filter out directories.
277
+ $files = \Aws\filter($files, function ($file) {
278
+ return !is_dir($file);
279
+ });
280
+ // Map each file into a promise that performs the actual transfer.
281
+ $files = \Aws\map($files, function ($file) {
282
+ return (filesize($file) >= $this->mupThreshold)
283
+ ? $this->uploadMultipart($file)
284
+ : $this->upload($file);
285
+ });
286
+
287
+ // Create an EachPromise, that will concurrently handle the upload
288
+ // operations' yielded promises from the iterator.
289
+ return Promise\each_limit_all($files, $this->concurrency);
290
+ }
291
+
292
+ private function upload($filename)
293
+ {
294
+ $args = $this->s3Args;
295
+ $args['SourceFile'] = $filename;
296
+ $args['Key'] = $this->createS3Key($filename);
297
+ $command = $this->client->getCommand('PutObject', $args);
298
+ $this->before and call_user_func($this->before, $command);
299
+
300
+ return $this->client->executeAsync($command);
301
+ }
302
+
303
+ private function uploadMultipart($filename)
304
+ {
305
+ $args = $this->s3Args;
306
+ $args['Key'] = $this->createS3Key($filename);
307
+
308
+ return (new MultipartUploader($this->client, $filename, [
309
+ 'bucket' => $args['Bucket'],
310
+ 'key' => $args['Key'],
311
+ 'before_initiate' => $this->before,
312
+ 'before_upload' => $this->before,
313
+ 'before_complete' => $this->before,
314
+ 'concurrency' => $this->concurrency,
315
+ ]))->promise();
316
+ }
317
+
318
+ private function createS3Key($filename)
319
+ {
320
+ $relative_file_path = ltrim(
321
+ preg_replace('#^' . preg_quote($this->source['path']) . '#', '', $filename),
322
+ '/\\'
323
+ );
324
+
325
+ if (isset($this->s3Args['Key'])) {
326
+ return rtrim($this->s3Args['Key'], '/').'/'.$relative_file_path;
327
+ }
328
+
329
+ return $relative_file_path;
330
+ }
331
+
332
+ private function addDebugToBefore($debug)
333
+ {
334
+ $before = $this->before;
335
+ $sourcePath = $this->source['path'];
336
+ $s3Args = $this->s3Args;
337
+
338
+ $this->before = static function (
339
+ CommandInterface $command
340
+ ) use ($before, $debug, $sourcePath, $s3Args) {
341
+ // Call the composed before function.
342
+ $before and $before($command);
343
+
344
+ // Determine the source and dest values based on operation.
345
+ switch ($operation = $command->getName()) {
346
+ case 'GetObject':
347
+ $source = "s3://{$command['Bucket']}/{$command['Key']}";
348
+ $dest = $command['@http']['sink'];
349
+ break;
350
+ case 'PutObject':
351
+ $source = $command['SourceFile'];
352
+ $dest = "s3://{$command['Bucket']}/{$command['Key']}";
353
+ break;
354
+ case 'UploadPart':
355
+ $part = $command['PartNumber'];
356
+ case 'CreateMultipartUpload':
357
+ case 'CompleteMultipartUpload':
358
+ $sourceKey = $command['Key'];
359
+ if (isset($s3Args['Key']) && strpos($sourceKey, $s3Args['Key']) === 0) {
360
+ $sourceKey = substr($sourceKey, strlen($s3Args['Key']) + 1);
361
+ }
362
+ $source = "{$sourcePath}/{$sourceKey}";
363
+ $dest = "s3://{$command['Bucket']}/{$command['Key']}";
364
+ break;
365
+ default:
366
+ throw new \UnexpectedValueException(
367
+ "Transfer encountered an unexpected operation: {$operation}."
368
+ );
369
+ }
370
+
371
+ // Print the debugging message.
372
+ $context = sprintf('%s -> %s (%s)', $source, $dest, $operation);
373
+ if (isset($part)) {
374
+ $context .= " : Part={$part}";
375
+ }
376
+ fwrite($debug, "Transferring {$context}\n");
377
+ };
378
+ }
379
+ }
includes/aws/Aws/Sdk.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ /**
5
+ * Builds AWS clients based on configuration settings.
6
+ *
7
+ * @method \Aws\ApiGateway\ApiGatewayClient createApiGateway(array $args = [])
8
+ * @method \Aws\AutoScaling\AutoScalingClient createAutoScaling(array $args = [])
9
+ * @method \Aws\CloudFormation\CloudFormationClient createCloudFormation(array $args = [])
10
+ * @method \Aws\CloudFront\CloudFrontClient createCloudFront(array $args = [])
11
+ * @method \Aws\CloudHsm\CloudHsmClient createCloudHsm(array $args = [])
12
+ * @method \Aws\CloudSearch\CloudSearchClient createCloudSearch(array $args = [])
13
+ * @method \Aws\CloudSearchDomain\CloudSearchDomainClient createCloudSearchDomain(array $args = [])
14
+ * @method \Aws\CloudTrail\CloudTrailClient createCloudTrail(array $args = [])
15
+ * @method \Aws\CloudWatch\CloudWatchClient createCloudWatch(array $args = [])
16
+ * @method \Aws\CloudWatchLogs\CloudWatchLogsClient createCloudWatchLogs(array $args = [])
17
+ * @method \Aws\CodeCommit\CodeCommitClient createCodeCommit(array $args = [])
18
+ * @method \Aws\CodeDeploy\CodeDeployClient createCodeDeploy(array $args = [])
19
+ * @method \Aws\CodePipeline\CodePipelineClient createCodePipeline(array $args = [])
20
+ * @method \Aws\CognitoIdentity\CognitoIdentityClient createCognitoIdentity(array $args = [])
21
+ * @method \Aws\CognitoSync\CognitoSyncClient createCognitoSync(array $args = [])
22
+ * @method \Aws\ConfigService\ConfigServiceClient createConfigService(array $args = [])
23
+ * @method \Aws\DataPipeline\DataPipelineClient createDataPipeline(array $args = [])
24
+ * @method \Aws\DeviceFarm\DeviceFarmClient createDeviceFarm(array $args = [])
25
+ * @method \Aws\DirectConnect\DirectConnectClient createDirectConnect(array $args = [])
26
+ * @method \Aws\DirectoryService\DirectoryServiceClient createDirectoryService(array $args = [])
27
+ * @method \Aws\DynamoDb\DynamoDbClient createDynamoDb(array $args = [])
28
+ * @method \Aws\DynamoDbStreams\DynamoDbStreamsClient createDynamoDbStreams(array $args = [])
29
+ * @method \Aws\Ec2\Ec2Client createEc2(array $args = [])
30
+ * @method \Aws\Ecr\EcrClient createEcr(array $args = [])
31
+ * @method \Aws\Ecs\EcsClient createEcs(array $args = [])
32
+ * @method \Aws\Efs\EfsClient createEfs(array $args = [])
33
+ * @method \Aws\ElastiCache\ElastiCacheClient createElastiCache(array $args = [])
34
+ * @method \Aws\ElasticBeanstalk\ElasticBeanstalkClient createElasticBeanstalk(array $args = [])
35
+ * @method \Aws\ElasticLoadBalancing\ElasticLoadBalancingClient createElasticLoadBalancing(array $args = [])
36
+ * @method \Aws\ElasticTranscoder\ElasticTranscoderClient createElasticTranscoder(array $args = [])
37
+ * @method \Aws\ElasticsearchService\ElasticsearchServiceClient createElasticsearchService(array $args = [])
38
+ * @method \Aws\Emr\EmrClient createEmr(array $args = [])
39
+ * @method \Aws\Firehose\FirehoseClient createFirehose(array $args = [])
40
+ * @method \Aws\Glacier\GlacierClient createGlacier(array $args = [])
41
+ * @method \Aws\Iam\IamClient createIam(array $args = [])
42
+ * @method \Aws\Inspector\InspectorClient createInspector(array $args = [])
43
+ * @method \Aws\Iot\IotClient createIot(array $args = [])
44
+ * @method \Aws\IotDataPlane\IotDataPlaneClient createIotDataPlane(array $args = [])
45
+ * @method \Aws\Kinesis\KinesisClient createKinesis(array $args = [])
46
+ * @method \Aws\Kms\KmsClient createKms(array $args = [])
47
+ * @method \Aws\Lambda\LambdaClient createLambda(array $args = [])
48
+ * @method \Aws\MachineLearning\MachineLearningClient createMachineLearning(array $args = [])
49
+ * @method \Aws\MarketplaceCommerceAnalytics\MarketplaceCommerceAnalyticsClient createMarketplaceCommerceAnalytics(array $args = [])
50
+ * @method \Aws\OpsWorks\OpsWorksClient createOpsWorks(array $args = [])
51
+ * @method \Aws\Rds\RdsClient createRds(array $args = [])
52
+ * @method \Aws\Redshift\RedshiftClient createRedshift(array $args = [])
53
+ * @method \Aws\Route53\Route53Client createRoute53(array $args = [])
54
+ * @method \Aws\Route53Domains\Route53DomainsClient createRoute53Domains(array $args = [])
55
+ * @method \Aws\S3\S3Client createS3(array $args = [])
56
+ * @method \Aws\Ses\SesClient createSes(array $args = [])
57
+ * @method \Aws\Sns\SnsClient createSns(array $args = [])
58
+ * @method \Aws\Sqs\SqsClient createSqs(array $args = [])
59
+ * @method \Aws\Ssm\SsmClient createSsm(array $args = [])
60
+ * @method \Aws\StorageGateway\StorageGatewayClient createStorageGateway(array $args = [])
61
+ * @method \Aws\Sts\StsClient createSts(array $args = [])
62
+ * @method \Aws\Support\SupportClient createSupport(array $args = [])
63
+ * @method \Aws\Swf\SwfClient createSwf(array $args = [])
64
+ * @method \Aws\Waf\WafClient createWaf(array $args = [])
65
+ * @method \Aws\WorkSpaces\WorkSpacesClient createWorkSpaces(array $args = [])
66
+ */
67
+ class Sdk
68
+ {
69
+ const VERSION = '3.12.0';
70
+
71
+ /** @var array Arguments for creating clients */
72
+ private $args;
73
+
74
+ /**
75
+ * Constructs a new SDK object with an associative array of default
76
+ * client settings.
77
+ *
78
+ * @param array $args
79
+ *
80
+ * @throws \InvalidArgumentException
81
+ * @see Aws\Sdk::getClient for a list of available options.
82
+ */
83
+ public function __construct(array $args = [])
84
+ {
85
+ $this->args = $args;
86
+
87
+ if (!isset($args['handler']) && !isset($args['http_handler'])) {
88
+ $this->args['http_handler'] = default_http_handler();
89
+ }
90
+ }
91
+
92
+ public function __call($name, array $args)
93
+ {
94
+ if (strpos($name, 'create') === 0) {
95
+ return $this->createClient(
96
+ substr($name, 6),
97
+ isset($args[0]) ? $args[0] : []
98
+ );
99
+ }
100
+
101
+ throw new \BadMethodCallException("Unknown method: {$name}.");
102
+ }
103
+
104
+ /**
105
+ * Get a client by name using an array of constructor options.
106
+ *
107
+ * @param string $name Service name or namespace (e.g., DynamoDb, s3).
108
+ * @param array $args Arguments to configure the client.
109
+ *
110
+ * @return AwsClientInterface
111
+ * @throws \InvalidArgumentException if any required options are missing or
112
+ * the service is not supported.
113
+ * @see Aws\AwsClient::__construct for a list of available options for args.
114
+ */
115
+ public function createClient($name, array $args = [])
116
+ {
117
+ // Get information about the service from the manifest file.
118
+ $service = manifest($name);
119
+ $namespace = $service['namespace'];
120
+
121
+ // Merge provided args with stored, service-specific args.
122
+ if (isset($this->args[$namespace])) {
123
+ $args += $this->args[$namespace];
124
+ }
125
+
126
+ // Provide the endpoint prefix in the args.
127
+ if (!isset($args['service'])) {
128
+ $args['service'] = $service['endpoint'];
129
+ }
130
+
131
+ // Instantiate the client class.
132
+ $client = "Aws\\{$namespace}\\{$namespace}Client";
133
+ return new $client($args + $this->args);
134
+ }
135
+
136
+ /**
137
+ * Determine the endpoint prefix from a client namespace.
138
+ *
139
+ * @param string $name Namespace name
140
+ *
141
+ * @return string
142
+ * @internal
143
+ * @deprecated Use the `\Aws\manifest()` function instead.
144
+ */
145
+ public static function getEndpointPrefix($name)
146
+ {
147
+ return manifest($name)['endpoint'];
148
+ }
149
+ }
includes/aws/Aws/Signature/AnonymousSignature.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Signature;
3
+
4
+ use Aws\Credentials\CredentialsInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+
7
+ /**
8
+ * Provides anonymous client access (does not sign requests).
9
+ */
10
+ class AnonymousSignature implements SignatureInterface
11
+ {
12
+ public function signRequest(
13
+ RequestInterface $request,
14
+ CredentialsInterface $credentials
15
+ ) {
16
+ return $request;
17
+ }
18
+
19
+ public function presign(
20
+ RequestInterface $request,
21
+ CredentialsInterface $credentials,
22
+ $expires
23
+ ) {
24
+ return $request;
25
+ }
26
+ }
includes/aws/Aws/Signature/S3SignatureV4.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Signature;
3
+
4
+ use Aws\Credentials\CredentialsInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+
7
+ /**
8
+ * Amazon S3 signature version 4 support.
9
+ */
10
+ class S3SignatureV4 extends SignatureV4
11
+ {
12
+ /**
13
+ * Always add a x-amz-content-sha-256 for data integrity.
14
+ */
15
+ public function signRequest(
16
+ RequestInterface $request,
17
+ CredentialsInterface $credentials
18
+ ) {
19
+ if (!$request->hasHeader('x-amz-content-sha256')) {
20
+ $request = $request->withHeader(
21
+ 'X-Amz-Content-Sha256',
22
+ $this->getPayload($request)
23
+ );
24
+ }
25
+
26
+ return parent::signRequest($request, $credentials);
27
+ }
28
+
29
+ /**
30
+ * Override used to allow pre-signed URLs to be created for an
31
+ * in-determinate request payload.
32
+ */
33
+ protected function getPresignedPayload(RequestInterface $request)
34
+ {
35
+ return 'UNSIGNED-PAYLOAD';
36
+ }
37
+
38
+ /**
39
+ * Amazon S3 does not double-encode the path component in the canonical request
40
+ */
41
+ protected function createCanonicalizedPath($path)
42
+ {
43
+ return '/' . ltrim($path, '/');
44
+ }
45
+ }
includes/aws/Aws/Signature/SignatureInterface.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Signature;
3
+
4
+ use Aws\Credentials\CredentialsInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+
7
+ /**
8
+ * Interface used to provide interchangeable strategies for signing requests
9
+ * using the various AWS signature protocols.
10
+ */
11
+ interface SignatureInterface
12
+ {
13
+ /**
14
+ * Signs the specified request with an AWS signing protocol by using the
15
+ * provided AWS account credentials and adding the required headers to the
16
+ * request.
17
+ *
18
+ * @param RequestInterface $request Request to sign
19
+ * @param CredentialsInterface $credentials Signing credentials
20
+ *
21
+ * @return RequestInterface Returns the modified request.
22
+ */
23
+ public function signRequest(
24
+ RequestInterface $request,
25
+ CredentialsInterface $credentials
26
+ );
27
+
28
+ /**
29
+ * Create a pre-signed request.
30
+ *
31
+ * @param RequestInterface $request Request to sign
32
+ * @param CredentialsInterface $credentials Credentials used to sign
33
+ * @param int|string|\DateTime $expires The time at which the URL should
34
+ * expire. This can be a Unix timestamp, a PHP DateTime object, or a
35
+ * string that can be evaluated by strtotime.
36
+ *
37
+ * @return RequestInterface
38
+ */
39
+ public function presign(
40
+ RequestInterface $request,
41
+ CredentialsInterface $credentials,
42
+ $expires
43
+ );
44
+ }
includes/aws/Aws/Signature/SignatureProvider.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Signature;
3
+
4
+ use Aws\Exception\UnresolvedSignatureException;
5
+
6
+ /**
7
+ * Signature providers.
8
+ *
9
+ * A signature provider is a function that accepts a version, service, and
10
+ * region and returns a {@see SignatureInterface} object on success or NULL if
11
+ * no signature can be created from the provided arguments.
12
+ *
13
+ * You can wrap your calls to a signature provider with the
14
+ * {@see SignatureProvider::resolve} function to ensure that a signature object
15
+ * is created. If a signature object is not created, then the resolve()
16
+ * function will throw a {@see Aws\Exception\UnresolvedSignatureException}.
17
+ *
18
+ * use Aws\Signature\SignatureProvider;
19
+ * $provider = SignatureProvider::defaultProvider();
20
+ * // Returns a SignatureInterface or NULL.
21
+ * $signer = $provider('v4', 's3', 'us-west-2');
22
+ * // Returns a SignatureInterface or throws.
23
+ * $signer = SignatureProvider::resolve($provider, 'no', 's3', 'foo');
24
+ *
25
+ * You can compose multiple providers into a single provider using
26
+ * {@see Aws\or_chain}. This function accepts providers as arguments and
27
+ * returns a new function that will invoke each provider until a non-null value
28
+ * is returned.
29
+ *
30
+ * $a = SignatureProvider::defaultProvider();
31
+ * $b = function ($version, $service, $region) {
32
+ * if ($version === 'foo') {
33
+ * return new MyFooSignature();
34
+ * }
35
+ * };
36
+ * $c = \Aws\or_chain($a, $b);
37
+ * $signer = $c('v4', 'abc', '123'); // $a handles this.
38
+ * $signer = $c('foo', 'abc', '123'); // $b handles this.
39
+ * $nullValue = $c('???', 'abc', '123'); // Neither can handle this.
40
+ */
41
+ class SignatureProvider
42
+ {
43
+ /**
44
+ * Resolves and signature provider and ensures a non-null return value.
45
+ *
46
+ * @param callable $provider Provider function to invoke.
47
+ * @param string $version Signature version.
48
+ * @param string $service Service name.
49
+ * @param string $region Region name.
50
+ *
51
+ * @return SignatureInterface
52
+ * @throws UnresolvedSignatureException
53
+ */
54
+ public static function resolve(callable $provider, $version, $service, $region)
55
+ {
56
+ $result = $provider($version, $service, $region);
57
+ if ($result instanceof SignatureInterface) {
58
+ return $result;
59
+ }
60
+
61
+ throw new UnresolvedSignatureException(
62
+ "Unable to resolve a signature for $version/$service/$region.\n"
63
+ . "Valid signature versions include v4 and anonymous."
64
+ );
65
+ }
66
+
67
+ /**
68
+ * Default SDK signature provider.
69
+ *
70
+ * @return callable
71
+ */
72
+ public static function defaultProvider()
73
+ {
74
+ return self::memoize(self::version());
75
+ }
76
+
77
+ /**
78
+ * Creates a signature provider that caches previously created signature
79
+ * objects. The computed cache key is the concatenation of the version,
80
+ * service, and region.
81
+ *
82
+ * @param callable $provider Signature provider to wrap.
83
+ *
84
+ * @return callable
85
+ */
86
+ public static function memoize(callable $provider)
87
+ {
88
+ $cache = [];
89
+ return function ($version, $service, $region) use (&$cache, $provider) {
90
+ $key = "($version)($service)($region)";
91
+ if (!isset($cache[$key])) {
92
+ $cache[$key] = $provider($version, $service, $region);
93
+ }
94
+ return $cache[$key];
95
+ };
96
+ }
97
+
98
+ /**
99
+ * Creates signature objects from known signature versions.
100
+ *
101
+ * This provider currently recognizes the following signature versions:
102
+ *
103
+ * - v4: Signature version 4.
104
+ * - anonymous: Does not sign requests.
105
+ *
106
+ * @return callable
107
+ */
108
+ public static function version()
109
+ {
110
+ return function ($version, $service, $region) {
111
+ switch ($version) {
112
+ case 'v4':
113
+ return $service === 's3'
114
+ ? new S3SignatureV4($service, $region)
115
+ : new SignatureV4($service, $region);
116
+ case 'anonymous':
117
+ return new AnonymousSignature();
118
+ default:
119
+ return null;
120
+ }
121
+ };
122
+ }
123
+ }
includes/aws/Aws/Signature/SignatureV4.php ADDED
@@ -0,0 +1,368 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Signature;
3
+
4
+ use Aws\Credentials\CredentialsInterface;
5
+ use Aws\Exception\CouldNotCreateChecksumException;
6
+ use GuzzleHttp\Psr7;
7
+ use Psr\Http\Message\RequestInterface;
8
+
9
+ /**
10
+ * Signature Version 4
11
+ * @link http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
12
+ */
13
+ class SignatureV4 implements SignatureInterface
14
+ {
15
+ const ISO8601_BASIC = 'Ymd\THis\Z';
16
+
17
+ /** @var string */
18
+ private $service;
19
+
20
+ /** @var string */
21
+ private $region;
22
+
23
+ /** @var array Cache of previously signed values */
24
+ private $cache = [];
25
+
26
+ /** @var int Size of the hash cache */
27
+ private $cacheSize = 0;
28
+
29
+ /**
30
+ * @param string $service Service name to use when signing
31
+ * @param string $region Region name to use when signing
32
+ */
33
+ public function __construct($service, $region)
34
+ {
35
+ $this->service = $service;
36
+ $this->region = $region;
37
+ }
38
+
39
+ public function signRequest(
40
+ RequestInterface $request,
41
+ CredentialsInterface $credentials
42
+ ) {
43
+ $ldt = gmdate(self::ISO8601_BASIC);
44
+ $sdt = substr($ldt, 0, 8);
45
+ $parsed = $this->parseRequest($request);
46
+ $parsed['headers']['X-Amz-Date'] = [$ldt];
47
+
48
+ if ($token = $credentials->getSecurityToken()) {
49
+ $parsed['headers']['X-Amz-Security-Token'] = [$token];
50
+ }
51
+
52
+ $cs = $this->createScope($sdt, $this->region, $this->service);
53
+ $payload = $this->getPayload($request);
54
+ $context = $this->createContext($parsed, $payload);
55
+ $toSign = $this->createStringToSign($ldt, $cs, $context['creq']);
56
+ $signingKey = $this->getSigningKey(
57
+ $sdt,
58
+ $this->region,
59
+ $this->service,
60
+ $credentials->getSecretKey()
61
+ );
62
+ $signature = hash_hmac('sha256', $toSign, $signingKey);
63
+ $parsed['headers']['Authorization'] = [
64
+ "AWS4-HMAC-SHA256 "
65
+ . "Credential={$credentials->getAccessKeyId()}/{$cs}, "
66
+ . "SignedHeaders={$context['headers']}, Signature={$signature}"
67
+ ];
68
+
69
+ return $this->buildRequest($parsed);
70
+ }
71
+
72
+ public function presign(
73
+ RequestInterface $request,
74
+ CredentialsInterface $credentials,
75
+ $expires
76
+ ) {
77
+ $parsed = $this->createPresignedRequest($request, $credentials);
78
+ $payload = $this->getPresignedPayload($request);
79
+ $httpDate = gmdate(self::ISO8601_BASIC, time());
80
+ $shortDate = substr($httpDate, 0, 8);
81
+ $scope = $this->createScope($shortDate, $this->region, $this->service);
82
+ $credential = $credentials->getAccessKeyId() . '/' . $scope;
83
+ $parsed['query']['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256';
84
+ $parsed['query']['X-Amz-Credential'] = $credential;
85
+ $parsed['query']['X-Amz-Date'] = gmdate('Ymd\THis\Z', time());
86
+ $parsed['query']['X-Amz-SignedHeaders'] = 'Host';
87
+ $parsed['query']['X-Amz-Expires'] = $this->convertExpires($expires);
88
+ $context = $this->createContext($parsed, $payload);
89
+ $stringToSign = $this->createStringToSign($httpDate, $scope, $context['creq']);
90
+ $key = $this->getSigningKey(
91
+ $shortDate,
92
+ $this->region,
93
+ $this->service,
94
+ $credentials->getSecretKey()
95
+ );
96
+ $parsed['query']['X-Amz-Signature'] = hash_hmac('sha256', $stringToSign, $key);
97
+
98
+ return $this->buildRequest($parsed);
99
+ }
100
+
101
+ /**
102
+ * Converts a POST request to a GET request by moving POST fields into the
103
+ * query string.
104
+ *
105
+ * Useful for pre-signing query protocol requests.
106
+ *
107
+ * @param RequestInterface $request Request to clone
108
+ *
109
+ * @return RequestInterface
110
+ * @throws \InvalidArgumentException if the method is not POST
111
+ */
112
+ public static function convertPostToGet(RequestInterface $request)
113
+ {
114
+ if ($request->getMethod() !== 'POST') {
115
+ throw new \InvalidArgumentException('Expected a POST request but '
116
+ . 'received a ' . $request->getMethod() . ' request.');
117
+ }
118
+
119
+ $sr = $request->withMethod('GET')
120
+ ->withBody(Psr7\stream_for(''))
121
+ ->withoutHeader('Content-Type')
122
+ ->withoutHeader('Content-Length');
123
+
124
+ // Move POST fields to the query if they are present
125
+ if ($request->getHeaderLine('Content-Type') === 'application/x-www-form-urlencoded') {
126
+ $body = (string) $request->getBody();
127
+ $sr = $sr->withUri($sr->getUri()->withQuery($body));
128
+ }
129
+
130
+ return $sr;
131
+ }
132
+
133
+ protected function getPayload(RequestInterface $request)
134
+ {
135
+ // Calculate the request signature payload
136
+ if ($request->hasHeader('X-Amz-Content-Sha256')) {
137
+ // Handle streaming operations (e.g. Glacier.UploadArchive)
138
+ return $request->getHeaderLine('X-Amz-Content-Sha256');
139
+ }
140
+
141
+ if (!$request->getBody()->isSeekable()) {
142
+ throw new CouldNotCreateChecksumException('sha256');
143
+ }
144
+
145
+ try {
146
+ return Psr7\hash($request->getBody(), 'sha256');
147
+ } catch (\Exception $e) {
148
+ throw new CouldNotCreateChecksumException('sha256', $e);
149
+ }
150
+ }
151
+
152
+ protected function getPresignedPayload(RequestInterface $request)
153
+ {
154
+ return $this->getPayload($request);
155
+ }
156
+
157
+ protected function createCanonicalizedPath($path)
158
+ {
159
+ $doubleEncoded = rawurlencode(ltrim($path, '/'));
160
+
161
+ return '/' . str_replace('%2F', '/', $doubleEncoded);
162
+ }
163
+
164
+ private function createStringToSign($longDate, $credentialScope, $creq)
165
+ {
166
+ $hash = hash('sha256', $creq);
167
+
168
+ return "AWS4-HMAC-SHA256\n{$longDate}\n{$credentialScope}\n{$hash}";
169
+ }
170
+
171
+ private function createPresignedRequest(
172
+ RequestInterface $request,
173
+ CredentialsInterface $credentials
174
+ ) {
175
+ $parsedRequest = $this->parseRequest($request);
176
+
177
+ // Make sure to handle temporary credentials
178
+ if ($token = $credentials->getSecurityToken()) {
179
+ $parsedRequest['headers']['X-Amz-Security-Token'] = [$token];
180
+ }
181
+
182
+ return $this->moveHeadersToQuery($parsedRequest);
183
+ }
184
+
185
+ /**
186
+ * @param array $parsedRequest
187
+ * @param string $payload Hash of the request payload
188
+ * @return array Returns an array of context information
189
+ */
190
+ private function createContext(array $parsedRequest, $payload)
191
+ {
192
+ // The following headers are not signed because signing these headers
193
+ // would potentially cause a signature mismatch when sending a request
194
+ // through a proxy or if modified at the HTTP client level.
195
+ static $blacklist = [
196
+ 'cache-control' => true,
197
+ 'content-type' => true,
198
+ 'content-length' => true,
199
+ 'expect' => true,
200
+ 'max-forwards' => true,
201
+ 'pragma' => true,
202
+ 'range' => true,
203
+ 'te' => true,
204
+ 'if-match' => true,
205
+ 'if-none-match' => true,
206
+ 'if-modified-since' => true,
207
+ 'if-unmodified-since' => true,
208
+ 'if-range' => true,
209
+ 'accept' => true,
210
+ 'authorization' => true,
211
+ 'proxy-authorization' => true,
212
+ 'from' => true,
213
+ 'referer' => true,
214
+ 'user-agent' => true
215
+ ];
216
+
217
+ // Normalize the path as required by SigV4
218
+ $canon = $parsedRequest['method'] . "\n"
219
+ . $this->createCanonicalizedPath($parsedRequest['path']) . "\n"
220
+ . $this->getCanonicalizedQuery($parsedRequest['query']) . "\n";
221
+
222
+ // Case-insensitively aggregate all of the headers.
223
+ $aggregate = [];
224
+ foreach ($parsedRequest['headers'] as $key => $values) {
225
+ $key = strtolower($key);
226
+ if (!isset($blacklist[$key])) {
227
+ foreach ($values as $v) {
228
+ $aggregate[$key][] = $v;
229
+ }
230
+ }
231
+ }
232
+
233
+ ksort($aggregate);
234
+ $canonHeaders = [];
235
+ foreach ($aggregate as $k => $v) {
236
+ if (count($v) > 0) {
237
+ sort($v);
238
+ }
239
+ $canonHeaders[] = $k . ':' . preg_replace('/\s+/', ' ', implode(',', $v));
240
+ }
241
+
242
+ $signedHeadersString = implode(';', array_keys($aggregate));
243
+ $canon .= implode("\n", $canonHeaders) . "\n\n"
244
+ . $signedHeadersString . "\n"
245
+ . $payload;
246
+
247
+ return ['creq' => $canon, 'headers' => $signedHeadersString];
248
+ }
249
+
250
+ private function getSigningKey($shortDate, $region, $service, $secretKey)
251
+ {
252
+ $k = $shortDate . '_' . $region . '_' . $service . '_' . $secretKey;
253
+
254
+ if (!isset($this->cache[$k])) {
255
+ // Clear the cache when it reaches 50 entries
256
+ if (++$this->cacheSize > 50) {
257
+ $this->cache = [];
258
+ $this->cacheSize = 0;
259
+ }
260
+ $dateKey = hash_hmac('sha256', $shortDate, "AWS4{$secretKey}", true);
261
+ $regionKey = hash_hmac('sha256', $region, $dateKey, true);
262
+ $serviceKey = hash_hmac('sha256', $service, $regionKey, true);
263
+ $this->cache[$k] = hash_hmac('sha256', 'aws4_request', $serviceKey, true);
264
+ }
265
+
266
+ return $this->cache[$k];
267
+ }
268
+
269
+ private function getCanonicalizedQuery(array $query)
270
+ {
271
+ unset($query['X-Amz-Signature']);
272
+
273
+ if (!$query) {
274
+ return '';
275
+ }
276
+
277
+ $qs = '';
278
+ ksort($query);
279
+ foreach ($query as $k => $v) {
280
+ if (!is_array($v)) {
281
+ $qs .= rawurlencode($k) . '=' . rawurlencode($v) . '&';
282
+ } else {
283
+ sort($v);
284
+ foreach ($v as $value) {
285
+ $qs .= rawurlencode($k) . '=' . rawurlencode($value) . '&';
286
+ }
287
+ }
288
+ }
289
+
290
+ return substr($qs, 0, -1);
291
+ }
292
+
293
+ private function convertExpires($expires)
294
+ {
295
+ if ($expires instanceof \DateTime) {
296
+ $expires = $expires->getTimestamp();
297
+ } elseif (!is_numeric($expires)) {
298
+ $expires = strtotime($expires);
299
+ }
300
+
301
+ $duration = $expires - time();
302
+
303
+ // Ensure that the duration of the signature is not longer than a week
304
+ if ($duration > 604800) {
305
+ throw new \InvalidArgumentException('The expiration date of a '
306
+ . 'signature version 4 presigned URL must be less than one '
307
+ . 'week');
308
+ }
309
+
310
+ return $duration;
311
+ }
312
+
313
+ private function createScope($shortDate, $region, $service)
314
+ {
315
+ return "$shortDate/$region/$service/aws4_request";
316
+ }
317
+
318
+ private function moveHeadersToQuery(array $parsedRequest)
319
+ {
320
+ foreach ($parsedRequest['headers'] as $name => $header) {
321
+ $lname = strtolower($name);
322
+ if (substr($lname, 0, 5) == 'x-amz') {
323
+ $parsedRequest['query'][$name] = $header;
324
+ }
325
+ if ($lname !== 'host') {
326
+ unset($parsedRequest['headers'][$name]);
327
+ }
328
+ }
329
+
330
+ return $parsedRequest;
331
+ }
332
+
333
+ private function parseRequest(RequestInterface $request)
334
+ {
335
+ // Clean up any previously set headers.
336
+ /** @var RequestInterface $request */
337
+ $request = $request
338
+ ->withoutHeader('X-Amz-Date')
339
+ ->withoutHeader('Date')
340
+ ->withoutHeader('Authorization');
341
+ $uri = $request->getUri();
342
+
343
+ return [
344
+ 'method' => $request->getMethod(),
345
+ 'path' => $uri->getPath(),
346
+ 'query' => Psr7\parse_query($uri->getQuery()),
347
+ 'uri' => $uri,
348
+ 'headers' => $request->getHeaders(),
349
+ 'body' => $request->getBody(),
350
+ 'version' => $request->getProtocolVersion()
351
+ ];
352
+ }
353
+
354
+ private function buildRequest(array $req)
355
+ {
356
+ if ($req['query']) {
357
+ $req['uri'] = $req['uri']->withQuery(Psr7\build_query($req['query']));
358
+ }
359
+
360
+ return new Psr7\Request(
361
+ $req['method'],
362
+ $req['uri'],
363
+ $req['headers'],
364
+ $req['body'],
365
+ $req['version']
366
+ );
367
+ }
368
+ }
includes/aws/Aws/StorageGateway/Exception/StorageGatewayException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\StorageGateway\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error interacting with the AWS Storage Gateway service.
8
+ */
9
+ class StorageGatewayException extends AwsException {}
includes/aws/Aws/StorageGateway/StorageGatewayClient.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\StorageGateway;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * AWS Storage Gateway client.
8
+ *
9
+ * @method \Aws\Result activateGateway(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise activateGatewayAsync(array $args = [])
11
+ * @method \Aws\Result addCache(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise addCacheAsync(array $args = [])
13
+ * @method \Aws\Result addTagsToResource(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise addTagsToResourceAsync(array $args = [])
15
+ * @method \Aws\Result addUploadBuffer(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise addUploadBufferAsync(array $args = [])
17
+ * @method \Aws\Result addWorkingStorage(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise addWorkingStorageAsync(array $args = [])
19
+ * @method \Aws\Result cancelArchival(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise cancelArchivalAsync(array $args = [])
21
+ * @method \Aws\Result cancelRetrieval(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise cancelRetrievalAsync(array $args = [])
23
+ * @method \Aws\Result createCachediSCSIVolume(array $args = [])
24
+ * @method \GuzzleHttp\Promise\Promise createCachediSCSIVolumeAsync(array $args = [])
25
+ * @method \Aws\Result createSnapshot(array $args = [])
26
+ * @method \GuzzleHttp\Promise\Promise createSnapshotAsync(array $args = [])
27
+ * @method \Aws\Result createSnapshotFromVolumeRecoveryPoint(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise createSnapshotFromVolumeRecoveryPointAsync(array $args = [])
29
+ * @method \Aws\Result createStorediSCSIVolume(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise createStorediSCSIVolumeAsync(array $args = [])
31
+ * @method \Aws\Result createTapes(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise createTapesAsync(array $args = [])
33
+ * @method \Aws\Result deleteBandwidthRateLimit(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise deleteBandwidthRateLimitAsync(array $args = [])
35
+ * @method \Aws\Result deleteChapCredentials(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise deleteChapCredentialsAsync(array $args = [])
37
+ * @method \Aws\Result deleteGateway(array $args = [])
38
+ * @method \GuzzleHttp\Promise\Promise deleteGatewayAsync(array $args = [])
39
+ * @method \Aws\Result deleteSnapshotSchedule(array $args = [])
40
+ * @method \GuzzleHttp\Promise\Promise deleteSnapshotScheduleAsync(array $args = [])
41
+ * @method \Aws\Result deleteTape(array $args = [])
42
+ * @method \GuzzleHttp\Promise\Promise deleteTapeAsync(array $args = [])
43
+ * @method \Aws\Result deleteTapeArchive(array $args = [])
44
+ * @method \GuzzleHttp\Promise\Promise deleteTapeArchiveAsync(array $args = [])
45
+ * @method \Aws\Result deleteVolume(array $args = [])
46
+ * @method \GuzzleHttp\Promise\Promise deleteVolumeAsync(array $args = [])
47
+ * @method \Aws\Result describeBandwidthRateLimit(array $args = [])
48
+ * @method \GuzzleHttp\Promise\Promise describeBandwidthRateLimitAsync(array $args = [])
49
+ * @method \Aws\Result describeCache(array $args = [])
50
+ * @method \GuzzleHttp\Promise\Promise describeCacheAsync(array $args = [])
51
+ * @method \Aws\Result describeCachediSCSIVolumes(array $args = [])
52
+ * @method \GuzzleHttp\Promise\Promise describeCachediSCSIVolumesAsync(array $args = [])
53
+ * @method \Aws\Result describeChapCredentials(array $args = [])
54
+ * @method \GuzzleHttp\Promise\Promise describeChapCredentialsAsync(array $args = [])
55
+ * @method \Aws\Result describeGatewayInformation(array $args = [])
56
+ * @method \GuzzleHttp\Promise\Promise describeGatewayInformationAsync(array $args = [])
57
+ * @method \Aws\Result describeMaintenanceStartTime(array $args = [])
58
+ * @method \GuzzleHttp\Promise\Promise describeMaintenanceStartTimeAsync(array $args = [])
59
+ * @method \Aws\Result describeSnapshotSchedule(array $args = [])
60
+ * @method \GuzzleHttp\Promise\Promise describeSnapshotScheduleAsync(array $args = [])
61
+ * @method \Aws\Result describeStorediSCSIVolumes(array $args = [])
62
+ * @method \GuzzleHttp\Promise\Promise describeStorediSCSIVolumesAsync(array $args = [])
63
+ * @method \Aws\Result describeTapeArchives(array $args = [])
64
+ * @method \GuzzleHttp\Promise\Promise describeTapeArchivesAsync(array $args = [])
65
+ * @method \Aws\Result describeTapeRecoveryPoints(array $args = [])
66
+ * @method \GuzzleHttp\Promise\Promise describeTapeRecoveryPointsAsync(array $args = [])
67
+ * @method \Aws\Result describeTapes(array $args = [])
68
+ * @method \GuzzleHttp\Promise\Promise describeTapesAsync(array $args = [])
69
+ * @method \Aws\Result describeUploadBuffer(array $args = [])
70
+ * @method \GuzzleHttp\Promise\Promise describeUploadBufferAsync(array $args = [])
71
+ * @method \Aws\Result describeVTLDevices(array $args = [])
72
+ * @method \GuzzleHttp\Promise\Promise describeVTLDevicesAsync(array $args = [])
73
+ * @method \Aws\Result describeWorkingStorage(array $args = [])
74
+ * @method \GuzzleHttp\Promise\Promise describeWorkingStorageAsync(array $args = [])
75
+ * @method \Aws\Result disableGateway(array $args = [])
76
+ * @method \GuzzleHttp\Promise\Promise disableGatewayAsync(array $args = [])
77
+ * @method \Aws\Result listGateways(array $args = [])
78
+ * @method \GuzzleHttp\Promise\Promise listGatewaysAsync(array $args = [])
79
+ * @method \Aws\Result listLocalDisks(array $args = [])
80
+ * @method \GuzzleHttp\Promise\Promise listLocalDisksAsync(array $args = [])
81
+ * @method \Aws\Result listTagsForResource(array $args = [])
82
+ * @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = [])
83
+ * @method \Aws\Result listVolumeInitiators(array $args = [])
84
+ * @method \GuzzleHttp\Promise\Promise listVolumeInitiatorsAsync(array $args = [])
85
+ * @method \Aws\Result listVolumeRecoveryPoints(array $args = [])
86
+ * @method \GuzzleHttp\Promise\Promise listVolumeRecoveryPointsAsync(array $args = [])
87
+ * @method \Aws\Result listVolumes(array $args = [])
88
+ * @method \GuzzleHttp\Promise\Promise listVolumesAsync(array $args = [])
89
+ * @method \Aws\Result removeTagsFromResource(array $args = [])
90
+ * @method \GuzzleHttp\Promise\Promise removeTagsFromResourceAsync(array $args = [])
91
+ * @method \Aws\Result resetCache(array $args = [])
92
+ * @method \GuzzleHttp\Promise\Promise resetCacheAsync(array $args = [])
93
+ * @method \Aws\Result retrieveTapeArchive(array $args = [])
94
+ * @method \GuzzleHttp\Promise\Promise retrieveTapeArchiveAsync(array $args = [])
95
+ * @method \Aws\Result retrieveTapeRecoveryPoint(array $args = [])
96
+ * @method \GuzzleHttp\Promise\Promise retrieveTapeRecoveryPointAsync(array $args = [])
97
+ * @method \Aws\Result shutdownGateway(array $args = [])
98
+ * @method \GuzzleHttp\Promise\Promise shutdownGatewayAsync(array $args = [])
99
+ * @method \Aws\Result startGateway(array $args = [])
100
+ * @method \GuzzleHttp\Promise\Promise startGatewayAsync(array $args = [])
101
+ * @method \Aws\Result updateBandwidthRateLimit(array $args = [])
102
+ * @method \GuzzleHttp\Promise\Promise updateBandwidthRateLimitAsync(array $args = [])
103
+ * @method \Aws\Result updateChapCredentials(array $args = [])
104
+ * @method \GuzzleHttp\Promise\Promise updateChapCredentialsAsync(array $args = [])
105
+ * @method \Aws\Result updateGatewayInformation(array $args = [])
106
+ * @method \GuzzleHttp\Promise\Promise updateGatewayInformationAsync(array $args = [])
107
+ * @method \Aws\Result updateGatewaySoftwareNow(array $args = [])
108
+ * @method \GuzzleHttp\Promise\Promise updateGatewaySoftwareNowAsync(array $args = [])
109
+ * @method \Aws\Result updateMaintenanceStartTime(array $args = [])
110
+ * @method \GuzzleHttp\Promise\Promise updateMaintenanceStartTimeAsync(array $args = [])
111
+ * @method \Aws\Result updateSnapshotSchedule(array $args = [])
112
+ * @method \GuzzleHttp\Promise\Promise updateSnapshotScheduleAsync(array $args = [])
113
+ * @method \Aws\Result updateVTLDeviceType(array $args = [])
114
+ * @method \GuzzleHttp\Promise\Promise updateVTLDeviceTypeAsync(array $args = [])
115
+ */
116
+ class StorageGatewayClient extends AwsClient {}
includes/aws/Aws/Support/Exception/SupportException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Support\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * AWS Support service exception.
8
+ */
9
+ class SupportException extends AwsException {}
includes/aws/Aws/Support/SupportClient.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\Support;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * AWS Support client.
8
+ *
9
+ * @method \Aws\Result addAttachmentsToSet(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise addAttachmentsToSetAsync(array $args = [])
11
+ * @method \Aws\Result addCommunicationToCase(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise addCommunicationToCaseAsync(array $args = [])
13
+ * @method \Aws\Result createCase(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise createCaseAsync(array $args = [])
15
+ * @method \Aws\Result describeAttachment(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise describeAttachmentAsync(array $args = [])
17
+ * @method \Aws\Result describeCases(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise describeCasesAsync(array $args = [])
19
+ * @method \Aws\Result describeCommunications(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise describeCommunicationsAsync(array $args = [])
21
+ * @method \Aws\Result describeServices(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise describeServicesAsync(array $args = [])
23
+ * @method \Aws\Result describeSeverityLevels(array $args = [])
24
+ * @method \GuzzleHttp\Promise\Promise describeSeverityLevelsAsync(array $args = [])
25
+ * @method \Aws\Result describeTrustedAdvisorCheckRefreshStatuses(array $args = [])
26
+ * @method \GuzzleHttp\Promise\Promise describeTrustedAdvisorCheckRefreshStatusesAsync(array $args = [])
27
+ * @method \Aws\Result describeTrustedAdvisorCheckResult(array $args = [])
28
+ * @method \GuzzleHttp\Promise\Promise describeTrustedAdvisorCheckResultAsync(array $args = [])
29
+ * @method \Aws\Result describeTrustedAdvisorCheckSummaries(array $args = [])
30
+ * @method \GuzzleHttp\Promise\Promise describeTrustedAdvisorCheckSummariesAsync(array $args = [])
31
+ * @method \Aws\Result describeTrustedAdvisorChecks(array $args = [])
32
+ * @method \GuzzleHttp\Promise\Promise describeTrustedAdvisorChecksAsync(array $args = [])
33
+ * @method \Aws\Result refreshTrustedAdvisorCheck(array $args = [])
34
+ * @method \GuzzleHttp\Promise\Promise refreshTrustedAdvisorCheckAsync(array $args = [])
35
+ * @method \Aws\Result resolveCase(array $args = [])
36
+ * @method \GuzzleHttp\Promise\Promise resolveCaseAsync(array $args = [])
37
+ */
38
+ class SupportClient extends AwsClient {}
includes/aws/Aws/TraceMiddleware.php ADDED
@@ -0,0 +1,302 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Aws\Exception\AwsException;
5
+ use GuzzleHttp\Promise\RejectedPromise;
6
+ use Psr\Http\Message\RequestInterface;
7
+ use Psr\Http\Message\ResponseInterface;
8
+ use Psr\Http\Message\StreamInterface;
9
+
10
+ /**
11
+ * Traces state changes between middlewares.
12
+ */
13
+ class TraceMiddleware
14
+ {
15
+ private $prevOutput;
16
+ private $prevInput;
17
+ private $config;
18
+
19
+ private static $authHeaders = [
20
+ 'X-Amz-Security-Token' => '[TOKEN]',
21
+ ];
22
+
23
+ private static $authStrings = [
24
+ // S3Signature
25
+ '/AWSAccessKeyId=[A-Z0-9]{20}&/i' => 'AWSAccessKeyId=[KEY]&',
26
+ // SignatureV4 Signature and S3Signature
27
+ '/Signature=.+/i' => 'Signature=[SIGNATURE]',
28
+ // SignatureV4 access key ID
29
+ '/Credential=[A-Z0-9]{20}\//i' => 'Credential=[KEY]/',
30
+ // S3 signatures
31
+ '/AWS [A-Z0-9]{20}:.+/' => 'AWS AKI[KEY]:[SIGNATURE]',
32
+ // STS Presigned URLs
33
+ '/X-Amz-Security-Token=[^&]+/i' => 'X-Amz-Security-Token=[TOKEN]',
34
+ ];
35
+
36
+ /**
37
+ * Configuration array can contain the following key value pairs.
38
+ *
39
+ * - logfn: (callable) Function that is invoked with log messages. By
40
+ * default, PHP's "echo" function will be utilized.
41
+ * - stream_size: (int) When the size of a stream is greater than this
42
+ * number, the stream data will not be logged. Set to "0" to not log any
43
+ * stream data.
44
+ * - scrub_auth: (bool) Set to false to disable the scrubbing of auth data
45
+ * from the logged messages.
46
+ * - http: (bool) Set to false to disable the "debug" feature of lower
47
+ * level HTTP adapters (e.g., verbose curl output).
48
+ * - auth_strings: (array) A mapping of authentication string regular
49
+ * expressions to scrubbed strings. These mappings are passed directly to
50
+ * preg_replace (e.g., preg_replace($key, $value, $debugOutput) if
51
+ * "scrub_auth" is set to true.
52
+ * - auth_headers: (array) A mapping of header names known to contain
53
+ * sensitive data to what the scrubbed value should be. The value of any
54
+ * headers contained in this array will be replaced with the if
55
+ * "scrub_auth" is set to true.
56
+ */
57
+ public function __construct(array $config = [])
58
+ {
59
+ $this->config = $config + [
60
+ 'logfn' => function ($value) { echo $value; },
61
+ 'stream_size' => 524288,
62
+ 'scrub_auth' => true,
63
+ 'http' => true,
64
+ 'auth_strings' => [],
65
+ 'auth_headers' => [],
66
+ ];
67
+
68
+ $this->config['auth_strings'] += self::$authStrings;
69
+ $this->config['auth_headers'] += self::$authHeaders;
70
+ }
71
+
72
+ public function __invoke($step, $name)
73
+ {
74
+ $this->prevOutput = $this->prevInput = [];
75
+
76
+ return function (callable $next) use ($step, $name) {
77
+ return function (
78
+ CommandInterface $command,
79
+ RequestInterface $request = null
80
+ ) use ($next, $step, $name) {
81
+ $this->createHttpDebug($command);
82
+ $start = microtime(true);
83
+ $this->stepInput([
84
+ 'step' => $step,
85
+ 'name' => $name,
86
+ 'request' => $this->requestArray($request),
87
+ 'command' => $this->commandArray($command)
88
+ ]);
89
+
90
+ return $next($command, $request)->then(
91
+ function ($value) use ($step, $name, $command, $start) {
92
+ $this->flushHttpDebug($command);
93
+ $this->stepOutput($start, [
94
+ 'step' => $step,
95
+ 'name' => $name,
96
+ 'result' => $this->resultArray($value),
97
+ 'error' => null
98
+ ]);
99
+ return $value;
100
+ },
101
+ function ($reason) use ($step, $name, $start, $command) {
102
+ $this->flushHttpDebug($command);
103
+ $this->stepOutput($start, [
104
+ 'step' => $step,
105
+ 'name' => $name,
106
+ 'result' => null,
107
+ 'error' => $this->exceptionArray($reason)
108
+ ]);
109
+ return new RejectedPromise($reason);
110
+ }
111
+ );
112
+ };
113
+ };
114
+ }
115
+
116
+ private function stepInput($entry)
117
+ {
118
+ static $keys = ['command', 'request'];
119
+ $this->compareStep($this->prevInput, $entry, '-> Entering', $keys);
120
+ $this->write("\n");
121
+ $this->prevInput = $entry;
122
+ }
123
+
124
+ private function stepOutput($start, $entry)
125
+ {
126
+ static $keys = ['result', 'error'];
127
+ $this->compareStep($this->prevOutput, $entry, '<- Leaving', $keys);
128
+ $totalTime = microtime(true) - $start;
129
+ $this->write(" Inclusive step time: " . $totalTime . "\n\n");
130
+ $this->prevOutput = $entry;
131
+ }
132
+
133
+ private function compareStep(array $a, array $b, $title, array $keys)
134
+ {
135
+ $changes = [];
136
+ foreach ($keys as $key) {
137
+ $av = isset($a[$key]) ? $a[$key] : null;
138
+ $bv = isset($b[$key]) ? $b[$key] : null;
139
+ $this->compareArray($av, $bv, $key, $changes);
140
+ }
141
+ $str = "\n{$title} step {$b['step']}, name '{$b['name']}'";
142
+ $str .= "\n" . str_repeat('-', strlen($str) - 1) . "\n\n ";
143
+ $str .= $changes
144
+ ? implode("\n ", str_replace("\n", "\n ", $changes))
145
+ : 'no changes';
146
+ $this->write($str . "\n");
147
+ }
148
+
149
+ private function commandArray(CommandInterface $cmd)
150
+ {
151
+ return [
152
+ 'instance' => spl_object_hash($cmd),
153
+ 'name' => $cmd->getName(),
154
+ 'params' => $cmd->toArray()
155
+ ];
156
+ }
157
+
158
+ private function requestArray(RequestInterface $request = null)
159
+ {
160
+ return !$request ? [] : array_filter([
161
+ 'instance' => spl_object_hash($request),
162
+ 'method' => $request->getMethod(),
163
+ 'headers' => $this->redactHeaders($request->getHeaders()),
164
+ 'body' => $this->streamStr($request->getBody()),
165
+ 'scheme' => $request->getUri()->getScheme(),
166
+ 'port' => $request->getUri()->getPort(),
167
+ 'path' => $request->getUri()->getPath(),
168
+ 'query' => $request->getUri()->getQuery(),
169
+ ]);
170
+ }
171
+
172
+ private function responseArray(ResponseInterface $response = null)
173
+ {
174
+ return !$response ? [] : [
175
+ 'instance' => spl_object_hash($response),
176
+ 'statusCode' => $response->getStatusCode(),
177
+ 'headers' => $this->redactHeaders($response->getHeaders()),
178
+ 'body' => $this->streamStr($response->getBody())
179
+ ];
180
+ }
181
+
182
+ private function resultArray($value)
183
+ {
184
+ return $value instanceof ResultInterface
185
+ ? [
186
+ 'instance' => spl_object_hash($value),
187
+ 'data' => $value->toArray()
188
+ ] : $value;
189
+ }
190
+
191
+ private function exceptionArray($e)
192
+ {
193
+ if (!($e instanceof \Exception)) {
194
+ return $e;
195
+ }
196
+
197
+ $result = [
198
+ 'instance' => spl_object_hash($e),
199
+ 'class' => get_class($e),
200
+ 'message' => $e->getMessage(),
201
+ 'file' => $e->getFile(),
202
+ 'line' => $e->getLine(),
203
+ 'trace' => $e->getTraceAsString(),
204
+ ];
205
+
206
+ if ($e instanceof AwsException) {
207
+ $result += [
208
+ 'type' => $e->getAwsErrorType(),
209
+ 'code' => $e->getAwsErrorCode(),
210
+ 'requestId' => $e->getAwsRequestId(),
211
+ 'statusCode' => $e->getStatusCode(),
212
+ 'result' => $this->resultArray($e->getResult()),
213
+ 'request' => $this->requestArray($e->getRequest()),
214
+ 'response' => $this->responseArray($e->getResponse()),
215
+ ];
216
+ }
217
+
218
+ return $result;
219
+ }
220
+
221
+ private function compareArray($a, $b, $path, array &$diff)
222
+ {
223
+ if ($a === $b) {
224
+ return;
225
+ } elseif (is_array($a)) {
226
+ $b = (array) $b;
227
+ $keys = array_unique(array_merge(array_keys($a), array_keys($b)));
228
+ foreach ($keys as $k) {
229
+ if (!array_key_exists($k, $a)) {
230
+ $this->compareArray(null, $b[$k], "{$path}.{$k}", $diff);
231
+ } elseif (!array_key_exists($k, $b)) {
232
+ $this->compareArray($a[$k], null, "{$path}.{$k}", $diff);
233
+ } else {
234
+ $this->compareArray($a[$k], $b[$k], "{$path}.{$k}", $diff);
235
+ }
236
+ }
237
+ } elseif ($a !== null && $b === null) {
238
+ $diff[] = "{$path} was unset";
239
+ } elseif ($a === null && $b !== null) {
240
+ $diff[] = sprintf("%s was set to %s", $path, $this->str($b));
241
+ } else {
242
+ $diff[] = sprintf("%s changed from %s to %s", $path, $this->str($a), $this->str($b));
243
+ }
244
+ }
245
+
246
+ private function str($value)
247
+ {
248
+ if (is_scalar($value)) {
249
+ return (string) $value;
250
+ } elseif ($value instanceof \Exception) {
251
+ $value = $this->exceptionArray($value);
252
+ }
253
+
254
+ ob_start();
255
+ var_dump($value);
256
+ return ob_get_clean();
257
+ }
258
+
259
+ private function streamStr(StreamInterface $body)
260
+ {
261
+ return $body->getSize() < $this->config['stream_size']
262
+ ? (string) $body
263
+ : 'stream(size=' . $body->getSize() . ')';
264
+ }
265
+
266
+ private function createHttpDebug(CommandInterface $command)
267
+ {
268
+ if ($this->config['http'] && !isset($command['@http']['debug'])) {
269
+ $command['@http']['debug'] = fopen('php://temp', 'w+');
270
+ }
271
+ }
272
+
273
+ private function flushHttpDebug(CommandInterface $command)
274
+ {
275
+ if ($res = $command['@http']['debug']) {
276
+ rewind($res);
277
+ $this->write(stream_get_contents($res));
278
+ fclose($res);
279
+ $command['@http']['debug'] = null;
280
+ }
281
+ }
282
+
283
+ private function write($value)
284
+ {
285
+ if ($this->config['scrub_auth']) {
286
+ foreach ($this->config['auth_strings'] as $pattern => $replacement) {
287
+ $value = preg_replace($pattern, $replacement, $value);
288
+ }
289
+ }
290
+
291
+ call_user_func($this->config['logfn'], $value);
292
+ }
293
+
294
+ private function redactHeaders(array $headers)
295
+ {
296
+ if ($this->config['scrub_auth']) {
297
+ $headers = $this->config['auth_headers'] + $headers;
298
+ }
299
+
300
+ return $headers;
301
+ }
302
+ }
includes/aws/Aws/Waiter.php ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Aws\Exception\AwsException;
5
+ use GuzzleHttp\Promise;
6
+ use GuzzleHttp\Promise\PromisorInterface;
7
+ use GuzzleHttp\Promise\RejectedPromise;
8
+
9
+ /**
10
+ * "Waiters" are associated with an AWS resource (e.g., EC2 instance), and poll
11
+ * that resource and until it is in a particular state.
12
+
13
+ * The Waiter object produces a promise that is either a.) resolved once the
14
+ * waiting conditions are met, or b.) rejected if the waiting conditions cannot
15
+ * be met or has exceeded the number of allowed attempts at meeting the
16
+ * conditions. You can use waiters in a blocking or non-blocking way, depending
17
+ * on whether you call wait() on the promise.
18
+
19
+ * The configuration for the waiter must include information about the operation
20
+ * and the conditions for wait completion.
21
+ */
22
+ class Waiter implements PromisorInterface
23
+ {
24
+ /** @var AwsClientInterface Client used to execute each attempt. */
25
+ private $client;
26
+
27
+ /** @var string Name of the waiter. */
28
+ private $name;
29
+
30
+ /** @var array Params to use with each attempt operation. */
31
+ private $args;
32
+
33
+ /** @var array Waiter configuration. */
34
+ private $config;
35
+
36
+ /** @var array Default configuration options. */
37
+ private static $defaults = ['initDelay' => 0, 'before' => null];
38
+
39
+ /** @var array Required configuration options. */
40
+ private static $required = [
41
+ 'acceptors',
42
+ 'delay',
43
+ 'maxAttempts',
44
+ 'operation',
45
+ ];
46
+
47
+ /**
48
+ * The array of configuration options include:
49
+ *
50
+ * - acceptors: (array) Array of acceptor options
51
+ * - delay: (int) Number of seconds to delay between attempts
52
+ * - maxAttempts: (int) Maximum number of attempts before failing
53
+ * - operation: (string) Name of the API operation to use for polling
54
+ * - before: (callable) Invoked before attempts. Accepts command and tries.
55
+ *
56
+ * @param AwsClientInterface $client Client used to execute commands.
57
+ * @param string $name Waiter name.
58
+ * @param array $args Command arguments.
59
+ * @param array $config Waiter config that overrides defaults.
60
+ *
61
+ * @throws \InvalidArgumentException if the configuration is incomplete.
62
+ */
63
+ public function __construct(
64
+ AwsClientInterface $client,
65
+ $name,
66
+ array $args = [],
67
+ array $config = []
68
+ ) {
69
+ $this->client = $client;
70
+ $this->name = $name;
71
+ $this->args = $args;
72
+
73
+ // Prepare and validate config.
74
+ $this->config = $config + self::$defaults;
75
+ foreach (self::$required as $key) {
76
+ if (!isset($this->config[$key])) {
77
+ throw new \InvalidArgumentException(
78
+ 'The provided waiter configuration was incomplete.'
79
+ );
80
+ }
81
+ }
82
+ if ($this->config['before'] && !is_callable($this->config['before'])) {
83
+ throw new \InvalidArgumentException(
84
+ 'The provided "before" callback is not callable.'
85
+ );
86
+ }
87
+ }
88
+
89
+ public function promise()
90
+ {
91
+ return Promise\coroutine(function () {
92
+ $name = $this->config['operation'];
93
+ for ($state = 'retry', $attempt = 1; $state === 'retry'; $attempt++) {
94
+ // Execute the operation.
95
+ $args = $this->getArgsForAttempt($attempt);
96
+ $command = $this->client->getCommand($name, $args);
97
+ try {
98
+ if ($this->config['before']) {
99
+ $this->config['before']($command, $attempt);
100
+ }
101
+ $result = (yield $this->client->executeAsync($command));
102
+ } catch (AwsException $e) {
103
+ $result = $e;
104
+ }
105
+
106
+ // Determine the waiter's state and what to do next.
107
+ $state = $this->determineState($result);
108
+ if ($state === 'success') {
109
+ yield $command;
110
+ } elseif ($state === 'failed') {
111
+ $msg = "The {$this->name} waiter entered a failure state.";
112
+ if ($result instanceof \Exception) {
113
+ $msg .= ' Reason: ' . $result->getMessage();
114
+ }
115
+ yield new RejectedPromise(new \RuntimeException($msg));
116
+ } elseif ($state === 'retry'
117
+ && $attempt >= $this->config['maxAttempts']
118
+ ) {
119
+ $state = 'failed';
120
+ yield new RejectedPromise(new \RuntimeException(
121
+ "The {$this->name} waiter failed after attempt #{$attempt}."
122
+ ));
123
+ }
124
+ }
125
+ });
126
+ }
127
+
128
+ /**
129
+ * Gets the operation arguments for the attempt, including the delay.
130
+ *
131
+ * @param $attempt Number of the current attempt.
132
+ *
133
+ * @return mixed integer
134
+ */
135
+ private function getArgsForAttempt($attempt)
136
+ {
137
+ $args = $this->args;
138
+
139
+ // Determine the delay.
140
+ $delay = ($attempt === 1)
141
+ ? $this->config['initDelay']
142
+ : $this->config['delay'];
143
+ if (is_callable($delay)) {
144
+ $delay = $delay($attempt);
145
+ }
146
+
147
+ // Set the delay. (Note: handlers except delay in milliseconds.)
148
+ if (!isset($args['@http'])) {
149
+ $args['@http'] = [];
150
+ }
151
+ $args['@http']['delay'] = $delay * 1000;
152
+
153
+ return $args;
154
+ }
155
+
156
+ /**
157
+ * Determines the state of the waiter attempt, based on the result of
158
+ * polling the resource. A waiter can have the state of "success", "failed",
159
+ * or "retry".
160
+ *
161
+ * @param mixed $result
162
+ *
163
+ * @return string Will be "success", "failed", or "retry"
164
+ */
165
+ private function determineState($result)
166
+ {
167
+ foreach ($this->config['acceptors'] as $acceptor) {
168
+ $matcher = 'matches' . ucfirst($acceptor['matcher']);
169
+ if ($this->{$matcher}($result, $acceptor)) {
170
+ return $acceptor['state'];
171
+ }
172
+ }
173
+
174
+ return $result instanceof \Exception ? 'failed' : 'retry';
175
+ }
176
+
177
+ /**
178
+ * @param result $result Result or exception.
179
+ * @param array $acceptor Acceptor configuration being checked.
180
+ *
181
+ * @return bool
182
+ */
183
+ private function matchesPath($result, array $acceptor)
184
+ {
185
+ return !($result instanceof ResultInterface)
186
+ ? false
187
+ : $acceptor['expected'] == $result->search($acceptor['argument']);
188
+ }
189
+
190
+ /**
191
+ * @param result $result Result or exception.
192
+ * @param array $acceptor Acceptor configuration being checked.
193
+ *
194
+ * @return bool
195
+ */
196
+ private function matchesPathAll($result, array $acceptor)
197
+ {
198
+ if (!($result instanceof ResultInterface)) {
199
+ return false;
200
+ }
201
+
202
+ $actuals = $result->search($acceptor['argument']) ?: [];
203
+ foreach ($actuals as $actual) {
204
+ if ($actual != $acceptor['expected']) {
205
+ return false;
206
+ }
207
+ }
208
+
209
+ return true;
210
+ }
211
+
212
+ /**
213
+ * @param result $result Result or exception.
214
+ * @param array $acceptor Acceptor configuration being checked.
215
+ *
216
+ * @return bool
217
+ */
218
+ private function matchesPathAny($result, array $acceptor)
219
+ {
220
+ if (!($result instanceof ResultInterface)) {
221
+ return false;
222
+ }
223
+
224
+ $actuals = $result->search($acceptor['argument']) ?: [];
225
+ foreach ($actuals as $actual) {
226
+ if ($actual == $acceptor['expected']) {
227
+ return true;
228
+ }
229
+ }
230
+
231
+ return false;
232
+ }
233
+
234
+ /**
235
+ * @param result $result Result or exception.
236
+ * @param array $acceptor Acceptor configuration being checked.
237
+ *
238
+ * @return bool
239
+ */
240
+ private function matchesStatus($result, array $acceptor)
241
+ {
242
+ if ($result instanceof ResultInterface) {
243
+ return $acceptor['expected'] == $result['@metadata']['statusCode'];
244
+ } elseif ($result instanceof AwsException && $response = $result->getResponse()) {
245
+ return $acceptor['expected'] == $response->getStatusCode();
246
+ } else {
247
+ return false;
248
+ }
249
+ }
250
+
251
+ /**
252
+ * @param result $result Result or exception.
253
+ * @param array $acceptor Acceptor configuration being checked.
254
+ *
255
+ * @return bool
256
+ */
257
+ private function matchesError($result, array $acceptor)
258
+ {
259
+ if ($result instanceof AwsException) {
260
+ return $result->isConnectionError()
261
+ || $result->getAwsErrorCode() == $acceptor['expected'];
262
+ }
263
+
264
+ return false;
265
+ }
266
+ }
includes/aws/Aws/WorkSpaces/Exception/WorkSpacesException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\WorkSpaces\Exception;
3
+
4
+ use Aws\Exception\AwsException;
5
+
6
+ /**
7
+ * Represents an error while interacting with Amazon WorkSpaces.
8
+ */
9
+ class WorkSpacesException extends AwsException {}
includes/aws/Aws/WorkSpaces/WorkSpacesClient.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws\WorkSpaces;
3
+
4
+ use Aws\AwsClient;
5
+
6
+ /**
7
+ * Amazon WorkSpaces client.
8
+ *
9
+ * @method \Aws\Result createWorkspaces(array $args = [])
10
+ * @method \GuzzleHttp\Promise\Promise createWorkspacesAsync(array $args = [])
11
+ * @method \Aws\Result describeWorkspaceBundles(array $args = [])
12
+ * @method \GuzzleHttp\Promise\Promise describeWorkspaceBundlesAsync(array $args = [])
13
+ * @method \Aws\Result describeWorkspaceDirectories(array $args = [])
14
+ * @method \GuzzleHttp\Promise\Promise describeWorkspaceDirectoriesAsync(array $args = [])
15
+ * @method \Aws\Result describeWorkspaces(array $args = [])
16
+ * @method \GuzzleHttp\Promise\Promise describeWorkspacesAsync(array $args = [])
17
+ * @method \Aws\Result rebootWorkspaces(array $args = [])
18
+ * @method \GuzzleHttp\Promise\Promise rebootWorkspacesAsync(array $args = [])
19
+ * @method \Aws\Result rebuildWorkspaces(array $args = [])
20
+ * @method \GuzzleHttp\Promise\Promise rebuildWorkspacesAsync(array $args = [])
21
+ * @method \Aws\Result terminateWorkspaces(array $args = [])
22
+ * @method \GuzzleHttp\Promise\Promise terminateWorkspacesAsync(array $args = [])
23
+ */
24
+ class WorkSpacesClient extends AwsClient {}
includes/aws/Aws/WrappedHttpHandler.php ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Aws\Api\Parser\Exception\ParserException;
5
+ use GuzzleHttp\Promise;
6
+ use Psr\Http\Message\RequestInterface;
7
+ use Psr\Http\Message\ResponseInterface;
8
+
9
+ /**
10
+ * Converts an HTTP handler into a Command HTTP handler.
11
+ *
12
+ * HTTP handlers have the following signature:
13
+ * function(RequestInterface $request, array $options) : PromiseInterface
14
+ *
15
+ * The promise returned form an HTTP handler must resolve to a PSR-7 response
16
+ * object when fulfilled or an error array when rejected. The error array
17
+ * can contain the following data:
18
+ *
19
+ * - exception: (required, Exception) Exception that was encountered.
20
+ * - response: (ResponseInterface) PSR-7 response that was received (if a
21
+ * response) was received.
22
+ * - connection_error: (bool) True if the error is the result of failing to
23
+ * connect.
24
+ */
25
+ class WrappedHttpHandler
26
+ {
27
+ private $httpHandler;
28
+ private $parser;
29
+ private $errorParser;
30
+ private $exceptionClass;
31
+
32
+ /**
33
+ * @param callable $httpHandler Function that accepts a request and array
34
+ * of request options and returns a promise
35
+ * that fulfills with a response or rejects
36
+ * with an error array.
37
+ * @param callable $parser Function that accepts a response object
38
+ * and returns an AWS result object.
39
+ * @param callable $errorParser Function that parses a response object
40
+ * into AWS error data.
41
+ * @param string $exceptionClass Exception class to throw.
42
+ */
43
+ public function __construct(
44
+ callable $httpHandler,
45
+ callable $parser,
46
+ callable $errorParser,
47
+ $exceptionClass = 'Aws\Exception\AwsException'
48
+ ) {
49
+ $this->httpHandler = $httpHandler;
50
+ $this->parser = $parser;
51
+ $this->errorParser = $errorParser;
52
+ $this->exceptionClass = $exceptionClass;
53
+ }
54
+
55
+ /**
56
+ * Calls the simpler HTTP specific handler and wraps the returned promise
57
+ * with AWS specific values (e.g., a result object or AWS exception).
58
+ *
59
+ * @param CommandInterface $command Command being executed.
60
+ * @param RequestInterface $request Request to send.
61
+ *
62
+ * @return Promise\PromiseInterface
63
+ */
64
+ public function __invoke(
65
+ CommandInterface $command,
66
+ RequestInterface $request
67
+ ) {
68
+ $fn = $this->httpHandler;
69
+
70
+ return Promise\promise_for($fn($request, $command['@http'] ?: []))
71
+ ->then(
72
+ function (ResponseInterface $res) use ($command, $request) {
73
+ return $this->parseResponse($command, $request, $res);
74
+ },
75
+ function ($err) use ($request, $command) {
76
+ if (is_array($err)) {
77
+ $exception = $this->parseError($err, $request, $command);
78
+ return new Promise\RejectedPromise($exception);
79
+ }
80
+ return new Promise\RejectedPromise($err);
81
+ }
82
+ );
83
+ }
84
+
85
+ /**
86
+ * @param CommandInterface $command
87
+ * @param RequestInterface $request
88
+ * @param ResponseInterface $response
89
+ *
90
+ * @return ResultInterface
91
+ */
92
+ private function parseResponse(
93
+ CommandInterface $command,
94
+ RequestInterface $request,
95
+ ResponseInterface $response
96
+ ) {
97
+ $parser = $this->parser;
98
+ $status = $response->getStatusCode();
99
+ $result = $status < 300
100
+ ? $parser($command, $response)
101
+ : new Result();
102
+
103
+ $metadata = [
104
+ 'statusCode' => $status,
105
+ 'effectiveUri' => (string) $request->getUri(),
106
+ 'headers' => []
107
+ ];
108
+
109
+ // Bring headers into the metadata array.
110
+ foreach ($response->getHeaders() as $name => $values) {
111
+ $metadata['headers'][strtolower($name)] = $values[0];
112
+ }
113
+
114
+ $result['@metadata'] = $metadata;
115
+
116
+ return $result;
117
+ }
118
+
119
+ /**
120
+ * Parses a rejection into an AWS error.
121
+ *
122
+ * @param array $err Rejection error array.
123
+ * @param RequestInterface $request Request that was sent.
124
+ * @param CommandInterface $command Command being sent.
125
+ *
126
+ * @return \Exception
127
+ */
128
+ private function parseError(
129
+ array $err,
130
+ RequestInterface $request,
131
+ CommandInterface $command
132
+ ) {
133
+ if (!isset($err['exception'])) {
134
+ throw new \RuntimeException('The HTTP handler was rejected without an "exception" key value pair.');
135
+ }
136
+
137
+ $serviceError = "AWS HTTP error: " . $err['exception']->getMessage();
138
+
139
+ if (!isset($err['response'])) {
140
+ $parts = ['response' => null];
141
+ } else {
142
+ try {
143
+ $parts = call_user_func($this->errorParser, $err['response']);
144
+ $serviceError .= " {$parts['code']} ({$parts['type']}): "
145
+ . "{$parts['message']} - " . $err['response']->getBody();
146
+ } catch (ParserException $e) {
147
+ $parts = [];
148
+ $serviceError .= ' Unable to parse error information from '
149
+ . "response - {$e->getMessage()}";
150
+ }
151
+
152
+ $parts['response'] = $err['response'];
153
+ }
154
+
155
+ $parts['exception'] = $err['exception'];
156
+ $parts['request'] = $request;
157
+ $parts['connection_error'] = !empty($err['connection_error']);
158
+
159
+ return new $this->exceptionClass(
160
+ sprintf(
161
+ 'Error executing "%s" on "%s"; %s',
162
+ $command->getName(),
163
+ $request->getUri(),
164
+ $serviceError
165
+ ),
166
+ $command,
167
+ $parts,
168
+ $err['exception']
169
+ );
170
+ }
171
+ }
includes/aws/Aws/data/cloudfront/2015-09-17/api-2.json.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ // This file was auto-generated from sdk-root/src/data/cloudfront/2015-09-17/api-2.json
3
+ return [ 'version' => '2.0', 'metadata' => [ 'apiVersion' => '2015-09-17', 'endpointPrefix' => 'cloudfront', 'globalEndpoint' => 'cloudfront.amazonaws.com', 'protocol' => 'rest-xml', 'serviceAbbreviation' => 'CloudFront', 'serviceFullName' => 'Amazon CloudFront', 'signatureVersion' => 'v4', ], 'operations' => [ 'CreateCloudFrontOriginAccessIdentity' => [ 'name' => 'CreateCloudFrontOriginAccessIdentity2015_09_17', 'http' => [ 'method' => 'POST', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront', 'responseCode' => 201, ], 'input' => [ 'shape' => 'CreateCloudFrontOriginAccessIdentityRequest', ], 'output' => [ 'shape' => 'CreateCloudFrontOriginAccessIdentityResult', ], 'errors' => [ [ 'shape' => 'CloudFrontOriginAccessIdentityAlreadyExists', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'TooManyCloudFrontOriginAccessIdentities', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InconsistentQuantities', ], ], ], 'CreateDistribution' => [ 'name' => 'CreateDistribution2015_09_17', 'http' => [ 'method' => 'POST', 'requestUri' => '/2015-09-17/distribution', 'responseCode' => 201, ], 'input' => [ 'shape' => 'CreateDistributionRequest', ], 'output' => [ 'shape' => 'CreateDistributionResult', ], 'errors' => [ [ 'shape' => 'CNAMEAlreadyExists', ], [ 'shape' => 'DistributionAlreadyExists', ], [ 'shape' => 'InvalidOrigin', ], [ 'shape' => 'InvalidOriginAccessIdentity', ], [ 'shape' => 'AccessDenied', ], [ 'shape' => 'TooManyTrustedSigners', ], [ 'shape' => 'TrustedSignerDoesNotExist', ], [ 'shape' => 'InvalidViewerCertificate', ], [ 'shape' => 'InvalidMinimumProtocolVersion', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'TooManyDistributionCNAMEs', ], [ 'shape' => 'TooManyDistributions', ], [ 'shape' => 'InvalidDefaultRootObject', ], [ 'shape' => 'InvalidRelativePath', ], [ 'shape' => 'InvalidErrorCode', ], [ 'shape' => 'InvalidResponseCode', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InvalidRequiredProtocol', ], [ 'shape' => 'NoSuchOrigin', ], [ 'shape' => 'TooManyOrigins', ], [ 'shape' => 'TooManyCacheBehaviors', ], [ 'shape' => 'TooManyCookieNamesInWhiteList', ], [ 'shape' => 'InvalidForwardCookies', ], [ 'shape' => 'TooManyHeadersInForwardedValues', ], [ 'shape' => 'InvalidHeadersForS3Origin', ], [ 'shape' => 'InconsistentQuantities', ], [ 'shape' => 'TooManyCertificates', ], [ 'shape' => 'InvalidLocationCode', ], [ 'shape' => 'InvalidGeoRestrictionParameter', ], [ 'shape' => 'InvalidProtocolSettings', ], [ 'shape' => 'InvalidTTLOrder', ], [ 'shape' => 'InvalidWebACLId', ], ], ], 'CreateInvalidation' => [ 'name' => 'CreateInvalidation2015_09_17', 'http' => [ 'method' => 'POST', 'requestUri' => '/2015-09-17/distribution/{DistributionId}/invalidation', 'responseCode' => 201, ], 'input' => [ 'shape' => 'CreateInvalidationRequest', ], 'output' => [ 'shape' => 'CreateInvalidationResult', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'BatchTooLarge', ], [ 'shape' => 'TooManyInvalidationsInProgress', ], [ 'shape' => 'InconsistentQuantities', ], ], ], 'CreateStreamingDistribution' => [ 'name' => 'CreateStreamingDistribution2015_09_17', 'http' => [ 'method' => 'POST', 'requestUri' => '/2015-09-17/streaming-distribution', 'responseCode' => 201, ], 'input' => [ 'shape' => 'CreateStreamingDistributionRequest', ], 'output' => [ 'shape' => 'CreateStreamingDistributionResult', ], 'errors' => [ [ 'shape' => 'CNAMEAlreadyExists', ], [ 'shape' => 'StreamingDistributionAlreadyExists', ], [ 'shape' => 'InvalidOrigin', ], [ 'shape' => 'InvalidOriginAccessIdentity', ], [ 'shape' => 'AccessDenied', ], [ 'shape' => 'TooManyTrustedSigners', ], [ 'shape' => 'TrustedSignerDoesNotExist', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'TooManyStreamingDistributionCNAMEs', ], [ 'shape' => 'TooManyStreamingDistributions', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InconsistentQuantities', ], ], ], 'DeleteCloudFrontOriginAccessIdentity' => [ 'name' => 'DeleteCloudFrontOriginAccessIdentity2015_09_17', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront/{Id}', 'responseCode' => 204, ], 'input' => [ 'shape' => 'DeleteCloudFrontOriginAccessIdentityRequest', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'NoSuchCloudFrontOriginAccessIdentity', ], [ 'shape' => 'PreconditionFailed', ], [ 'shape' => 'CloudFrontOriginAccessIdentityInUse', ], ], ], 'DeleteDistribution' => [ 'name' => 'DeleteDistribution2015_09_17', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/2015-09-17/distribution/{Id}', 'responseCode' => 204, ], 'input' => [ 'shape' => 'DeleteDistributionRequest', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'DistributionNotDisabled', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'PreconditionFailed', ], ], ], 'DeleteStreamingDistribution' => [ 'name' => 'DeleteStreamingDistribution2015_09_17', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/2015-09-17/streaming-distribution/{Id}', 'responseCode' => 204, ], 'input' => [ 'shape' => 'DeleteStreamingDistributionRequest', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'StreamingDistributionNotDisabled', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'NoSuchStreamingDistribution', ], [ 'shape' => 'PreconditionFailed', ], ], ], 'GetCloudFrontOriginAccessIdentity' => [ 'name' => 'GetCloudFrontOriginAccessIdentity2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront/{Id}', ], 'input' => [ 'shape' => 'GetCloudFrontOriginAccessIdentityRequest', ], 'output' => [ 'shape' => 'GetCloudFrontOriginAccessIdentityResult', ], 'errors' => [ [ 'shape' => 'NoSuchCloudFrontOriginAccessIdentity', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetCloudFrontOriginAccessIdentityConfig' => [ 'name' => 'GetCloudFrontOriginAccessIdentityConfig2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront/{Id}/config', ], 'input' => [ 'shape' => 'GetCloudFrontOriginAccessIdentityConfigRequest', ], 'output' => [ 'shape' => 'GetCloudFrontOriginAccessIdentityConfigResult', ], 'errors' => [ [ 'shape' => 'NoSuchCloudFrontOriginAccessIdentity', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetDistribution' => [ 'name' => 'GetDistribution2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distribution/{Id}', ], 'input' => [ 'shape' => 'GetDistributionRequest', ], 'output' => [ 'shape' => 'GetDistributionResult', ], 'errors' => [ [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetDistributionConfig' => [ 'name' => 'GetDistributionConfig2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distribution/{Id}/config', ], 'input' => [ 'shape' => 'GetDistributionConfigRequest', ], 'output' => [ 'shape' => 'GetDistributionConfigResult', ], 'errors' => [ [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetInvalidation' => [ 'name' => 'GetInvalidation2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distribution/{DistributionId}/invalidation/{Id}', ], 'input' => [ 'shape' => 'GetInvalidationRequest', ], 'output' => [ 'shape' => 'GetInvalidationResult', ], 'errors' => [ [ 'shape' => 'NoSuchInvalidation', ], [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetStreamingDistribution' => [ 'name' => 'GetStreamingDistribution2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/streaming-distribution/{Id}', ], 'input' => [ 'shape' => 'GetStreamingDistributionRequest', ], 'output' => [ 'shape' => 'GetStreamingDistributionResult', ], 'errors' => [ [ 'shape' => 'NoSuchStreamingDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetStreamingDistributionConfig' => [ 'name' => 'GetStreamingDistributionConfig2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/streaming-distribution/{Id}/config', ], 'input' => [ 'shape' => 'GetStreamingDistributionConfigRequest', ], 'output' => [ 'shape' => 'GetStreamingDistributionConfigResult', ], 'errors' => [ [ 'shape' => 'NoSuchStreamingDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'ListCloudFrontOriginAccessIdentities' => [ 'name' => 'ListCloudFrontOriginAccessIdentities2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront', ], 'input' => [ 'shape' => 'ListCloudFrontOriginAccessIdentitiesRequest', ], 'output' => [ 'shape' => 'ListCloudFrontOriginAccessIdentitiesResult', ], 'errors' => [ [ 'shape' => 'InvalidArgument', ], ], ], 'ListDistributions' => [ 'name' => 'ListDistributions2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distribution', ], 'input' => [ 'shape' => 'ListDistributionsRequest', ], 'output' => [ 'shape' => 'ListDistributionsResult', ], 'errors' => [ [ 'shape' => 'InvalidArgument', ], ], ], 'ListDistributionsByWebACLId' => [ 'name' => 'ListDistributionsByWebACLId2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distributionsByWebACLId/{WebACLId}', ], 'input' => [ 'shape' => 'ListDistributionsByWebACLIdRequest', ], 'output' => [ 'shape' => 'ListDistributionsByWebACLIdResult', ], 'errors' => [ [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InvalidWebACLId', ], ], ], 'ListInvalidations' => [ 'name' => 'ListInvalidations2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distribution/{DistributionId}/invalidation', ], 'input' => [ 'shape' => 'ListInvalidationsRequest', ], 'output' => [ 'shape' => 'ListInvalidationsResult', ], 'errors' => [ [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'ListStreamingDistributions' => [ 'name' => 'ListStreamingDistributions2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/streaming-distribution', ], 'input' => [ 'shape' => 'ListStreamingDistributionsRequest', ], 'output' => [ 'shape' => 'ListStreamingDistributionsResult', ], 'errors' => [ [ 'shape' => 'InvalidArgument', ], ], ], 'UpdateCloudFrontOriginAccessIdentity' => [ 'name' => 'UpdateCloudFrontOriginAccessIdentity2015_09_17', 'http' => [ 'method' => 'PUT', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront/{Id}/config', ], 'input' => [ 'shape' => 'UpdateCloudFrontOriginAccessIdentityRequest', ], 'output' => [ 'shape' => 'UpdateCloudFrontOriginAccessIdentityResult', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'IllegalUpdate', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'NoSuchCloudFrontOriginAccessIdentity', ], [ 'shape' => 'PreconditionFailed', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InconsistentQuantities', ], ], ], 'UpdateDistribution' => [ 'name' => 'UpdateDistribution2015_09_17', 'http' => [ 'method' => 'PUT', 'requestUri' => '/2015-09-17/distribution/{Id}/config', ], 'input' => [ 'shape' => 'UpdateDistributionRequest', ], 'output' => [ 'shape' => 'UpdateDistributionResult', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'CNAMEAlreadyExists', ], [ 'shape' => 'IllegalUpdate', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'PreconditionFailed', ], [ 'shape' => 'TooManyDistributionCNAMEs', ], [ 'shape' => 'InvalidDefaultRootObject', ], [ 'shape' => 'InvalidRelativePath', ], [ 'shape' => 'InvalidErrorCode', ], [ 'shape' => 'InvalidResponseCode', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InvalidOriginAccessIdentity', ], [ 'shape' => 'TooManyTrustedSigners', ], [ 'shape' => 'TrustedSignerDoesNotExist', ], [ 'shape' => 'InvalidViewerCertificate', ], [ 'shape' => 'InvalidMinimumProtocolVersion', ], [ 'shape' => 'InvalidRequiredProtocol', ], [ 'shape' => 'NoSuchOrigin', ], [ 'shape' => 'TooManyOrigins', ], [ 'shape' => 'TooManyCacheBehaviors', ], [ 'shape' => 'TooManyCookieNamesInWhiteList', ], [ 'shape' => 'InvalidForwardCookies', ], [ 'shape' => 'TooManyHeadersInForwardedValues', ], [ 'shape' => 'InvalidHeadersForS3Origin', ], [ 'shape' => 'InconsistentQuantities', ], [ 'shape' => 'TooManyCertificates', ], [ 'shape' => 'InvalidLocationCode', ], [ 'shape' => 'InvalidGeoRestrictionParameter', ], [ 'shape' => 'InvalidTTLOrder', ], [ 'shape' => 'InvalidWebACLId', ], ], ], 'UpdateStreamingDistribution' => [ 'name' => 'UpdateStreamingDistribution2015_09_17', 'http' => [ 'method' => 'PUT', 'requestUri' => '/2015-09-17/streaming-distribution/{Id}/config', ], 'input' => [ 'shape' => 'UpdateStreamingDistributionRequest', ], 'output' => [ 'shape' => 'UpdateStreamingDistributionResult', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'CNAMEAlreadyExists', ], [ 'shape' => 'IllegalUpdate', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'NoSuchStreamingDistribution', ], [ 'shape' => 'PreconditionFailed', ], [ 'shape' => 'TooManyStreamingDistributionCNAMEs', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InvalidOriginAccessIdentity', ], [ 'shape' => 'TooManyTrustedSigners', ], [ 'shape' => 'TrustedSignerDoesNotExist', ], [ 'shape' => 'InconsistentQuantities', ], ], ], ], 'shapes' => [ 'AccessDenied' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 403, ], 'exception' => true, ], 'ActiveTrustedSigners' => [ 'type' => 'structure', 'required' => [ 'Enabled', 'Quantity', ], 'members' => [ 'Enabled' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'SignerList', ], ], ], 'AliasList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'CNAME', ], ], 'Aliases' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'AliasList', ], ], ], 'AllowedMethods' => [ 'type' => 'structure', 'required' => [ 'Quantity', 'Items', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'MethodsList', ], 'CachedMethods' => [ 'shape' => 'CachedMethods', ], ], ], 'AwsAccountNumberList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'AwsAccountNumber', ], ], 'BatchTooLarge' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 413, ], 'exception' => true, ], 'CNAMEAlreadyExists' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'CacheBehavior' => [ 'type' => 'structure', 'required' => [ 'PathPattern', 'TargetOriginId', 'ForwardedValues', 'TrustedSigners', 'ViewerProtocolPolicy', 'MinTTL', ], 'members' => [ 'PathPattern' => [ 'shape' => 'string', ], 'TargetOriginId' => [ 'shape' => 'string', ], 'ForwardedValues' => [ 'shape' => 'ForwardedValues', ], 'TrustedSigners' => [ 'shape' => 'TrustedSigners', ], 'ViewerProtocolPolicy' => [ 'shape' => 'ViewerProtocolPolicy', ], 'MinTTL' => [ 'shape' => 'long', ], 'AllowedMethods' => [ 'shape' => 'AllowedMethods', ], 'SmoothStreaming' => [ 'shape' => 'boolean', ], 'DefaultTTL' => [ 'shape' => 'long', ], 'MaxTTL' => [ 'shape' => 'long', ], 'Compress' => [ 'shape' => 'boolean', ], ], ], 'CacheBehaviorList' => [ 'type' => 'list', 'member' => [ 'shape' => 'CacheBehavior', 'locationName' => 'CacheBehavior', ], ], 'CacheBehaviors' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'CacheBehaviorList', ], ], ], 'CachedMethods' => [ 'type' => 'structure', 'required' => [ 'Quantity', 'Items', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'MethodsList', ], ], ], 'CertificateSource' => [ 'type' => 'string', 'enum' => [ 'cloudfront', 'iam', ], ], 'CloudFrontOriginAccessIdentity' => [ 'type' => 'structure', 'required' => [ 'Id', 'S3CanonicalUserId', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'S3CanonicalUserId' => [ 'shape' => 'string', ], 'CloudFrontOriginAccessIdentityConfig' => [ 'shape' => 'CloudFrontOriginAccessIdentityConfig', ], ], ], 'CloudFrontOriginAccessIdentityAlreadyExists' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'CloudFrontOriginAccessIdentityConfig' => [ 'type' => 'structure', 'required' => [ 'CallerReference', 'Comment', ], 'members' => [ 'CallerReference' => [ 'shape' => 'string', ], 'Comment' => [ 'shape' => 'string', ], ], ], 'CloudFrontOriginAccessIdentityInUse' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'CloudFrontOriginAccessIdentityList' => [ 'type' => 'structure', 'required' => [ 'Marker', 'MaxItems', 'IsTruncated', 'Quantity', ], 'members' => [ 'Marker' => [ 'shape' => 'string', ], 'NextMarker' => [ 'shape' => 'string', ], 'MaxItems' => [ 'shape' => 'integer', ], 'IsTruncated' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'CloudFrontOriginAccessIdentitySummaryList', ], ], ], 'CloudFrontOriginAccessIdentitySummary' => [ 'type' => 'structure', 'required' => [ 'Id', 'S3CanonicalUserId', 'Comment', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'S3CanonicalUserId' => [ 'shape' => 'string', ], 'Comment' => [ 'shape' => 'string', ], ], ], 'CloudFrontOriginAccessIdentitySummaryList' => [ 'type' => 'list', 'member' => [ 'shape' => 'CloudFrontOriginAccessIdentitySummary', 'locationName' => 'CloudFrontOriginAccessIdentitySummary', ], ], 'CookieNameList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'Name', ], ], 'CookieNames' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'CookieNameList', ], ], ], 'CookiePreference' => [ 'type' => 'structure', 'required' => [ 'Forward', ], 'members' => [ 'Forward' => [ 'shape' => 'ItemSelection', ], 'WhitelistedNames' => [ 'shape' => 'CookieNames', ], ], ], 'CreateCloudFrontOriginAccessIdentityRequest' => [ 'type' => 'structure', 'required' => [ 'CloudFrontOriginAccessIdentityConfig', ], 'members' => [ 'CloudFrontOriginAccessIdentityConfig' => [ 'shape' => 'CloudFrontOriginAccessIdentityConfig', 'locationName' => 'CloudFrontOriginAccessIdentityConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], ], 'payload' => 'CloudFrontOriginAccessIdentityConfig', ], 'CreateCloudFrontOriginAccessIdentityResult' => [ 'type' => 'structure', 'members' => [ 'CloudFrontOriginAccessIdentity' => [ 'shape' => 'CloudFrontOriginAccessIdentity', ], 'Location' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'Location', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'CloudFrontOriginAccessIdentity', ], 'CreateDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'DistributionConfig', ], 'members' => [ 'DistributionConfig' => [ 'shape' => 'DistributionConfig', 'locationName' => 'DistributionConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], ], 'payload' => 'DistributionConfig', ], 'CreateDistributionResult' => [ 'type' => 'structure', 'members' => [ 'Distribution' => [ 'shape' => 'Distribution', ], 'Location' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'Location', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'Distribution', ], 'CreateInvalidationRequest' => [ 'type' => 'structure', 'required' => [ 'DistributionId', 'InvalidationBatch', ], 'members' => [ 'DistributionId' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'DistributionId', ], 'InvalidationBatch' => [ 'shape' => 'InvalidationBatch', 'locationName' => 'InvalidationBatch', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], ], 'payload' => 'InvalidationBatch', ], 'CreateInvalidationResult' => [ 'type' => 'structure', 'members' => [ 'Location' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'Location', ], 'Invalidation' => [ 'shape' => 'Invalidation', ], ], 'payload' => 'Invalidation', ], 'CreateStreamingDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'StreamingDistributionConfig', ], 'members' => [ 'StreamingDistributionConfig' => [ 'shape' => 'StreamingDistributionConfig', 'locationName' => 'StreamingDistributionConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], ], 'payload' => 'StreamingDistributionConfig', ], 'CreateStreamingDistributionResult' => [ 'type' => 'structure', 'members' => [ 'StreamingDistribution' => [ 'shape' => 'StreamingDistribution', ], 'Location' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'Location', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'StreamingDistribution', ], 'CustomErrorResponse' => [ 'type' => 'structure', 'required' => [ 'ErrorCode', ], 'members' => [ 'ErrorCode' => [ 'shape' => 'integer', ], 'ResponsePagePath' => [ 'shape' => 'string', ], 'ResponseCode' => [ 'shape' => 'string', ], 'ErrorCachingMinTTL' => [ 'shape' => 'long', ], ], ], 'CustomErrorResponseList' => [ 'type' => 'list', 'member' => [ 'shape' => 'CustomErrorResponse', 'locationName' => 'CustomErrorResponse', ], ], 'CustomErrorResponses' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'CustomErrorResponseList', ], ], ], 'CustomOriginConfig' => [ 'type' => 'structure', 'required' => [ 'HTTPPort', 'HTTPSPort', 'OriginProtocolPolicy', ], 'members' => [ 'HTTPPort' => [ 'shape' => 'integer', ], 'HTTPSPort' => [ 'shape' => 'integer', ], 'OriginProtocolPolicy' => [ 'shape' => 'OriginProtocolPolicy', ], ], ], 'DefaultCacheBehavior' => [ 'type' => 'structure', 'required' => [ 'TargetOriginId', 'ForwardedValues', 'TrustedSigners', 'ViewerProtocolPolicy', 'MinTTL', ], 'members' => [ 'TargetOriginId' => [ 'shape' => 'string', ], 'ForwardedValues' => [ 'shape' => 'ForwardedValues', ], 'TrustedSigners' => [ 'shape' => 'TrustedSigners', ], 'ViewerProtocolPolicy' => [ 'shape' => 'ViewerProtocolPolicy', ], 'MinTTL' => [ 'shape' => 'long', ], 'AllowedMethods' => [ 'shape' => 'AllowedMethods', ], 'SmoothStreaming' => [ 'shape' => 'boolean', ], 'DefaultTTL' => [ 'shape' => 'long', ], 'MaxTTL' => [ 'shape' => 'long', ], 'Compress' => [ 'shape' => 'boolean', ], ], ], 'DeleteCloudFrontOriginAccessIdentityRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], ], 'DeleteDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], ], 'DeleteStreamingDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], ], 'Distribution' => [ 'type' => 'structure', 'required' => [ 'Id', 'Status', 'LastModifiedTime', 'InProgressInvalidationBatches', 'DomainName', 'ActiveTrustedSigners', 'DistributionConfig', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'Status' => [ 'shape' => 'string', ], 'LastModifiedTime' => [ 'shape' => 'timestamp', ], 'InProgressInvalidationBatches' => [ 'shape' => 'integer', ], 'DomainName' => [ 'shape' => 'string', ], 'ActiveTrustedSigners' => [ 'shape' => 'ActiveTrustedSigners', ], 'DistributionConfig' => [ 'shape' => 'DistributionConfig', ], ], ], 'DistributionAlreadyExists' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'DistributionConfig' => [ 'type' => 'structure', 'required' => [ 'CallerReference', 'Origins', 'DefaultCacheBehavior', 'Comment', 'Enabled', ], 'members' => [ 'CallerReference' => [ 'shape' => 'string', ], 'Aliases' => [ 'shape' => 'Aliases', ], 'DefaultRootObject' => [ 'shape' => 'string', ], 'Origins' => [ 'shape' => 'Origins', ], 'DefaultCacheBehavior' => [ 'shape' => 'DefaultCacheBehavior', ], 'CacheBehaviors' => [ 'shape' => 'CacheBehaviors', ], 'CustomErrorResponses' => [ 'shape' => 'CustomErrorResponses', ], 'Comment' => [ 'shape' => 'string', ], 'Logging' => [ 'shape' => 'LoggingConfig', ], 'PriceClass' => [ 'shape' => 'PriceClass', ], 'Enabled' => [ 'shape' => 'boolean', ], 'ViewerCertificate' => [ 'shape' => 'ViewerCertificate', ], 'Restrictions' => [ 'shape' => 'Restrictions', ], 'WebACLId' => [ 'shape' => 'string', ], ], ], 'DistributionList' => [ 'type' => 'structure', 'required' => [ 'Marker', 'MaxItems', 'IsTruncated', 'Quantity', ], 'members' => [ 'Marker' => [ 'shape' => 'string', ], 'NextMarker' => [ 'shape' => 'string', ], 'MaxItems' => [ 'shape' => 'integer', ], 'IsTruncated' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'DistributionSummaryList', ], ], ], 'DistributionNotDisabled' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'DistributionSummary' => [ 'type' => 'structure', 'required' => [ 'Id', 'Status', 'LastModifiedTime', 'DomainName', 'Aliases', 'Origins', 'DefaultCacheBehavior', 'CacheBehaviors', 'CustomErrorResponses', 'Comment', 'PriceClass', 'Enabled', 'ViewerCertificate', 'Restrictions', 'WebACLId', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'Status' => [ 'shape' => 'string', ], 'LastModifiedTime' => [ 'shape' => 'timestamp', ], 'DomainName' => [ 'shape' => 'string', ], 'Aliases' => [ 'shape' => 'Aliases', ], 'Origins' => [ 'shape' => 'Origins', ], 'DefaultCacheBehavior' => [ 'shape' => 'DefaultCacheBehavior', ], 'CacheBehaviors' => [ 'shape' => 'CacheBehaviors', ], 'CustomErrorResponses' => [ 'shape' => 'CustomErrorResponses', ], 'Comment' => [ 'shape' => 'string', ], 'PriceClass' => [ 'shape' => 'PriceClass', ], 'Enabled' => [ 'shape' => 'boolean', ], 'ViewerCertificate' => [ 'shape' => 'ViewerCertificate', ], 'Restrictions' => [ 'shape' => 'Restrictions', ], 'WebACLId' => [ 'shape' => 'string', ], ], ], 'DistributionSummaryList' => [ 'type' => 'list', 'member' => [ 'shape' => 'DistributionSummary', 'locationName' => 'DistributionSummary', ], ], 'ForwardedValues' => [ 'type' => 'structure', 'required' => [ 'QueryString', 'Cookies', ], 'members' => [ 'QueryString' => [ 'shape' => 'boolean', ], 'Cookies' => [ 'shape' => 'CookiePreference', ], 'Headers' => [ 'shape' => 'Headers', ], ], ], 'GeoRestriction' => [ 'type' => 'structure', 'required' => [ 'RestrictionType', 'Quantity', ], 'members' => [ 'RestrictionType' => [ 'shape' => 'GeoRestrictionType', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'LocationList', ], ], ], 'GeoRestrictionType' => [ 'type' => 'string', 'enum' => [ 'blacklist', 'whitelist', 'none', ], ], 'GetCloudFrontOriginAccessIdentityConfigRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetCloudFrontOriginAccessIdentityConfigResult' => [ 'type' => 'structure', 'members' => [ 'CloudFrontOriginAccessIdentityConfig' => [ 'shape' => 'CloudFrontOriginAccessIdentityConfig', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'CloudFrontOriginAccessIdentityConfig', ], 'GetCloudFrontOriginAccessIdentityRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetCloudFrontOriginAccessIdentityResult' => [ 'type' => 'structure', 'members' => [ 'CloudFrontOriginAccessIdentity' => [ 'shape' => 'CloudFrontOriginAccessIdentity', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'CloudFrontOriginAccessIdentity', ], 'GetDistributionConfigRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetDistributionConfigResult' => [ 'type' => 'structure', 'members' => [ 'DistributionConfig' => [ 'shape' => 'DistributionConfig', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'DistributionConfig', ], 'GetDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetDistributionResult' => [ 'type' => 'structure', 'members' => [ 'Distribution' => [ 'shape' => 'Distribution', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'Distribution', ], 'GetInvalidationRequest' => [ 'type' => 'structure', 'required' => [ 'DistributionId', 'Id', ], 'members' => [ 'DistributionId' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'DistributionId', ], 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetInvalidationResult' => [ 'type' => 'structure', 'members' => [ 'Invalidation' => [ 'shape' => 'Invalidation', ], ], 'payload' => 'Invalidation', ], 'GetStreamingDistributionConfigRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetStreamingDistributionConfigResult' => [ 'type' => 'structure', 'members' => [ 'StreamingDistributionConfig' => [ 'shape' => 'StreamingDistributionConfig', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'StreamingDistributionConfig', ], 'GetStreamingDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetStreamingDistributionResult' => [ 'type' => 'structure', 'members' => [ 'StreamingDistribution' => [ 'shape' => 'StreamingDistribution', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'StreamingDistribution', ], 'HeaderList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'Name', ], ], 'Headers' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'HeaderList', ], ], ], 'IllegalUpdate' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InconsistentQuantities' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidArgument' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidDefaultRootObject' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidErrorCode' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidForwardCookies' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidGeoRestrictionParameter' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidHeadersForS3Origin' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidIfMatchVersion' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidLocationCode' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidMinimumProtocolVersion' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidOrigin' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidOriginAccessIdentity' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidProtocolSettings' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidRelativePath' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidRequiredProtocol' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidResponseCode' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidTTLOrder' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidViewerCertificate' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidWebACLId' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'Invalidation' => [ 'type' => 'structure', 'required' => [ 'Id', 'Status', 'CreateTime', 'InvalidationBatch', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'Status' => [ 'shape' => 'string', ], 'CreateTime' => [ 'shape' => 'timestamp', ], 'InvalidationBatch' => [ 'shape' => 'InvalidationBatch', ], ], ], 'InvalidationBatch' => [ 'type' => 'structure', 'required' => [ 'Paths', 'CallerReference', ], 'members' => [ 'Paths' => [ 'shape' => 'Paths', ], 'CallerReference' => [ 'shape' => 'string', ], ], ], 'InvalidationList' => [ 'type' => 'structure', 'required' => [ 'Marker', 'MaxItems', 'IsTruncated', 'Quantity', ], 'members' => [ 'Marker' => [ 'shape' => 'string', ], 'NextMarker' => [ 'shape' => 'string', ], 'MaxItems' => [ 'shape' => 'integer', ], 'IsTruncated' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'InvalidationSummaryList', ], ], ], 'InvalidationSummary' => [ 'type' => 'structure', 'required' => [ 'Id', 'CreateTime', 'Status', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'CreateTime' => [ 'shape' => 'timestamp', ], 'Status' => [ 'shape' => 'string', ], ], ], 'InvalidationSummaryList' => [ 'type' => 'list', 'member' => [ 'shape' => 'InvalidationSummary', 'locationName' => 'InvalidationSummary', ], ], 'ItemSelection' => [ 'type' => 'string', 'enum' => [ 'none', 'whitelist', 'all', ], ], 'KeyPairIdList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'KeyPairId', ], ], 'KeyPairIds' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'KeyPairIdList', ], ], ], 'ListCloudFrontOriginAccessIdentitiesRequest' => [ 'type' => 'structure', 'members' => [ 'Marker' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'Marker', ], 'MaxItems' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'MaxItems', ], ], ], 'ListCloudFrontOriginAccessIdentitiesResult' => [ 'type' => 'structure', 'members' => [ 'CloudFrontOriginAccessIdentityList' => [ 'shape' => 'CloudFrontOriginAccessIdentityList', ], ], 'payload' => 'CloudFrontOriginAccessIdentityList', ], 'ListDistributionsByWebACLIdRequest' => [ 'type' => 'structure', 'required' => [ 'WebACLId', ], 'members' => [ 'Marker' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'Marker', ], 'MaxItems' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'MaxItems', ], 'WebACLId' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'WebACLId', ], ], ], 'ListDistributionsByWebACLIdResult' => [ 'type' => 'structure', 'members' => [ 'DistributionList' => [ 'shape' => 'DistributionList', ], ], 'payload' => 'DistributionList', ], 'ListDistributionsRequest' => [ 'type' => 'structure', 'members' => [ 'Marker' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'Marker', ], 'MaxItems' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'MaxItems', ], ], ], 'ListDistributionsResult' => [ 'type' => 'structure', 'members' => [ 'DistributionList' => [ 'shape' => 'DistributionList', ], ], 'payload' => 'DistributionList', ], 'ListInvalidationsRequest' => [ 'type' => 'structure', 'required' => [ 'DistributionId', ], 'members' => [ 'DistributionId' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'DistributionId', ], 'Marker' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'Marker', ], 'MaxItems' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'MaxItems', ], ], ], 'ListInvalidationsResult' => [ 'type' => 'structure', 'members' => [ 'InvalidationList' => [ 'shape' => 'InvalidationList', ], ], 'payload' => 'InvalidationList', ], 'ListStreamingDistributionsRequest' => [ 'type' => 'structure', 'members' => [ 'Marker' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'Marker', ], 'MaxItems' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'MaxItems', ], ], ], 'ListStreamingDistributionsResult' => [ 'type' => 'structure', 'members' => [ 'StreamingDistributionList' => [ 'shape' => 'StreamingDistributionList', ], ], 'payload' => 'StreamingDistributionList', ], 'LocationList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'Location', ], ], 'LoggingConfig' => [ 'type' => 'structure', 'required' => [ 'Enabled', 'IncludeCookies', 'Bucket', 'Prefix', ], 'members' => [ 'Enabled' => [ 'shape' => 'boolean', ], 'IncludeCookies' => [ 'shape' => 'boolean', ], 'Bucket' => [ 'shape' => 'string', ], 'Prefix' => [ 'shape' => 'string', ], ], ], 'Method' => [ 'type' => 'string', 'enum' => [ 'GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE', ], ], 'MethodsList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Method', 'locationName' => 'Method', ], ], 'MinimumProtocolVersion' => [ 'type' => 'string', 'enum' => [ 'SSLv3', 'TLSv1', ], ], 'MissingBody' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'NoSuchCloudFrontOriginAccessIdentity' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 404, ], 'exception' => true, ], 'NoSuchDistribution' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 404, ], 'exception' => true, ], 'NoSuchInvalidation' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 404, ], 'exception' => true, ], 'NoSuchOrigin' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 404, ], 'exception' => true, ], 'NoSuchStreamingDistribution' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 404, ], 'exception' => true, ], 'Origin' => [ 'type' => 'structure', 'required' => [ 'Id', 'DomainName', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'DomainName' => [ 'shape' => 'string', ], 'OriginPath' => [ 'shape' => 'string', ], 'S3OriginConfig' => [ 'shape' => 'S3OriginConfig', ], 'CustomOriginConfig' => [ 'shape' => 'CustomOriginConfig', ], ], ], 'OriginList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Origin', 'locationName' => 'Origin', ], 'min' => 1, ], 'OriginProtocolPolicy' => [ 'type' => 'string', 'enum' => [ 'http-only', 'match-viewer', ], ], 'Origins' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'OriginList', ], ], ], 'PathList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'Path', ], ], 'Paths' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'PathList', ], ], ], 'PreconditionFailed' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 412, ], 'exception' => true, ], 'PriceClass' => [ 'type' => 'string', 'enum' => [ 'PriceClass_100', 'PriceClass_200', 'PriceClass_All', ], ], 'Restrictions' => [ 'type' => 'structure', 'required' => [ 'GeoRestriction', ], 'members' => [ 'GeoRestriction' => [ 'shape' => 'GeoRestriction', ], ], ], 'S3Origin' => [ 'type' => 'structure', 'required' => [ 'DomainName', 'OriginAccessIdentity', ], 'members' => [ 'DomainName' => [ 'shape' => 'string', ], 'OriginAccessIdentity' => [ 'shape' => 'string', ], ], ], 'S3OriginConfig' => [ 'type' => 'structure', 'required' => [ 'OriginAccessIdentity', ], 'members' => [ 'OriginAccessIdentity' => [ 'shape' => 'string', ], ], ], 'SSLSupportMethod' => [ 'type' => 'string', 'enum' => [ 'sni-only', 'vip', ], ], 'Signer' => [ 'type' => 'structure', 'members' => [ 'AwsAccountNumber' => [ 'shape' => 'string', ], 'KeyPairIds' => [ 'shape' => 'KeyPairIds', ], ], ], 'SignerList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Signer', 'locationName' => 'Signer', ], ], 'StreamingDistribution' => [ 'type' => 'structure', 'required' => [ 'Id', 'Status', 'DomainName', 'ActiveTrustedSigners', 'StreamingDistributionConfig', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'Status' => [ 'shape' => 'string', ], 'LastModifiedTime' => [ 'shape' => 'timestamp', ], 'DomainName' => [ 'shape' => 'string', ], 'ActiveTrustedSigners' => [ 'shape' => 'ActiveTrustedSigners', ], 'StreamingDistributionConfig' => [ 'shape' => 'StreamingDistributionConfig', ], ], ], 'StreamingDistributionAlreadyExists' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'StreamingDistributionConfig' => [ 'type' => 'structure', 'required' => [ 'CallerReference', 'S3Origin', 'Comment', 'TrustedSigners', 'Enabled', ], 'members' => [ 'CallerReference' => [ 'shape' => 'string', ], 'S3Origin' => [ 'shape' => 'S3Origin', ], 'Aliases' => [ 'shape' => 'Aliases', ], 'Comment' => [ 'shape' => 'string', ], 'Logging' => [ 'shape' => 'StreamingLoggingConfig', ], 'TrustedSigners' => [ 'shape' => 'TrustedSigners', ], 'PriceClass' => [ 'shape' => 'PriceClass', ], 'Enabled' => [ 'shape' => 'boolean', ], ], ], 'StreamingDistributionList' => [ 'type' => 'structure', 'required' => [ 'Marker', 'MaxItems', 'IsTruncated', 'Quantity', ], 'members' => [ 'Marker' => [ 'shape' => 'string', ], 'NextMarker' => [ 'shape' => 'string', ], 'MaxItems' => [ 'shape' => 'integer', ], 'IsTruncated' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'StreamingDistributionSummaryList', ], ], ], 'StreamingDistributionNotDisabled' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'StreamingDistributionSummary' => [ 'type' => 'structure', 'required' => [ 'Id', 'Status', 'LastModifiedTime', 'DomainName', 'S3Origin', 'Aliases', 'TrustedSigners', 'Comment', 'PriceClass', 'Enabled', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'Status' => [ 'shape' => 'string', ], 'LastModifiedTime' => [ 'shape' => 'timestamp', ], 'DomainName' => [ 'shape' => 'string', ], 'S3Origin' => [ 'shape' => 'S3Origin', ], 'Aliases' => [ 'shape' => 'Aliases', ], 'TrustedSigners' => [ 'shape' => 'TrustedSigners', ], 'Comment' => [ 'shape' => 'string', ], 'PriceClass' => [ 'shape' => 'PriceClass', ], 'Enabled' => [ 'shape' => 'boolean', ], ], ], 'StreamingDistributionSummaryList' => [ 'type' => 'list', 'member' => [ 'shape' => 'StreamingDistributionSummary', 'locationName' => 'StreamingDistributionSummary', ], ], 'StreamingLoggingConfig' => [ 'type' => 'structure', 'required' => [ 'Enabled', 'Bucket', 'Prefix', ], 'members' => [ 'Enabled' => [ 'shape' => 'boolean', ], 'Bucket' => [ 'shape' => 'string', ], 'Prefix' => [ 'shape' => 'string', ], ], ], 'TooManyCacheBehaviors' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyCertificates' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyCloudFrontOriginAccessIdentities' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyCookieNamesInWhiteList' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyDistributionCNAMEs' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyDistributions' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyHeadersInForwardedValues' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyInvalidationsInProgress' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyOrigins' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyStreamingDistributionCNAMEs' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyStreamingDistributions' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyTrustedSigners' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TrustedSignerDoesNotExist' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TrustedSigners' => [ 'type' => 'structure', 'required' => [ 'Enabled', 'Quantity', ], 'members' => [ 'Enabled' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'AwsAccountNumberList', ], ], ], 'UpdateCloudFrontOriginAccessIdentityRequest' => [ 'type' => 'structure', 'required' => [ 'CloudFrontOriginAccessIdentityConfig', 'Id', ], 'members' => [ 'CloudFrontOriginAccessIdentityConfig' => [ 'shape' => 'CloudFrontOriginAccessIdentityConfig', 'locationName' => 'CloudFrontOriginAccessIdentityConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], 'payload' => 'CloudFrontOriginAccessIdentityConfig', ], 'UpdateCloudFrontOriginAccessIdentityResult' => [ 'type' => 'structure', 'members' => [ 'CloudFrontOriginAccessIdentity' => [ 'shape' => 'CloudFrontOriginAccessIdentity', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'CloudFrontOriginAccessIdentity', ], 'UpdateDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'DistributionConfig', 'Id', ], 'members' => [ 'DistributionConfig' => [ 'shape' => 'DistributionConfig', 'locationName' => 'DistributionConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], 'payload' => 'DistributionConfig', ], 'UpdateDistributionResult' => [ 'type' => 'structure', 'members' => [ 'Distribution' => [ 'shape' => 'Distribution', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'Distribution', ], 'UpdateStreamingDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'StreamingDistributionConfig', 'Id', ], 'members' => [ 'StreamingDistributionConfig' => [ 'shape' => 'StreamingDistributionConfig', 'locationName' => 'StreamingDistributionConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], 'payload' => 'StreamingDistributionConfig', ], 'UpdateStreamingDistributionResult' => [ 'type' => 'structure', 'members' => [ 'StreamingDistribution' => [ 'shape' => 'StreamingDistribution', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'StreamingDistribution', ], 'ViewerCertificate' => [ 'type' => 'structure', 'members' => [ 'Certificate' => [ 'shape' => 'string', ], 'CertificateSource' => [ 'shape' => 'CertificateSource', ], 'SSLSupportMethod' => [ 'shape' => 'SSLSupportMethod', ], 'MinimumProtocolVersion' => [ 'shape' => 'MinimumProtocolVersion', ], 'IAMCertificateId' => [ 'shape' => 'string', 'deprecated' => true, ], 'CloudFrontDefaultCertificate' => [ 'shape' => 'boolean', 'deprecated' => true, ], ], ], 'ViewerProtocolPolicy' => [ 'type' => 'string', 'enum' => [ 'allow-all', 'https-only', 'redirect-to-https', ], ], 'boolean' => [ 'type' => 'boolean', ], 'integer' => [ 'type' => 'integer', ], 'long' => [ 'type' => 'long', ], 'string' => [ 'type' => 'string', ], 'timestamp' => [ 'type' => 'timestamp', ], ],];
includes/aws/Aws/data/cloudfront/2015-09-17/examples-1.json.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ // This file was auto-generated from sdk-root/src/data/cloudfront/2015-09-17/examples-1.json
3
+ return [ 'version' => '1.0', 'examples' => [],];
includes/aws/Aws/data/cloudfront/2015-09-17/paginators-1.json.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ // This file was auto-generated from sdk-root/src/data/cloudfront/2015-09-17/paginators-1.json
3
+ return [ 'pagination' => [ 'ListCloudFrontOriginAccessIdentities' => [ 'input_token' => 'Marker', 'output_token' => 'CloudFrontOriginAccessIdentityList.NextMarker', 'limit_key' => 'MaxItems', 'more_results' => 'CloudFrontOriginAccessIdentityList.IsTruncated', 'result_key' => 'CloudFrontOriginAccessIdentityList.Items', ], 'ListDistributions' => [ 'input_token' => 'Marker', 'output_token' => 'DistributionList.NextMarker', 'limit_key' => 'MaxItems', 'more_results' => 'DistributionList.IsTruncated', 'result_key' => 'DistributionList.Items', ], 'ListInvalidations' => [ 'input_token' => 'Marker', 'output_token' => 'InvalidationList.NextMarker', 'limit_key' => 'MaxItems', 'more_results' => 'InvalidationList.IsTruncated', 'result_key' => 'InvalidationList.Items', ], 'ListStreamingDistributions' => [ 'input_token' => 'Marker', 'output_token' => 'StreamingDistributionList.NextMarker', 'limit_key' => 'MaxItems', 'more_results' => 'StreamingDistributionList.IsTruncated', 'result_key' => 'StreamingDistributionList.Items', ], ],];
includes/aws/Aws/data/cloudfront/2015-09-17/waiters-2.json.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ // This file was auto-generated from sdk-root/src/data/cloudfront/2015-09-17/waiters-2.json
3
+ return [ 'version' => 2, 'waiters' => [ 'DistributionDeployed' => [ 'delay' => 60, 'operation' => 'GetDistribution', 'maxAttempts' => 25, 'description' => 'Wait until a distribution is deployed.', 'acceptors' => [ [ 'expected' => 'Deployed', 'matcher' => 'path', 'state' => 'success', 'argument' => 'Status', ], ], ], 'InvalidationCompleted' => [ 'delay' => 20, 'operation' => 'GetInvalidation', 'maxAttempts' => 30, 'description' => 'Wait until an invalidation has completed.', 'acceptors' => [ [ 'expected' => 'Completed', 'matcher' => 'path', 'state' => 'success', 'argument' => 'Status', ], ], ], 'StreamingDistributionDeployed' => [ 'delay' => 60, 'operation' => 'GetStreamingDistribution', 'maxAttempts' => 25, 'description' => 'Wait until a streaming distribution is deployed.', 'acceptors' => [ [ 'expected' => 'Deployed', 'matcher' => 'path', 'state' => 'success', 'argument' => 'Status', ], ], ], ],];
includes/aws/Aws/data/config/2014-11-12/api-2.json.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ // This file was auto-generated from sdk-root/src/data/config/2014-11-12/api-2.json
3
+ return [ 'version' => '2.0', 'metadata' => [ 'apiVersion' => '2014-11-12', 'endpointPrefix' => 'config', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceAbbreviation' => 'Config Service', 'serviceFullName' => 'AWS Config', 'signatureVersion' => 'v4', 'targetPrefix' => 'StarlingDoveService', ], 'operations' => [ 'DeleteConfigRule' => [ 'name' => 'DeleteConfigRule', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DeleteConfigRuleRequest', ], 'errors' => [ [ 'shape' => 'NoSuchConfigRuleException', ], [ 'shape' => 'ResourceInUseException', ], ], ], 'DeleteDeliveryChannel' => [ 'name' => 'DeleteDeliveryChannel', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DeleteDeliveryChannelRequest', ], 'errors' => [ [ 'shape' => 'NoSuchDeliveryChannelException', ], [ 'shape' => 'LastDeliveryChannelDeleteFailedException', ], ], ], 'DeliverConfigSnapshot' => [ 'name' => 'DeliverConfigSnapshot', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DeliverConfigSnapshotRequest', ], 'output' => [ 'shape' => 'DeliverConfigSnapshotResponse', ], 'errors' => [ [ 'shape' => 'NoSuchDeliveryChannelException', ], [ 'shape' => 'NoAvailableConfigurationRecorderException', ], [ 'shape' => 'NoRunningConfigurationRecorderException', ], ], ], 'DescribeComplianceByConfigRule' => [ 'name' => 'DescribeComplianceByConfigRule', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeComplianceByConfigRuleRequest', ], 'output' => [ 'shape' => 'DescribeComplianceByConfigRuleResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], [ 'shape' => 'NoSuchConfigRuleException', ], ], ], 'DescribeComplianceByResource' => [ 'name' => 'DescribeComplianceByResource', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeComplianceByResourceRequest', ], 'output' => [ 'shape' => 'DescribeComplianceByResourceResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], [ 'shape' => 'InvalidNextTokenException', ], ], ], 'DescribeConfigRuleEvaluationStatus' => [ 'name' => 'DescribeConfigRuleEvaluationStatus', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeConfigRuleEvaluationStatusRequest', ], 'output' => [ 'shape' => 'DescribeConfigRuleEvaluationStatusResponse', ], 'errors' => [ [ 'shape' => 'NoSuchConfigRuleException', ], ], ], 'DescribeConfigRules' => [ 'name' => 'DescribeConfigRules', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeConfigRulesRequest', ], 'output' => [ 'shape' => 'DescribeConfigRulesResponse', ], 'errors' => [ [ 'shape' => 'NoSuchConfigRuleException', ], ], ], 'DescribeConfigurationRecorderStatus' => [ 'name' => 'DescribeConfigurationRecorderStatus', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeConfigurationRecorderStatusRequest', ], 'output' => [ 'shape' => 'DescribeConfigurationRecorderStatusResponse', ], 'errors' => [ [ 'shape' => 'NoSuchConfigurationRecorderException', ], ], ], 'DescribeConfigurationRecorders' => [ 'name' => 'DescribeConfigurationRecorders', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeConfigurationRecordersRequest', ], 'output' => [ 'shape' => 'DescribeConfigurationRecordersResponse', ], 'errors' => [ [ 'shape' => 'NoSuchConfigurationRecorderException', ], ], ], 'DescribeDeliveryChannelStatus' => [ 'name' => 'DescribeDeliveryChannelStatus', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeDeliveryChannelStatusRequest', ], 'output' => [ 'shape' => 'DescribeDeliveryChannelStatusResponse', ], 'errors' => [ [ 'shape' => 'NoSuchDeliveryChannelException', ], ], ], 'DescribeDeliveryChannels' => [ 'name' => 'DescribeDeliveryChannels', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeDeliveryChannelsRequest', ], 'output' => [ 'shape' => 'DescribeDeliveryChannelsResponse', ], 'errors' => [ [ 'shape' => 'NoSuchDeliveryChannelException', ], ], ], 'GetComplianceDetailsByConfigRule' => [ 'name' => 'GetComplianceDetailsByConfigRule', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'GetComplianceDetailsByConfigRuleRequest', ], 'output' => [ 'shape' => 'GetComplianceDetailsByConfigRuleResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], [ 'shape' => 'InvalidNextTokenException', ], [ 'shape' => 'NoSuchConfigRuleException', ], ], ], 'GetComplianceDetailsByResource' => [ 'name' => 'GetComplianceDetailsByResource', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'GetComplianceDetailsByResourceRequest', ], 'output' => [ 'shape' => 'GetComplianceDetailsByResourceResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], ], ], 'GetComplianceSummaryByConfigRule' => [ 'name' => 'GetComplianceSummaryByConfigRule', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'output' => [ 'shape' => 'GetComplianceSummaryByConfigRuleResponse', ], ], 'GetComplianceSummaryByResourceType' => [ 'name' => 'GetComplianceSummaryByResourceType', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'GetComplianceSummaryByResourceTypeRequest', ], 'output' => [ 'shape' => 'GetComplianceSummaryByResourceTypeResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], ], ], 'GetResourceConfigHistory' => [ 'name' => 'GetResourceConfigHistory', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'GetResourceConfigHistoryRequest', ], 'output' => [ 'shape' => 'GetResourceConfigHistoryResponse', ], 'errors' => [ [ 'shape' => 'ValidationException', ], [ 'shape' => 'InvalidTimeRangeException', ], [ 'shape' => 'InvalidLimitException', ], [ 'shape' => 'InvalidNextTokenException', ], [ 'shape' => 'NoAvailableConfigurationRecorderException', ], [ 'shape' => 'ResourceNotDiscoveredException', ], ], ], 'ListDiscoveredResources' => [ 'name' => 'ListDiscoveredResources', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'ListDiscoveredResourcesRequest', ], 'output' => [ 'shape' => 'ListDiscoveredResourcesResponse', ], 'errors' => [ [ 'shape' => 'ValidationException', ], [ 'shape' => 'InvalidLimitException', ], [ 'shape' => 'InvalidNextTokenException', ], [ 'shape' => 'NoAvailableConfigurationRecorderException', ], ], ], 'PutConfigRule' => [ 'name' => 'PutConfigRule', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'PutConfigRuleRequest', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], [ 'shape' => 'MaxNumberOfConfigRulesExceededException', ], [ 'shape' => 'ResourceInUseException', ], [ 'shape' => 'InsufficientPermissionsException', ], ], ], 'PutConfigurationRecorder' => [ 'name' => 'PutConfigurationRecorder', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'PutConfigurationRecorderRequest', ], 'errors' => [ [ 'shape' => 'MaxNumberOfConfigurationRecordersExceededException', ], [ 'shape' => 'InvalidConfigurationRecorderNameException', ], [ 'shape' => 'InvalidRoleException', ], [ 'shape' => 'InvalidRecordingGroupException', ], ], ], 'PutDeliveryChannel' => [ 'name' => 'PutDeliveryChannel', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'PutDeliveryChannelRequest', ], 'errors' => [ [ 'shape' => 'MaxNumberOfDeliveryChannelsExceededException', ], [ 'shape' => 'NoAvailableConfigurationRecorderException', ], [ 'shape' => 'InvalidDeliveryChannelNameException', ], [ 'shape' => 'NoSuchBucketException', ], [ 'shape' => 'InvalidS3KeyPrefixException', ], [ 'shape' => 'InvalidSNSTopicARNException', ], [ 'shape' => 'InsufficientDeliveryPolicyException', ], ], ], 'PutEvaluations' => [ 'name' => 'PutEvaluations', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'PutEvaluationsRequest', ], 'output' => [ 'shape' => 'PutEvaluationsResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], [ 'shape' => 'InvalidResultTokenException', ], [ 'shape' => 'NoSuchConfigRuleException', ], ], ], 'StartConfigurationRecorder' => [ 'name' => 'StartConfigurationRecorder', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'StartConfigurationRecorderRequest', ], 'errors' => [ [ 'shape' => 'NoSuchConfigurationRecorderException', ], [ 'shape' => 'NoAvailableDeliveryChannelException', ], ], ], 'StopConfigurationRecorder' => [ 'name' => 'StopConfigurationRecorder', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'StopConfigurationRecorderRequest', ], 'errors' => [ [ 'shape' => 'NoSuchConfigurationRecorderException', ], ], ], ], 'shapes' => [ 'ARN' => [ 'type' => 'string', ], 'AccountId' => [ 'type' => 'string', ], 'AllSupported' => [ 'type' => 'boolean', ], 'AvailabilityZone' => [ 'type' => 'string', ], 'AwsRegion' => [ 'type' => 'string', ], 'Boolean' => [ 'type' => 'boolean', ], 'ChannelName' => [ 'type' => 'string', 'max' => 256, 'min' => 1, ], 'ChronologicalOrder' => [ 'type' => 'string', 'enum' => [ 'Reverse', 'Forward', ], ], 'Compliance' => [ 'type' => 'structure', 'members' => [ 'ComplianceType' => [ 'shape' => 'ComplianceType', ], 'ComplianceContributorCount' => [ 'shape' => 'ComplianceContributorCount', ], ], ], 'ComplianceByConfigRule' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], 'Compliance' => [ 'shape' => 'Compliance', ], ], ], 'ComplianceByConfigRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'ComplianceByConfigRule', ], ], 'ComplianceByResource' => [ 'type' => 'structure', 'members' => [ 'ResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ResourceId' => [ 'shape' => 'StringWithCharLimit256', ], 'Compliance' => [ 'shape' => 'Compliance', ], ], ], 'ComplianceByResources' => [ 'type' => 'list', 'member' => [ 'shape' => 'ComplianceByResource', ], ], 'ComplianceContributorCount' => [ 'type' => 'structure', 'members' => [ 'CappedCount' => [ 'shape' => 'Integer', ], 'CapExceeded' => [ 'shape' => 'Boolean', ], ], ], 'ComplianceResourceTypes' => [ 'type' => 'list', 'member' => [ 'shape' => 'StringWithCharLimit256', ], 'max' => 100, 'min' => 0, ], 'ComplianceSummariesByResourceType' => [ 'type' => 'list', 'member' => [ 'shape' => 'ComplianceSummaryByResourceType', ], ], 'ComplianceSummary' => [ 'type' => 'structure', 'members' => [ 'CompliantResourceCount' => [ 'shape' => 'ComplianceContributorCount', ], 'NonCompliantResourceCount' => [ 'shape' => 'ComplianceContributorCount', ], 'ComplianceSummaryTimestamp' => [ 'shape' => 'Date', ], ], ], 'ComplianceSummaryByResourceType' => [ 'type' => 'structure', 'members' => [ 'ResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceSummary' => [ 'shape' => 'ComplianceSummary', ], ], ], 'ComplianceType' => [ 'type' => 'string', 'enum' => [ 'COMPLIANT', 'NON_COMPLIANT', 'NOT_APPLICABLE', 'INSUFFICIENT_DATA', ], ], 'ComplianceTypes' => [ 'type' => 'list', 'member' => [ 'shape' => 'ComplianceType', ], 'max' => 3, 'min' => 0, ], 'ConfigExportDeliveryInfo' => [ 'type' => 'structure', 'members' => [ 'lastStatus' => [ 'shape' => 'DeliveryStatus', ], 'lastErrorCode' => [ 'shape' => 'String', ], 'lastErrorMessage' => [ 'shape' => 'String', ], 'lastAttemptTime' => [ 'shape' => 'Date', ], 'lastSuccessfulTime' => [ 'shape' => 'Date', ], 'nextDeliveryTime' => [ 'shape' => 'Date', ], ], ], 'ConfigRule' => [ 'type' => 'structure', 'required' => [ 'Source', ], 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], 'ConfigRuleArn' => [ 'shape' => 'String', ], 'ConfigRuleId' => [ 'shape' => 'String', ], 'Description' => [ 'shape' => 'EmptiableStringWithCharLimit256', ], 'Scope' => [ 'shape' => 'Scope', ], 'Source' => [ 'shape' => 'Source', ], 'InputParameters' => [ 'shape' => 'StringWithCharLimit256', ], 'MaximumExecutionFrequency' => [ 'shape' => 'MaximumExecutionFrequency', ], 'ConfigRuleState' => [ 'shape' => 'ConfigRuleState', ], ], ], 'ConfigRuleEvaluationStatus' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], 'ConfigRuleArn' => [ 'shape' => 'String', ], 'ConfigRuleId' => [ 'shape' => 'String', ], 'LastSuccessfulInvocationTime' => [ 'shape' => 'Date', ], 'LastFailedInvocationTime' => [ 'shape' => 'Date', ], 'LastSuccessfulEvaluationTime' => [ 'shape' => 'Date', ], 'LastFailedEvaluationTime' => [ 'shape' => 'Date', ], 'FirstActivatedTime' => [ 'shape' => 'Date', ], 'LastErrorCode' => [ 'shape' => 'String', ], 'LastErrorMessage' => [ 'shape' => 'String', ], 'FirstEvaluationStarted' => [ 'shape' => 'Boolean', ], ], ], 'ConfigRuleEvaluationStatusList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ConfigRuleEvaluationStatus', ], ], 'ConfigRuleNames' => [ 'type' => 'list', 'member' => [ 'shape' => 'StringWithCharLimit64', ], 'max' => 25, 'min' => 0, ], 'ConfigRuleState' => [ 'type' => 'string', 'enum' => [ 'ACTIVE', 'DELETING', ], ], 'ConfigRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'ConfigRule', ], ], 'ConfigSnapshotDeliveryProperties' => [ 'type' => 'structure', 'members' => [ 'deliveryFrequency' => [ 'shape' => 'MaximumExecutionFrequency', ], ], ], 'ConfigStreamDeliveryInfo' => [ 'type' => 'structure', 'members' => [ 'lastStatus' => [ 'shape' => 'DeliveryStatus', ], 'lastErrorCode' => [ 'shape' => 'String', ], 'lastErrorMessage' => [ 'shape' => 'String', ], 'lastStatusChangeTime' => [ 'shape' => 'Date', ], ], ], 'Configuration' => [ 'type' => 'string', ], 'ConfigurationItem' => [ 'type' => 'structure', 'members' => [ 'version' => [ 'shape' => 'Version', ], 'accountId' => [ 'shape' => 'AccountId', ], 'configurationItemCaptureTime' => [ 'shape' => 'ConfigurationItemCaptureTime', ], 'configurationItemStatus' => [ 'shape' => 'ConfigurationItemStatus', ], 'configurationStateId' => [ 'shape' => 'ConfigurationStateId', ], 'configurationItemMD5Hash' => [ 'shape' => 'ConfigurationItemMD5Hash', ], 'arn' => [ 'shape' => 'ARN', ], 'resourceType' => [ 'shape' => 'ResourceType', ], 'resourceId' => [ 'shape' => 'ResourceId', ], 'resourceName' => [ 'shape' => 'ResourceName', ], 'awsRegion' => [ 'shape' => 'AwsRegion', ], 'availabilityZone' => [ 'shape' => 'AvailabilityZone', ], 'resourceCreationTime' => [ 'shape' => 'ResourceCreationTime', ], 'tags' => [ 'shape' => 'Tags', ], 'relatedEvents' => [ 'shape' => 'RelatedEventList', ], 'relationships' => [ 'shape' => 'RelationshipList', ], 'configuration' => [ 'shape' => 'Configuration', ], ], ], 'ConfigurationItemCaptureTime' => [ 'type' => 'timestamp', ], 'ConfigurationItemList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ConfigurationItem', ], ], 'ConfigurationItemMD5Hash' => [ 'type' => 'string', ], 'ConfigurationItemStatus' => [ 'type' => 'string', 'enum' => [ 'Ok', 'Failed', 'Discovered', 'Deleted', ], ], 'ConfigurationRecorder' => [ 'type' => 'structure', 'members' => [ 'name' => [ 'shape' => 'RecorderName', ], 'roleARN' => [ 'shape' => 'String', ], 'recordingGroup' => [ 'shape' => 'RecordingGroup', ], ], ], 'ConfigurationRecorderList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ConfigurationRecorder', ], ], 'ConfigurationRecorderNameList' => [ 'type' => 'list', 'member' => [ 'shape' => 'RecorderName', ], ], 'ConfigurationRecorderStatus' => [ 'type' => 'structure', 'members' => [ 'name' => [ 'shape' => 'String', ], 'lastStartTime' => [ 'shape' => 'Date', ], 'lastStopTime' => [ 'shape' => 'Date', ], 'recording' => [ 'shape' => 'Boolean', ], 'lastStatus' => [ 'shape' => 'RecorderStatus', ], 'lastErrorCode' => [ 'shape' => 'String', ], 'lastErrorMessage' => [ 'shape' => 'String', ], 'lastStatusChangeTime' => [ 'shape' => 'Date', ], ], ], 'ConfigurationRecorderStatusList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ConfigurationRecorderStatus', ], ], 'ConfigurationStateId' => [ 'type' => 'string', ], 'Date' => [ 'type' => 'timestamp', ], 'DeleteConfigRuleRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigRuleName', ], 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], ], ], 'DeleteDeliveryChannelRequest' => [ 'type' => 'structure', 'required' => [ 'DeliveryChannelName', ], 'members' => [ 'DeliveryChannelName' => [ 'shape' => 'ChannelName', ], ], ], 'DeliverConfigSnapshotRequest' => [ 'type' => 'structure', 'required' => [ 'deliveryChannelName', ], 'members' => [ 'deliveryChannelName' => [ 'shape' => 'ChannelName', ], ], ], 'DeliverConfigSnapshotResponse' => [ 'type' => 'structure', 'members' => [ 'configSnapshotId' => [ 'shape' => 'String', ], ], ], 'DeliveryChannel' => [ 'type' => 'structure', 'members' => [ 'name' => [ 'shape' => 'ChannelName', ], 's3BucketName' => [ 'shape' => 'String', ], 's3KeyPrefix' => [ 'shape' => 'String', ], 'snsTopicARN' => [ 'shape' => 'String', ], 'configSnapshotDeliveryProperties' => [ 'shape' => 'ConfigSnapshotDeliveryProperties', ], ], ], 'DeliveryChannelList' => [ 'type' => 'list', 'member' => [ 'shape' => 'DeliveryChannel', ], ], 'DeliveryChannelNameList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ChannelName', ], ], 'DeliveryChannelStatus' => [ 'type' => 'structure', 'members' => [ 'name' => [ 'shape' => 'String', ], 'configSnapshotDeliveryInfo' => [ 'shape' => 'ConfigExportDeliveryInfo', ], 'configHistoryDeliveryInfo' => [ 'shape' => 'ConfigExportDeliveryInfo', ], 'configStreamDeliveryInfo' => [ 'shape' => 'ConfigStreamDeliveryInfo', ], ], ], 'DeliveryChannelStatusList' => [ 'type' => 'list', 'member' => [ 'shape' => 'DeliveryChannelStatus', ], ], 'DeliveryStatus' => [ 'type' => 'string', 'enum' => [ 'Success', 'Failure', 'Not_Applicable', ], ], 'DescribeComplianceByConfigRuleRequest' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleNames' => [ 'shape' => 'ConfigRuleNames', ], 'ComplianceTypes' => [ 'shape' => 'ComplianceTypes', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'DescribeComplianceByConfigRuleResponse' => [ 'type' => 'structure', 'members' => [ 'ComplianceByConfigRules' => [ 'shape' => 'ComplianceByConfigRules', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'DescribeComplianceByResourceRequest' => [ 'type' => 'structure', 'members' => [ 'ResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ResourceId' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceTypes' => [ 'shape' => 'ComplianceTypes', ], 'Limit' => [ 'shape' => 'Limit', ], 'NextToken' => [ 'shape' => 'NextToken', ], ], ], 'DescribeComplianceByResourceResponse' => [ 'type' => 'structure', 'members' => [ 'ComplianceByResources' => [ 'shape' => 'ComplianceByResources', ], 'NextToken' => [ 'shape' => 'NextToken', ], ], ], 'DescribeConfigRuleEvaluationStatusRequest' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleNames' => [ 'shape' => 'ConfigRuleNames', ], ], ], 'DescribeConfigRuleEvaluationStatusResponse' => [ 'type' => 'structure', 'members' => [ 'ConfigRulesEvaluationStatus' => [ 'shape' => 'ConfigRuleEvaluationStatusList', ], ], ], 'DescribeConfigRulesRequest' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleNames' => [ 'shape' => 'ConfigRuleNames', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'DescribeConfigRulesResponse' => [ 'type' => 'structure', 'members' => [ 'ConfigRules' => [ 'shape' => 'ConfigRules', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'DescribeConfigurationRecorderStatusRequest' => [ 'type' => 'structure', 'members' => [ 'ConfigurationRecorderNames' => [ 'shape' => 'ConfigurationRecorderNameList', ], ], ], 'DescribeConfigurationRecorderStatusResponse' => [ 'type' => 'structure', 'members' => [ 'ConfigurationRecordersStatus' => [ 'shape' => 'ConfigurationRecorderStatusList', ], ], ], 'DescribeConfigurationRecordersRequest' => [ 'type' => 'structure', 'members' => [ 'ConfigurationRecorderNames' => [ 'shape' => 'ConfigurationRecorderNameList', ], ], ], 'DescribeConfigurationRecordersResponse' => [ 'type' => 'structure', 'members' => [ 'ConfigurationRecorders' => [ 'shape' => 'ConfigurationRecorderList', ], ], ], 'DescribeDeliveryChannelStatusRequest' => [ 'type' => 'structure', 'members' => [ 'DeliveryChannelNames' => [ 'shape' => 'DeliveryChannelNameList', ], ], ], 'DescribeDeliveryChannelStatusResponse' => [ 'type' => 'structure', 'members' => [ 'DeliveryChannelsStatus' => [ 'shape' => 'DeliveryChannelStatusList', ], ], ], 'DescribeDeliveryChannelsRequest' => [ 'type' => 'structure', 'members' => [ 'DeliveryChannelNames' => [ 'shape' => 'DeliveryChannelNameList', ], ], ], 'DescribeDeliveryChannelsResponse' => [ 'type' => 'structure', 'members' => [ 'DeliveryChannels' => [ 'shape' => 'DeliveryChannelList', ], ], ], 'EarlierTime' => [ 'type' => 'timestamp', ], 'EmptiableStringWithCharLimit256' => [ 'type' => 'string', 'max' => 256, 'min' => 0, ], 'Evaluation' => [ 'type' => 'structure', 'required' => [ 'ComplianceResourceType', 'ComplianceResourceId', 'ComplianceType', 'OrderingTimestamp', ], 'members' => [ 'ComplianceResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceResourceId' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceType' => [ 'shape' => 'ComplianceType', ], 'Annotation' => [ 'shape' => 'StringWithCharLimit256', ], 'OrderingTimestamp' => [ 'shape' => 'OrderingTimestamp', ], ], ], 'EvaluationResult' => [ 'type' => 'structure', 'members' => [ 'EvaluationResultIdentifier' => [ 'shape' => 'EvaluationResultIdentifier', ], 'ComplianceType' => [ 'shape' => 'ComplianceType', ], 'ResultRecordedTime' => [ 'shape' => 'Date', ], 'ConfigRuleInvokedTime' => [ 'shape' => 'Date', ], 'Annotation' => [ 'shape' => 'StringWithCharLimit256', ], 'ResultToken' => [ 'shape' => 'String', ], ], ], 'EvaluationResultIdentifier' => [ 'type' => 'structure', 'members' => [ 'EvaluationResultQualifier' => [ 'shape' => 'EvaluationResultQualifier', ], 'OrderingTimestamp' => [ 'shape' => 'Date', ], ], ], 'EvaluationResultQualifier' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], 'ResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ResourceId' => [ 'shape' => 'StringWithCharLimit256', ], ], ], 'EvaluationResults' => [ 'type' => 'list', 'member' => [ 'shape' => 'EvaluationResult', ], ], 'Evaluations' => [ 'type' => 'list', 'member' => [ 'shape' => 'Evaluation', ], 'max' => 100, 'min' => 0, ], 'EventSource' => [ 'type' => 'string', 'enum' => [ 'aws.config', ], ], 'GetComplianceDetailsByConfigRuleRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigRuleName', ], 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], 'ComplianceTypes' => [ 'shape' => 'ComplianceTypes', ], 'Limit' => [ 'shape' => 'Limit', ], 'NextToken' => [ 'shape' => 'NextToken', ], ], ], 'GetComplianceDetailsByConfigRuleResponse' => [ 'type' => 'structure', 'members' => [ 'EvaluationResults' => [ 'shape' => 'EvaluationResults', ], 'NextToken' => [ 'shape' => 'NextToken', ], ], ], 'GetComplianceDetailsByResourceRequest' => [ 'type' => 'structure', 'required' => [ 'ResourceType', 'ResourceId', ], 'members' => [ 'ResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ResourceId' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceTypes' => [ 'shape' => 'ComplianceTypes', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'GetComplianceDetailsByResourceResponse' => [ 'type' => 'structure', 'members' => [ 'EvaluationResults' => [ 'shape' => 'EvaluationResults', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'GetComplianceSummaryByConfigRuleResponse' => [ 'type' => 'structure', 'members' => [ 'ComplianceSummary' => [ 'shape' => 'ComplianceSummary', ], ], ], 'GetComplianceSummaryByResourceTypeRequest' => [ 'type' => 'structure', 'members' => [ 'ResourceTypes' => [ 'shape' => 'ResourceTypes', ], ], ], 'GetComplianceSummaryByResourceTypeResponse' => [ 'type' => 'structure', 'members' => [ 'ComplianceSummariesByResourceType' => [ 'shape' => 'ComplianceSummariesByResourceType', ], ], ], 'GetResourceConfigHistoryRequest' => [ 'type' => 'structure', 'required' => [ 'resourceType', 'resourceId', ], 'members' => [ 'resourceType' => [ 'shape' => 'ResourceType', ], 'resourceId' => [ 'shape' => 'ResourceId', ], 'laterTime' => [ 'shape' => 'LaterTime', ], 'earlierTime' => [ 'shape' => 'EarlierTime', ], 'chronologicalOrder' => [ 'shape' => 'ChronologicalOrder', ], 'limit' => [ 'shape' => 'Limit', ], 'nextToken' => [ 'shape' => 'NextToken', ], ], ], 'GetResourceConfigHistoryResponse' => [ 'type' => 'structure', 'members' => [ 'configurationItems' => [ 'shape' => 'ConfigurationItemList', ], 'nextToken' => [ 'shape' => 'NextToken', ], ], ], 'IncludeGlobalResourceTypes' => [ 'type' => 'boolean', ], 'InsufficientDeliveryPolicyException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InsufficientPermissionsException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'Integer' => [ 'type' => 'integer', ], 'InvalidConfigurationRecorderNameException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidDeliveryChannelNameException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidLimitException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidNextTokenException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidParameterValueException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidRecordingGroupException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidResultTokenException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidRoleException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidS3KeyPrefixException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidSNSTopicARNException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidTimeRangeException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'LastDeliveryChannelDeleteFailedException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'LaterTime' => [ 'type' => 'timestamp', ], 'Limit' => [ 'type' => 'integer', 'max' => 100, 'min' => 0, ], 'ListDiscoveredResourcesRequest' => [ 'type' => 'structure', 'required' => [ 'resourceType', ], 'members' => [ 'resourceType' => [ 'shape' => 'ResourceType', ], 'resourceIds' => [ 'shape' => 'ResourceIdList', ], 'resourceName' => [ 'shape' => 'ResourceName', ], 'limit' => [ 'shape' => 'Limit', ], 'includeDeletedResources' => [ 'shape' => 'Boolean', ], 'nextToken' => [ 'shape' => 'NextToken', ], ], ], 'ListDiscoveredResourcesResponse' => [ 'type' => 'structure', 'members' => [ 'resourceIdentifiers' => [ 'shape' => 'ResourceIdentifierList', ], 'nextToken' => [ 'shape' => 'NextToken', ], ], ], 'MaxNumberOfConfigRulesExceededException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'MaxNumberOfConfigurationRecordersExceededException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'MaxNumberOfDeliveryChannelsExceededException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'MaximumExecutionFrequency' => [ 'type' => 'string', 'enum' => [ 'One_Hour', 'Three_Hours', 'Six_Hours', 'Twelve_Hours', 'TwentyFour_Hours', ], ], 'MessageType' => [ 'type' => 'string', 'enum' => [ 'ConfigurationItemChangeNotification', 'ConfigurationSnapshotDeliveryCompleted', ], ], 'Name' => [ 'type' => 'string', ], 'NextToken' => [ 'type' => 'string', ], 'NoAvailableConfigurationRecorderException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoAvailableDeliveryChannelException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoRunningConfigurationRecorderException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchBucketException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchConfigRuleException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchConfigurationRecorderException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchDeliveryChannelException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'OrderingTimestamp' => [ 'type' => 'timestamp', ], 'Owner' => [ 'type' => 'string', 'enum' => [ 'CUSTOM_LAMBDA', 'AWS', ], ], 'PutConfigRuleRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigRule', ], 'members' => [ 'ConfigRule' => [ 'shape' => 'ConfigRule', ], ], ], 'PutConfigurationRecorderRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigurationRecorder', ], 'members' => [ 'ConfigurationRecorder' => [ 'shape' => 'ConfigurationRecorder', ], ], ], 'PutDeliveryChannelRequest' => [ 'type' => 'structure', 'required' => [ 'DeliveryChannel', ], 'members' => [ 'DeliveryChannel' => [ 'shape' => 'DeliveryChannel', ], ], ], 'PutEvaluationsRequest' => [ 'type' => 'structure', 'required' => [ 'ResultToken', ], 'members' => [ 'Evaluations' => [ 'shape' => 'Evaluations', ], 'ResultToken' => [ 'shape' => 'String', ], ], ], 'PutEvaluationsResponse' => [ 'type' => 'structure', 'members' => [ 'FailedEvaluations' => [ 'shape' => 'Evaluations', ], ], ], 'RecorderName' => [ 'type' => 'string', 'max' => 256, 'min' => 1, ], 'RecorderStatus' => [ 'type' => 'string', 'enum' => [ 'Pending', 'Success', 'Failure', ], ], 'RecordingGroup' => [ 'type' => 'structure', 'members' => [ 'allSupported' => [ 'shape' => 'AllSupported', ], 'includeGlobalResourceTypes' => [ 'shape' => 'IncludeGlobalResourceTypes', ], 'resourceTypes' => [ 'shape' => 'ResourceTypeList', ], ], ], 'RelatedEvent' => [ 'type' => 'string', ], 'RelatedEventList' => [ 'type' => 'list', 'member' => [ 'shape' => 'RelatedEvent', ], ], 'Relationship' => [ 'type' => 'structure', 'members' => [ 'resourceType' => [ 'shape' => 'ResourceType', ], 'resourceId' => [ 'shape' => 'ResourceId', ], 'resourceName' => [ 'shape' => 'ResourceName', ], 'relationshipName' => [ 'shape' => 'RelationshipName', ], ], ], 'RelationshipList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Relationship', ], ], 'RelationshipName' => [ 'type' => 'string', ], 'ResourceCreationTime' => [ 'type' => 'timestamp', ], 'ResourceDeletionTime' => [ 'type' => 'timestamp', ], 'ResourceId' => [ 'type' => 'string', ], 'ResourceIdList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ResourceId', ], ], 'ResourceIdentifier' => [ 'type' => 'structure', 'members' => [ 'resourceType' => [ 'shape' => 'ResourceType', ], 'resourceId' => [ 'shape' => 'ResourceId', ], 'resourceName' => [ 'shape' => 'ResourceName', ], 'resourceDeletionTime' => [ 'shape' => 'ResourceDeletionTime', ], ], ], 'ResourceIdentifierList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ResourceIdentifier', ], ], 'ResourceInUseException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'ResourceName' => [ 'type' => 'string', ], 'ResourceNotDiscoveredException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'ResourceType' => [ 'type' => 'string', 'enum' => [ 'AWS::EC2::CustomerGateway', 'AWS::EC2::EIP', 'AWS::EC2::Host', 'AWS::EC2::Instance', 'AWS::EC2::InternetGateway', 'AWS::EC2::NetworkAcl', 'AWS::EC2::NetworkInterface', 'AWS::EC2::RouteTable', 'AWS::EC2::SecurityGroup', 'AWS::EC2::Subnet', 'AWS::CloudTrail::Trail', 'AWS::EC2::Volume', 'AWS::EC2::VPC', 'AWS::EC2::VPNConnection', 'AWS::EC2::VPNGateway', 'AWS::IAM::Group', 'AWS::IAM::Policy', 'AWS::IAM::Role', 'AWS::IAM::User', ], ], 'ResourceTypeList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ResourceType', ], ], 'ResourceTypes' => [ 'type' => 'list', 'member' => [ 'shape' => 'StringWithCharLimit256', ], 'max' => 100, 'min' => 0, ], 'Scope' => [ 'type' => 'structure', 'members' => [ 'ComplianceResourceTypes' => [ 'shape' => 'ComplianceResourceTypes', ], 'TagKey' => [ 'shape' => 'StringWithCharLimit128', ], 'TagValue' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceResourceId' => [ 'shape' => 'StringWithCharLimit256', ], ], ], 'Source' => [ 'type' => 'structure', 'members' => [ 'Owner' => [ 'shape' => 'Owner', ], 'SourceIdentifier' => [ 'shape' => 'StringWithCharLimit256', ], 'SourceDetails' => [ 'shape' => 'SourceDetails', ], ], ], 'SourceDetail' => [ 'type' => 'structure', 'members' => [ 'EventSource' => [ 'shape' => 'EventSource', ], 'MessageType' => [ 'shape' => 'MessageType', ], ], ], 'SourceDetails' => [ 'type' => 'list', 'member' => [ 'shape' => 'SourceDetail', ], 'max' => 25, 'min' => 0, ], 'StartConfigurationRecorderRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigurationRecorderName', ], 'members' => [ 'ConfigurationRecorderName' => [ 'shape' => 'RecorderName', ], ], ], 'StopConfigurationRecorderRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigurationRecorderName', ], 'members' => [ 'ConfigurationRecorderName' => [ 'shape' => 'RecorderName', ], ], ], 'String' => [ 'type' => 'string', ], 'StringWithCharLimit128' => [ 'type' => 'string', 'max' => 128, 'min' => 1, ], 'StringWithCharLimit256' => [ 'type' => 'string', 'max' => 256, 'min' => 1, ], 'StringWithCharLimit64' => [ 'type' => 'string', 'max' => 64, 'min' => 1, ], 'Tags' => [ 'type' => 'map', 'key' => [ 'shape' => 'Name', ], 'value' => [ 'shape' => 'Value', ], ], 'ValidationException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'Value' => [ 'type' => 'string', ], 'Version' => [ 'type' => 'string', ], ],];
includes/aws/Aws/data/config/2014-11-12/paginators-1.json.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ // This file was auto-generated from sdk-root/src/data/config/2014-11-12/paginators-1.json
3
+ return [ 'pagination' => [ 'GetResourceConfigHistory' => [ 'input_token' => 'nextToken', 'output_token' => 'nextToken', 'limit_key' => 'limit', 'result_key' => 'configurationItems', ], ],];
includes/aws/Aws/data/endpoints.json.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ // This file was auto-generated from sdk-root/src/data/endpoints.json
3
+ return [ 'version' => 2, 'endpoints' => [ '*/*' => [ 'endpoint' => '{service}.{region}.amazonaws.com', ], 'cn-north-1/*' => [ 'endpoint' => '{service}.{region}.amazonaws.com.cn', 'signatureVersion' => 'v4', ], 'us-gov-west-1/iam' => [ 'endpoint' => 'iam.us-gov.amazonaws.com', ], 'us-gov-west-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], '*/cloudfront' => [ 'endpoint' => 'cloudfront.amazonaws.com', ], '*/iam' => [ 'endpoint' => 'iam.amazonaws.com', ], 'us-gov-west-1/sts' => [ 'endpoint' => 'sts.us-gov-west-1.amazonaws.com', ], '*/importexport' => [ 'endpoint' => 'importexport.amazonaws.com', ], '*/route53' => [ 'endpoint' => 'route53.amazonaws.com', ], '*/sts' => [ 'endpoint' => 'sts.amazonaws.com', ], '*/waf' => [ 'endpoint' => 'waf.amazonaws.com', ], 'us-east-1/sdb' => [ 'endpoint' => 'sdb.amazonaws.com', ], 'us-east-1/s3' => [ 'endpoint' => 's3.amazonaws.com', ], 'us-west-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'us-west-2/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'eu-west-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'ap-southeast-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'ap-southeast-2/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'ap-northeast-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'sa-east-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], ],];
includes/aws/Aws/data/manifest.json.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ // This file was auto-generated from sdk-root/src/data/manifest.json
3
+ return [ 'apigateway' => [ 'namespace' => 'ApiGateway', 'versions' => [ 'latest' => '2015-07-09', '2015-07-09' => '2015-07-09', '2015-06-01' => '2015-07-09', ], ], 'autoscaling' => [ 'namespace' => 'AutoScaling', 'versions' => [ 'latest' => '2011-01-01', '2011-01-01' => '2011-01-01', ], ], 'cloudformation' => [ 'namespace' => 'CloudFormation', 'versions' => [ 'latest' => '2010-05-15', '2010-05-15' => '2010-05-15', ], ], 'cloudfront' => [ 'namespace' => 'CloudFront', 'versions' => [ 'latest' => '2015-09-17', '2015-09-17' => '2015-09-17', '2015-07-27' => '2015-09-17', '2015-04-17' => '2015-09-17', '2014-11-06' => '2015-09-17', ], ], 'cloudhsm' => [ 'namespace' => 'CloudHsm', 'versions' => [ 'latest' => '2014-05-30', '2014-05-30' => '2014-05-30', ], ], 'cloudsearch' => [ 'namespace' => 'CloudSearch', 'versions' => [ 'latest' => '2013-01-01', '2013-01-01' => '2013-01-01', ], ], 'cloudsearchdomain' => [ 'namespace' => 'CloudSearchDomain', 'versions' => [ 'latest' => '2013-01-01', '2013-01-01' => '2013-01-01', ], ], 'cloudtrail' => [ 'namespace' => 'CloudTrail', 'versions' => [ 'latest' => '2013-11-01', '2013-11-01' => '2013-11-01', ], ], 'codecommit' => [ 'namespace' => 'CodeCommit', 'versions' => [ 'latest' => '2015-04-13', '2015-04-13' => '2015-04-13', ], ], 'codedeploy' => [ 'namespace' => 'CodeDeploy', 'versions' => [ 'latest' => '2014-10-06', '2014-10-06' => '2014-10-06', ], ], 'codepipeline' => [ 'namespace' => 'CodePipeline', 'versions' => [ 'latest' => '2015-07-09', '2015-07-09' => '2015-07-09', ], ], 'cognito-identity' => [ 'namespace' => 'CognitoIdentity', 'versions' => [ 'latest' => '2014-06-30', '2014-06-30' => '2014-06-30', ], ], 'cognito-sync' => [ 'namespace' => 'CognitoSync', 'versions' => [ 'latest' => '2014-06-30', '2014-06-30' => '2014-06-30', ], ], 'config' => [ 'namespace' => 'ConfigService', 'versions' => [ 'latest' => '2014-11-12', '2014-11-12' => '2014-11-12', ], ], 'data.iot' => [ 'namespace' => 'IotDataPlane', 'versions' => [ 'latest' => '2015-05-28', '2015-05-28' => '2015-05-28', ], ], 'datapipeline' => [ 'namespace' => 'DataPipeline', 'versions' => [ 'latest' => '2012-10-29', '2012-10-29' => '2012-10-29', ], ], 'devicefarm' => [ 'namespace' => 'DeviceFarm', 'versions' => [ 'latest' => '2015-06-23', '2015-06-23' => '2015-06-23', ], ], 'directconnect' => [ 'namespace' => 'DirectConnect', 'versions' => [ 'latest' => '2012-10-25', '2012-10-25' => '2012-10-25', ], ], 'ds' => [ 'namespace' => 'DirectoryService', 'versions' => [ 'latest' => '2015-04-16', '2015-04-16' => '2015-04-16', ], ], 'dynamodb' => [ 'namespace' => 'DynamoDb', 'versions' => [ 'latest' => '2012-08-10', '2012-08-10' => '2012-08-10', ], ], 'ec2' => [ 'namespace' => 'Ec2', 'versions' => [ 'latest' => '2015-10-01', '2015-10-01' => '2015-10-01', '2015-04-15' => '2015-10-01', ], ], 'ecr' => [ 'namespace' => 'Ecr', 'versions' => [ 'latest' => '2015-09-21', '2015-09-21' => '2015-09-21', ], ], 'ecs' => [ 'namespace' => 'Ecs', 'versions' => [ 'latest' => '2014-11-13', '2014-11-13' => '2014-11-13', ], ], 'elasticache' => [ 'namespace' => 'ElastiCache', 'versions' => [ 'latest' => '2015-02-02', '2015-02-02' => '2015-02-02', ], ], 'elasticbeanstalk' => [ 'namespace' => 'ElasticBeanstalk', 'versions' => [ 'latest' => '2010-12-01', '2010-12-01' => '2010-12-01', ], ], 'elasticfilesystem' => [ 'namespace' => 'Efs', 'versions' => [ 'latest' => '2015-02-01', '2015-02-01' => '2015-02-01', ], ], 'elasticloadbalancing' => [ 'namespace' => 'ElasticLoadBalancing', 'versions' => [ 'latest' => '2012-06-01', '2012-06-01' => '2012-06-01', ], ], 'elasticmapreduce' => [ 'namespace' => 'Emr', 'versions' => [ 'latest' => '2009-03-31', '2009-03-31' => '2009-03-31', ], ], 'elastictranscoder' => [ 'namespace' => 'ElasticTranscoder', 'versions' => [ 'latest' => '2012-09-25', '2012-09-25' => '2012-09-25', ], ], 'email' => [ 'namespace' => 'Ses', 'versions' => [ 'latest' => '2010-12-01', '2010-12-01' => '2010-12-01', ], ], 'es' => [ 'namespace' => 'ElasticsearchService', 'versions' => [ 'latest' => '2015-01-01', '2015-01-01' => '2015-01-01', ], ], 'firehose' => [ 'namespace' => 'Firehose', 'versions' => [ 'latest' => '2015-08-04', '2015-08-04' => '2015-08-04', ], ], 'glacier' => [ 'namespace' => 'Glacier', 'versions' => [ 'latest' => '2012-06-01', '2012-06-01' => '2012-06-01', ], ], 'iam' => [ 'namespace' => 'Iam', 'versions' => [ 'latest' => '2010-05-08', '2010-05-08' => '2010-05-08', ], ], 'inspector' => [ 'namespace' => 'Inspector', 'versions' => [ 'latest' => '2015-08-18', '2015-08-18' => '2015-08-18', ], ], 'iot' => [ 'namespace' => 'Iot', 'versions' => [ 'latest' => '2015-05-28', '2015-05-28' => '2015-05-28', ], ], 'kinesis' => [ 'namespace' => 'Kinesis', 'versions' => [ 'latest' => '2013-12-02', '2013-12-02' => '2013-12-02', ], ], 'kms' => [ 'namespace' => 'Kms', 'versions' => [ 'latest' => '2014-11-01', '2014-11-01' => '2014-11-01', ], ], 'lambda' => [ 'namespace' => 'Lambda', 'versions' => [ 'latest' => '2015-03-31', '2015-03-31' => '2015-03-31', ], ], 'logs' => [ 'namespace' => 'CloudWatchLogs', 'versions' => [ 'latest' => '2014-03-28', '2014-03-28' => '2014-03-28', ], ], 'machinelearning' => [ 'namespace' => 'MachineLearning', 'versions' => [ 'latest' => '2014-12-12', '2014-12-12' => '2014-12-12', ], ], 'marketplacecommerceanalytics' => [ 'namespace' => 'MarketplaceCommerceAnalytics', 'versions' => [ 'latest' => '2015-07-01', '2015-07-01' => '2015-07-01', ], ], 'monitoring' => [ 'namespace' => 'CloudWatch', 'versions' => [ 'latest' => '2010-08-01', '2010-08-01' => '2010-08-01', ], ], 'opsworks' => [ 'namespace' => 'OpsWorks', 'versions' => [ 'latest' => '2013-02-18', '2013-02-18' => '2013-02-18', ], ], 'rds' => [ 'namespace' => 'Rds', 'versions' => [ 'latest' => '2014-10-31', '2014-10-31' => '2014-10-31', ], ], 'redshift' => [ 'namespace' => 'Redshift', 'versions' => [ 'latest' => '2012-12-01', '2012-12-01' => '2012-12-01', ], ], 'route53' => [ 'namespace' => 'Route53', 'versions' => [ 'latest' => '2013-04-01', '2013-04-01' => '2013-04-01', ], ], 'route53domains' => [ 'namespace' => 'Route53Domains', 'versions' => [ 'latest' => '2014-05-15', '2014-05-15' => '2014-05-15', ], ], 's3' => [ 'namespace' => 'S3', 'versions' => [ 'latest' => '2006-03-01', '2006-03-01' => '2006-03-01', ], ], 'sns' => [ 'namespace' => 'Sns', 'versions' => [ 'latest' => '2010-03-31', '2010-03-31' => '2010-03-31', ], ], 'sqs' => [ 'namespace' => 'Sqs', 'versions' => [ 'latest' => '2012-11-05', '2012-11-05' => '2012-11-05', ], ], 'ssm' => [ 'namespace' => 'Ssm', 'versions' => [ 'latest' => '2014-11-06', '2014-11-06' => '2014-11-06', ], ], 'storagegateway' => [ 'namespace' => 'StorageGateway', 'versions' => [ 'latest' => '2013-06-30', '2013-06-30' => '2013-06-30', ], ], 'streams.dynamodb' => [ 'namespace' => 'DynamoDbStreams', 'versions' => [ 'latest' => '2012-08-10', '2012-08-10' => '2012-08-10', ], ], 'sts' => [ 'namespace' => 'Sts', 'versions' => [ 'latest' => '2011-06-15', '2011-06-15' => '2011-06-15', ], ], 'support' => [ 'namespace' => 'Support', 'versions' => [ 'latest' => '2013-04-15', '2013-04-15' => '2013-04-15', ], ], 'swf' => [ 'namespace' => 'Swf', 'versions' => [ 'latest' => '2012-01-25', '2012-01-25' => '2012-01-25', ], ], 'waf' => [ 'namespace' => 'Waf', 'versions' => [ 'latest' => '2015-08-24', '2015-08-24' => '2015-08-24', ], ], 'workspaces' => [ 'namespace' => 'WorkSpaces', 'versions' => [ 'latest' => '2015-04-08', '2015-04-08' => '2015-04-08', ], ],];
includes/aws/Aws/data/s3/2006-03-01/api-2.json.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ // This file was auto-generated from sdk-root/src/data/s3/2006-03-01/api-2.json
3
+ return [ 'version' => '2.0', 'metadata' => [ 'apiVersion' => '2006-03-01', 'checksumFormat' => 'md5', 'endpointPrefix' => 's3', 'globalEndpoint' => 's3.amazonaws.com', 'protocol' => 'rest-xml', 'serviceAbbreviation' => 'Amazon S3', 'serviceFullName' => 'Amazon Simple Storage Service', 'signatureVersion' => 'v4', 'timestampFormat' => 'rfc822', ], 'operations' => [ 'AbortMultipartUpload' => [ 'name' => 'AbortMultipartUpload', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'AbortMultipartUploadRequest', ], 'output' => [ 'shape' => 'AbortMultipartUploadOutput', ], 'errors' => [ [ 'shape' => 'NoSuchUpload', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadAbort.html', ], 'CompleteMultipartUpload' => [ 'name' => 'CompleteMultipartUpload', 'http' => [ 'method' => 'POST', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'CompleteMultipartUploadRequest', ], 'output' => [ 'shape' => 'CompleteMultipartUploadOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadComplete.html', ], 'CopyObject' => [ 'name' => 'CopyObject', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'CopyObjectRequest', ], 'output' => [ 'shape' => 'CopyObjectOutput', ], 'errors' => [ [ 'shape' => 'ObjectNotInActiveTierError', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectCOPY.html', 'alias' => 'PutObjectCopy', ], 'CreateBucket' => [ 'name' => 'CreateBucket', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}', ], 'input' => [ 'shape' => 'CreateBucketRequest', ], 'output' => [ 'shape' => 'CreateBucketOutput', ], 'errors' => [ [ 'shape' => 'BucketAlreadyExists', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUT.html', 'alias' => 'PutBucket', ], 'CreateMultipartUpload' => [ 'name' => 'CreateMultipartUpload', 'http' => [ 'method' => 'POST', 'requestUri' => '/{Bucket}/{Key+}?uploads', ], 'input' => [ 'shape' => 'CreateMultipartUploadRequest', ], 'output' => [ 'shape' => 'CreateMultipartUploadOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadInitiate.html', 'alias' => 'InitiateMultipartUpload', ], 'DeleteBucket' => [ 'name' => 'DeleteBucket', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}', ], 'input' => [ 'shape' => 'DeleteBucketRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETE.html', ], 'DeleteBucketCors' => [ 'name' => 'DeleteBucketCors', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?cors', ], 'input' => [ 'shape' => 'DeleteBucketCorsRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETEcors.html', ], 'DeleteBucketLifecycle' => [ 'name' => 'DeleteBucketLifecycle', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?lifecycle', ], 'input' => [ 'shape' => 'DeleteBucketLifecycleRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETElifecycle.html', ], 'DeleteBucketPolicy' => [ 'name' => 'DeleteBucketPolicy', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?policy', ], 'input' => [ 'shape' => 'DeleteBucketPolicyRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETEpolicy.html', ], 'DeleteBucketReplication' => [ 'name' => 'DeleteBucketReplication', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?replication', ], 'input' => [ 'shape' => 'DeleteBucketReplicationRequest', ], ], 'DeleteBucketTagging' => [ 'name' => 'DeleteBucketTagging', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?tagging', ], 'input' => [ 'shape' => 'DeleteBucketTaggingRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETEtagging.html', ], 'DeleteBucketWebsite' => [ 'name' => 'DeleteBucketWebsite', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?website', ], 'input' => [ 'shape' => 'DeleteBucketWebsiteRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETEwebsite.html', ], 'DeleteObject' => [ 'name' => 'DeleteObject', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'DeleteObjectRequest', ], 'output' => [ 'shape' => 'DeleteObjectOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectDELETE.html', ], 'DeleteObjects' => [ 'name' => 'DeleteObjects', 'http' => [ 'method' => 'POST', 'requestUri' => '/{Bucket}?delete', ], 'input' => [ 'shape' => 'DeleteObjectsRequest', ], 'output' => [ 'shape' => 'DeleteObjectsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/multiobjectdeleteapi.html', 'alias' => 'DeleteMultipleObjects', ], 'GetBucketAcl' => [ 'name' => 'GetBucketAcl', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?acl', ], 'input' => [ 'shape' => 'GetBucketAclRequest', ], 'output' => [ 'shape' => 'GetBucketAclOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETacl.html', ], 'GetBucketCors' => [ 'name' => 'GetBucketCors', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?cors', ], 'input' => [ 'shape' => 'GetBucketCorsRequest', ], 'output' => [ 'shape' => 'GetBucketCorsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETcors.html', ], 'GetBucketLifecycle' => [ 'name' => 'GetBucketLifecycle', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?lifecycle', ], 'input' => [ 'shape' => 'GetBucketLifecycleRequest', ], 'output' => [ 'shape' => 'GetBucketLifecycleOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETlifecycle.html', 'deprecated' => true, ], 'GetBucketLifecycleConfiguration' => [ 'name' => 'GetBucketLifecycleConfiguration', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?lifecycle', ], 'input' => [ 'shape' => 'GetBucketLifecycleConfigurationRequest', ], 'output' => [ 'shape' => 'GetBucketLifecycleConfigurationOutput', ], ], 'GetBucketLocation' => [ 'name' => 'GetBucketLocation', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?location', ], 'input' => [ 'shape' => 'GetBucketLocationRequest', ], 'output' => [ 'shape' => 'GetBucketLocationOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETlocation.html', ], 'GetBucketLogging' => [ 'name' => 'GetBucketLogging', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?logging', ], 'input' => [ 'shape' => 'GetBucketLoggingRequest', ], 'output' => [ 'shape' => 'GetBucketLoggingOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETlogging.html', ], 'GetBucketNotification' => [ 'name' => 'GetBucketNotification', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?notification', ], 'input' => [ 'shape' => 'GetBucketNotificationConfigurationRequest', ], 'output' => [ 'shape' => 'NotificationConfigurationDeprecated', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETnotification.html', 'deprecated' => true, ], 'GetBucketNotificationConfiguration' => [ 'name' => 'GetBucketNotificationConfiguration', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?notification', ], 'input' => [ 'shape' => 'GetBucketNotificationConfigurationRequest', ], 'output' => [ 'shape' => 'NotificationConfiguration', ], ], 'GetBucketPolicy' => [ 'name' => 'GetBucketPolicy', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?policy', ], 'input' => [ 'shape' => 'GetBucketPolicyRequest', ], 'output' => [ 'shape' => 'GetBucketPolicyOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETpolicy.html', ], 'GetBucketReplication' => [ 'name' => 'GetBucketReplication', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?replication', ], 'input' => [ 'shape' => 'GetBucketReplicationRequest', ], 'output' => [ 'shape' => 'GetBucketReplicationOutput', ], ], 'GetBucketRequestPayment' => [ 'name' => 'GetBucketRequestPayment', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?requestPayment', ], 'input' => [ 'shape' => 'GetBucketRequestPaymentRequest', ], 'output' => [ 'shape' => 'GetBucketRequestPaymentOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTrequestPaymentGET.html', ], 'GetBucketTagging' => [ 'name' => 'GetBucketTagging', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?tagging', ], 'input' => [ 'shape' => 'GetBucketTaggingRequest', ], 'output' => [ 'shape' => 'GetBucketTaggingOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETtagging.html', ], 'GetBucketVersioning' => [ 'name' => 'GetBucketVersioning', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?versioning', ], 'input' => [ 'shape' => 'GetBucketVersioningRequest', ], 'output' => [ 'shape' => 'GetBucketVersioningOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETversioningStatus.html', ], 'GetBucketWebsite' => [ 'name' => 'GetBucketWebsite', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?website', ], 'input' => [ 'shape' => 'GetBucketWebsiteRequest', ], 'output' => [ 'shape' => 'GetBucketWebsiteOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETwebsite.html', ], 'GetObject' => [ 'name' => 'GetObject', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'GetObjectRequest', ], 'output' => [ 'shape' => 'GetObjectOutput', ], 'errors' => [ [ 'shape' => 'NoSuchKey', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectGET.html', ], 'GetObjectAcl' => [ 'name' => 'GetObjectAcl', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}/{Key+}?acl', ], 'input' => [ 'shape' => 'GetObjectAclRequest', ], 'output' => [ 'shape' => 'GetObjectAclOutput', ], 'errors' => [ [ 'shape' => 'NoSuchKey', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectGETacl.html', ], 'GetObjectTorrent' => [ 'name' => 'GetObjectTorrent', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}/{Key+}?torrent', ], 'input' => [ 'shape' => 'GetObjectTorrentRequest', ], 'output' => [ 'shape' => 'GetObjectTorrentOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectGETtorrent.html', ], 'HeadBucket' => [ 'name' => 'HeadBucket', 'http' => [ 'method' => 'HEAD', 'requestUri' => '/{Bucket}', ], 'input' => [ 'shape' => 'HeadBucketRequest', ], 'errors' => [ [ 'shape' => 'NoSuchBucket', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketHEAD.html', ], 'HeadObject' => [ 'name' => 'HeadObject', 'http' => [ 'method' => 'HEAD', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'HeadObjectRequest', ], 'output' => [ 'shape' => 'HeadObjectOutput', ], 'errors' => [ [ 'shape' => 'NoSuchKey', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectHEAD.html', ], 'ListBuckets' => [ 'name' => 'ListBuckets', 'http' => [ 'method' => 'GET', 'requestUri' => '/', ], 'output' => [ 'shape' => 'ListBucketsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTServiceGET.html', 'alias' => 'GetService', ], 'ListMultipartUploads' => [ 'name' => 'ListMultipartUploads', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?uploads', ], 'input' => [ 'shape' => 'ListMultipartUploadsRequest', ], 'output' => [ 'shape' => 'ListMultipartUploadsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadListMPUpload.html', ], 'ListObjectVersions' => [ 'name' => 'ListObjectVersions', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?versions', ], 'input' => [ 'shape' => 'ListObjectVersionsRequest', ], 'output' => [ 'shape' => 'ListObjectVersionsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETVersion.html', 'alias' => 'GetBucketObjectVersions', ], 'ListObjects' => [ 'name' => 'ListObjects', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}', ], 'input' => [ 'shape' => 'ListObjectsRequest', ], 'output' => [ 'shape' => 'ListObjectsOutput', ], 'errors' => [ [ 'shape' => 'NoSuchBucket', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGET.html', 'alias' => 'GetBucket', ], 'ListParts' => [ 'name' => 'ListParts', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'ListPartsRequest', ], 'output' => [ 'shape' => 'ListPartsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadListParts.html', ], 'PutBucketAcl' => [ 'name' => 'PutBucketAcl', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?acl', ], 'input' => [ 'shape' => 'PutBucketAclRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTacl.html', ], 'PutBucketCors' => [ 'name' => 'PutBucketCors', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?cors', ], 'input' => [ 'shape' => 'PutBucketCorsRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTcors.html', ], 'PutBucketLifecycle' => [ 'name' => 'PutBucketLifecycle', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?lifecycle', ], 'input' => [ 'shape' => 'PutBucketLifecycleRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTlifecycle.html', 'deprecated' => true, ], 'PutBucketLifecycleConfiguration' => [ 'name' => 'PutBucketLifecycleConfiguration', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?lifecycle', ], 'input' => [ 'shape' => 'PutBucketLifecycleConfigurationRequest', ], ], 'PutBucketLogging' => [ 'name' => 'PutBucketLogging', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?logging', ], 'input' => [ 'shape' => 'PutBucketLoggingRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTlogging.html', ], 'PutBucketNotification' => [ 'name' => 'PutBucketNotification', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?notification', ], 'input' => [ 'shape' => 'PutBucketNotificationRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTnotification.html', 'deprecated' => true, ], 'PutBucketNotificationConfiguration' => [ 'name' => 'PutBucketNotificationConfiguration', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?notification', ], 'input' => [ 'shape' => 'PutBucketNotificationConfigurationRequest', ], ], 'PutBucketPolicy' => [ 'name' => 'PutBucketPolicy', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?policy', ], 'input' => [ 'shape' => 'PutBucketPolicyRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTpolicy.html', ], 'PutBucketReplication' => [ 'name' => 'PutBucketReplication', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?replication', ], 'input' => [ 'shape' => 'PutBucketReplicationRequest', ], ], 'PutBucketRequestPayment' => [ 'name' => 'PutBucketRequestPayment', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?requestPayment', ], 'input' => [ 'shape' => 'PutBucketRequestPaymentRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTrequestPaymentPUT.html', ], 'PutBucketTagging' => [ 'name' => 'PutBucketTagging', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?tagging', ], 'input' => [ 'shape' => 'PutBucketTaggingRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTtagging.html', ], 'PutBucketVersioning' => [ 'name' => 'PutBucketVersioning', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?versioning', ], 'input' => [ 'shape' => 'PutBucketVersioningRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTVersioningStatus.html', ], 'PutBucketWebsite' => [ 'name' => 'PutBucketWebsite', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?website', ], 'input' => [ 'shape' => 'PutBucketWebsiteRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTwebsite.html', ], 'PutObject' => [ 'name' => 'PutObject', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'PutObjectRequest', ], 'output' => [ 'shape' => 'PutObjectOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectPUT.html', ], 'PutObjectAcl' => [ 'name' => 'PutObjectAcl', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}/{Key+}?acl', ], 'input' => [ 'shape' => 'PutObjectAclRequest', ], 'output' => [ 'shape' => 'PutObjectAclOutput', ], 'errors' => [ [ 'shape' => 'NoSuchKey', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectPUTacl.html', ], 'RestoreObject' => [ 'name' => 'RestoreObject', 'http' => [ 'method' => 'POST', 'requestUri' => '/{Bucket}/{Key+}?restore', ], 'input' => [ 'shape' => 'RestoreObjectRequest', ], 'output' => [ 'shape' => 'RestoreObjectOutput', ], 'errors' => [ [ 'shape' => 'ObjectAlreadyInActiveTierError', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectRestore.html', 'alias' => 'PostObjectRestore', ], 'UploadPart' => [ 'name' => 'UploadPart', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'UploadPartRequest', ], 'output' => [ 'shape' => 'UploadPartOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadUploadPart.html', ], 'UploadPartCopy' => [ 'name' => 'UploadPartCopy', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'UploadPartCopyRequest', ], 'output' => [ 'shape' => 'UploadPartCopyOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadUploadPartCopy.html', ], ], 'shapes' => [ 'AbortMultipartUploadOutput' => [ 'type' => 'structure', 'members' => [ 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'AbortMultipartUploadRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', 'UploadId', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', 'location' => 'querystring', 'locationName' => 'uploadId', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'AcceptRanges' => [ 'type' => 'string', ], 'AccessControlPolicy' => [ 'type' => 'structure', 'members' => [ 'Grants' => [ 'shape' => 'Grants', 'locationName' => 'AccessControlList', ], 'Owner' => [ 'shape' => 'Owner', ], ], ], 'AllowedHeader' => [ 'type' => 'string', ], 'AllowedHeaders' => [ 'type' => 'list', 'member' => [ 'shape' => 'AllowedHeader', ], 'flattened' => true, ], 'AllowedMethod' => [ 'type' => 'string', ], 'AllowedMethods' => [ 'type' => 'list', 'member' => [ 'shape' => 'AllowedMethod', ], 'flattened' => true, ], 'AllowedOrigin' => [ 'type' => 'string', ], 'AllowedOrigins' => [ 'type' => 'list', 'member' => [ 'shape' => 'AllowedOrigin', ], 'flattened' => true, ], 'Body' => [ 'type' => 'blob', ], 'Bucket' => [ 'type' => 'structure', 'members' => [ 'Name' => [ 'shape' => 'BucketName', ], 'CreationDate' => [ 'shape' => 'CreationDate', ], ], ], 'BucketAlreadyExists' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'BucketCannedACL' => [ 'type' => 'string', 'enum' => [ 'private', 'public-read', 'public-read-write', 'authenticated-read', ], ], 'BucketLifecycleConfiguration' => [ 'type' => 'structure', 'required' => [ 'Rules', ], 'members' => [ 'Rules' => [ 'shape' => 'LifecycleRules', 'locationName' => 'Rule', ], ], ], 'BucketLocationConstraint' => [ 'type' => 'string', 'enum' => [ 'EU', 'eu-west-1', 'us-west-1', 'us-west-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'sa-east-1', 'cn-north-1', 'eu-central-1', ], ], 'BucketLoggingStatus' => [ 'type' => 'structure', 'members' => [ 'LoggingEnabled' => [ 'shape' => 'LoggingEnabled', ], ], ], 'BucketLogsPermission' => [ 'type' => 'string', 'enum' => [ 'FULL_CONTROL', 'READ', 'WRITE', ], ], 'BucketName' => [ 'type' => 'string', ], 'BucketVersioningStatus' => [ 'type' => 'string', 'enum' => [ 'Enabled', 'Suspended', ], ], 'Buckets' => [ 'type' => 'list', 'member' => [ 'shape' => 'Bucket', 'locationName' => 'Bucket', ], ], 'CORSConfiguration' => [ 'type' => 'structure', 'required' => [ 'CORSRules', ], 'members' => [ 'CORSRules' => [ 'shape' => 'CORSRules', 'locationName' => 'CORSRule', ], ], ], 'CORSRule' => [ 'type' => 'structure', 'required' => [ 'AllowedMethods', 'AllowedOrigins', ], 'members' => [ 'AllowedHeaders' => [ 'shape' => 'AllowedHeaders', 'locationName' => 'AllowedHeader', ], 'AllowedMethods' => [ 'shape' => 'AllowedMethods', 'locationName' => 'AllowedMethod', ], 'AllowedOrigins' => [ 'shape' => 'AllowedOrigins', 'locationName' => 'AllowedOrigin', ], 'ExposeHeaders' => [ 'shape' => 'ExposeHeaders', 'locationName' => 'ExposeHeader', ], 'MaxAgeSeconds' => [ 'shape' => 'MaxAgeSeconds', ], ], ], 'CORSRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'CORSRule', ], 'flattened' => true, ], 'CacheControl' => [ 'type' => 'string', ], 'CloudFunction' => [ 'type' => 'string', ], 'CloudFunctionConfiguration' => [ 'type' => 'structure', 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'Event' => [ 'shape' => 'Event', 'deprecated' => true, ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'CloudFunction' => [ 'shape' => 'CloudFunction', ], 'InvocationRole' => [ 'shape' => 'CloudFunctionInvocationRole', ], ], ], 'CloudFunctionInvocationRole' => [ 'type' => 'string', ], 'Code' => [ 'type' => 'string', ], 'CommonPrefix' => [ 'type' => 'structure', 'members' => [ 'Prefix' => [ 'shape' => 'Prefix', ], ], ], 'CommonPrefixList' => [ 'type' => 'list', 'member' => [ 'shape' => 'CommonPrefix', ], 'flattened' => true, ], 'CompleteMultipartUploadOutput' => [ 'type' => 'structure', 'members' => [ 'Location' => [ 'shape' => 'Location', ], 'Bucket' => [ 'shape' => 'BucketName', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'Expiration' => [ 'shape' => 'Expiration', 'location' => 'header', 'locationName' => 'x-amz-expiration', ], 'ETag' => [ 'shape' => 'ETag', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'CompleteMultipartUploadRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', 'UploadId', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'MultipartUpload' => [ 'shape' => 'CompletedMultipartUpload', 'locationName' => 'CompleteMultipartUpload', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'UploadId' => [ 'shape' => 'MultipartUploadId', 'location' => 'querystring', 'locationName' => 'uploadId', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'MultipartUpload', ], 'CompletedMultipartUpload' => [ 'type' => 'structure', 'members' => [ 'Parts' => [ 'shape' => 'CompletedPartList', 'locationName' => 'Part', ], ], ], 'CompletedPart' => [ 'type' => 'structure', 'members' => [ 'ETag' => [ 'shape' => 'ETag', ], 'PartNumber' => [ 'shape' => 'PartNumber', ], ], ], 'CompletedPartList' => [ 'type' => 'list', 'member' => [ 'shape' => 'CompletedPart', ], 'flattened' => true, ], 'Condition' => [ 'type' => 'structure', 'members' => [ 'HttpErrorCodeReturnedEquals' => [ 'shape' => 'HttpErrorCodeReturnedEquals', ], 'KeyPrefixEquals' => [ 'shape' => 'KeyPrefixEquals', ], ], ], 'ContentDisposition' => [ 'type' => 'string', ], 'ContentEncoding' => [ 'type' => 'string', ], 'ContentLanguage' => [ 'type' => 'string', ], 'ContentLength' => [ 'type' => 'integer', ], 'ContentMD5' => [ 'type' => 'string', ], 'ContentRange' => [ 'type' => 'string', ], 'ContentType' => [ 'type' => 'string', ], 'CopyObjectOutput' => [ 'type' => 'structure', 'members' => [ 'CopyObjectResult' => [ 'shape' => 'CopyObjectResult', ], 'Expiration' => [ 'shape' => 'Expiration', 'location' => 'header', 'locationName' => 'x-amz-expiration', ], 'CopySourceVersionId' => [ 'shape' => 'CopySourceVersionId', 'location' => 'header', 'locationName' => 'x-amz-copy-source-version-id', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], 'payload' => 'CopyObjectResult', ], 'CopyObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'CopySource', 'Key', ], 'members' => [ 'ACL' => [ 'shape' => 'ObjectCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CacheControl' => [ 'shape' => 'CacheControl', 'location' => 'header', 'locationName' => 'Cache-Control', ], 'ContentDisposition' => [ 'shape' => 'ContentDisposition', 'location' => 'header', 'locationName' => 'Content-Disposition', ], 'ContentEncoding' => [ 'shape' => 'ContentEncoding', 'location' => 'header', 'locationName' => 'Content-Encoding', ], 'ContentLanguage' => [ 'shape' => 'ContentLanguage', 'location' => 'header', 'locationName' => 'Content-Language', ], 'ContentType' => [ 'shape' => 'ContentType', 'location' => 'header', 'locationName' => 'Content-Type', ], 'CopySource' => [ 'shape' => 'CopySource', 'location' => 'header', 'locationName' => 'x-amz-copy-source', ], 'CopySourceIfMatch' => [ 'shape' => 'CopySourceIfMatch', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-match', ], 'CopySourceIfModifiedSince' => [ 'shape' => 'CopySourceIfModifiedSince', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-modified-since', ], 'CopySourceIfNoneMatch' => [ 'shape' => 'CopySourceIfNoneMatch', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-none-match', ], 'CopySourceIfUnmodifiedSince' => [ 'shape' => 'CopySourceIfUnmodifiedSince', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-unmodified-since', ], 'Expires' => [ 'shape' => 'Expires', 'location' => 'header', 'locationName' => 'Expires', ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'Metadata' => [ 'shape' => 'Metadata', 'location' => 'headers', 'locationName' => 'x-amz-meta-', ], 'MetadataDirective' => [ 'shape' => 'MetadataDirective', 'location' => 'header', 'locationName' => 'x-amz-metadata-directive', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'StorageClass' => [ 'shape' => 'StorageClass', 'location' => 'header', 'locationName' => 'x-amz-storage-class', ], 'WebsiteRedirectLocation' => [ 'shape' => 'WebsiteRedirectLocation', 'location' => 'header', 'locationName' => 'x-amz-website-redirect-location', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'CopySourceSSECustomerAlgorithm' => [ 'shape' => 'CopySourceSSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-algorithm', ], 'CopySourceSSECustomerKey' => [ 'shape' => 'CopySourceSSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-key', ], 'CopySourceSSECustomerKeyMD5' => [ 'shape' => 'CopySourceSSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-key-MD5', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'CopyObjectResult' => [ 'type' => 'structure', 'members' => [ 'ETag' => [ 'shape' => 'ETag', ], 'LastModified' => [ 'shape' => 'LastModified', ], ], ], 'CopyPartResult' => [ 'type' => 'structure', 'members' => [ 'ETag' => [ 'shape' => 'ETag', ], 'LastModified' => [ 'shape' => 'LastModified', ], ], ], 'CopySource' => [ 'type' => 'string', 'pattern' => '\\/.+\\/.+', ], 'CopySourceIfMatch' => [ 'type' => 'string', ], 'CopySourceIfModifiedSince' => [ 'type' => 'timestamp', ], 'CopySourceIfNoneMatch' => [ 'type' => 'string', ], 'CopySourceIfUnmodifiedSince' => [ 'type' => 'timestamp', ], 'CopySourceRange' => [ 'type' => 'string', ], 'CopySourceSSECustomerAlgorithm' => [ 'type' => 'string', ], 'CopySourceSSECustomerKey' => [ 'type' => 'string', 'sensitive' => true, ], 'CopySourceSSECustomerKeyMD5' => [ 'type' => 'string', ], 'CopySourceVersionId' => [ 'type' => 'string', ], 'CreateBucketConfiguration' => [ 'type' => 'structure', 'members' => [ 'LocationConstraint' => [ 'shape' => 'BucketLocationConstraint', ], ], ], 'CreateBucketOutput' => [ 'type' => 'structure', 'members' => [ 'Location' => [ 'shape' => 'Location', 'location' => 'header', 'locationName' => 'Location', ], ], ], 'CreateBucketRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'ACL' => [ 'shape' => 'BucketCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CreateBucketConfiguration' => [ 'shape' => 'CreateBucketConfiguration', 'locationName' => 'CreateBucketConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWrite' => [ 'shape' => 'GrantWrite', 'location' => 'header', 'locationName' => 'x-amz-grant-write', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], ], 'payload' => 'CreateBucketConfiguration', ], 'CreateMultipartUploadOutput' => [ 'type' => 'structure', 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'CreateMultipartUploadRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'ACL' => [ 'shape' => 'ObjectCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CacheControl' => [ 'shape' => 'CacheControl', 'location' => 'header', 'locationName' => 'Cache-Control', ], 'ContentDisposition' => [ 'shape' => 'ContentDisposition', 'location' => 'header', 'locationName' => 'Content-Disposition', ], 'ContentEncoding' => [ 'shape' => 'ContentEncoding', 'location' => 'header', 'locationName' => 'Content-Encoding', ], 'ContentLanguage' => [ 'shape' => 'ContentLanguage', 'location' => 'header', 'locationName' => 'Content-Language', ], 'ContentType' => [ 'shape' => 'ContentType', 'location' => 'header', 'locationName' => 'Content-Type', ], 'Expires' => [ 'shape' => 'Expires', 'location' => 'header', 'locationName' => 'Expires', ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'Metadata' => [ 'shape' => 'Metadata', 'location' => 'headers', 'locationName' => 'x-amz-meta-', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'StorageClass' => [ 'shape' => 'StorageClass', 'location' => 'header', 'locationName' => 'x-amz-storage-class', ], 'WebsiteRedirectLocation' => [ 'shape' => 'WebsiteRedirectLocation', 'location' => 'header', 'locationName' => 'x-amz-website-redirect-location', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'CreationDate' => [ 'type' => 'timestamp', ], 'Date' => [ 'type' => 'timestamp', 'timestampFormat' => 'iso8601', ], 'Days' => [ 'type' => 'integer', ], 'Delete' => [ 'type' => 'structure', 'required' => [ 'Objects', ], 'members' => [ 'Objects' => [ 'shape' => 'ObjectIdentifierList', 'locationName' => 'Object', ], 'Quiet' => [ 'shape' => 'Quiet', ], ], ], 'DeleteBucketCorsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketLifecycleRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketPolicyRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketReplicationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketTaggingRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketWebsiteRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteMarker' => [ 'type' => 'boolean', ], 'DeleteMarkerEntry' => [ 'type' => 'structure', 'members' => [ 'Owner' => [ 'shape' => 'Owner', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', ], 'IsLatest' => [ 'shape' => 'IsLatest', ], 'LastModified' => [ 'shape' => 'LastModified', ], ], ], 'DeleteMarkerVersionId' => [ 'type' => 'string', ], 'DeleteMarkers' => [ 'type' => 'list', 'member' => [ 'shape' => 'DeleteMarkerEntry', ], 'flattened' => true, ], 'DeleteObjectOutput' => [ 'type' => 'structure', 'members' => [ 'DeleteMarker' => [ 'shape' => 'DeleteMarker', 'location' => 'header', 'locationName' => 'x-amz-delete-marker', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'DeleteObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'MFA' => [ 'shape' => 'MFA', 'location' => 'header', 'locationName' => 'x-amz-mfa', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'querystring', 'locationName' => 'versionId', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'DeleteObjectsOutput' => [ 'type' => 'structure', 'members' => [ 'Deleted' => [ 'shape' => 'DeletedObjects', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], 'Errors' => [ 'shape' => 'Errors', 'locationName' => 'Error', ], ], ], 'DeleteObjectsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Delete', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Delete' => [ 'shape' => 'Delete', 'locationName' => 'Delete', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'MFA' => [ 'shape' => 'MFA', 'location' => 'header', 'locationName' => 'x-amz-mfa', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'Delete', ], 'DeletedObject' => [ 'type' => 'structure', 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', ], 'DeleteMarker' => [ 'shape' => 'DeleteMarker', ], 'DeleteMarkerVersionId' => [ 'shape' => 'DeleteMarkerVersionId', ], ], ], 'DeletedObjects' => [ 'type' => 'list', 'member' => [ 'shape' => 'DeletedObject', ], 'flattened' => true, ], 'Delimiter' => [ 'type' => 'string', ], 'Destination' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', ], 'StorageClass' => [ 'shape' => 'StorageClass', ], ], ], 'DisplayName' => [ 'type' => 'string', ], 'ETag' => [ 'type' => 'string', ], 'EmailAddress' => [ 'type' => 'string', ], 'EncodingType' => [ 'type' => 'string', 'enum' => [ 'url', ], ], 'Error' => [ 'type' => 'structure', 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', ], 'Code' => [ 'shape' => 'Code', ], 'Message' => [ 'shape' => 'Message', ], ], ], 'ErrorDocument' => [ 'type' => 'structure', 'required' => [ 'Key', ], 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], ], ], 'Errors' => [ 'type' => 'list', 'member' => [ 'shape' => 'Error', ], 'flattened' => true, ], 'Event' => [ 'type' => 'string', 'enum' => [ 's3:ReducedRedundancyLostObject', 's3:ObjectCreated:*', 's3:ObjectCreated:Put', 's3:ObjectCreated:Post', 's3:ObjectCreated:Copy', 's3:ObjectCreated:CompleteMultipartUpload', 's3:ObjectRemoved:*', 's3:ObjectRemoved:Delete', 's3:ObjectRemoved:DeleteMarkerCreated', ], ], 'EventList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Event', ], 'flattened' => true, ], 'Expiration' => [ 'type' => 'string', ], 'ExpirationStatus' => [ 'type' => 'string', 'enum' => [ 'Enabled', 'Disabled', ], ], 'Expires' => [ 'type' => 'timestamp', ], 'ExposeHeader' => [ 'type' => 'string', ], 'ExposeHeaders' => [ 'type' => 'list', 'member' => [ 'shape' => 'ExposeHeader', ], 'flattened' => true, ], 'FilterRule' => [ 'type' => 'structure', 'members' => [ 'Name' => [ 'shape' => 'FilterRuleName', ], 'Value' => [ 'shape' => 'FilterRuleValue', ], ], ], 'FilterRuleList' => [ 'type' => 'list', 'member' => [ 'shape' => 'FilterRule', ], 'flattened' => true, ], 'FilterRuleName' => [ 'type' => 'string', 'enum' => [ 'prefix', 'suffix', ], ], 'FilterRuleValue' => [ 'type' => 'string', ], 'GetBucketAclOutput' => [ 'type' => 'structure', 'members' => [ 'Owner' => [ 'shape' => 'Owner', ], 'Grants' => [ 'shape' => 'Grants', 'locationName' => 'AccessControlList', ], ], ], 'GetBucketAclRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketCorsOutput' => [ 'type' => 'structure', 'members' => [ 'CORSRules' => [ 'shape' => 'CORSRules', 'locationName' => 'CORSRule', ], ], ], 'GetBucketCorsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketLifecycleConfigurationOutput' => [ 'type' => 'structure', 'members' => [ 'Rules' => [ 'shape' => 'LifecycleRules', 'locationName' => 'Rule', ], ], ], 'GetBucketLifecycleConfigurationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketLifecycleOutput' => [ 'type' => 'structure', 'members' => [ 'Rules' => [ 'shape' => 'Rules', 'locationName' => 'Rule', ], ], ], 'GetBucketLifecycleRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketLocationOutput' => [ 'type' => 'structure', 'members' => [ 'LocationConstraint' => [ 'shape' => 'BucketLocationConstraint', ], ], ], 'GetBucketLocationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketLoggingOutput' => [ 'type' => 'structure', 'members' => [ 'LoggingEnabled' => [ 'shape' => 'LoggingEnabled', ], ], ], 'GetBucketLoggingRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketNotificationConfigurationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketPolicyOutput' => [ 'type' => 'structure', 'members' => [ 'Policy' => [ 'shape' => 'Policy', ], ], 'payload' => 'Policy', ], 'GetBucketPolicyRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketReplicationOutput' => [ 'type' => 'structure', 'members' => [ 'ReplicationConfiguration' => [ 'shape' => 'ReplicationConfiguration', ], ], 'payload' => 'ReplicationConfiguration', ], 'GetBucketReplicationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketRequestPaymentOutput' => [ 'type' => 'structure', 'members' => [ 'Payer' => [ 'shape' => 'Payer', ], ], ], 'GetBucketRequestPaymentRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketTaggingOutput' => [ 'type' => 'structure', 'required' => [ 'TagSet', ], 'members' => [ 'TagSet' => [ 'shape' => 'TagSet', ], ], ], 'GetBucketTaggingRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketVersioningOutput' => [ 'type' => 'structure', 'members' => [ 'Status' => [ 'shape' => 'BucketVersioningStatus', ], 'MFADelete' => [ 'shape' => 'MFADeleteStatus', 'locationName' => 'MfaDelete', ], ], ], 'GetBucketVersioningRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketWebsiteOutput' => [ 'type' => 'structure', 'members' => [ 'RedirectAllRequestsTo' => [ 'shape' => 'RedirectAllRequestsTo', ], 'IndexDocument' => [ 'shape' => 'IndexDocument', ], 'ErrorDocument' => [ 'shape' => 'ErrorDocument', ], 'RoutingRules' => [ 'shape' => 'RoutingRules', ], ], ], 'GetBucketWebsiteRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetObjectAclOutput' => [ 'type' => 'structure', 'members' => [ 'Owner' => [ 'shape' => 'Owner', ], 'Grants' => [ 'shape' => 'Grants', 'locationName' => 'AccessControlList', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'GetObjectAclRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'querystring', 'locationName' => 'versionId', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'GetObjectOutput' => [ 'type' => 'structure', 'members' => [ 'Body' => [ 'shape' => 'Body', 'streaming' => true, ], 'DeleteMarker' => [ 'shape' => 'DeleteMarker', 'location' => 'header', 'locationName' => 'x-amz-delete-marker', ], 'AcceptRanges' => [ 'shape' => 'AcceptRanges', 'location' => 'header', 'locationName' => 'accept-ranges', ], 'Expiration' => [ 'shape' => 'Expiration', 'location' => 'header', 'locationName' => 'x-amz-expiration', ], 'Restore' => [ 'shape' => 'Restore', 'location' => 'header', 'locationName' => 'x-amz-restore', ], 'LastModified' => [ 'shape' => 'LastModified', 'location' => 'header', 'locationName' => 'Last-Modified', ], 'ContentLength' => [ 'shape' => 'ContentLength', 'location' => 'header', 'locationName' => 'Content-Length', ], 'ETag' => [ 'shape' => 'ETag', 'location' => 'header', 'locationName' => 'ETag', ], 'MissingMeta' => [ 'shape' => 'MissingMeta', 'location' => 'header', 'locationName' => 'x-amz-missing-meta', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'CacheControl' => [ 'shape' => 'CacheControl', 'location' => 'header', 'locationName' => 'Cache-Control', ], 'ContentDisposition' => [ 'shape' => 'ContentDisposition', 'location' => 'header', 'locationName' => 'Content-Disposition', ], 'ContentEncoding' => [ 'shape' => 'ContentEncoding', 'location' => 'header', 'locationName' => 'Content-Encoding', ], 'ContentLanguage' => [ 'shape' => 'ContentLanguage', 'location' => 'header', 'locationName' => 'Content-Language', ], 'ContentRange' => [ 'shape' => 'ContentRange', 'location' => 'header', 'locationName' => 'Content-Range', ], 'ContentType' => [ 'shape' => 'ContentType', 'location' => 'header', 'locationName' => 'Content-Type', ], 'Expires' => [ 'shape' => 'Expires', 'location' => 'header', 'locationName' => 'Expires', ], 'WebsiteRedirectLocation' => [ 'shape' => 'WebsiteRedirectLocation', 'location' => 'header', 'locationName' => 'x-amz-website-redirect-location', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'Metadata' => [ 'shape' => 'Metadata', 'location' => 'headers', 'locationName' => 'x-amz-meta-', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'StorageClass' => [ 'shape' => 'StorageClass', 'location' => 'header', 'locationName' => 'x-amz-storage-class', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], 'ReplicationStatus' => [ 'shape' => 'ReplicationStatus', 'location' => 'header', 'locationName' => 'x-amz-replication-status', ], ], 'payload' => 'Body', ], 'GetObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'IfMatch' => [ 'shape' => 'IfMatch', 'location' => 'header', 'locationName' => 'If-Match', ], 'IfModifiedSince' => [ 'shape' => 'IfModifiedSince', 'location' => 'header', 'locationName' => 'If-Modified-Since', ], 'IfNoneMatch' => [ 'shape' => 'IfNoneMatch', 'location' => 'header', 'locationName' => 'If-None-Match', ], 'IfUnmodifiedSince' => [ 'shape' => 'IfUnmodifiedSince', 'location' => 'header', 'locationName' => 'If-Unmodified-Since', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'Range' => [ 'shape' => 'Range', 'location' => 'header', 'locationName' => 'Range', ], 'ResponseCacheControl' => [ 'shape' => 'ResponseCacheControl', 'location' => 'querystring', 'locationName' => 'response-cache-control', ], 'ResponseContentDisposition' => [ 'shape' => 'ResponseContentDisposition', 'location' => 'querystring', 'locationName' => 'response-content-disposition', ], 'ResponseContentEncoding' => [ 'shape' => 'ResponseContentEncoding', 'location' => 'querystring', 'locationName' => 'response-content-encoding', ], 'ResponseContentLanguage' => [ 'shape' => 'ResponseContentLanguage', 'location' => 'querystring', 'locationName' => 'response-content-language', ], 'ResponseContentType' => [ 'shape' => 'ResponseContentType', 'location' => 'querystring', 'locationName' => 'response-content-type', ], 'ResponseExpires' => [ 'shape' => 'ResponseExpires', 'location' => 'querystring', 'locationName' => 'response-expires', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'querystring', 'locationName' => 'versionId', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'GetObjectTorrentOutput' => [ 'type' => 'structure', 'members' => [ 'Body' => [ 'shape' => 'Body', 'streaming' => true, ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], 'payload' => 'Body', ], 'GetObjectTorrentRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'Grant' => [ 'type' => 'structure', 'members' => [ 'Grantee' => [ 'shape' => 'Grantee', ], 'Permission' => [ 'shape' => 'Permission', ], ], ], 'GrantFullControl' => [ 'type' => 'string', ], 'GrantRead' => [ 'type' => 'string', ], 'GrantReadACP' => [ 'type' => 'string', ], 'GrantWrite' => [ 'type' => 'string', ], 'GrantWriteACP' => [ 'type' => 'string', ], 'Grantee' => [ 'type' => 'structure', 'required' => [ 'Type', ], 'members' => [ 'DisplayName' => [ 'shape' => 'DisplayName', ], 'EmailAddress' => [ 'shape' => 'EmailAddress', ], 'ID' => [ 'shape' => 'ID', ], 'Type' => [ 'shape' => 'Type', 'locationName' => 'xsi:type', 'xmlAttribute' => true, ], 'URI' => [ 'shape' => 'URI', ], ], 'xmlNamespace' => [ 'prefix' => 'xsi', 'uri' => 'http://www.w3.org/2001/XMLSchema-instance', ], ], 'Grants' => [ 'type' => 'list', 'member' => [ 'shape' => 'Grant', 'locationName' => 'Grant', ], ], 'HeadBucketRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'HeadObjectOutput' => [ 'type' => 'structure', 'members' => [ 'DeleteMarker' => [ 'shape' => 'DeleteMarker', 'location' => 'header', 'locationName' => 'x-amz-delete-marker', ], 'AcceptRanges' => [ 'shape' => 'AcceptRanges', 'location' => 'header', 'locationName' => 'accept-ranges', ], 'Expiration' => [ 'shape' => 'Expiration', 'location' => 'header', 'locationName' => 'x-amz-expiration', ], 'Restore' => [ 'shape' => 'Restore', 'location' => 'header', 'locationName' => 'x-amz-restore', ], 'LastModified' => [ 'shape' => 'LastModified', 'location' => 'header', 'locationName' => 'Last-Modified', ], 'ContentLength' => [ 'shape' => 'ContentLength', 'location' => 'header', 'locationName' => 'Content-Length', ], 'ETag' => [ 'shape' => 'ETag', 'location' => 'header', 'locationName' => 'ETag', ], 'MissingMeta' => [ 'shape' => 'MissingMeta', 'location' => 'header', 'locationName' => 'x-amz-missing-meta', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'CacheControl' => [ 'shape' => 'CacheControl', 'location' => 'header', 'locationName' => 'Cache-Control', ], 'ContentDisposition' => [ 'shape' => 'ContentDisposition', 'location' => 'header', 'locationName' => 'Content-Disposition', ], 'ContentEncoding' => [ 'shape' => 'ContentEncoding', 'location' => 'header', 'locationName' => 'Content-Encoding', ], 'ContentLanguage' => [ 'shape' => 'ContentLanguage', 'location' => 'header', 'locationName' => 'Content-Language', ], 'ContentType' => [ 'shape' => 'ContentType', 'location' => 'header', 'locationName' => 'Content-Type', ], 'Expires' => [ 'shape' => 'Expires', 'location' => 'header', 'locationName' => 'Expires', ], 'WebsiteRedirectLocation' => [ 'shape' => 'WebsiteRedirectLocation', 'location' => 'header', 'locationName' => 'x-amz-website-redirect-location', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'Metadata' => [ 'shape' => 'Metadata', 'location' => 'headers', 'locationName' => 'x-amz-meta-', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'StorageClass' => [ 'shape' => 'StorageClass', 'location' => 'header', 'locationName' => 'x-amz-storage-class', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], 'ReplicationStatus' => [ 'shape' => 'ReplicationStatus', 'location' => 'header', 'locationName' => 'x-amz-replication-status', ], ], ], 'HeadObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'IfMatch' => [ 'shape' => 'IfMatch', 'location' => 'header', 'locationName' => 'If-Match', ], 'IfModifiedSince' => [ 'shape' => 'IfModifiedSince', 'location' => 'header', 'locationName' => 'If-Modified-Since', ], 'IfNoneMatch' => [ 'shape' => 'IfNoneMatch', 'location' => 'header', 'locationName' => 'If-None-Match', ], 'IfUnmodifiedSince' => [ 'shape' => 'IfUnmodifiedSince', 'location' => 'header', 'locationName' => 'If-Unmodified-Since', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'Range' => [ 'shape' => 'Range', 'location' => 'header', 'locationName' => 'Range', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'querystring', 'locationName' => 'versionId', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'HostName' => [ 'type' => 'string', ], 'HttpErrorCodeReturnedEquals' => [ 'type' => 'string', ], 'HttpRedirectCode' => [ 'type' => 'string', ], 'ID' => [ 'type' => 'string', ], 'IfMatch' => [ 'type' => 'string', ], 'IfModifiedSince' => [ 'type' => 'timestamp', ], 'IfNoneMatch' => [ 'type' => 'string', ], 'IfUnmodifiedSince' => [ 'type' => 'timestamp', ], 'IndexDocument' => [ 'type' => 'structure', 'required' => [ 'Suffix', ], 'members' => [ 'Suffix' => [ 'shape' => 'Suffix', ], ], ], 'Initiated' => [ 'type' => 'timestamp', ], 'Initiator' => [ 'type' => 'structure', 'members' => [ 'ID' => [ 'shape' => 'ID', ], 'DisplayName' => [ 'shape' => 'DisplayName', ], ], ], 'IsLatest' => [ 'type' => 'boolean', ], 'IsTruncated' => [ 'type' => 'boolean', ], 'KeyMarker' => [ 'type' => 'string', ], 'KeyPrefixEquals' => [ 'type' => 'string', ], 'LambdaFunctionArn' => [ 'type' => 'string', ], 'LambdaFunctionConfiguration' => [ 'type' => 'structure', 'required' => [ 'LambdaFunctionArn', 'Events', ], 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'LambdaFunctionArn' => [ 'shape' => 'LambdaFunctionArn', 'locationName' => 'CloudFunction', ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'Filter' => [ 'shape' => 'NotificationConfigurationFilter', ], ], ], 'LambdaFunctionConfigurationList' => [ 'type' => 'list', 'member' => [ 'shape' => 'LambdaFunctionConfiguration', ], 'flattened' => true, ], 'LastModified' => [ 'type' => 'timestamp', ], 'LifecycleConfiguration' => [ 'type' => 'structure', 'required' => [ 'Rules', ], 'members' => [ 'Rules' => [ 'shape' => 'Rules', 'locationName' => 'Rule', ], ], ], 'LifecycleExpiration' => [ 'type' => 'structure', 'members' => [ 'Date' => [ 'shape' => 'Date', ], 'Days' => [ 'shape' => 'Days', ], ], ], 'LifecycleRule' => [ 'type' => 'structure', 'required' => [ 'Prefix', 'Status', ], 'members' => [ 'Expiration' => [ 'shape' => 'LifecycleExpiration', ], 'ID' => [ 'shape' => 'ID', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Status' => [ 'shape' => 'ExpirationStatus', ], 'Transitions' => [ 'shape' => 'TransitionList', 'locationName' => 'Transition', ], 'NoncurrentVersionTransitions' => [ 'shape' => 'NoncurrentVersionTransitionList', 'locationName' => 'NoncurrentVersionTransition', ], 'NoncurrentVersionExpiration' => [ 'shape' => 'NoncurrentVersionExpiration', ], ], ], 'LifecycleRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'LifecycleRule', ], 'flattened' => true, ], 'ListBucketsOutput' => [ 'type' => 'structure', 'members' => [ 'Buckets' => [ 'shape' => 'Buckets', ], 'Owner' => [ 'shape' => 'Owner', ], ], ], 'ListMultipartUploadsOutput' => [ 'type' => 'structure', 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', ], 'KeyMarker' => [ 'shape' => 'KeyMarker', ], 'UploadIdMarker' => [ 'shape' => 'UploadIdMarker', ], 'NextKeyMarker' => [ 'shape' => 'NextKeyMarker', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Delimiter' => [ 'shape' => 'Delimiter', ], 'NextUploadIdMarker' => [ 'shape' => 'NextUploadIdMarker', ], 'MaxUploads' => [ 'shape' => 'MaxUploads', ], 'IsTruncated' => [ 'shape' => 'IsTruncated', ], 'Uploads' => [ 'shape' => 'MultipartUploadList', 'locationName' => 'Upload', ], 'CommonPrefixes' => [ 'shape' => 'CommonPrefixList', ], 'EncodingType' => [ 'shape' => 'EncodingType', ], ], ], 'ListMultipartUploadsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Delimiter' => [ 'shape' => 'Delimiter', 'location' => 'querystring', 'locationName' => 'delimiter', ], 'EncodingType' => [ 'shape' => 'EncodingType', 'location' => 'querystring', 'locationName' => 'encoding-type', ], 'KeyMarker' => [ 'shape' => 'KeyMarker', 'location' => 'querystring', 'locationName' => 'key-marker', ], 'MaxUploads' => [ 'shape' => 'MaxUploads', 'location' => 'querystring', 'locationName' => 'max-uploads', ], 'Prefix' => [ 'shape' => 'Prefix', 'location' => 'querystring', 'locationName' => 'prefix', ], 'UploadIdMarker' => [ 'shape' => 'UploadIdMarker', 'location' => 'querystring', 'locationName' => 'upload-id-marker', ], ], ], 'ListObjectVersionsOutput' => [ 'type' => 'structure', 'members' => [ 'IsTruncated' => [ 'shape' => 'IsTruncated', ], 'KeyMarker' => [ 'shape' => 'KeyMarker', ], 'VersionIdMarker' => [ 'shape' => 'VersionIdMarker', ], 'NextKeyMarker' => [ 'shape' => 'NextKeyMarker', ], 'NextVersionIdMarker' => [ 'shape' => 'NextVersionIdMarker', ], 'Versions' => [ 'shape' => 'ObjectVersionList', 'locationName' => 'Version', ], 'DeleteMarkers' => [ 'shape' => 'DeleteMarkers', 'locationName' => 'DeleteMarker', ], 'Name' => [ 'shape' => 'BucketName', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Delimiter' => [ 'shape' => 'Delimiter', ], 'MaxKeys' => [ 'shape' => 'MaxKeys', ], 'CommonPrefixes' => [ 'shape' => 'CommonPrefixList', ], 'EncodingType' => [ 'shape' => 'EncodingType', ], ], ], 'ListObjectVersionsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Delimiter' => [ 'shape' => 'Delimiter', 'location' => 'querystring', 'locationName' => 'delimiter', ], 'EncodingType' => [ 'shape' => 'EncodingType', 'location' => 'querystring', 'locationName' => 'encoding-type', ], 'KeyMarker' => [ 'shape' => 'KeyMarker', 'location' => 'querystring', 'locationName' => 'key-marker', ], 'MaxKeys' => [ 'shape' => 'MaxKeys', 'location' => 'querystring', 'locationName' => 'max-keys', ], 'Prefix' => [ 'shape' => 'Prefix', 'location' => 'querystring', 'locationName' => 'prefix', ], 'VersionIdMarker' => [ 'shape' => 'VersionIdMarker', 'location' => 'querystring', 'locationName' => 'version-id-marker', ], ], ], 'ListObjectsOutput' => [ 'type' => 'structure', 'members' => [ 'IsTruncated' => [ 'shape' => 'IsTruncated', ], 'Marker' => [ 'shape' => 'Marker', ], 'NextMarker' => [ 'shape' => 'NextMarker', ], 'Contents' => [ 'shape' => 'ObjectList', ], 'Name' => [ 'shape' => 'BucketName', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Delimiter' => [ 'shape' => 'Delimiter', ], 'MaxKeys' => [ 'shape' => 'MaxKeys', ], 'CommonPrefixes' => [ 'shape' => 'CommonPrefixList', ], 'EncodingType' => [ 'shape' => 'EncodingType', ], ], ], 'ListObjectsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Delimiter' => [ 'shape' => 'Delimiter', 'location' => 'querystring', 'locationName' => 'delimiter', ], 'EncodingType' => [ 'shape' => 'EncodingType', 'location' => 'querystring', 'locationName' => 'encoding-type', ], 'Marker' => [ 'shape' => 'Marker', 'location' => 'querystring', 'locationName' => 'marker', ], 'MaxKeys' => [ 'shape' => 'MaxKeys', 'location' => 'querystring', 'locationName' => 'max-keys', ], 'Prefix' => [ 'shape' => 'Prefix', 'location' => 'querystring', 'locationName' => 'prefix', ], ], ], 'ListPartsOutput' => [ 'type' => 'structure', 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', ], 'PartNumberMarker' => [ 'shape' => 'PartNumberMarker', ], 'NextPartNumberMarker' => [ 'shape' => 'NextPartNumberMarker', ], 'MaxParts' => [ 'shape' => 'MaxParts', ], 'IsTruncated' => [ 'shape' => 'IsTruncated', ], 'Parts' => [ 'shape' => 'Parts', 'locationName' => 'Part', ], 'Initiator' => [ 'shape' => 'Initiator', ], 'Owner' => [ 'shape' => 'Owner', ], 'StorageClass' => [ 'shape' => 'StorageClass', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'ListPartsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', 'UploadId', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'MaxParts' => [ 'shape' => 'MaxParts', 'location' => 'querystring', 'locationName' => 'max-parts', ], 'PartNumberMarker' => [ 'shape' => 'PartNumberMarker', 'location' => 'querystring', 'locationName' => 'part-number-marker', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', 'location' => 'querystring', 'locationName' => 'uploadId', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'Location' => [ 'type' => 'string', ], 'LoggingEnabled' => [ 'type' => 'structure', 'members' => [ 'TargetBucket' => [ 'shape' => 'TargetBucket', ], 'TargetGrants' => [ 'shape' => 'TargetGrants', ], 'TargetPrefix' => [ 'shape' => 'TargetPrefix', ], ], ], 'MFA' => [ 'type' => 'string', ], 'MFADelete' => [ 'type' => 'string', 'enum' => [ 'Enabled', 'Disabled', ], ], 'MFADeleteStatus' => [ 'type' => 'string', 'enum' => [ 'Enabled', 'Disabled', ], ], 'Marker' => [ 'type' => 'string', ], 'MaxAgeSeconds' => [ 'type' => 'integer', ], 'MaxKeys' => [ 'type' => 'integer', ], 'MaxParts' => [ 'type' => 'integer', ], 'MaxUploads' => [ 'type' => 'integer', ], 'Message' => [ 'type' => 'string', ], 'Metadata' => [ 'type' => 'map', 'key' => [ 'shape' => 'MetadataKey', ], 'value' => [ 'shape' => 'MetadataValue', ], ], 'MetadataDirective' => [ 'type' => 'string', 'enum' => [ 'COPY', 'REPLACE', ], ], 'MetadataKey' => [ 'type' => 'string', ], 'MetadataValue' => [ 'type' => 'string', ], 'MissingMeta' => [ 'type' => 'integer', ], 'MultipartUpload' => [ 'type' => 'structure', 'members' => [ 'UploadId' => [ 'shape' => 'MultipartUploadId', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'Initiated' => [ 'shape' => 'Initiated', ], 'StorageClass' => [ 'shape' => 'StorageClass', ], 'Owner' => [ 'shape' => 'Owner', ], 'Initiator' => [ 'shape' => 'Initiator', ], ], ], 'MultipartUploadId' => [ 'type' => 'string', ], 'MultipartUploadList' => [ 'type' => 'list', 'member' => [ 'shape' => 'MultipartUpload', ], 'flattened' => true, ], 'NextKeyMarker' => [ 'type' => 'string', ], 'NextMarker' => [ 'type' => 'string', ], 'NextPartNumberMarker' => [ 'type' => 'integer', ], 'NextUploadIdMarker' => [ 'type' => 'string', ], 'NextVersionIdMarker' => [ 'type' => 'string', ], 'NoSuchBucket' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchKey' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchUpload' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoncurrentVersionExpiration' => [ 'type' => 'structure', 'members' => [ 'NoncurrentDays' => [ 'shape' => 'Days', ], ], ], 'NoncurrentVersionTransition' => [ 'type' => 'structure', 'members' => [ 'NoncurrentDays' => [ 'shape' => 'Days', ], 'StorageClass' => [ 'shape' => 'TransitionStorageClass', ], ], ], 'NoncurrentVersionTransitionList' => [ 'type' => 'list', 'member' => [ 'shape' => 'NoncurrentVersionTransition', ], 'flattened' => true, ], 'NotificationConfiguration' => [ 'type' => 'structure', 'members' => [ 'TopicConfigurations' => [ 'shape' => 'TopicConfigurationList', 'locationName' => 'TopicConfiguration', ], 'QueueConfigurations' => [ 'shape' => 'QueueConfigurationList', 'locationName' => 'QueueConfiguration', ], 'LambdaFunctionConfigurations' => [ 'shape' => 'LambdaFunctionConfigurationList', 'locationName' => 'CloudFunctionConfiguration', ], ], ], 'NotificationConfigurationDeprecated' => [ 'type' => 'structure', 'members' => [ 'TopicConfiguration' => [ 'shape' => 'TopicConfigurationDeprecated', ], 'QueueConfiguration' => [ 'shape' => 'QueueConfigurationDeprecated', ], 'CloudFunctionConfiguration' => [ 'shape' => 'CloudFunctionConfiguration', ], ], ], 'NotificationConfigurationFilter' => [ 'type' => 'structure', 'members' => [ 'Key' => [ 'shape' => 'S3KeyFilter', 'locationName' => 'S3Key', ], ], ], 'NotificationId' => [ 'type' => 'string', ], 'Object' => [ 'type' => 'structure', 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], 'LastModified' => [ 'shape' => 'LastModified', ], 'ETag' => [ 'shape' => 'ETag', ], 'Size' => [ 'shape' => 'Size', ], 'StorageClass' => [ 'shape' => 'ObjectStorageClass', ], 'Owner' => [ 'shape' => 'Owner', ], ], ], 'ObjectAlreadyInActiveTierError' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'ObjectCannedACL' => [ 'type' => 'string', 'enum' => [ 'private', 'public-read', 'public-read-write', 'authenticated-read', 'aws-exec-read', 'bucket-owner-read', 'bucket-owner-full-control', ], ], 'ObjectIdentifier' => [ 'type' => 'structure', 'required' => [ 'Key', ], 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', ], ], ], 'ObjectIdentifierList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ObjectIdentifier', ], 'flattened' => true, ], 'ObjectKey' => [ 'type' => 'string', 'min' => 1, ], 'ObjectList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Object', ], 'flattened' => true, ], 'ObjectNotInActiveTierError' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'ObjectStorageClass' => [ 'type' => 'string', 'enum' => [ 'STANDARD', 'REDUCED_REDUNDANCY', 'GLACIER', ], ], 'ObjectVersion' => [ 'type' => 'structure', 'members' => [ 'ETag' => [ 'shape' => 'ETag', ], 'Size' => [ 'shape' => 'Size', ], 'StorageClass' => [ 'shape' => 'ObjectVersionStorageClass', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', ], 'IsLatest' => [ 'shape' => 'IsLatest', ], 'LastModified' => [ 'shape' => 'LastModified', ], 'Owner' => [ 'shape' => 'Owner', ], ], ], 'ObjectVersionId' => [ 'type' => 'string', ], 'ObjectVersionList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ObjectVersion', ], 'flattened' => true, ], 'ObjectVersionStorageClass' => [ 'type' => 'string', 'enum' => [ 'STANDARD', ], ], 'Owner' => [ 'type' => 'structure', 'members' => [ 'DisplayName' => [ 'shape' => 'DisplayName', ], 'ID' => [ 'shape' => 'ID', ], ], ], 'Part' => [ 'type' => 'structure', 'members' => [ 'PartNumber' => [ 'shape' => 'PartNumber', ], 'LastModified' => [ 'shape' => 'LastModified', ], 'ETag' => [ 'shape' => 'ETag', ], 'Size' => [ 'shape' => 'Size', ], ], ], 'PartNumber' => [ 'type' => 'integer', ], 'PartNumberMarker' => [ 'type' => 'integer', ], 'Parts' => [ 'type' => 'list', 'member' => [ 'shape' => 'Part', ], 'flattened' => true, ], 'Payer' => [ 'type' => 'string', 'enum' => [ 'Requester', 'BucketOwner', ], ], 'Permission' => [ 'type' => 'string', 'enum' => [ 'FULL_CONTROL', 'WRITE', 'WRITE_ACP', 'READ', 'READ_ACP', ], ], 'Policy' => [ 'type' => 'string', ], 'Prefix' => [ 'type' => 'string', ], 'Protocol' => [ 'type' => 'string', 'enum' => [ 'http', 'https', ], ], 'PutBucketAclRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'ACL' => [ 'shape' => 'BucketCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'AccessControlPolicy' => [ 'shape' => 'AccessControlPolicy', 'locationName' => 'AccessControlPolicy', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWrite' => [ 'shape' => 'GrantWrite', 'location' => 'header', 'locationName' => 'x-amz-grant-write', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], ], 'payload' => 'AccessControlPolicy', ], 'PutBucketCorsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'CORSConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CORSConfiguration' => [ 'shape' => 'CORSConfiguration', 'locationName' => 'CORSConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], ], 'payload' => 'CORSConfiguration', ], 'PutBucketLifecycleConfigurationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'LifecycleConfiguration' => [ 'shape' => 'BucketLifecycleConfiguration', 'locationName' => 'LifecycleConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'LifecycleConfiguration', ], 'PutBucketLifecycleRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'LifecycleConfiguration' => [ 'shape' => 'LifecycleConfiguration', 'locationName' => 'LifecycleConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'LifecycleConfiguration', ], 'PutBucketLoggingRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'BucketLoggingStatus', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'BucketLoggingStatus' => [ 'shape' => 'BucketLoggingStatus', 'locationName' => 'BucketLoggingStatus', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], ], 'payload' => 'BucketLoggingStatus', ], 'PutBucketNotificationConfigurationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'NotificationConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'NotificationConfiguration' => [ 'shape' => 'NotificationConfiguration', 'locationName' => 'NotificationConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'NotificationConfiguration', ], 'PutBucketNotificationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'NotificationConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'NotificationConfiguration' => [ 'shape' => 'NotificationConfigurationDeprecated', 'locationName' => 'NotificationConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'NotificationConfiguration', ], 'PutBucketPolicyRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Policy', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'Policy' => [ 'shape' => 'Policy', ], ], 'payload' => 'Policy', ], 'PutBucketReplicationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'ReplicationConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'ReplicationConfiguration' => [ 'shape' => 'ReplicationConfiguration', 'locationName' => 'ReplicationConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'ReplicationConfiguration', ], 'PutBucketRequestPaymentRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'RequestPaymentConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'RequestPaymentConfiguration' => [ 'shape' => 'RequestPaymentConfiguration', 'locationName' => 'RequestPaymentConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'RequestPaymentConfiguration', ], 'PutBucketTaggingRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Tagging', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'Tagging' => [ 'shape' => 'Tagging', 'locationName' => 'Tagging', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'Tagging', ], 'PutBucketVersioningRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'VersioningConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'MFA' => [ 'shape' => 'MFA', 'location' => 'header', 'locationName' => 'x-amz-mfa', ], 'VersioningConfiguration' => [ 'shape' => 'VersioningConfiguration', 'locationName' => 'VersioningConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'VersioningConfiguration', ], 'PutBucketWebsiteRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'WebsiteConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'WebsiteConfiguration' => [ 'shape' => 'WebsiteConfiguration', 'locationName' => 'WebsiteConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'WebsiteConfiguration', ], 'PutObjectAclOutput' => [ 'type' => 'structure', 'members' => [ 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'PutObjectAclRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'ACL' => [ 'shape' => 'ObjectCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'AccessControlPolicy' => [ 'shape' => 'AccessControlPolicy', 'locationName' => 'AccessControlPolicy', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWrite' => [ 'shape' => 'GrantWrite', 'location' => 'header', 'locationName' => 'x-amz-grant-write', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'AccessControlPolicy', ], 'PutObjectOutput' => [ 'type' => 'structure', 'members' => [ 'Expiration' => [ 'shape' => 'Expiration', 'location' => 'header', 'locationName' => 'x-amz-expiration', ], 'ETag' => [ 'shape' => 'ETag', 'location' => 'header', 'locationName' => 'ETag', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'PutObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'ACL' => [ 'shape' => 'ObjectCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'Body' => [ 'shape' => 'Body', 'streaming' => true, ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CacheControl' => [ 'shape' => 'CacheControl', 'location' => 'header', 'locationName' => 'Cache-Control', ], 'ContentDisposition' => [ 'shape' => 'ContentDisposition', 'location' => 'header', 'locationName' => 'Content-Disposition', ], 'ContentEncoding' => [ 'shape' => 'ContentEncoding', 'location' => 'header', 'locationName' => 'Content-Encoding', ], 'ContentLanguage' => [ 'shape' => 'ContentLanguage', 'location' => 'header', 'locationName' => 'Content-Language', ], 'ContentLength' => [ 'shape' => 'ContentLength', 'location' => 'header', 'locationName' => 'Content-Length', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'ContentType' => [ 'shape' => 'ContentType', 'location' => 'header', 'locationName' => 'Content-Type', ], 'Expires' => [ 'shape' => 'Expires', 'location' => 'header', 'locationName' => 'Expires', ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'Metadata' => [ 'shape' => 'Metadata', 'location' => 'headers', 'locationName' => 'x-amz-meta-', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'StorageClass' => [ 'shape' => 'StorageClass', 'location' => 'header', 'locationName' => 'x-amz-storage-class', ], 'WebsiteRedirectLocation' => [ 'shape' => 'WebsiteRedirectLocation', 'location' => 'header', 'locationName' => 'x-amz-website-redirect-location', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'Body', ], 'QueueArn' => [ 'type' => 'string', ], 'QueueConfiguration' => [ 'type' => 'structure', 'required' => [ 'QueueArn', 'Events', ], 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'QueueArn' => [ 'shape' => 'QueueArn', 'locationName' => 'Queue', ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'Filter' => [ 'shape' => 'NotificationConfigurationFilter', ], ], ], 'QueueConfigurationDeprecated' => [ 'type' => 'structure', 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'Event' => [ 'shape' => 'Event', 'deprecated' => true, ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'Queue' => [ 'shape' => 'QueueArn', ], ], ], 'QueueConfigurationList' => [ 'type' => 'list', 'member' => [ 'shape' => 'QueueConfiguration', ], 'flattened' => true, ], 'Quiet' => [ 'type' => 'boolean', ], 'Range' => [ 'type' => 'string', ], 'Redirect' => [ 'type' => 'structure', 'members' => [ 'HostName' => [ 'shape' => 'HostName', ], 'HttpRedirectCode' => [ 'shape' => 'HttpRedirectCode', ], 'Protocol' => [ 'shape' => 'Protocol', ], 'ReplaceKeyPrefixWith' => [ 'shape' => 'ReplaceKeyPrefixWith', ], 'ReplaceKeyWith' => [ 'shape' => 'ReplaceKeyWith', ], ], ], 'RedirectAllRequestsTo' => [ 'type' => 'structure', 'required' => [ 'HostName', ], 'members' => [ 'HostName' => [ 'shape' => 'HostName', ], 'Protocol' => [ 'shape' => 'Protocol', ], ], ], 'ReplaceKeyPrefixWith' => [ 'type' => 'string', ], 'ReplaceKeyWith' => [ 'type' => 'string', ], 'ReplicationConfiguration' => [ 'type' => 'structure', 'required' => [ 'Role', 'Rules', ], 'members' => [ 'Role' => [ 'shape' => 'Role', ], 'Rules' => [ 'shape' => 'ReplicationRules', 'locationName' => 'Rule', ], ], ], 'ReplicationRule' => [ 'type' => 'structure', 'required' => [ 'Prefix', 'Status', 'Destination', ], 'members' => [ 'ID' => [ 'shape' => 'ID', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Status' => [ 'shape' => 'ReplicationRuleStatus', ], 'Destination' => [ 'shape' => 'Destination', ], ], ], 'ReplicationRuleStatus' => [ 'type' => 'string', 'enum' => [ 'Enabled', 'Disabled', ], ], 'ReplicationRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'ReplicationRule', ], 'flattened' => true, ], 'ReplicationStatus' => [ 'type' => 'string', 'enum' => [ 'COMPLETE', 'PENDING', 'FAILED', 'REPLICA', ], ], 'RequestCharged' => [ 'type' => 'string', 'enum' => [ 'requester', ], ], 'RequestPayer' => [ 'type' => 'string', 'enum' => [ 'requester', ], ], 'RequestPaymentConfiguration' => [ 'type' => 'structure', 'required' => [ 'Payer', ], 'members' => [ 'Payer' => [ 'shape' => 'Payer', ], ], ], 'ResponseCacheControl' => [ 'type' => 'string', ], 'ResponseContentDisposition' => [ 'type' => 'string', ], 'ResponseContentEncoding' => [ 'type' => 'string', ], 'ResponseContentLanguage' => [ 'type' => 'string', ], 'ResponseContentType' => [ 'type' => 'string', ], 'ResponseExpires' => [ 'type' => 'timestamp', ], 'Restore' => [ 'type' => 'string', ], 'RestoreObjectOutput' => [ 'type' => 'structure', 'members' => [ 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'RestoreObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'querystring', 'locationName' => 'versionId', ], 'RestoreRequest' => [ 'shape' => 'RestoreRequest', 'locationName' => 'RestoreRequest', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'RestoreRequest', ], 'RestoreRequest' => [ 'type' => 'structure', 'required' => [ 'Days', ], 'members' => [ 'Days' => [ 'shape' => 'Days', ], ], ], 'Role' => [ 'type' => 'string', ], 'RoutingRule' => [ 'type' => 'structure', 'required' => [ 'Redirect', ], 'members' => [ 'Condition' => [ 'shape' => 'Condition', ], 'Redirect' => [ 'shape' => 'Redirect', ], ], ], 'RoutingRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'RoutingRule', 'locationName' => 'RoutingRule', ], ], 'Rule' => [ 'type' => 'structure', 'required' => [ 'Prefix', 'Status', ], 'members' => [ 'Expiration' => [ 'shape' => 'LifecycleExpiration', ], 'ID' => [ 'shape' => 'ID', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Status' => [ 'shape' => 'ExpirationStatus', ], 'Transition' => [ 'shape' => 'Transition', ], 'NoncurrentVersionTransition' => [ 'shape' => 'NoncurrentVersionTransition', ], 'NoncurrentVersionExpiration' => [ 'shape' => 'NoncurrentVersionExpiration', ], ], ], 'Rules' => [ 'type' => 'list', 'member' => [ 'shape' => 'Rule', ], 'flattened' => true, ], 'S3KeyFilter' => [ 'type' => 'structure', 'members' => [ 'FilterRules' => [ 'shape' => 'FilterRuleList', 'locationName' => 'FilterRule', ], ], ], 'SSECustomerAlgorithm' => [ 'type' => 'string', ], 'SSECustomerKey' => [ 'type' => 'string', 'sensitive' => true, ], 'SSECustomerKeyMD5' => [ 'type' => 'string', ], 'SSEKMSKeyId' => [ 'type' => 'string', 'sensitive' => true, ], 'ServerSideEncryption' => [ 'type' => 'string', 'enum' => [ 'AES256', 'aws:kms', ], ], 'Size' => [ 'type' => 'integer', ], 'StorageClass' => [ 'type' => 'string', 'enum' => [ 'STANDARD', 'REDUCED_REDUNDANCY', 'STANDARD_IA', ], ], 'Suffix' => [ 'type' => 'string', ], 'Tag' => [ 'type' => 'structure', 'required' => [ 'Key', 'Value', ], 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], 'Value' => [ 'shape' => 'Value', ], ], ], 'TagSet' => [ 'type' => 'list', 'member' => [ 'shape' => 'Tag', 'locationName' => 'Tag', ], ], 'Tagging' => [ 'type' => 'structure', 'required' => [ 'TagSet', ], 'members' => [ 'TagSet' => [ 'shape' => 'TagSet', ], ], ], 'TargetBucket' => [ 'type' => 'string', ], 'TargetGrant' => [ 'type' => 'structure', 'members' => [ 'Grantee' => [ 'shape' => 'Grantee', ], 'Permission' => [ 'shape' => 'BucketLogsPermission', ], ], ], 'TargetGrants' => [ 'type' => 'list', 'member' => [ 'shape' => 'TargetGrant', 'locationName' => 'Grant', ], ], 'TargetPrefix' => [ 'type' => 'string', ], 'TopicArn' => [ 'type' => 'string', ], 'TopicConfiguration' => [ 'type' => 'structure', 'required' => [ 'TopicArn', 'Events', ], 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'TopicArn' => [ 'shape' => 'TopicArn', 'locationName' => 'Topic', ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'Filter' => [ 'shape' => 'NotificationConfigurationFilter', ], ], ], 'TopicConfigurationDeprecated' => [ 'type' => 'structure', 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'Event' => [ 'shape' => 'Event', 'deprecated' => true, ], 'Topic' => [ 'shape' => 'TopicArn', ], ], ], 'TopicConfigurationList' => [ 'type' => 'list', 'member' => [ 'shape' => 'TopicConfiguration', ], 'flattened' => true, ], 'Transition' => [ 'type' => 'structure', 'members' => [ 'Date' => [ 'shape' => 'Date', ], 'Days' => [ 'shape' => 'Days', ], 'StorageClass' => [ 'shape' => 'TransitionStorageClass', ], ], ], 'TransitionList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Transition', ], 'flattened' => true, ], 'TransitionStorageClass' => [ 'type' => 'string', 'enum' => [ 'GLACIER', 'STANDARD_IA', ], ], 'Type' => [ 'type' => 'string', 'enum' => [ 'CanonicalUser', 'AmazonCustomerByEmail', 'Group', ], ], 'URI' => [ 'type' => 'string', ], 'UploadIdMarker' => [ 'type' => 'string', ], 'UploadPartCopyOutput' => [ 'type' => 'structure', 'members' => [ 'CopySourceVersionId' => [ 'shape' => 'CopySourceVersionId', 'location' => 'header', 'locationName' => 'x-amz-copy-source-version-id', ], 'CopyPartResult' => [ 'shape' => 'CopyPartResult', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], 'payload' => 'CopyPartResult', ], 'UploadPartCopyRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'CopySource', 'Key', 'PartNumber', 'UploadId', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CopySource' => [ 'shape' => 'CopySource', 'location' => 'header', 'locationName' => 'x-amz-copy-source', ], 'CopySourceIfMatch' => [ 'shape' => 'CopySourceIfMatch', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-match', ], 'CopySourceIfModifiedSince' => [ 'shape' => 'CopySourceIfModifiedSince', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-modified-since', ], 'CopySourceIfNoneMatch' => [ 'shape' => 'CopySourceIfNoneMatch', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-none-match', ], 'CopySourceIfUnmodifiedSince' => [ 'shape' => 'CopySourceIfUnmodifiedSince', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-unmodified-since', ], 'CopySourceRange' => [ 'shape' => 'CopySourceRange', 'location' => 'header', 'locationName' => 'x-amz-copy-source-range', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'PartNumber' => [ 'shape' => 'PartNumber', 'location' => 'querystring', 'locationName' => 'partNumber', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', 'location' => 'querystring', 'locationName' => 'uploadId', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'CopySourceSSECustomerAlgorithm' => [ 'shape' => 'CopySourceSSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-algorithm', ], 'CopySourceSSECustomerKey' => [ 'shape' => 'CopySourceSSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-key', ], 'CopySourceSSECustomerKeyMD5' => [ 'shape' => 'CopySourceSSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-key-MD5', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'UploadPartOutput' => [ 'type' => 'structure', 'members' => [ 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'ETag' => [ 'shape' => 'ETag', 'location' => 'header', 'locationName' => 'ETag', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'UploadPartRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', 'PartNumber', 'UploadId', ], 'members' => [ 'Body' => [ 'shape' => 'Body', 'streaming' => true, ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentLength' => [ 'shape' => 'ContentLength', 'location' => 'header', 'locationName' => 'Content-Length', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'PartNumber' => [ 'shape' => 'PartNumber', 'location' => 'querystring', 'locationName' => 'partNumber', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', 'location' => 'querystring', 'locationName' => 'uploadId', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'Body', ], 'Value' => [ 'type' => 'string', ], 'VersionIdMarker' => [ 'type' => 'string', ], 'VersioningConfiguration' => [ 'type' => 'structure', 'members' => [ 'MFADelete' => [ 'shape' => 'MFADelete', 'locationName' => 'MfaDelete', ], 'Status' => [ 'shape' => 'BucketVersioningStatus', ], ], ], 'WebsiteConfiguration' => [ 'type' => 'structure', 'members' => [ 'ErrorDocument' => [ 'shape' => 'ErrorDocument', ], 'IndexDocument' => [ 'shape' => 'IndexDocument', ], 'RedirectAllRequestsTo' => [ 'shape' => 'RedirectAllRequestsTo', ], 'RoutingRules' => [ 'shape' => 'RoutingRules', ], ], ], 'WebsiteRedirectLocation' => [ 'type' => 'string', ], ],];
includes/aws/Aws/data/s3/2006-03-01/paginators-1.json.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ // This file was auto-generated from sdk-root/src/data/s3/2006-03-01/paginators-1.json
3
+ return [ 'pagination' => [ 'ListBuckets' => [ 'result_key' => 'Buckets', ], 'ListMultipartUploads' => [ 'input_token' => [ 'KeyMarker', 'UploadIdMarker', ], 'limit_key' => 'MaxUploads', 'more_results' => 'IsTruncated', 'output_token' => [ 'NextKeyMarker', 'NextUploadIdMarker', ], 'result_key' => [ 'Uploads', 'CommonPrefixes', ], ], 'ListObjectVersions' => [ 'input_token' => [ 'KeyMarker', 'VersionIdMarker', ], 'limit_key' => 'MaxKeys', 'more_results' => 'IsTruncated', 'output_token' => [ 'NextKeyMarker', 'NextVersionIdMarker', ], 'result_key' => [ 'Versions', 'DeleteMarkers', 'CommonPrefixes', ], ], 'ListObjects' => [ 'input_token' => 'Marker', 'limit_key' => 'MaxKeys', 'more_results' => 'IsTruncated', 'output_token' => 'NextMarker || Contents[-1].Key', 'result_key' => [ 'Contents', 'CommonPrefixes', ], ], 'ListParts' => [ 'input_token' => 'PartNumberMarker', 'limit_key' => 'MaxParts', 'more_results' => 'IsTruncated', 'output_token' => 'NextPartNumberMarker', 'result_key' => 'Parts', ], ],];
includes/aws/Aws/data/s3/2006-03-01/waiters-2.json.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ // This file was auto-generated from sdk-root/src/data/s3/2006-03-01/waiters-2.json
3
+ return [ 'version' => 2, 'waiters' => [ 'BucketExists' => [ 'acceptors' => [ [ 'expected' => 200, 'matcher' => 'status', 'state' => 'success', ], [ 'expected' => 403, 'matcher' => 'status', 'state' => 'success', ], [ 'expected' => 404, 'matcher' => 'status', 'state' => 'retry', ], ], 'delay' => 5, 'maxAttempts' => 20, 'operation' => 'HeadBucket', ], 'BucketNotExists' => [ 'acceptors' => [ [ 'expected' => 404, 'matcher' => 'status', 'state' => 'success', ], ], 'delay' => 5, 'maxAttempts' => 20, 'operation' => 'HeadBucket', ], 'ObjectExists' => [ 'acceptors' => [ [ 'expected' => 200, 'matcher' => 'status', 'state' => 'success', ], [ 'expected' => 404, 'matcher' => 'status', 'state' => 'retry', ], ], 'delay' => 5, 'maxAttempts' => 20, 'operation' => 'HeadObject', ], 'ObjectNotExists' => [ 'acceptors' => [ [ 'expected' => 404, 'matcher' => 'status', 'state' => 'success', ], ], 'delay' => 5, 'maxAttempts' => 20, 'operation' => 'HeadObject', ], ],];
includes/aws/Aws/functions.php ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Aws;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+ use GuzzleHttp\ClientInterface;
6
+ use GuzzleHttp\Promise\FulfilledPromise;
7
+
8
+ //-----------------------------------------------------------------------------
9
+ // Functional functions
10
+ //-----------------------------------------------------------------------------
11
+
12
+ /**
13
+ * Returns a function that always returns the same value;
14
+ *
15
+ * @param mixed $value Value to return.
16
+ *
17
+ * @return callable
18
+ */
19
+ function constantly($value)
20
+ {
21
+ return function () use ($value) { return $value; };
22
+ }
23
+
24
+ /**
25
+ * Filters values that do not satisfy the predicate function $pred.
26
+ *
27
+ * @param mixed $iterable Iterable sequence of data.
28
+ * @param callable $pred Function that accepts a value and returns true/false
29
+ *
30
+ * @return \Generator
31
+ */
32
+ function filter($iterable, callable $pred)
33
+ {
34
+ foreach ($iterable as $value) {
35
+ if ($pred($value)) {
36
+ yield $value;
37
+ }
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Applies a map function $f to each value in a collection.
43
+ *
44
+ * @param mixed $iterable Iterable sequence of data.
45
+ * @param callable $f Map function to apply.
46
+ *
47
+ * @return \Generator
48
+ */
49
+ function map($iterable, callable $f)
50
+ {
51
+ foreach ($iterable as $value) {
52
+ yield $f($value);
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Creates a generator that iterates over a sequence, then iterates over each
58
+ * value in the sequence and yields the application of the map function to each
59
+ * value.
60
+ *
61
+ * @param mixed $iterable Iterable sequence of data.
62
+ * @param callable $f Map function to apply.
63
+ *
64
+ * @return \Generator
65
+ */
66
+ function flatmap($iterable, callable $f)
67
+ {
68
+ foreach (map($iterable, $f) as $outer) {
69
+ foreach ($outer as $inner) {
70
+ yield $inner;
71
+ }
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Partitions the input sequence into partitions of the specified size.
77
+ *
78
+ * @param mixed $iterable Iterable sequence of data.
79
+ * @param int $size Size to make each partition (except possibly the last chunk)
80
+ *
81
+ * @return \Generator
82
+ */
83
+ function partition($iterable, $size)
84
+ {
85
+ $buffer = [];
86
+ foreach ($iterable as $value) {
87
+ $buffer[] = $value;
88
+ if (count($buffer) === $size) {
89
+ yield $buffer;
90
+ $buffer = [];
91
+ }
92
+ }
93
+
94
+ if ($buffer) {
95
+ yield $buffer;
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Returns a function that invokes the provided variadic functions one
101
+ * after the other until one of the functions returns a non-null value.
102
+ * The return function will call each passed function with any arguments it
103
+ * is provided.
104
+ *
105
+ * $a = function ($x, $y) { return null; };
106
+ * $b = function ($x, $y) { return $x + $y; };
107
+ * $fn = \Aws\or_chain($a, $b);
108
+ * echo $fn(1, 2); // 3
109
+ *
110
+ * @return callable
111
+ */
112
+ function or_chain()
113
+ {
114
+ $fns = func_get_args();
115
+ return function () use ($fns) {
116
+ $args = func_get_args();
117
+ foreach ($fns as $fn) {
118
+ $result = $args ? call_user_func_array($fn, $args) : $fn();
119
+ if ($result) {
120
+ return $result;
121
+ }
122
+ }
123
+ return null;
124
+ };
125
+ }
126
+
127
+ //-----------------------------------------------------------------------------
128
+ // JSON compiler and loading functions
129
+ //-----------------------------------------------------------------------------
130
+
131
+ /**
132
+ * Loads a compiled JSON file from a PHP file.
133
+ *
134
+ * If the JSON file has not been cached to disk as a PHP file, it will be loaded
135
+ * from the JSON source file and returned.
136
+ *
137
+ * @param string $path Path to the JSON file on disk
138
+ *
139
+ * @return mixed Returns the JSON decoded data. Note that JSON objects are
140
+ * decoded as associative arrays.
141
+ */
142
+ function load_compiled_json($path)
143
+ {
144
+ if ($compiled = @include("$path.php")) {
145
+ return $compiled;
146
+ }
147
+
148
+ if (!file_exists($path)) {
149
+ throw new \InvalidArgumentException(
150
+ sprintf("File not found: %s", $path)
151
+ );
152
+ }
153
+
154
+ return json_decode(file_get_contents($path), true);
155
+ }
156
+
157
+ /**
158
+ * No-op
159
+ */
160
+ function clear_compiled_json()
161
+ {
162
+ // pass
163
+ }
164
+
165
+ //-----------------------------------------------------------------------------
166
+ // Directory iterator functions.
167
+ //-----------------------------------------------------------------------------
168
+
169
+ /**
170
+ * Iterates over the files in a directory and works with custom wrappers.
171
+ *
172
+ * @param string $path Path to open (e.g., "s3://foo/bar").
173
+ * @param resource $context Stream wrapper context.
174
+ *
175
+ * @return \Generator Yields relative filename strings.
176
+ */
177
+ function dir_iterator($path, $context = null)
178
+ {
179
+ $dh = $context ? opendir($path, $context) : opendir($path);
180
+ if (!$dh) {
181
+ throw new \InvalidArgumentException('File not found: ' . $path);
182
+ }
183
+ while (($file = readdir($dh)) !== false) {
184
+ yield $file;
185
+ }
186
+ closedir($dh);
187
+ }
188
+
189
+ /**
190
+ * Returns a recursive directory iterator that yields absolute filenames.
191
+ *
192
+ * This iterator is not broken like PHP's built-in DirectoryIterator (which
193
+ * will read the first file from a stream wrapper, then rewind, then read
194
+ * it again).
195
+ *
196
+ * @param string $path Path to traverse (e.g., s3://bucket/key, /tmp)
197
+ * @param resource $context Stream context options.
198
+ *
199
+ * @return \Generator Yields absolute filenames.
200
+ */
201
+ function recursive_dir_iterator($path, $context = null)
202
+ {
203
+ $invalid = ['.' => true, '..' => true];
204
+ $pathLen = strlen($path) + 1;
205
+ $iterator = dir_iterator($path, $context);
206
+ $queue = [];
207
+ do {
208
+ while ($iterator->valid()) {
209
+ $file = $iterator->current();
210
+ $iterator->next();
211
+ if (isset($invalid[basename($file)])) {
212
+ continue;
213
+ }
214
+ $fullPath = "{$path}/{$file}";
215
+ yield $fullPath;
216
+ if (is_dir($fullPath)) {
217
+ $queue[] = $iterator;
218
+ $iterator = map(
219
+ dir_iterator($fullPath, $context),
220
+ function ($file) use ($fullPath, $pathLen) {
221
+ return substr("{$fullPath}/{$file}", $pathLen);
222
+ }
223
+ );
224
+ continue;
225
+ }
226
+ }
227
+ $iterator = array_pop($queue);
228
+ } while ($iterator);
229
+ }
230
+
231
+ //-----------------------------------------------------------------------------
232
+ // Misc. functions.
233
+ //-----------------------------------------------------------------------------
234
+
235
+ /**
236
+ * Debug function used to describe the provided value type and class.
237
+ *
238
+ * @param mixed $input
239
+ *
240
+ * @return string Returns a string containing the type of the variable and
241
+ * if a class is provided, the class name.
242
+ */
243
+ function describe_type($input)
244
+ {
245
+ switch (gettype($input)) {
246
+ case 'object':
247
+ return 'object(' . get_class($input) . ')';
248
+ case 'array':
249
+ return 'array(' . count($input) . ')';
250
+ default:
251
+ ob_start();
252
+ var_dump($input);
253
+ // normalize float vs double
254
+ return str_replace('double(', 'float(', rtrim(ob_get_clean()));
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Creates a default HTTP handler based on the available clients.
260
+ *
261
+ * @return callable
262
+ */
263
+ function default_http_handler()
264
+ {
265
+ $version = (string) ClientInterface::VERSION;
266
+ if ($version[0] === '5') {
267
+ return new \Aws\Handler\GuzzleV5\GuzzleHandler();
268
+ } elseif ($version[0] === '6') {
269
+ return new \Aws\Handler\GuzzleV6\GuzzleHandler();
270
+ } else {
271
+ throw new \RuntimeException('Unknown Guzzle version: ' . $version);
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Serialize a request for a command but do not send it.
277
+ *
278
+ * Returns a promise that is fulfilled with the serialized request.
279
+ *
280
+ * @param CommandInterface $command Command to serialize.
281
+ *
282
+ * @return RequestInterface
283
+ * @throws \RuntimeException
284
+ */
285
+ function serialize(CommandInterface $command)
286
+ {
287
+ $request = null;
288
+ $handlerList = $command->getHandlerList();
289
+
290
+ // Return a mock result.
291
+ $handlerList->setHandler(
292
+ function (CommandInterface $_, RequestInterface $r) use (&$request) {
293
+ $request = $r;
294
+ return new FulfilledPromise(new Result([]));
295
+ }
296
+ );
297
+
298
+ call_user_func($handlerList->resolve(), $command)->wait();
299
+ if (!$request instanceof RequestInterface) {
300
+ throw new \RuntimeException(
301
+ 'Calling handler did not serialize request'
302
+ );
303
+ }
304
+
305
+ return $request;
306
+ }
307
+
308
+ /**
309
+ * Retrieves data for a service from the SDK's service manifest file.
310
+ *
311
+ * Manifest data is stored statically, so it does not need to be loaded more
312
+ * than once per process. The JSON data is also cached in opcache.
313
+ *
314
+ * @param string $service Case-insensitive namespace or endpoint prefix of the
315
+ * service for which you are retrieving manifest data.
316
+ *
317
+ * @return array
318
+ * @throws \InvalidArgumentException if the service is not supported.
319
+ */
320
+ function manifest($service = null)
321
+ {
322
+ // Load the manifest and create aliases for lowercased namespaces
323
+ static $manifest = [];
324
+ static $aliases = [];
325
+ if (empty($manifest)) {
326
+ $manifest = load_compiled_json(__DIR__ . '/data/manifest.json');
327
+ foreach ($manifest as $endpoint => $info) {
328
+ $alias = strtolower($info['namespace']);
329
+ if ($alias !== $endpoint) {
330
+ $aliases[$alias] = $endpoint;
331
+ }
332
+ }
333
+ }
334
+
335
+ // If no service specified, then return the whole manifest.
336
+ if ($service === null) {
337
+ return $manifest;
338
+ }
339
+
340
+ // Look up the service's info in the manifest data.
341
+ $service = strtolower($service);
342
+ if (isset($manifest[$service])) {
343
+ return $manifest[$service] + ['endpoint' => $service];
344
+ } elseif (isset($aliases[$service])) {
345
+ return manifest($aliases[$service]);
346
+ } else {
347
+ throw new \InvalidArgumentException(
348
+ "The service \"{$service}\" is not provided by the AWS SDK for PHP."
349
+ );
350
+ }
351
+ }
includes/aws/CHANGELOG.md ADDED
@@ -0,0 +1,1387 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CHANGELOG
2
+
3
+ ## 3.12.0 - 2015-12-21
4
+
5
+ * `Aws\Ecr` - Added support for the Amazon EC2 Container Registry.
6
+ * `Aws\Emr` - Added support for specifying a service security group when calling
7
+ the RunJobFlow API.
8
+
9
+ ## 3.11.7 - 2015-12-17
10
+
11
+ * `Aws\CloudFront` - Added support for generating signed cookies.
12
+ * `Aws\CloudFront` - Added support for GZip compression.
13
+ * `Aws\CloudTrail` - Added support for multi-region trails.
14
+ * `Aws\Config` - Added for IAM resource types.
15
+ * `Aws\Ec2` - Added support for managed NATs.
16
+ * `Aws\Rds` - Added support for enhanced monitoring.
17
+
18
+ ## 3.11.6 - 2015-12-15
19
+
20
+ * `Aws\Ec2` - Added support for specifying encryption on CopyImage commands.
21
+
22
+ ## 3.11.5 - 2015-12-08
23
+
24
+ * `Aws\AutoScaling` - Added support for setting and describing instance
25
+ protection status.
26
+ * `Aws\Emr` - Added support for using release labels instead of version numbers.
27
+ * `Aws\Rds` - Added support for Aurora encryption at rest.
28
+
29
+ ## 3.11.4 - 2015-12-03
30
+
31
+ * `Aws\DirectoryService` - Added support for launching a fully managed Microsoft
32
+ Active Directory.
33
+ * `Aws\Rds` - Added support for specifying a port number when modifying database
34
+ instances.
35
+ * `Aws\Route53` - Added support for Traffic Flow, a traffic management service.
36
+ * `Aws\Ses` - Added support for generating SMTP passwords from credentials.
37
+
38
+ ## 3.11.3 - 2015-12-01
39
+
40
+ * `Aws\Config` - Update documentation.
41
+
42
+ ## 3.11.2 - 2015-11-23
43
+
44
+ * `Aws\Config` - Reverted doc model change.
45
+
46
+ ## 3.11.1 - 2015-11-23
47
+
48
+ * `Aws\Ec2` - Added support for EC2 dedicated hosts.
49
+ * `Aws\Ecs` - Added support for task stopped reasons and task start and stop
50
+ times.
51
+ * `Aws\ElasticBeanstalk` - Added support for composable web applications.
52
+ * `Aws\S3` - Added support for the `aws-exec-read` canned ACL on objects.
53
+
54
+ ## 3.11.0 - 2015-11-19
55
+
56
+ * `Aws\CognitoIdentity` - Added a CognitoIdentity credentials provider.
57
+ * `Aws\DeviceFarm` - Marked app ARN as optional on `ScheduleRun` and
58
+ `GetDevicePoolCompatibility` operations.
59
+ * `Aws\DynamoDb` - Fixed bug where calling `session_regenerate_id` without
60
+ changing session data would prevent data from being carried over from the
61
+ previous session ID.
62
+ * `Aws\Inspector` - Added support for client-side validation of required
63
+ parameters throughout service.
64
+ * Fixed error parser bug where certain errors could throw an uncaught
65
+ parsing exception.
66
+
67
+ ## 3.10.1 - 2015-11-12
68
+
69
+ * `Aws\Config` - Fixed parsing of null responses.
70
+ * `Aws\Rds` - Added support for snapshot attributes.
71
+
72
+ ## 3.10.0 - 2015-11-10
73
+
74
+ * `Aws\ApiGateway` - Added support for stage variables.
75
+ * `Aws\DynamoDb` - Updated the session handler to emit warnings on write and
76
+ delete failures.
77
+ * `Aws\DynamoDb` - Fixed session ID assignment timing bug encountered in PHP 7.
78
+ * `Aws\S3` - Removed ServerSideEncryption parameter from UploadPart operation.
79
+ * Added jitter to the default retry delay algorithm.
80
+ * Updated the compatibility test script.
81
+
82
+ ## 3.9.4 - 2015-11-03
83
+
84
+ * `Aws\DeviceFarm` - Added support for managing projects, device pools, runs,
85
+ and uploads.
86
+ * `Aws\Sts` - Added support for 64-character role session names.
87
+
88
+ ## 3.9.3 - 2015-11-02
89
+
90
+ * `Aws\Iam` - Added support for service-aware policy simulation.
91
+
92
+ ## 3.9.2 - 2015-10-29
93
+
94
+ * `Aws\ApiGateway` - Fixed parameter name collision that occurred when calling
95
+ `PutIntegration`.
96
+ * `Aws\S3` - Added support for asynchronous copy and upload.
97
+ * `Aws\S3` - Added support for setting a location constraint other than the
98
+ region of the S3 client.
99
+
100
+ ## 3.9.1 - 2015-10-26
101
+
102
+ * `Aws\ApiGateway` - Fixed erroneous version number. Previous version number
103
+ support kept for backwards compatibility, but "2015-06-01" should be
104
+ considered deprecated.
105
+
106
+ ## 3.9.0 - 2015-10-26
107
+
108
+ * `Aws\ApiGateway` - Added support for the **AWS API Gateway** service.
109
+ * `Aws\Ssm` - Added support for EC2 Run Command, a new EC2 feature that enables
110
+ you to securely and remotely manage the configuration of your Amazon EC2
111
+ Windows instances.
112
+
113
+ ## 3.8.2 - 2015-10-22
114
+
115
+ * `Aws\AutoScaling` - Added support for EBS encryption.
116
+ * `Aws\Iam` - Added support for resource-based policy simulations.
117
+
118
+ ## 3.8.1 - 2015-10-15
119
+
120
+ * `Aws\Kms` - Added support for scheduling and cancelling key deletions and
121
+ listing retirable grants.
122
+ * `Aws\S3` - Added support for specifying server side encryption on an when
123
+ uploading a part of a multipart upload.
124
+
125
+ ## 3.8.0 - 2015-10-08
126
+
127
+ * `Aws\Ecs` - Added support for more Docker options hostname, Docker labels,
128
+ working directory, networking disabled, privileged execution, read-only root
129
+ filesystem, DNS servers, DNS search domains, ulimits, log configuration, extra
130
+ hosts (hosts to add to /etc/hosts), and security options (for MLS systems like
131
+ SELinux).
132
+ * `Aws\Iot` - Added support for the **AWS IoT** service.
133
+ * `Aws\IotDataPlane` - Added support for the **AWS IoT Data Plane** service.
134
+ * `Aws\Lambda` - Added support for function versioning.
135
+
136
+ ## 3.7.0 - 2015-10-07
137
+
138
+ * `Aws\ConfigService` - Added support for config rules, evaluation strategies,
139
+ and compliance querying.
140
+ * `Aws\Firehose` - Added support for the **Amazon Kinesis Firehose** service.
141
+ * `Aws\Inspector` - Added support for the **Amazon Inspector** service.
142
+ * `Aws\Kinesis` - Added support for increasing and decreasing stream retention
143
+ periods.
144
+ * `Aws\MarketplaceCommerceAnalytics` - Added support for the **AWS Marketplace
145
+ Commerce Analytics** service.
146
+
147
+ ## 3.6.0 - 2015-10-06
148
+
149
+ * `Aws\CloudFront` - Added support for WebACL identifiers and related
150
+ operations.
151
+ * `Aws\CloudFront` - Fixed URL presigner to always sign URL-encoded URLs.
152
+ * `Aws\Ec2` - Added support for spot blocks.
153
+ * `Aws\S3` - Fixed byte range specified on multipart copies.
154
+ * `Aws\Waf` - Added support for AWS WAF.
155
+
156
+ ## 3.5.0 - 2015-10-01
157
+
158
+ * `Aws\Cloudtrail` - Added support for log file integrity validation, log
159
+ encryption with AWS KMS–Managed Keys (SSE-KMS), and trail tagging.
160
+ * `Aws\ElasticsearchService` - Added support for the Amazon Elasticsearch
161
+ Service.
162
+ * `Aws\Rds` - Added support for resource tags.
163
+ * `Aws\S3` - Added support for copying objects of any size.
164
+ * `Aws\Workspaces` - Added support for storage volume encryption with AWS KMS.
165
+
166
+ ## 3.4.1 - 2015-09-29
167
+
168
+ * `Aws\CloudFormation` - Added support for specifying affected resource types
169
+ in `CreateStack` and `UpdateStack` operations.
170
+ * `Aws\CloudFormation` - Added support for the `DescribeAccountLimits` API.
171
+ * `Aws\Ec2` - Added support modifying previously created spot fleet requests.
172
+ * `Aws\Ses` - Added support for inbound email APIs.
173
+ * Fixed validation to allow using objects implementing `__toString` for string
174
+ fields in serialized output.
175
+
176
+ ## 3.4.0 - 2015-09-24
177
+
178
+ * `Aws\S3` - Fixed retry handling of networking errors and client socket timeout
179
+ errors to ensure the client `retries` option is respected.
180
+ * Added `@method` annotations on all clients to support autocomplete and static
181
+ analysis.
182
+ * Added performance tests to the acceptance test suite.
183
+ * Fixed error when `getIterator` was called on a paginator with no specified
184
+ `output_token`.
185
+ * Added support for reading the `aws_session_token` parameter from credentials
186
+ files.
187
+
188
+ ## 3.3.8 - 2015-09-17
189
+
190
+ * `Aws\CloudWatchLogs` - Added support for export task operations.
191
+
192
+ ## 3.3.7 - 2015-09-16
193
+
194
+ * `Aws\S3` - Added support for new `STANDARD_IA` storage class.
195
+ * `Aws\S3` - Added support for specifying storage class in cross-region
196
+ replication configuration.
197
+ * `Aws\Sqs` - Added a 'QueueExists' waiter to create a queue and wait until it
198
+ has been fully provisioned.
199
+
200
+ ## 3.3.6 - 2015-09-15
201
+
202
+ * `Aws\Ec2` - Added support for the "diversified" SpotFleet allocation strategy.
203
+ * `Aws\Ec2` - Added support for reading `StateMessage` and `DataEncryptionKeyId`
204
+ from a `DescribeSnapshots` response.
205
+ * `Aws\Efs` - Added support for using a `MountTargetId` parameter instead of a
206
+ `FileSystemId` parameter with the `DescribeMountTargets` command.
207
+ * `Aws\Route53` - Added support for calculated and latency health checks.
208
+ * `Aws\S3` - Fixed warning emitted by `BatchDelete` when no matching objects
209
+ were found to delete.
210
+
211
+ ## 3.3.5 - 2015-09-10
212
+
213
+ * `Aws\Iam` - Added support for new policy simulation APIs.
214
+ * `Aws\Kinesis` - Added support for timestamped GetRecords call.
215
+ * `Aws\MachineLearning` - Fixed invalid validation constraint on `Predict`
216
+ operation.
217
+ * `Aws\S3` - Added support for retrying special error cases with the
218
+ `ListObjects`, `CompleteMultipartUpload`, `CopyObject`, and `UploadPartCopy`.
219
+
220
+ ## 3.3.4 - 2015-09-03
221
+
222
+ * `Aws\StorageGateway` - Added support for tagging and untagging resources.
223
+
224
+ ## 3.3.3 - 2015-08-31
225
+
226
+ * `Aws\Ec2` - Added support for using instance weights with the
227
+ `RequestSpotFleet` API.
228
+
229
+ ## 3.3.2 - 2015-08-27
230
+
231
+ * `Aws\ConfigService` - Added support for the `ListDiscoveredResources`
232
+ operation and new resource types.
233
+
234
+ ## 3.3.1 - 2015-08-25
235
+
236
+ * `Aws\CodePipeline` - Added support for using encryption keys with artifact
237
+ stores.
238
+
239
+ ## 3.3.0 - 2015-08-20
240
+
241
+ * `Aws\S3` - Added support for event notification filters.
242
+ * Fixed waiter logic to always retry connection errors.
243
+ * Added support for per-command retry count overrides.
244
+ * Added support for defining custom patterns for the client debug log to use
245
+ to scrub sensitive data from the output logged.
246
+ * Moved the work being done by `Aws\JsonCompiler` from run time to build time.
247
+ * Fixed bug causing the phar autoloader not to be found when the phar was loaded
248
+ from opcache instead of from the filesystem.
249
+
250
+ ## 3.2.6 - 2015-08-12
251
+
252
+ * `Aws\ElasticBeanstalk` - Added support for enhanced health reporting.
253
+ * `Aws\S3` - Fixed retry middleware to ensure that S3 requests are retried
254
+ following errors raised by the HTTP handler.
255
+ * `Aws\S3` - Made the keys of the configuration array passed to the constructor
256
+ of `MultipartUploader` case-insensitive so that its configuration would not
257
+ rely on differently-cased keys from that of the `S3Client::putObject`
258
+ operation.
259
+ * Added an endpoint validation step to the `Aws\AwsClient` constructor so that
260
+ invalid endpoint would be reported immediately.
261
+
262
+ ## 3.2.5 - 2015-08-06
263
+
264
+ * `Aws\Swf` - Added support for invoking AWS Lambda tasks from an Amazon SWF
265
+ workflow.
266
+
267
+ ## 3.2.4 - 2015-08-04
268
+
269
+ * `Aws\DeviceFarm` - Added support for the `GetAccountSettings` operation and
270
+ update documentation to reflect new iOS support.
271
+ * Made PHP7 test failures fail the build.
272
+ * Added support for custom user-agent additions.
273
+
274
+ ## 3.2.3 - 2015-07-30
275
+
276
+ * `Aws\OpsWorks` - Added support for operations on ECS clusters.
277
+ * `Aws\Rds` - Added support for cluster operations for Amazon Aurora.
278
+
279
+ ## 3.2.2 - 2015-07-28
280
+
281
+ * `Aws\S3` - Added support for receiving the storage class in the responses for
282
+ `GetObject` and `HeadObject` operations.
283
+ * `Aws\CloudWatchLogs` - Added support for 4 new operations: `PutDestination`,
284
+ `PutDestinationPolicy`, `DescribeDestinations`, and `DeleteDestination`.
285
+
286
+ ## 3.2.1 - 2015-07-23
287
+
288
+ * **SECURITY FIX**: This release addresses a security issue associated with
289
+ CVE-2015-5723, specifically, fixes improper default directory umask behavior
290
+ that could potentially allow unauthorized modifications of PHP code.
291
+ * `Aws\Ec2` - Added support for SpotFleetLaunchSpecification.
292
+ * `Aws\Emr` - Added support for Amazon EMR release 4.0.0, which includes a new
293
+ application installation and configuration experience, upgraded versions of
294
+ Hadoop, Hive, and Spark, and now uses open source standards for ports and
295
+ paths. To specify an Amazon EMR release, use the release label parameter (AMI
296
+ versions 3.x and 2.x can still be specified with the AMI version parameter).
297
+ * `Aws\Glacier` - Added support for the InitiateVaultLock, GetVaultLock,
298
+ AbortVaultLock, and CompleteVaultLock API operations.
299
+ * Fixed a memory leak that occurred when clients were created and never used.
300
+ * Updated JsonCompiler by addressing a potential race condition and ensuring
301
+ that caches are invalidated when upgrading to a new version of the SDK.
302
+ * Updated protocol and acceptance tests.
303
+
304
+ ## 3.2.0 - 2015-07-14
305
+
306
+ * `Aws\DeviceFarm` - Added support for AWS DeviceFarm, an app testing service
307
+ that enables you to test your Android and Fire OS apps on real, physical
308
+ phones and tablets that are hosted by AWS.
309
+ * `Aws\DynamoDb` - Added support for consistent scans and update streams.
310
+ * `Aws\DynamoDbStreams` - Added support for Amazon DynamoDB Streams, giving you
311
+ the ability to subscribe to the transactional log of all changes transpiring
312
+ in your DynamoDB table.
313
+ * `Aws\S3` - Fixed checksum encoding on multipart upload of non-seekable
314
+ streams.
315
+ * `Aws\S3\StreamWrapper` - Added guard on rename functionality to ensure wrapper
316
+ initialized.
317
+
318
+
319
+ ## 3.1.0 - 2015-07-09
320
+
321
+ * `Aws\CodeCommit` - Added support for AWS CodeCommit, a secure, highly
322
+ scalable, managed source control service that hosts private Git repositories.
323
+ * `Aws\CodePipeline` - Added support for AWS CodePipeline, a continuous delivery
324
+ service that enables you to model, visualize, and automate the steps required
325
+ to release your software.
326
+ * `Aws\Iam` - Added support for uploading SSH public keys for authentication
327
+ with AWS CodeCommit.
328
+ * `Aws\Ses` - Added support for cross-account sending through the sending
329
+ authorization feature.
330
+
331
+ ## 3.0.7 - 2015-07-07
332
+
333
+ * `Aws\AutoScaling` - Added support for step policies.
334
+ * `Aws\CloudHsm` - Fixed a naming collision with the `GetConfig` operation. This
335
+ operation is now available through the `GetConfigFiles` method.
336
+ * `Aws\DynamoDb` - Improved performance when unmarshalling complex documents.
337
+ * `Aws\DynamoDb` - Fixed checksum comparison of uncompressed responses.
338
+ * `Aws\Ec2` - Added support for encrypted snapshots.
339
+ * `Aws\S3` - Added support for user-provided SHA256 checksums for S3 uploads.
340
+ * `Aws\S3` - Added support for custom protocols in `Aws\S3\StreamWrapper`.
341
+ * Added cucumber integration tests.
342
+ * Updated the test suite to be compatible with PHP 7-alpha 2.
343
+
344
+ ## 3.0.6 - 2015-06-24
345
+
346
+ * `Aws\CloudFront` - Added support for configurable `MaxTTL` and `DefaultTTL`.
347
+ * `Aws\ConfigService` - Added support for recording changes for specific
348
+ resource types.
349
+ * `Aws\Ecs` - Added support for sorting, deregistering, and overriding
350
+ environment variables for task definitions.
351
+ * `Aws\Glacier` - Added support for the `AddTagsToVault`, `ListTagsForVault`,
352
+ and `RemoveTagsFromVault` API operations.
353
+ * `Aws\OpwWorks` - Added support for specifying agent versions to be used on
354
+ instances.
355
+ * `Aws\Redshift` - Added support for the `CreateSnapshotCopyGrant`,
356
+ `DescribeSnapshotCopyGrants`, and `DeleteSnapshotCopyGrant` API operations.
357
+ * Fixed XML attribute serialization.
358
+
359
+ ## 3.0.5 - 2015-06-18
360
+
361
+ * `Aws\CognitoSync` - Fixed an issue in the Signature Version 4 implementation
362
+ that was causing issues when signing requests to the Cognito Sync service.
363
+ * `Aws\ConfigService` - Fixed an issue that was preventing the
364
+ `ConfigServiceClient` from working properly.
365
+ * `Aws\Ecs` - Added support for sorting, deregistering, and overriding
366
+ environment variables for task definitions.
367
+ * `Aws\Iam` - Added new paginator and waiter configurations.
368
+ * `Aws\S3` - Added support for the `SaveAs` parameter that was in V2.
369
+ * `Aws\Sqs` - Fixed an issue that was preventing batch message deletion from
370
+ working properly.
371
+ * `Aws` - The `Aws\Sdk::createClient()` method is no longer case-sensitive with
372
+ service names.
373
+
374
+ ## 3.0.4 - 2015-06-11
375
+
376
+ * `Aws\AutoScaling` - Added support for attaching and detaching load balancers.
377
+ * `Aws\CloudWatchLogs` - Added support for the PutSubscriptionFilter,
378
+ DescribeSubscriptionFilters, and DeleteSubscriptionFilter operations.
379
+ * `Aws\CognitoIdentity` - Added support for the DeleteIdentities operation,
380
+ and hiding disabled identities with the ListIdentities operation.
381
+ * `Aws\Ec2` - Added support for VPC flow logs and the M4 instance types.
382
+ * `Aws\Ecs` - Added support for the UpdateContainerAgent operation.
383
+ * `Aws\S3` - Improvements to how errors are handled in the `StreamWrapper`.
384
+ * `Aws\StorageGateway` - Added support for the ListVolumeInitiators operation.
385
+ * `Aws` - Fixes a bug such that empty maps are handled correctly in JSON
386
+ requests.
387
+
388
+ ## 3.0.3 - 2015-06-01
389
+
390
+ * `Aws\MachineLearning` - Fixed the `Predict` operation to use the provided
391
+ `PredictEndpoint` as the host.
392
+
393
+ ## 3.0.2 - 2015-05-29
394
+
395
+ * `Aws` - Fixed an issue preventing some clients from being instantiated via
396
+ their constructors due to a mismatch between class name and endpoint prefix.
397
+
398
+ ## 3.0.1 - 2015-05-28
399
+
400
+ * `Aws\Lambda` - Added Amazon S3 upload support.
401
+
402
+ ## 3.0.0 - 2015-05-27
403
+
404
+ * Asynchronous requests.
405
+ * Features like _waiters_ and _multipart uploaders_ can also be used
406
+ asynchronously.
407
+ * Asynchronous workflows can be created using _promises_ and _coroutines_.
408
+ * Improved performance of concurrent/batched requests via _command pools_.
409
+ * Decoupled HTTP layer.
410
+ * [Guzzle 6](http://guzzlephp.org) is used by default to send requests,
411
+ but Guzzle 5 is also supported out of the box.
412
+ * The SDK can now work in environments where cURL is not available.
413
+ * Custom HTTP handlers are also supported.
414
+ * Follows the [PSR-4 and PSR-7 standards](http://php-fig.org).
415
+ * Middleware system for customizing service client behavior.
416
+ * Flexible _paginators_ for iterating through paginated results.
417
+ * Ability to query data from _result_ and _paginator_ objects with
418
+ [JMESPath](http://jmespath.org/).
419
+ * Easy debugging via the `'debug'` client configuration option.
420
+ * Customizable retries via the `'retries'` client configuration option.
421
+ * More flexibility in credential loading via _credential providers_.
422
+ * Strictly follows the [SemVer](http://semver.org/) standard going forward.
423
+ * **For more details about what has changed, see the
424
+ [Migration Guide](http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/migration.html)**.
425
+
426
+ ## 2.8.7 - 2015-05-26
427
+
428
+ * `Aws\Efs` - Added support for the [Amazon Elastic File System (Amazon
429
+ EFS)](http://aws.amazon.com/efs/)
430
+ * Failing to parse an XML error response will now fail gracefully as a
431
+ `PhpInternalXmlParseError` AWS error code.
432
+
433
+ ## 2.8.6 - 2015-05-21
434
+
435
+ * `Aws\ElasticBeanstalk` - Added support for ResourceName configuration.
436
+ * `Aws\ElasticTranscoder` - Added support for configuring AudioPackingMode and
437
+ additional CodecOptions.
438
+ * `Aws\Kinesis` - Added support for MillisBehindLatest in the result of
439
+ GetRecordsOutput.
440
+ * `Aws\Kms` - Added support for the UpdateAlias operation.
441
+ * `Aws\Lambda` - Fixed an issue with the UpdateFunctionCode operation.
442
+
443
+ ## 2.8.5 - 2015-05-18
444
+
445
+ * `Aws\Ec2\Ec2Client` - Added support for the new spot fleet API operations.
446
+ * `Aws\OpsWorks\OpsWorksClient` - Added support for custom auto-scaling based
447
+ on CloudWatch alarms.
448
+
449
+ ## 2.8.4 - 2015-05-14
450
+
451
+ * `Aws\DirectoryService` - Added support for the AWS Directory Service.
452
+ * `Aws\CloudWatchLogs` - Adds support for the FilterLogEvents operation.
453
+ * `Aws\CloudFormation` - Adds additional data to the GetTemplateSummary
454
+ operation.
455
+ * `Aws\Ec2` - Adds support for Amazon VPC endpoints for Amazon S3 and APIs for
456
+ migrating Elastic IP Address from EC2-Classic to EC2-VPC.
457
+ * `Aws\Ec2` - Fixed an issue with cross-region CopySnapshot such that it now
458
+ works with temporary credentials.
459
+ * `Aws\Common` - During credential discovery, an invalid credentials file now
460
+ allows failover to Instance Profile credentials.
461
+
462
+ ## 2.8.3 - 2015-05-07
463
+
464
+ * `Aws\Glacier` - Added support for vault access policies.
465
+ * `Aws\Route53` - Fixed a `GetCheckerIpRangesResponse` response parsing issue.
466
+ * `Aws\S3` - Retrying CompleteMultipartUpload failures by retrying the request.
467
+ * `Aws\S3` - Corrected some response handling in the S3 multipart upload
468
+ abstraction.
469
+ * Expiring instance metadata credentials 30 minutes in advance for more eager
470
+ refreshes before the credentials expire.
471
+
472
+ ## 2.8.2 - 2015-04-23
473
+
474
+ * `Aws\Ec2` - Added support for new VM Import APIs, `including ImportImage`.
475
+ * `Aws\Iam` - Added support for the `GetAccessKeyLastUsed` operation.
476
+ * `Aws\CloudSearchDomain` - Search responses now include the expressions requested.
477
+
478
+ ## 2.8.1 - 2015-04-16
479
+
480
+ * `Aws\ConfigService` - Added the 'GetResourceConfigHistory' iterator.
481
+ * `Aws\CognitoSync` - Added support for events.
482
+ * `Aws\Lambda` - Fixed an issue with the Invoke operation.
483
+
484
+ ## 2.8.0 - 2015-04-09
485
+
486
+ See the [Upgrading Guide](https://github.com/aws/aws-sdk-php/blob/master/UPGRADING.md)
487
+ for details about any changes you may need to make to your code for this upgrade.
488
+
489
+ * `Aws\MachineLearning` - Added support for the Amazon Machine Learning service.
490
+ * `Aws\WorkSpaces` - Added support for the Amazon WorkSpaces service.
491
+ * `Aws\Ecs` - Added support for the ECS service scheduler operations.
492
+ * `Aws\S3` - Added support for the `getBucketNotificationConfiguration` and
493
+ `putBucketNotificationConfiguration` operations to the `S3Client` to replace
494
+ the, now deprecated, `getBucketNotification` and `putBucketNotification`
495
+ operations.
496
+ * [BC] `Aws\Lambda` - Added support for the new AWS Lambda API, which has been
497
+ changed based on customer feedback during Lambda's preview period.
498
+ * `Aws\Common` - Deprecated "facades". They will not be present in Version 3 of
499
+ the SDK.
500
+ * `Aws\Common` - Added `getAwsErrorCode`, `getAwsErrorType` and `getAwsRequestId`
501
+ methods to the `ServiceResponseException` to be forward-compatible with
502
+ Version 3 of the SDK.
503
+
504
+ ## 2.7.27 - 2015-04-07
505
+
506
+ * `Aws\DataPipeline` - Added support for `DeactivatePipeline`
507
+ * `Aws\ElasticBeanstalk` - Added support for `AbortEnvironmentUpdate`
508
+
509
+ ## 2.7.26 - 2015-04-02
510
+
511
+ * `Aws\CodeDeploy` - Added support deployments to on-premises instances.
512
+ * `Aws\Rds` - Added support for the `DescribeCertificates` operation.
513
+ * `Aws\ElasticTranscoder` - Added support for protecting content with PlayReady
514
+ Digital Rights Management (DRM).
515
+
516
+ ## 2.7.25 - 2015-03-26
517
+
518
+ * `Aws\ElasticTranscoder` - Added support for job timing.
519
+ * `Aws\Iam` - Added `NamedPolicy` to `GetAccountAuthorizationDetails`.
520
+ * `Aws\OpsWorks` - Added `BlockDeviceMapping` support.
521
+
522
+ ## 2.7.24 - 2015-03-24
523
+
524
+ * `Aws\S3` - Added support for cross-region replication.
525
+ * `Aws\S3` - Added support for ["Requester Pays" buckets](http://docs.aws.amazon.com/AmazonS3/latest/dev/RequesterPaysBuckets.html).
526
+
527
+ ## 2.7.23 - 2015-03-19
528
+
529
+ * `Aws\ElasticTranscoder` - API update to support AppliedColorSpaceConversion.
530
+ * `Aws\CloudSearchDomain` - Adding 504 status code to retry list.
531
+
532
+ ## 2.7.22 - 2015-03-12
533
+
534
+ * `Aws\CloudFront` - Fixed #482, which affected pre-signing CloudFront URLs.
535
+ * `Aws\CloudTrail` - Added support for the `LookupEvents` operation.
536
+ * `Aws\CloudWatchLogs` - Added ordering parameters to the `DescribeLogStreams`
537
+ * `Aws\Ec2` - Added pagination parameters to the `DescribeSnapshots` operation.
538
+ operation.
539
+
540
+ ## 2.7.21 - 2015-03-04
541
+
542
+ * `Aws\CognitoSync` - Added support for Amazon Cognito Streams.
543
+
544
+ ## 2.7.20 - 2015-02-23
545
+
546
+ * `Aws\DataPipeline` - Added support for pipeline tagging via the `AddTags` and
547
+ `RemoveTags` operations.
548
+ * `Aws\Route53` - Added support for the `GetHostedZoneCount` and
549
+ `ListHostedZonesByName` operations.
550
+
551
+ ## 2.7.19 - 2015-02-20
552
+
553
+ * `Aws\CloudFront` - Added support for origin paths in web distributions.
554
+ * `Aws\Ecs` - Added support for specifying volumes and mount points. Also
555
+ * `Aws\ElasticTranscoder` - Added support for cross-regional resource warnings.
556
+ * `Aws\Route53Domains` - Add iterators for `ListDomains` and `ListOperations`.
557
+ * `Aws\Ssm` - Added support for the **Amazon Simple Systems Management Service
558
+ (SSM)**.
559
+ * `Aws\Sts` - Added support for regional endpoints.
560
+ switched the client to use a JSON protocol.
561
+ * Changed our CHANGELOG format. ;-)
562
+
563
+ ## 2.7.18 - 2015-02-12
564
+
565
+ * Added support for named and managed policies to the IAM client.
566
+ * Added support for tagging operations to the Route 53 Domains client.
567
+ * Added support for tagging operations to the ElastiCache client.
568
+ * Added support for the Scan API for secondary indexes to the DynamoDB client.
569
+ * Added forward compatibility for the `'credentials'`, `'endpoint'`, and
570
+ `'http'` configuration options.
571
+ * Made the `marshalValue()` and `unmarshalValue()` methods public in the
572
+ DynamoDB Marshaler.
573
+
574
+ ## 2.7.17 - 2015-01-27
575
+
576
+ * Added support for `getShippingLabel` to the AWS Import/Export client.
577
+ * Added support for online indexing to the DynamoDB client.
578
+ * Updated the AWS Lambda client.
579
+
580
+ ## 2.7.16 - 2015-01-20
581
+
582
+ * Added support for custom security groups to the Amazon EMR client.
583
+ * Added support for the latest APIs to the Amazon Cognito Identity client.
584
+ * Added support for ClassicLink to the Auto Scaling client.
585
+ * Added the ability to set a client's API version to "latest" for forwards
586
+ compatibility with v3.
587
+
588
+ ## 2.7.15 - 2015-01-15
589
+
590
+ * Added support for [HLS Content Protection](https://aws.amazon.com/releasenotes/3388917394239147)
591
+ to the Elastic Transcoder client.
592
+ * Updated client factory logic to add the `SignatureListener`, even when
593
+ `NullCredentials` have been specified. This way, you can update a client's
594
+ credentials later if you want to begin signing requests.
595
+
596
+ ## 2.7.14 - 2015-01-09
597
+
598
+ * Fixed a regression in the CloudSearch Domain client (#448).
599
+
600
+ ## 2.7.13 - 2015-01-08
601
+
602
+ * Added the Amazon EC2 Container Service client.
603
+ * Added the Amazon CloudHSM client.
604
+ * Added support for dynamic fields to the Amazon CloudSearch client.
605
+ * Added support for the ClassicLink feature to the Amazon EC2 client.
606
+ * Updated the Amazon RDS client to use the latest 2014-10-31 API.
607
+ * Updated S3 signature so retries use a new Date header on each attempt.
608
+
609
+ ## 2.7.12 - 2014-12-18
610
+
611
+ * Added support for task priorities to Amazon Simple Workflow Service.
612
+
613
+ ## 2.7.11 - 2014-12-17
614
+
615
+ * Updated Amazon EMR to the latest API version.
616
+ * Added support for for the new ResetCache API operation to AWS Storage Gateway.
617
+
618
+ ## 2.7.10 - 2014-12-12
619
+
620
+ * Added support for user data to Amazon Elastic Transcoder.
621
+ * Added support for data retrieval policies and audit logging to the Amazon
622
+ Glacier client.
623
+ * Corrected the AWS Security Token Service endpoint.
624
+
625
+ ## 2.7.9 - 2014-12-08
626
+
627
+ * The Amazon Simple Queue Service client adds support for the PurgeQueue
628
+ operation.
629
+ * You can now use AWS OpsWorks with existing EC2 instances and on-premises
630
+ servers.
631
+
632
+ ## 2.7.8 - 2014-12-04
633
+
634
+ * Added support for the `PutRecords` batch operation to `KinesisClient`.
635
+ * Added support for the `GetAccountAuthorizationDetails` operation to the
636
+ `IamClient`.
637
+ * Added support for the `UpdateHostedZoneComment` operation to `Route53Client`.
638
+ * Added iterators for `ListEventSources` and `ListFunctions` operations the
639
+ `LambdaClient`.
640
+
641
+ ## 2.7.7 - 2014-11-25
642
+
643
+ * Added a DynamoDB `Marshaler` class, that allows you to marshal JSON documents
644
+ or native PHP arrays to the format that DynamoDB requires. You can also
645
+ unmarshal item data from operation results back into JSON documents or native
646
+ PHP arrays.
647
+ * Added support for media file encryption to Amazon Elastic Transcoder.
648
+ * Removing a few superfluous `x-amz-server-side-encryption-aws-kms-key-id` from
649
+ the Amazon S3 model.
650
+ * Added support for using AWS Data Pipeline templates to create pipelines and
651
+ bind values to parameters in the pipeline.
652
+
653
+ ## 2.7.6 - 2014-11-20
654
+
655
+ * Added support for AWS KMS integration to the Amazon Redshift Client.
656
+ * Fixed cn-north-1 endpoint for AWS Identity and Access Management.
657
+ * Updated `S3Client::getBucketLocation` method to work cross-region regardless
658
+ of the region's signature requirements.
659
+ * Fixed an issue with the DynamoDbClient that allows it to work better with
660
+ with DynamoDB Local.
661
+
662
+ ## 2.7.5 - 2014-11-13
663
+
664
+ * Added support for AWS Lambda.
665
+ * Added support for event notifications to the Amazon S3 client.
666
+ * Fixed an issue with S3 pre-signed URLs when using Signature V4.
667
+
668
+ ## 2.7.4 - 2014-11-12
669
+
670
+ * Added support for the AWS Key Management Service (AWS KMS).
671
+ * Added support for AWS CodeDeploy.
672
+ * Added support for AWS Config.
673
+ * Added support for AWS KMS encryption to the Amazon S3 client.
674
+ * Added support for AWS KMS encryption to the Amazon EC2 client.
675
+ * Added support for Amazon CloudWatch Logs delivery to the AWS CloudTrail
676
+ client.
677
+ * Added the GetTemplateSummary operation to the AWS CloudFormation client.
678
+ * Fixed an issue with sending signature version 4 Amazon S3 requests that
679
+ contained a 0 length body.
680
+
681
+ ## 2.7.3 - 2014-11-06
682
+
683
+ * Added support for private DNS for Amazon Virtual Private Clouds, health check
684
+ failure reasons, and reusable delegation sets to the Amazon Route 53 client.
685
+ * Updated the CloudFront model.
686
+ * Added support for configuring push synchronization to the Cognito Sync client.
687
+ * Updated docblocks in a few S3 and Glacier classes to improve IDE experience.
688
+
689
+ ## 3.0.0-beta.1 - 2014-10-14
690
+
691
+ * New requirements on Guzzle 5 and PHP 5.5.
692
+ * Event system now uses Guzzle 5 events and no longer utilizes Symfony2.
693
+ * `version` and `region` are noww required parameter for each client
694
+ constructor. You can op-into using the latest version of a service by
695
+ setting `version` to `latest`.
696
+ * Removed `Aws\S3\ResumableDownload`.
697
+ * More information to follow.
698
+
699
+ ## 2.7.2 - 2014-10-23
700
+
701
+ * Updated AWS Identity and Access Management (IAM) to the latest version.
702
+ * Updated Amazon Cognito Identity client to the latest version.
703
+ * Added auto-renew support to the Amazon Route 53 Domains client.
704
+ * Updated Amazon EC2 to the latest version.
705
+
706
+ ## 2.7.1 - 2014-10-16
707
+
708
+ * Updated the Amazon RDS client to the 2014-09-01 API version.
709
+ * Added support for advanced Japanese language processing to the Amazon
710
+ CloudSearch client.
711
+
712
+ ## 2.7.0 - 2014-10-08
713
+
714
+ * Added document model support to the Amazon DynamoDB client, including support
715
+ for the new data types (`L`, `M`, `BOOL`, and `NULL`), nested attributes, and
716
+ expressions.
717
+ * Deprecated the `Aws\DynamoDb\Model\Attribute`, `Aws\DynamoDb\Model\Item`,
718
+ and `Aws\DynamoDb\Iterator\ItemIterator` classes, and the
719
+ `Aws\DynamoDb\DynamoDbClient::formatValue` and
720
+ `Aws\DynamoDb\DynamoDbClient::formatAttribute` methods, since they do not
721
+ support the new types in the DynamoDB document model. These deprecated classes
722
+ and methods still work reliably with `S`, `N`, `B`, `SS`, `NS`, and `BS`
723
+ attributes.
724
+ * Updated the Amazon DynamoDB client to permanently disable client-side
725
+ parameter validation. This needed to be done in order to support the new
726
+ document model features.
727
+ * Updated the Amazon EC2 client to sign requests with Signature V4.
728
+ * Fixed an issue in the S3 service description to make the `VersionId`
729
+ work in `S3Client::restoreObject`.
730
+
731
+ ## 2.6.16 - 2014-09-11
732
+
733
+ * Added support for tagging to the Amazon Kinesis client.
734
+ * Added support for setting environment variables to the AWS OpsWorks client.
735
+ * Fixed issue #334 to allow the `before_upload` callback to work in the
736
+ `S3Client::upload` method.
737
+ * Fixed an issue in the Signature V4 signer that was causing an issue with some
738
+ CloudSearch Domain operations.
739
+
740
+ ## 2.6.15 - 2014-08-14
741
+
742
+ * Added support for signing requests to the Amazon CloudSearch Domain client.
743
+ * Added support for creating anonymous clients.
744
+
745
+ ## 2.6.14 - 2014-08-11
746
+
747
+ * Added support for tagging to the Elastic Load Balancing client.
748
+
749
+ ## 2.6.13 - 2014-07-31
750
+
751
+ * Added support for configurable idle timeouts to the Elastic Load Balancing
752
+ client.
753
+ * Added support for Lifecycle Hooks, Detach Instances, and Standby to the
754
+ AutoScaling client.
755
+ * Added support for creating Amazon ElastiCache for Memcached clusters with
756
+ nodes in multiple availability zones.
757
+ * Added minor fixes to the Amazon EC2 model for ImportVolume,
758
+ DescribeNetworkInterfaceAttribute, and DeleteVpcPeeringConnection
759
+ * Added support for getGeoLocation and listGeoLocations to the
760
+ Amazon Route 53 client.
761
+ * Added support for Amazon Route 53 Domains.
762
+ * Fixed an issue with deleting nested folders in the Amazon S3 stream wrapper.
763
+ * Fixed an issue with the Amazon S3 sync abstraction to ensure that S3->S3
764
+ communication works correctly.
765
+ * Added stricter validation to the Amazon SNS MessageValidator.
766
+
767
+ ## 2.6.12 - 2014-07-16
768
+
769
+ * Added support for adding attachments to support case communications to the
770
+ AWS Support API client.
771
+ * Added support for credential reports and password rotation features to the
772
+ AWS IAM client.
773
+ * Added the `ap-northeast-1`, `ap-southeast-1`, and `ap-southeast-2` regions to
774
+ the Amazon Kinesis client.
775
+ * Added a `listFilter` stream context option that can be used when using
776
+ `opendir()` and the Amazon S3 stream wrapper. This option is used to filter
777
+ out specific objects from the files yielded from the stream wrapper.
778
+ * Fixed #322 so that the download sync builder ignores objects that have a
779
+ `GLACIER` storage class.
780
+ * Fixed an issue with the S3 SSE-C logic so that HTTPS is only required when
781
+ the SSE-C parameters are provided.
782
+ * Updated the Travis configuration to include running HHVM tests.
783
+
784
+ ## 2.6.11 - 2014-07-09
785
+
786
+ * Added support for **Amazon Cognito Identity**.
787
+ * Added support for **Amazon Cognito Sync**.
788
+ * Added support for **Amazon CloudWatch Logs**.
789
+ * Added support for editing existing health checks and associating health checks
790
+ with tags to the Amazon Route 53 client.
791
+ * Added the ModifySubnetAttribute operation to the Amazon EC2 client.
792
+
793
+ ## 2.6.10 - 2014-07-02
794
+
795
+ * Added the `ap-northeast-1`, `ap-southeast-1`, and `sa-east-1` regions to the
796
+ Amazon CloudTrail client.
797
+ * Added the `eu-west-1` and `us-west-2` regions to the Amazon Kinesis client.
798
+ * Fixed an issue with the SignatureV4 implementation when used with Amazon S3.
799
+ * Fixed an issue with a test that was causing failures when run on EC2 instances
800
+ that have associated Instance Metadata credentials.
801
+
802
+ ## 2.6.9 - 2014-06-26
803
+
804
+ * Added support for the CloudSearchDomain client, which allows you to search and
805
+ upload documents to your CloudSearch domains.
806
+ * Added support for delivery notifications to the Amazon SES client.
807
+ * Updated the CloudFront client to support the 2014-05-31 API.
808
+ * Merged PR #316 as a better solution for issue #309.
809
+
810
+ ## 2.6.8 - 2014-06-20
811
+
812
+ * Added support for closed captions to the Elastic Transcoder client.
813
+ * Added support for IAM roles to the Elastic MapReduce client.
814
+ * Updated the S3 PostObject to ease customization.
815
+ * Fixed an issue in some EC2 waiters by merging PR #306.
816
+ * Fixed an issue with the DynamoDB `WriteRequestBatch` by merging PR #310.
817
+ * Fixed issue #309, where the `url_stat()` logic in the S3 Stream Wrapper was
818
+ affected by a change in PHP 5.5.13.
819
+
820
+ ## 2.6.7 - 2014-06-12
821
+
822
+ * Added support for Amazon S3 server-side encryption using customer-provided
823
+ encryption keys.
824
+ * Updated Amazon SNS to support message attributes.
825
+ * Updated the Amazon Redshift model to support new cluster parameters.
826
+ * Updated PHPUnit dev dependency to 4.* to work around a PHP serializing bug.
827
+
828
+ ## 2.6.6 - 2014-05-29
829
+
830
+ * Added support for the [Desired Partition Count scaling
831
+ option](http://aws.amazon.com/releasenotes/2440176739861815) to the
832
+ CloudSearch client. Hebrew is also now a supported language.
833
+ * Updated the STS service description to the latest version.
834
+ * [Docs] Updated some of the documentation about credential profiles.
835
+ * Fixed an issue with the regular expression in the `S3Client::isValidBucketName`
836
+ method. See #298.
837
+
838
+ ## 2.6.5 - 2014-05-22
839
+
840
+ * Added cross-region support for the Amazon EC2 CopySnapshot operation.
841
+ * Added AWS Relational Database (RDS) support to the AWS OpsWorks client.
842
+ * Added support for tagging environments to the AWS Elastic Beanstalk client.
843
+ * Refactored the signature version 4 implementation to be able to pre-sign
844
+ most operations.
845
+
846
+ ## 2.6.4 - 2014-05-20
847
+
848
+ * Added support for lifecycles on versioning enabled buckets to the Amazon S3
849
+ client.
850
+ * Fixed an Amazon S3 sync issue which resulted in unnecessary transfers when no
851
+ `$keyPrefix` argument was utilized.
852
+ * Corrected the `CopySourceIfMatch` and `CopySourceIfNoneMatch` parameter for
853
+ Amazon S3 to not use a timestamp shape.
854
+ * Corrected the sending of Amazon S3 PutBucketVersioning requests that utilize
855
+ the `MFADelete` parameter.
856
+
857
+ ## 2.6.3 - 2014-05-14
858
+
859
+ * Added the ability to modify Amazon SNS topic settings to the UpdateStack
860
+ operation of the AWS CloudFormation client.
861
+ * Added support for the us-west-1, ap-southeast-2, and eu-west-1 regions to the
862
+ AWS CloudTrail client.
863
+ * Removed no longer utilized AWS CloudTrail shapes from the model.
864
+
865
+ ## 2.6.2 - 2014-05-06
866
+
867
+ * Added support for Amazon SQS message attributes.
868
+ * Fixed Amazon S3 multi-part uploads so that manually set ContentType values are not overwritten.
869
+ * No longer recalculating file sizes when an Amazon S3 socket timeout occurs because this was causing issues with
870
+ multi-part uploads and it is very unlikely ever the culprit of a socket timeout.
871
+ * Added better environment variable detection.
872
+
873
+ ## 2.6.1 - 2014-04-25
874
+
875
+ * Added support for the `~/.aws/credentials` INI file and credential profiles (via the `profile` option) as a safer
876
+ alternative to using explicit credentials with the `key` and `secret` options.
877
+ * Added support for query filters and improved conditional expressions to the Amazon DynamoDB client.
878
+ * Added support for the `ChefConfiguration` parameter to a few operations on the AWS OpsWorks Client.
879
+ * Added support for Redis cache cluster snapshots to the Amazon ElastiCache client.
880
+ * Added support for the `PlacementTenancy` parameter to the `CreateLaunchConfiguration` operation of the Auto Scaling
881
+ client.
882
+ * Added support for the new R3 instance types to the Amazon EC2 client.
883
+ * Added the `SpotInstanceRequestFulfilled` waiter to the Amazon EC2 client (see #241).
884
+ * Improved the S3 Stream Wrapper by adding support for deleting pseudo directories (#264), updating error handling
885
+ (#276), and fixing `is_link()` for non-existent keys (#268).
886
+ * Fixed #252 and updated the DynamoDB `WriteRequestBatch` abstraction to handle batches that were completely rejected
887
+ due to exceeding provisioned throughput.
888
+ * Updated the SDK to support Guzzle 3.9.x
889
+
890
+ ## 2.6.0 - 2014-03-25
891
+
892
+ * [BC] Updated the Amazon CloudSearch client to use the new 2013-01-01 API version (see [their release
893
+ notes](http://aws.amazon.com/releasenotes/6125075708216342)). This API version of CloudSearch is significantly
894
+ different than the previous one, and is not backwards compatible. See the
895
+ [Upgrading Guide](https://github.com/aws/aws-sdk-php/blob/master/UPGRADING.md) for more details.
896
+ * Added support for the VPC peering features to the Amazon EC2 client.
897
+ * Updated the Amazon EC2 client to use the new 2014-02-01 API version.
898
+ * Added support for [resize progress data and the Cluster Revision Number
899
+ parameter](http://aws.amazon.com/releasenotes/0485739709714318) to the Amazon Redshift client.
900
+ * Added the `ap-northeast-1`, `ap-southeast-2`, and `sa-east-1` regions to the Amazon CloudSearch client.
901
+
902
+ ## 2.5.4 - 2014-03-20
903
+
904
+ * Added support for [access logs](http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/access-log-collection.html)
905
+ to the Elastic Load Balancing client.
906
+ * Updated the Elastic Load Balancing client to the latest API version.
907
+ * Added support for the `AWS_SECRET_ACCESS_KEY` environment variables.
908
+ * Updated the Amazon CloudFront client to use the 2014-01-31 API version. See [their release
909
+ notes](http://aws.amazon.com/releasenotes/1900016175520505).
910
+ * Updates the AWS OpsWorks client to the latest API version.
911
+ * Amazon S3 Stream Wrapper now works correctly with pseudo folder keys created by the AWS Management Console.
912
+ * Amazon S3 Stream Wrapper now implements `mkdir()` for nested folders similar to the AWS Management Console.
913
+ * Addressed an issue with Amazon S3 presigned-URLs where X-Amz-* headers were not being added to the query string.
914
+ * Addressed an issue with the Amazon S3 directory sync where paths that contained dot-segments were not properly.
915
+ resolved. Removing the dot segments consistently helps to ensure that files are uploaded to their intended.
916
+ destinations and that file key comparisons are accurately performed when determining which files to upload.
917
+
918
+ ## 2.5.3 - 2014-02-27
919
+
920
+ * Added support for HTTP and HTTPS string-match health checks and HTTPS health checks to the Amazon Route 53 client
921
+ * Added support for the UPSERT action for the Amazon Route 53 ChangeResourceRecordSets operation
922
+ * Added support for SerialNumber and TokenCode to the AssumeRole operation of the IAM Security Token Service (STS).
923
+ * Added support for RequestInterval and FailureThreshold to the Amazon Route53 client.
924
+ * Added support for smooth streaming to the Amazon CloudFront client.
925
+ * Added the us-west-2, eu-west-1, ap-southeast-2, and ap-northeast-1 regions to the AWS Data Pipeline client.
926
+ * Added iterators to the Amazon Kinesis client
927
+ * Updated iterator configurations for all services to match our new iterator config spec (care was taken to continue
928
+ supporting manually-specified configurations in the old format to prevent BC)
929
+ * Updated the Amazon EC2 model to include the latest updates and documentation. Removed deprecated license-related
930
+ operations (this is not considered a BC since we have confirmed that these operations are not used by customers)
931
+ * Updated the Amazon Route 53 client to use the 2013-04-01 API version
932
+ * Fixed several iterator configurations for various services to better support existing operations and parameters
933
+ * Fixed an issue with the Amazon S3 client where an exception was thrown when trying to add a default Content-MD5
934
+ header to a request that uses a non-rewindable stream.
935
+ * Updated the Amazon S3 PostObject class to work with CNAME style buckets.
936
+
937
+ ## 2.5.2 - 2014-01-29
938
+
939
+ * Added support for dead letter queues to Amazon SQS
940
+ * Added support for the new M3 medium and large instance types to the Amazon EC2 client
941
+ * Added support for using the `eu-west-1` and `us-west-2` regions to the Amazon SES client
942
+ * Adding content-type guessing to the Amazon S3 stream wrapper (see #210)
943
+ * Added an event to the Amazon S3 multipart upload helpers to allow granular customization of multipart uploads during
944
+ a sync (see #209)
945
+ * Updated Signature V4 logic for Amazon S3 to throw an exception if you attempt to create a presigned URL that expires
946
+ later than a week (see #215)
947
+ * Fixed the `downloadBucket` and `uploadDirectory` methods to support relative paths and better support
948
+ Windows (see #207)
949
+ * Fixed issue #195 in the Amazon S3 multipart upload helpers to properly support additional parameters (see #211)
950
+ * [Docs] Expanded examples in the [API reference](http://docs.aws.amazon.com/aws-sdk-php/latest/index.html) by default
951
+ so they don't get overlooked
952
+ * [Docs] Moved the API reference links in the [service-specific user guide
953
+ pages](http://docs.aws.amazon.com/aws-sdk-php/guide/latest/index.html#service-specific-guides) to the bottom so
954
+ the page's content takes priority
955
+
956
+ ## 2.5.1 - 2014-01-09
957
+
958
+ * Added support for attaching existing Amazon EC2 instances to an Auto Scaling group to the Auto Scaling client
959
+ * Added support for creating launch configurations from existing Amazon EC2 instances to the Auto Scaling client
960
+ * Added support for describing Auto Scaling account limits to the Auto Scaling client
961
+ * Added better support for block device mappings to the Amazon AutoScaling client when creating launch configurations
962
+ * Added support for [ranged inventory retrieval](http://docs.aws.amazon.com/amazonglacier/latest/dev/api-initiate-job-post.html#api-initiate-job-post-vault-inventory-list-filtering)
963
+ to the Amazon Glacier client
964
+ * [Docs] Updated and added a lot of content in the [User Guide](http://docs.aws.amazon.com/aws-sdk-php/guide/latest/index.html)
965
+ * Fixed a bug where the `KinesisClient::getShardIterator()` method was not working properly
966
+ * Fixed an issue with Amazon SimpleDB where the 'Value' attribute was marked as required on DeleteAttribute and BatchDeleteAttributes
967
+ * Fixed an issue with the Amazon S3 stream wrapper where empty place holder keys were being marked as files instead of directories
968
+ * Added the ability to specify a custom signature implementation using a string identifier (e.g., 'v4', 'v2', etc)
969
+
970
+ ## 2.5.0 - 2013-12-20
971
+
972
+ * Added support for the new **China (Beijing) Region** to various services. This region is currently in limited preview.
973
+ Please see <http://www.amazonaws.cn> for more information
974
+ * Added support for different audio compression schemes to the Elastic Transcoder client (includes AAC-LC, HE-AAC,
975
+ and HE-AACv2)
976
+ * Added support for preset and pipeline pagination to the Elastic Transcoder client. You can now view more than the
977
+ first 50 presets and pipelines with their corresponding list operations
978
+ * Added support for [geo restriction](http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithDownloadDistributions.html#georestrictions)
979
+ to the Amazon CloudFront client
980
+ * [SDK] Added Signature V4 support to the Amazon S3 and Amazon EC2 clients for the new China (Beijing) Region
981
+ * [BC] Updated the AWS CloudTrail client to use their latest API changes due to early user feedback. Some parameters in
982
+ the `CreateTrail`, `UpdateTrail`, and `GetTrailStatus` have been deprecated and will be completely unavailable as
983
+ early as February 15th, 2014. Please see [this announcement on the CloudTrail
984
+ forum](https://forums.aws.amazon.com/ann.jspa?annID=2286). We are calling this out as a breaking change now to
985
+ encourage you to update your code at this time.
986
+ * Updated the Amazon CloudFront client to use the 2013-11-11 API version
987
+ * [BC] Updated the Amazon EC2 client to use the latest API. This resulted in a small change to a parameter in the
988
+ `RequestSpotInstances` operation. See [this commit](https://github.com/aws/aws-sdk-php/commit/36ae0f68d2a6dcc3bc28222f60ecb318449c4092#diff-bad2f6eac12565bb684f2015364c22bd)
989
+ for the change
990
+ * [BC] Removed Signature V3 support (no longer needed) and refactored parts of the signature-related classes
991
+
992
+ ## 2.4.12 - 2013-12-12
993
+
994
+ * Added support for **Amazon Kinesis**
995
+ * Added the CloudTrail `LogRecordIterator`, `LogFileIterator`, and `LogFileReader` classes for reading log files
996
+ generated by the CloudTrail service
997
+ * Added support for resource-level permissions to the AWS OpsWorks client
998
+ * Added support for worker environment tiers to the AWS Elastic Beanstalk client
999
+ * Added support for the new I2 instance types to the Amazon EC2 client
1000
+ * Added support for resource tagging to the Amazon Elastic MapReduce client
1001
+ * Added support for specifying a key encoding type to the Amazon S3 client
1002
+ * Added support for global secondary indexes to the Amazon DynamoDB client
1003
+ * Updated the Amazon ElastiCache client to use Signature Version 4
1004
+ * Fixed an issue in the waiter factory that caused an error when getting the factory for service clients without any
1005
+ existing waiters
1006
+ * Fixed issue #187, where the DynamoDB Session Handler would fail to save the session if all the data is removed
1007
+
1008
+ ## 2.4.11 - 2013-11-26
1009
+
1010
+ * Added support for copying DB snapshots from one AWS region to another to the Amazon RDS client
1011
+ * Added support for pagination of the `DescribeInstances` and `DescribeTags` operations to the Amazon EC2 client
1012
+ * Added support for the new C3 instance types and the g2.2xlarge instance type to the Amazon EC2 client
1013
+ * Added support for enabling *Single Root I/O Virtualization* (SR-IOV) support for the new C3 instance types to the
1014
+ Amazon EC2 client
1015
+ * Updated the Amazon EC2 client to use the 2013-10-15 API version
1016
+ * Updated the Amazon RDS client to use the 2013-09-09 API version
1017
+ * Updated the Amazon CloudWatch client to use Signature Version 4
1018
+
1019
+ ## 2.4.10 - 2013-11-14
1020
+
1021
+ * Added support for **AWS CloudTrail**
1022
+ * Added support for identity federation using SAML 2.0 to the AWS STS client
1023
+ * Added support for configuring SAML-compliant identity providers to the AWS IAM client
1024
+ * Added support for event notifications to the Amazon Redshift client
1025
+ * Added support for HSM storage for encryption keys to the Amazon Redshift client
1026
+ * Added support for encryption key rotation to the Amazon Redshift client
1027
+ * Added support for database audit logging to the Amazon Redshift client
1028
+
1029
+ ## 2.4.9 - 2013-11-08
1030
+
1031
+ * Added support for [cross-zone load balancing](http://aws.amazon.com/about-aws/whats-new/2013/11/06/elastic-load-balancing-adds-cross-zone-load-balancing/)
1032
+ to the Elastic Load Balancing client.
1033
+ * Added support for a [new gateway configuration](http://aws.amazon.com/about-aws/whats-new/2013/11/05/aws-storage-gateway-announces-gateway-virtual-tape-library/),
1034
+ Gateway-Virtual Tape Library, to the AWS Storage Gateway client.
1035
+ * Added support for stack policies to the the AWS CloudFormation client.
1036
+ * Fixed issue #176 where attempting to upload a direct to Amazon S3 using the `UploadBuilder` failed when using a custom
1037
+ iterator that needs to be rewound.
1038
+
1039
+ ## 2.4.8 - 2013-10-31
1040
+
1041
+ * Updated the AWS Direct Connect client
1042
+ * Updated the Amazon Elastic MapReduce client to add support for new EMR APIs, termination of specific cluster
1043
+ instances, and unlimited EMR steps.
1044
+
1045
+ ## 2.4.7 - 2013-10-17
1046
+
1047
+ * Added support for audio transcoding features to the Amazon Elastic Transcoder client
1048
+ * Added support for modifying Reserved Instances in a region to the Amazon EC2 client
1049
+ * Added support for new resource management features to the AWS OpsWorks client
1050
+ * Added support for additional HTTP methods to the Amazon CloudFront client
1051
+ * Added support for custom error page configuration to the Amazon CloudFront client
1052
+ * Added support for the public IP address association of instances in Auto Scaling group via the Auto Scaling client
1053
+ * Added support for tags and filters to various operations in the Amazon RDS client
1054
+ * Added the ability to easily specify event listeners on waiters
1055
+ * Added support for using the `ap-southeast-2` region to the Amazon Glacier client
1056
+ * Added support for using the `ap-southeast-1` and `ap-southeast-2` regions to the Amazon Redshift client
1057
+ * Updated the Amazon EC2 client to use the 2013-09-11 API version
1058
+ * Updated the Amazon CloudFront client to use the 2013-09-27 API version
1059
+ * Updated the AWS OpsWorks client to use the 2013-07-15 API version
1060
+ * Updated the Amazon CloudSearch client to use Signature Version 4
1061
+ * Fixed an issue with the Amazon S3 Client so that the top-level XML element of the `CompleteMultipartUpload` operation
1062
+ is correctly sent as `CompleteMultipartUpload`
1063
+ * Fixed an issue with the Amazon S3 Client so that you can now disable bucket logging using with the `PutBucketLogging`
1064
+ operation
1065
+ * Fixed an issue with the Amazon CloudFront so that query string parameters in pre-signed URLs are correctly URL-encoded
1066
+ * Fixed an issue with the Signature Version 4 implementation where headers with multiple values were sometimes sorted
1067
+ and signed incorrectly
1068
+
1069
+ ## 2.4.6 - 2013-09-12
1070
+
1071
+ * Added support for modifying EC2 Reserved Instances to the Amazon EC2 client
1072
+ * Added support for VPC features to the AWS OpsWorks client
1073
+ * Updated the DynamoDB Session Handler to implement the SessionHandlerInterface of PHP 5.4 when available
1074
+ * Updated the SNS Message Validator to throw an exception, instead of an error, when the raw post data is invalid
1075
+ * Fixed an issue in the S3 signature which ensures that parameters are sorted correctly for signing
1076
+ * Fixed an issue in the S3 client where the Sydney region was not allowed as a `LocationConstraint` for the
1077
+ `PutObject` operation
1078
+
1079
+ ## 2.4.5 - 2013-09-04
1080
+
1081
+ * Added support for replication groups to the Amazon ElastiCache client
1082
+ * Added support for using the `us-gov-west-1` region to the AWS CloudFormation client
1083
+
1084
+ ## 2.4.4 - 2013-08-29
1085
+
1086
+ * Added support for assigning a public IP address to an instance at launch to the Amazon EC2 client
1087
+ * Updated the Amazon EC2 client to use the 2013-07-15 API version
1088
+ * Updated the Amazon SWF client to sign requests with Signature V4
1089
+ * Updated the Instance Metadata client to allow for higher and more customizable connection timeouts
1090
+ * Fixed an issue with the SDK where XML map structures were not being serialized correctly in some cases
1091
+ * Fixed issue #136 where a few of the new Amazon SNS mobile push operations were not working properly
1092
+ * Fixed an issue where the AWS STS `AssumeRoleWithWebIdentity` operation was requiring credentials and a signature
1093
+ unnecessarily
1094
+ * Fixed and issue with the `S3Client::uploadDirectory` method so that true key prefixes can be used
1095
+ * [Docs] Updated the API docs to include sample code for each operation that indicates the parameter structure
1096
+ * [Docs] Updated the API docs to include more information in the descriptions of operations and parameters
1097
+ * [Docs] Added a page about Iterators to the user guide
1098
+
1099
+ ## 2.4.3 - 2013-08-12
1100
+
1101
+ * Added support for mobile push notifications to the Amazon SNS client
1102
+ * Added support for progress reporting on snapshot restore operations to the the Amazon Redshift client
1103
+ * Updated the Amazon Elastic MapReduce client to use JSON serialization
1104
+ * Updated the Amazon Elastic MapReduce client to sign requests with Signature V4
1105
+ * Updated the SDK to throw `Aws\Common\Exception\TransferException` exceptions when a network error occurs instead of a
1106
+ `Guzzle\Http\Exception\CurlException`. The TransferException class, however, extends from
1107
+ `Guzzle\Http\Exception\CurlException`. You can continue to catch the Guzzle `CurlException` or catch
1108
+ `Aws\Common\Exception\AwsExceptionInterface` to catch any exception that can be thrown by an AWS client
1109
+ * Fixed an issue with the Amazon S3 stream wrapper where trailing slashes were being added when listing directories
1110
+
1111
+ ## 2.4.2 - 2013-07-25
1112
+
1113
+ * Added support for cross-account snapshot access control to the Amazon Redshift client
1114
+ * Added support for decoding authorization messages to the AWS STS client
1115
+ * Added support for checking for required permissions via the `DryRun` parameter to the Amazon EC2 client
1116
+ * Added support for custom Amazon Machine Images (AMIs) and Chef 11 to the AWS OpsWorks client
1117
+ * Added an SDK compatibility test to allow users to quickly determine if their system meets the requirements of the SDK
1118
+ * Updated the Amazon EC2 client to use the 2013-06-15 API version
1119
+ * Fixed an unmarshalling error with the Amazon EC2 `CreateKeyPair` operation
1120
+ * Fixed an unmarshalling error with the Amazon S3 `ListMultipartUploads` operation
1121
+ * Fixed an issue with the Amazon S3 stream wrapper "x" fopen mode
1122
+ * Fixed an issue with `Aws\S3\S3Client::downloadBucket` by removing leading slashes from the passed `$keyPrefix` argument
1123
+
1124
+ ## 2.4.1 - 2013-06-08
1125
+
1126
+ * Added support for setting watermarks and max framerates to the Amazon Elastic Transcoder client
1127
+ * Added the `Aws\DynamoDb\Iterator\ItemIterator` class to make it easier to get items from the results of DynamoDB
1128
+ operations in a simpler form
1129
+ * Added support for the `cr1.8xlarge` EC2 instance type. Use `Aws\Ec2\Enum\InstanceType::CR1_8XLARGE`
1130
+ * Added support for the suppression list SES mailbox simulator. Use `Aws\Ses\Enum\MailboxSimulator::SUPPRESSION_LIST`
1131
+ * [SDK] Fixed an issue with data formats throughout the SDK due to a regression. Dates are now sent over the wire with
1132
+ the correct format. This issue affected the Amazon EC2, Amazon ElastiCache, AWS Elastic Beanstalk, Amazon EMR, and
1133
+ Amazon RDS clients
1134
+ * Fixed an issue with the parameter serialization of the `ImportInstance` operation in the Amazon EC2 client
1135
+ * Fixed an issue with the Amazon S3 client where the `RoutingRules.Redirect.HostName` parameter of the
1136
+ `PutBucketWebsite` operation was erroneously marked as required
1137
+ * Fixed an issue with the Amazon S3 client where the `DeleteObject` operation was missing parameters
1138
+ * Fixed an issue with the Amazon S3 client where the `Status` parameter of the `PutBucketVersioning` operation did not
1139
+ properly support the "Suspended" value
1140
+ * Fixed an issue with the Amazon Glacier `UploadPartGenerator` class so that an exception is thrown if the provided body
1141
+ to upload is less than 1 byte
1142
+ * Added MD5 validation to Amazon SQS ReceiveMessage operations
1143
+
1144
+ ## 2.4.0 - 2013-06-18
1145
+
1146
+ * [BC] Updated the Amazon CloudFront client to use the new 2013-05-12 API version which includes changes in how you
1147
+ configure distributions. If you are not ready to upgrade to the new API, you can configure the SDK to use the previous
1148
+ version of the API by setting the `version` option to `2012-05-05` when you instantiate the client (See
1149
+ [`UPGRADING.md`](https://github.com/aws/aws-sdk-php/blob/master/UPGRADING.md))
1150
+ * Added abstractions for uploading a local directory to an Amazon S3 bucket (`$s3->uploadDirectory()`)
1151
+ * Added abstractions for downloading an Amazon S3 bucket to local directory (`$s3->downloadBucket()`)
1152
+ * Added an easy to way to delete objects from an Amazon S3 bucket that match a regular expression or key prefix
1153
+ * Added an easy to way to upload an object to Amazon S3 that automatically uses a multipart upload if the size of the
1154
+ object exceeds a customizable threshold (`$s3->upload()`)
1155
+ * [SDK] Added facade classes for simple, static access to clients (e.g., `S3::putObject([...])`)
1156
+ * Added the `Aws\S3\S3Client::getObjectUrl` convenience method for getting the URL of an Amazon S3 object. This works
1157
+ for both public and pre-signed URLs
1158
+ * Added support for using the `ap-northeast-1` region to the Amazon Redshift client
1159
+ * Added support for configuring custom SSL certificates to the Amazon CloudFront client via the `ViewerCertificate`
1160
+ parameter
1161
+ * Added support for read replica status to the Amazon RDS client
1162
+ * Added "magic" access to iterators to make using iterators more convenient (e.g., `$s3->getListBucketsIterator()`)
1163
+ * Added the `waitUntilDBInstanceAvailable` and `waitUntilDBInstanceDeleted` waiters to the Amazon RDS client
1164
+ * Added the `createCredentials` method to the AWS STS client to make it easier to create a credentials object from the
1165
+ results of an STS operation
1166
+ * Updated the Amazon RDS client to use the 2013-05-15 API version
1167
+ * Updated request retrying logic to automatically refresh expired credentials and retry with new ones
1168
+ * Updated the Amazon CloudFront client to sign requests with Signature V4
1169
+ * Updated the Amazon SNS client to sign requests with Signature V4, which enables larger payloads
1170
+ * Updated the S3 Stream Wrapper so that you can use stream resources in any S3 operation without having to manually
1171
+ specify the `ContentLength` option
1172
+ * Fixed issue #94 so that the `Aws\S3\BucketStyleListener` is invoked on `command.after_prepare` and presigned URLs
1173
+ are generated correctly from S3 commands
1174
+ * Fixed an issue so that creating presigned URLs using the Amazon S3 client now works with temporary credentials
1175
+ * Fixed an issue so that the `CORSRules.AllowedHeaders` parameter is now available when configuring CORS for Amazon S3
1176
+ * Set the Guzzle dependency to ~3.7.0
1177
+
1178
+ ## 2.3.4 - 2013-05-30
1179
+
1180
+ * Set the Guzzle dependency to ~3.6.0
1181
+
1182
+ ## 2.3.3 - 2013-05-28
1183
+
1184
+ * Added support for web identity federation in the AWS Security Token Service (STS) API
1185
+ * Fixed an issue with creating pre-signed Amazon CloudFront RTMP URLs
1186
+ * Fixed issue #85 to correct the parameter serialization of NetworkInterfaces within the Amazon EC2 RequestSpotInstances
1187
+ operation
1188
+
1189
+ ## 2.3.2 - 2013-05-15
1190
+
1191
+ * Added support for doing parallel scans to the Amazon DynamoDB client
1192
+ * [OpsWorks] Added support for using Elastic Load Balancer to the AWS OpsWorks client
1193
+ * Added support for using EBS-backed instances to the AWS OpsWorks client along with some other minor updates
1194
+ * Added support for finer-grained error messages to the AWS Data Pipeline client and updated the service description
1195
+ * Added the ability to set the `key_pair_id` and `private_key` options at the time of signing a CloudFront URL instead
1196
+ of when instantiating the client
1197
+ * Added a new [Zip Download](http://pear.amazonwebservices.com/get/aws.zip) for installing the SDK
1198
+ * Fixed the API version for the AWS Support client to be `2013-04-15`
1199
+ * Fixed issue #78 by implementing `Aws\S3\StreamWrapper::stream_cast()` for the S3 stream wrapper
1200
+ * Fixed issue #79 by updating the S3 `ClearBucket` object to work with the `ListObjects` operation
1201
+ * Fixed issue #80 where the `ETag` was incorrectly labeled as a header value instead of being in the XML body for
1202
+ the S3 `CompleteMultipartUpload` operation response
1203
+ * Fixed an issue where the `setCredentials()` method did not properly update the `SignatureListener`
1204
+ * Updated the required version of Guzzle to `">=3.4.3,<4"` to support Guzzle 3.5 which provides the SDK with improved
1205
+ memory management
1206
+
1207
+ ## 2.3.1 - 2013-04-30
1208
+
1209
+ * Added support for **AWS Support**
1210
+ * Added support for using the `eu-west-1` region to the Amazon Redshift client
1211
+ * Fixed an issue with the Amazon RDS client where the `DownloadDBLogFilePortion` operation was not being serialized
1212
+ properly
1213
+ * Fixed an issue with the Amazon S3 client where the `PutObjectCopy` alias was interfering with the `CopyObject`
1214
+ operation
1215
+ * Added the ability to manually set a Content-Length header when using the `PutObject` and `UploadPart` operations of
1216
+ the Amazon S3 client
1217
+ * Fixed an issue where the Amazon S3 class was not throwing an exception for a non-followable 301 redirect response
1218
+ * Fixed an issue where `fflush()` was called during the shutdown process of the stream handler for read-only streams
1219
+
1220
+ ## 2.3.0 - 2013-04-18
1221
+
1222
+ * Added support for Local Secondary Indexes to the Amazon DynamoDB client
1223
+ * [BC] Updated the Amazon DynamoDB client to use the new 2012-08-10 API version which includes changes in how you
1224
+ specify keys. If you are not ready to upgrade to the new API, you can configure the SDK to use the previous version of
1225
+ the API by setting the `version` option to `2011-12-05` when you instantiate the client (See
1226
+ [`UPGRADING.md`](https://github.com/aws/aws-sdk-php/blob/master/UPGRADING.md)).
1227
+ * Added an Amazon S3 stream wrapper that allows PHP native file functions to be used to interact with S3 buckets and
1228
+ objects
1229
+ * Added support for automatically retrying *throttled* requests with exponential backoff to all service clients
1230
+ * Added a new config option (`version`) to client objects to specify the API version to use if multiple are supported
1231
+ * Added a new config option (`gc_operation_delay`) to the DynamoDB Session Handler to specify a delay between requests
1232
+ to the service during garbage collection in order to help regulate the consumption of throughput
1233
+ * Added support for using the `us-west-2` region to the Amazon Redshift client
1234
+ * [Docs] Added a way to use marked integration test code as example code in the user guide and API docs
1235
+ * Updated the Amazon RDS client to sign requests with Signature V4
1236
+ * Updated the Amazon S3 client to automatically add the `Content-Type` to `PutObject` and other upload operations
1237
+ * Fixed an issue where service clients with a global endpoint could have their region for signing set incorrectly if a
1238
+ region other than `us-east-1` was specified.
1239
+ * Fixed an issue where reused command objects appended duplicate content to the user agent string
1240
+ * [SDK] Fixed an issue in a few operations (including `SQS::receiveMessage`) where the `curl.options` could not be
1241
+ modified
1242
+ * [Docs] Added key information to the DynamoDB service description to provide more accurate API docs for some operations
1243
+ * [Docs] Added a page about Waiters to the user guide
1244
+ * [Docs] Added a page about the DynamoDB Session Handler to the user guide
1245
+ * [Docs] Added a page about response Models to the user guide
1246
+ * Bumped the required version of Guzzle to ~3.4.1
1247
+
1248
+ ## 2.2.1 - 2013-03-18
1249
+
1250
+ * Added support for viewing and downloading DB log files to the Amazon RDS client
1251
+ * Added the ability to validate incoming Amazon SNS messages. See the `Aws\Sns\MessageValidator` namespace
1252
+ * Added the ability to easily change the credentials that a client is configured to use via `$client->setCredentials()`
1253
+ * Added the `client.region_changed` and `client.credentials_changed` events on the client that are triggered when the
1254
+ `setRegion()` and `setCredentials()` methods are called, respectively
1255
+ * Added support for using the `ap-southeast-2` region with the Amazon ElastiCache client
1256
+ * Added support for using the `us-gov-west-1` region with the Amazon SWF client
1257
+ * Updated the Amazon RDS client to use the 2013-02-12 API version
1258
+ * Fixed an issue in the Amazon EC2 service description that was affecting the use of the new `ModifyVpcAttribute` and
1259
+ `DescribeVpcAttribute` operations
1260
+ * Added `ObjectURL` to the output of an Amazon S3 PutObject operation so that you can more easily retrieve the URL of an
1261
+ object after uploading
1262
+ * Added a `createPresignedUrl()` method to any command object created by the Amazon S3 client to more easily create
1263
+ presigned URLs
1264
+
1265
+ ## 2.2.0 - 2013-03-11
1266
+
1267
+ * Added support for **Amazon Elastic MapReduce (Amazon EMR)**
1268
+ * Added support for **AWS Direct Connect**
1269
+ * Added support for **Amazon ElastiCache**
1270
+ * Added support for **AWS Storage Gateway**
1271
+ * Added support for **AWS Import/Export**
1272
+ * Added support for **AWS CloudFormation**
1273
+ * Added support for **Amazon CloudSearch**
1274
+ * Added support for [provisioned IOPS](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.ProvisionedIOPS.html)
1275
+ to the the Amazon RDS client
1276
+ * Added support for promoting [read replicas](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html)
1277
+ to the Amazon RDS client
1278
+ * Added support for [event notification subscriptions](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.html)
1279
+ to the Amazon RDS client
1280
+ * Added support for enabling\disabling DNS Hostnames and DNS Resolution in Amazon VPC to the Amazon EC2 client
1281
+ * Added support for enumerating account attributes to the Amazon EC2 client
1282
+ * Added support for copying AMIs across regions to the Amazon EC2 client
1283
+ * Added the ability to get a Waiter object from a client using the `getWaiter()` method
1284
+ * [SDK] Added the ability to load credentials from environmental variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_KEY`.
1285
+ This is compatible with AWS Elastic Beanstalk environment configurations
1286
+ * Added support for using the us-west-1, us-west-2, eu-west-1, and ap-southeast-1 regions with Amazon CloudSearch
1287
+ * Updated the Amazon RDS client to use the 2013-01-10 API version
1288
+ * Updated the Amazon EC2 client to use the 2013-02-01 API version
1289
+ * Added support for using SecurityToken with signature version 2 services
1290
+ * Added the client User-Agent header to exception messages for easier debugging
1291
+ * Added an easier way to disable operation parameter validation by setting `validation` to false when creating clients
1292
+ * Added the ability to disable the exponential backoff plugin
1293
+ * Added the ability to easily fetch the region name that a client is configured to use via `$client->getRegion()`
1294
+ * Added end-user guides available at http://docs.aws.amazon.com/aws-sdk-php/guide/latest/
1295
+ * Fixed issue #48 where signing Amazon S3 requests with null or empty metadata resulted in a signature error
1296
+ * Fixed issue #29 where Amazon S3 was intermittently closing a connection
1297
+ * Updated the Amazon S3 client to parse the AcceptRanges header for HeadObject and GetObject output
1298
+ * Updated the Amazon Glacier client to allow the `saveAs` parameter to be specified as an alias for `command.response_body`
1299
+ * Various performance improvements throughout the SDK
1300
+ * Removed endpoint providers and now placing service region information directly in service descriptions
1301
+ * Removed client resolvers when creating clients in a client's factory method (this should not have any impact to end users)
1302
+
1303
+ ## 2.1.2 - 2013-02-18
1304
+
1305
+ * Added support for **AWS OpsWorks**
1306
+
1307
+ ## 2.1.1 - 2013-02-15
1308
+
1309
+ * Added support for **Amazon Redshift**
1310
+ * Added support for **Amazon Simple Queue Service (Amazon SQS)**
1311
+ * Added support for **Amazon Simple Notification Service (Amazon SNS)**
1312
+ * Added support for **Amazon Simple Email Service (Amazon SES)**
1313
+ * Added support for **Auto Scaling**
1314
+ * Added support for **Amazon CloudWatch**
1315
+ * Added support for **Amazon Simple Workflow Service (Amazon SWF)**
1316
+ * Added support for **Amazon Relational Database Service (Amazon RDS)**
1317
+ * Added support for health checks and failover in Amazon Route 53
1318
+ * Updated the Amazon Route 53 client to use the 2012-12-12 API version
1319
+ * Updated `AbstractWaiter` to dispatch `waiter.before_attempt` and `waiter.before_wait` events
1320
+ * Updated `CallableWaiter` to allow for an array of context data to be passed to the callable
1321
+ * Fixed issue #29 so that the stat cache is cleared before performing multipart uploads
1322
+ * Fixed issue #38 so that Amazon CloudFront URLs are signed properly
1323
+ * Fixed an issue with Amazon S3 website redirects
1324
+ * Fixed a URL encoding inconsistency with Amazon S3 and pre-signed URLs
1325
+ * Fixed issue #42 to eliminate cURL error 65 for JSON services
1326
+ * Set Guzzle dependency to [~3.2.0](https://github.com/guzzle/guzzle/blob/master/CHANGELOG.md#320-2013-02-14)
1327
+ * Minimum version of PHP is now 5.3.3
1328
+
1329
+ ## 2.1.0 - 2013-01-28
1330
+
1331
+ * Waiters now require an associative array as input for the underlying operation performed by a waiter. See
1332
+ `UPGRADING.md` for details.
1333
+ * Added support for **Amazon Elastic Compute Cloud (Amazon EC2)**
1334
+ * Added support for **Amazon Elastic Transcoder**
1335
+ * Added support for **Amazon SimpleDB**
1336
+ * Added support for **Elastic Load Balancing**
1337
+ * Added support for **AWS Elastic Beanstalk**
1338
+ * Added support for **AWS Identity and Access Management (IAM)**
1339
+ * Added support for Amazon S3 website redirection rules
1340
+ * Added support for the `RetrieveByteRange` parameter of the `InitiateJob` operation in Amazon Glacier
1341
+ * Added support for Signature Version 2
1342
+ * Clients now gain more information from service descriptions rather than client factory methods
1343
+ * Service descriptions are now versioned for clients
1344
+ * Fixed an issue where Amazon S3 did not use "restore" as a signable resource
1345
+ * Fixed an issue with Amazon S3 where `x-amz-meta-*` headers were not properly added with the CopyObject operation
1346
+ * Fixed an issue where the Amazon Glacier client was not using the correct User-Agent header
1347
+ * Fixed issue #13 in which constants defined by referencing other constants caused errors with early versions of PHP 5.3
1348
+
1349
+ ## 2.0.3 - 2012-12-20
1350
+
1351
+ * Added support for **AWS Data Pipeline**
1352
+ * Added support for **Amazon Route 53**
1353
+ * Fixed an issue with the Amazon S3 client where object keys with slashes were causing errors
1354
+ * Added a `SaveAs` parameter to the Amazon S3 `GetObject` operation to allow saving the object directly to a file
1355
+ * Refactored iterators to remove code duplication and ease creation of future iterators
1356
+
1357
+ ## 2.0.2 - 2012-12-10
1358
+
1359
+ * Fixed an issue with the Amazon S3 client where non-DNS compatible buckets that was previously causing a signature
1360
+ mismatch error
1361
+ * Fixed an issue with the service description for the Amazon S3 `UploadPart` operation so that it works correctly
1362
+ * Fixed an issue with the Amazon S3 service description dealing with `response-*` query parameters of `GetObject`
1363
+ * Fixed an issue with the Amazon S3 client where object keys prefixed by the bucket name were being treated incorrectly
1364
+ * Fixed an issue with `Aws\S3\Model\MultipartUpload\ParallelTransfer` class
1365
+ * Added support for the `AssumeRole` operation for AWS STS
1366
+ * Added a the `UploadBodyListener` which allows upload operations in Amazon S3 and Amazon Glacier to accept file handles
1367
+ in the `Body` parameter and file paths in the `SourceFile` parameter
1368
+ * Added Content-Type guessing for uploads
1369
+ * Added new region endpoints, including sa-east-1 and us-gov-west-1 for Amazon DynamoDB
1370
+ * Added methods to `Aws\S3\Model\MultipartUpload\UploadBuilder` class to make setting ACL and Content-Type easier
1371
+
1372
+ ## 2.0.1 - 2012-11-13
1373
+
1374
+ * Fixed a signature issue encountered when a request to Amazon S3 is redirected
1375
+ * Added support for archiving Amazon S3 objects to Amazon Glacier
1376
+ * Added CRC32 validation of Amazon DynamoDB responses
1377
+ * Added ConsistentRead support to the `BatchGetItem` operation of Amazon DynamoDB
1378
+ * Added new region endpoints, including Sydney
1379
+
1380
+ ## 2.0.0 - 2012-11-02
1381
+
1382
+ * Initial release of the AWS SDK for PHP Version 2. See <http://aws.amazon.com/sdkforphp2/> for more information.
1383
+ * Added support for **Amazon Simple Storage Service (Amazon S3)**
1384
+ * Added support for **Amazon DynamoDB**
1385
+ * Added support for **Amazon Glacier**
1386
+ * Added support for **Amazon CloudFront**
1387
+ * Added support for **AWS Security Token Service (AWS STS)**
includes/aws/GuzzleHttp/Client.php ADDED
@@ -0,0 +1,397 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Cookie\CookieJar;
5
+ use GuzzleHttp\Promise;
6
+ use GuzzleHttp\Psr7;
7
+ use Psr\Http\Message\UriInterface;
8
+ use Psr\Http\Message\RequestInterface;
9
+ use Psr\Http\Message\ResponseInterface;
10
+
11
+ /**
12
+ * @method ResponseInterface get($uri, array $options = [])
13
+ * @method ResponseInterface head($uri, array $options = [])
14
+ * @method ResponseInterface put($uri, array $options = [])
15
+ * @method ResponseInterface post($uri, array $options = [])
16
+ * @method ResponseInterface patch($uri, array $options = [])
17
+ * @method ResponseInterface delete($uri, array $options = [])
18
+ * @method Promise\PromiseInterface getAsync($uri, array $options = [])
19
+ * @method Promise\PromiseInterface headAsync($uri, array $options = [])
20
+ * @method Promise\PromiseInterface putAsync($uri, array $options = [])
21
+ * @method Promise\PromiseInterface postAsync($uri, array $options = [])
22
+ * @method Promise\PromiseInterface patchAsync($uri, array $options = [])
23
+ * @method Promise\PromiseInterface deleteAsync($uri, array $options = [])
24
+ */
25
+ class Client implements ClientInterface
26
+ {
27
+ /** @var array Default request options */
28
+ private $config;
29
+
30
+ /**
31
+ * Clients accept an array of constructor parameters.
32
+ *
33
+ * Here's an example of creating a client using a base_uri and an array of
34
+ * default request options to apply to each request:
35
+ *
36
+ * $client = new Client([
37
+ * 'base_uri' => 'http://www.foo.com/1.0/',
38
+ * 'timeout' => 0,
39
+ * 'allow_redirects' => false,
40
+ * 'proxy' => '192.168.16.1:10'
41
+ * ]);
42
+ *
43
+ * Client configuration settings include the following options:
44
+ *
45
+ * - handler: (callable) Function that transfers HTTP requests over the
46
+ * wire. The function is called with a Psr7\Http\Message\RequestInterface
47
+ * and array of transfer options, and must return a
48
+ * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
49
+ * Psr7\Http\Message\ResponseInterface on success. "handler" is a
50
+ * constructor only option that cannot be overridden in per/request
51
+ * options. If no handler is provided, a default handler will be created
52
+ * that enables all of the request options below by attaching all of the
53
+ * default middleware to the handler.
54
+ * - base_uri: (string|UriInterface) Base URI of the client that is merged
55
+ * into relative URIs. Can be a string or instance of UriInterface.
56
+ * - **: any request option
57
+ *
58
+ * @param array $config Client configuration settings.
59
+ *
60
+ * @see \GuzzleHttp\RequestOptions for a list of available request options.
61
+ */
62
+ public function __construct(array $config = [])
63
+ {
64
+ if (!isset($config['handler'])) {
65
+ $config['handler'] = HandlerStack::create();
66
+ }
67
+
68
+ // Convert the base_uri to a UriInterface
69
+ if (isset($config['base_uri'])) {
70
+ $config['base_uri'] = Psr7\uri_for($config['base_uri']);
71
+ }
72
+
73
+ $this->configureDefaults($config);
74
+ }
75
+
76
+ public function __call($method, $args)
77
+ {
78
+ if (count($args) < 1) {
79
+ throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
80
+ }
81
+
82
+ $uri = $args[0];
83
+ $opts = isset($args[1]) ? $args[1] : [];
84
+
85
+ return substr($method, -5) === 'Async'
86
+ ? $this->requestAsync(substr($method, 0, -5), $uri, $opts)
87
+ : $this->request($method, $uri, $opts);
88
+ }
89
+
90
+ public function sendAsync(RequestInterface $request, array $options = [])
91
+ {
92
+ // Merge the base URI into the request URI if needed.
93
+ $options = $this->prepareDefaults($options);
94
+
95
+ return $this->transfer(
96
+ $request->withUri($this->buildUri($request->getUri(), $options)),
97
+ $options
98
+ );
99
+ }
100
+
101
+ public function send(RequestInterface $request, array $options = [])
102
+ {
103
+ $options[RequestOptions::SYNCHRONOUS] = true;
104
+ return $this->sendAsync($request, $options)->wait();
105
+ }
106
+
107
+ public function requestAsync($method, $uri = null, array $options = [])
108
+ {
109
+ $options = $this->prepareDefaults($options);
110
+ // Remove request modifying parameter because it can be done up-front.
111
+ $headers = isset($options['headers']) ? $options['headers'] : [];
112
+ $body = isset($options['body']) ? $options['body'] : null;
113
+ $version = isset($options['version']) ? $options['version'] : '1.1';
114
+ // Merge the URI into the base URI.
115
+ $uri = $this->buildUri($uri, $options);
116
+ if (is_array($body)) {
117
+ $this->invalidBody();
118
+ }
119
+ $request = new Psr7\Request($method, $uri, $headers, $body, $version);
120
+ // Remove the option so that they are not doubly-applied.
121
+ unset($options['headers'], $options['body'], $options['version']);
122
+
123
+ return $this->transfer($request, $options);
124
+ }
125
+
126
+ public function request($method, $uri = null, array $options = [])
127
+ {
128
+ $options[RequestOptions::SYNCHRONOUS] = true;
129
+ return $this->requestAsync($method, $uri, $options)->wait();
130
+ }
131
+
132
+ public function getConfig($option = null)
133
+ {
134
+ return $option === null
135
+ ? $this->config
136
+ : (isset($this->config[$option]) ? $this->config[$option] : null);
137
+ }
138
+
139
+ private function buildUri($uri, array $config)
140
+ {
141
+ if (!isset($config['base_uri'])) {
142
+ return $uri instanceof UriInterface ? $uri : new Psr7\Uri($uri);
143
+ }
144
+
145
+ return Psr7\Uri::resolve(Psr7\uri_for($config['base_uri']), $uri);
146
+ }
147
+
148
+ /**
149
+ * Configures the default options for a client.
150
+ *
151
+ * @param array $config
152
+ */
153
+ private function configureDefaults(array $config)
154
+ {
155
+ $defaults = [
156
+ 'allow_redirects' => RedirectMiddleware::$defaultSettings,
157
+ 'http_errors' => true,
158
+ 'decode_content' => true,
159
+ 'verify' => true,
160
+ 'cookies' => false
161
+ ];
162
+
163
+ // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set
164
+ if ($proxy = getenv('HTTP_PROXY')) {
165
+ $defaults['proxy']['http'] = $proxy;
166
+ }
167
+
168
+ if ($proxy = getenv('HTTPS_PROXY')) {
169
+ $defaults['proxy']['https'] = $proxy;
170
+ }
171
+
172
+ if ($noProxy = getenv('NO_PROXY')) {
173
+ $cleanedNoProxy = str_replace(' ', '', $noProxy);
174
+ $defaults['proxy']['no'] = explode(',', $cleanedNoProxy);
175
+ }
176
+
177
+ $this->config = $config + $defaults;
178
+
179
+ if (!empty($config['cookies']) && $config['cookies'] === true) {
180
+ $this->config['cookies'] = new CookieJar();
181
+ }
182
+
183
+ // Add the default user-agent header.
184
+ if (!isset($this->config['headers'])) {
185
+ $this->config['headers'] = ['User-Agent' => default_user_agent()];
186
+ } else {
187
+ // Add the User-Agent header if one was not already set.
188
+ foreach (array_keys($this->config['headers']) as $name) {
189
+ if (strtolower($name) === 'user-agent') {
190
+ return;
191
+ }
192
+ }
193
+ $this->config['headers']['User-Agent'] = default_user_agent();
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Merges default options into the array.
199
+ *
200
+ * @param array $options Options to modify by reference
201
+ *
202
+ * @return array
203
+ */
204
+ private function prepareDefaults($options)
205
+ {
206
+ $defaults = $this->config;
207
+
208
+ if (!empty($defaults['headers'])) {
209
+ // Default headers are only added if they are not present.
210
+ $defaults['_conditional'] = $defaults['headers'];
211
+ unset($defaults['headers']);
212
+ }
213
+
214
+ // Special handling for headers is required as they are added as
215
+ // conditional headers and as headers passed to a request ctor.
216
+ if (array_key_exists('headers', $options)) {
217
+ // Allows default headers to be unset.
218
+ if ($options['headers'] === null) {
219
+ $defaults['_conditional'] = null;
220
+ unset($options['headers']);
221
+ } elseif (!is_array($options['headers'])) {
222
+ throw new \InvalidArgumentException('headers must be an array');
223
+ }
224
+ }
225
+
226
+ // Shallow merge defaults underneath options.
227
+ $result = $options + $defaults;
228
+
229
+ // Remove null values.
230
+ foreach ($result as $k => $v) {
231
+ if ($v === null) {
232
+ unset($result[$k]);
233
+ }
234
+ }
235
+
236
+ return $result;
237
+ }
238
+
239
+ /**
240
+ * Transfers the given request and applies request options.
241
+ *
242
+ * The URI of the request is not modified and the request options are used
243
+ * as-is without merging in default options.
244
+ *
245
+ * @param RequestInterface $request
246
+ * @param array $options
247
+ *
248
+ * @return Promise\PromiseInterface
249
+ */
250
+ private function transfer(RequestInterface $request, array $options)
251
+ {
252
+ // save_to -> sink
253
+ if (isset($options['save_to'])) {
254
+ $options['sink'] = $options['save_to'];
255
+ unset($options['save_to']);
256
+ }
257
+
258
+ // exceptions -> http_error
259
+ if (isset($options['exceptions'])) {
260
+ $options['http_errors'] = $options['exceptions'];
261
+ unset($options['exceptions']);
262
+ }
263
+
264
+ $request = $this->applyOptions($request, $options);
265
+ $handler = $options['handler'];
266
+
267
+ try {
268
+ return Promise\promise_for($handler($request, $options));
269
+ } catch (\Exception $e) {
270
+ return Promise\rejection_for($e);
271
+ }
272
+ }
273
+
274
+ /**
275
+ * Applies the array of request options to a request.
276
+ *
277
+ * @param RequestInterface $request
278
+ * @param array $options
279
+ *
280
+ * @return RequestInterface
281
+ */
282
+ private function applyOptions(RequestInterface $request, array &$options)
283
+ {
284
+ $modify = [];
285
+
286
+ if (isset($options['form_params'])) {
287
+ if (isset($options['multipart'])) {
288
+ throw new \InvalidArgumentException('You cannot use '
289
+ . 'form_params and multipart at the same time. Use the '
290
+ . 'form_params option if you want to send application/'
291
+ . 'x-www-form-urlencoded requests, and the multipart '
292
+ . 'option to send multipart/form-data requests.');
293
+ }
294
+ $options['body'] = http_build_query($options['form_params'], null, '&');
295
+ unset($options['form_params']);
296
+ $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
297
+ }
298
+
299
+ if (isset($options['multipart'])) {
300
+ $elements = $options['multipart'];
301
+ unset($options['multipart']);
302
+ $options['body'] = new Psr7\MultipartStream($elements);
303
+ }
304
+
305
+ if (!empty($options['decode_content'])
306
+ && $options['decode_content'] !== true
307
+ ) {
308
+ $modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
309
+ }
310
+
311
+ if (isset($options['headers'])) {
312
+ if (isset($modify['set_headers'])) {
313
+ $modify['set_headers'] = $options['headers'] + $modify['set_headers'];
314
+ } else {
315
+ $modify['set_headers'] = $options['headers'];
316
+ }
317
+ unset($options['headers']);
318
+ }
319
+
320
+ if (isset($options['body'])) {
321
+ if (is_array($options['body'])) {
322
+ $this->invalidBody();
323
+ }
324
+ $modify['body'] = Psr7\stream_for($options['body']);
325
+ unset($options['body']);
326
+ }
327
+
328
+ if (!empty($options['auth'])) {
329
+ $value = $options['auth'];
330
+ $type = is_array($value)
331
+ ? (isset($value[2]) ? strtolower($value[2]) : 'basic')
332
+ : $value;
333
+ $config['auth'] = $value;
334
+ switch (strtolower($type)) {
335
+ case 'basic':
336
+ $modify['set_headers']['Authorization'] = 'Basic '
337
+ . base64_encode("$value[0]:$value[1]");
338
+ break;
339
+ case 'digest':
340
+ // @todo: Do not rely on curl
341
+ $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
342
+ $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
343
+ break;
344
+ }
345
+ }
346
+
347
+ if (isset($options['query'])) {
348
+ $value = $options['query'];
349
+ if (is_array($value)) {
350
+ $value = http_build_query($value, null, '&', PHP_QUERY_RFC3986);
351
+ }
352
+ if (!is_string($value)) {
353
+ throw new \InvalidArgumentException('query must be a string or array');
354
+ }
355
+ $modify['query'] = $value;
356
+ unset($options['query']);
357
+ }
358
+
359
+ if (isset($options['json'])) {
360
+ $modify['body'] = Psr7\stream_for(json_encode($options['json']));
361
+ $options['_conditional']['Content-Type'] = 'application/json';
362
+ unset($options['json']);
363
+ }
364
+
365
+ $request = Psr7\modify_request($request, $modify);
366
+ if ($request->getBody() instanceof Psr7\MultipartStream) {
367
+ // Use a multipart/form-data POST if a Content-Type is not set.
368
+ $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
369
+ . $request->getBody()->getBoundary();
370
+ }
371
+
372
+ // Merge in conditional headers if they are not present.
373
+ if (isset($options['_conditional'])) {
374
+ // Build up the changes so it's in a single clone of the message.
375
+ $modify = [];
376
+ foreach ($options['_conditional'] as $k => $v) {
377
+ if (!$request->hasHeader($k)) {
378
+ $modify['set_headers'][$k] = $v;
379
+ }
380
+ }
381
+ $request = Psr7\modify_request($request, $modify);
382
+ // Don't pass this internal value along to middleware/handlers.
383
+ unset($options['_conditional']);
384
+ }
385
+
386
+ return $request;
387
+ }
388
+
389
+ private function invalidBody()
390
+ {
391
+ throw new \InvalidArgumentException('Passing in the "body" request '
392
+ . 'option as an array to send a POST request has been deprecated. '
393
+ . 'Please use the "form_params" request option to send a '
394
+ . 'application/x-www-form-urlencoded request, or a the "multipart" '
395
+ . 'request option to send a multipart/form-data request.');
396
+ }
397
+ }
includes/aws/GuzzleHttp/ClientInterface.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Promise\PromiseInterface;
5
+ use GuzzleHttp\Exception\GuzzleException;
6
+ use Psr\Http\Message\RequestInterface;
7
+ use Psr\Http\Message\ResponseInterface;
8
+ use Psr\Http\Message\UriInterface;
9
+
10
+ /**
11
+ * Client interface for sending HTTP requests.
12
+ */
13
+ interface ClientInterface
14
+ {
15
+ const VERSION = '6.1.1';
16
+
17
+ /**
18
+ * Send an HTTP request.
19
+ *
20
+ * @param RequestInterface $request Request to send
21
+ * @param array $options Request options to apply to the given
22
+ * request and to the transfer.
23
+ *
24
+ * @return ResponseInterface
25
+ * @throws GuzzleException
26
+ */
27
+ public function send(RequestInterface $request, array $options = []);
28
+
29
+ /**
30
+ * Asynchronously send an HTTP request.
31
+ *
32
+ * @param RequestInterface $request Request to send
33
+ * @param array $options Request options to apply to the given
34
+ * request and to the transfer.
35
+ *
36
+ * @return PromiseInterface
37
+ */
38
+ public function sendAsync(RequestInterface $request, array $options = []);
39
+
40
+ /**
41
+ * Create and send an HTTP request.
42
+ *
43
+ * Use an absolute path to override the base path of the client, or a
44
+ * relative path to append to the base path of the client. The URL can
45
+ * contain the query string as well.
46
+ *
47
+ * @param string $method HTTP method
48
+ * @param string|UriInterface $uri URI object or string.
49
+ * @param array $options Request options to apply.
50
+ *
51
+ * @return ResponseInterface
52
+ * @throws GuzzleException
53
+ */
54
+ public function request($method, $uri, array $options = []);
55
+
56
+ /**
57
+ * Create and send an asynchronous HTTP request.
58
+ *
59
+ * Use an absolute path to override the base path of the client, or a
60
+ * relative path to append to the base path of the client. The URL can
61
+ * contain the query string as well. Use an array to provide a URL
62
+ * template and additional variables to use in the URL template expansion.
63
+ *
64
+ * @param string $method HTTP method
65
+ * @param string|UriInterface $uri URI object or string.
66
+ * @param array $options Request options to apply.
67
+ *
68
+ * @return PromiseInterface
69
+ */
70
+ public function requestAsync($method, $uri, array $options = []);
71
+
72
+ /**
73
+ * Get a client configuration option.
74
+ *
75
+ * These options include default request options of the client, a "handler"
76
+ * (if utilized by the concrete client), and a "base_uri" if utilized by
77
+ * the concrete client.
78
+ *
79
+ * @param string|null $option The config option to retrieve.
80
+ *
81
+ * @return mixed
82
+ */
83
+ public function getConfig($option = null);
84
+ }
includes/aws/GuzzleHttp/Cookie/CookieJar.php ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+ use Psr\Http\Message\ResponseInterface;
6
+
7
+ /**
8
+ * Cookie jar that stores cookies an an array
9
+ */
10
+ class CookieJar implements CookieJarInterface
11
+ {
12
+ /** @var SetCookie[] Loaded cookie data */
13
+ private $cookies = [];
14
+
15
+ /** @var bool */
16
+ private $strictMode;
17
+
18
+ /**
19
+ * @param bool $strictMode Set to true to throw exceptions when invalid
20
+ * cookies are added to the cookie jar.
21
+ * @param array $cookieArray Array of SetCookie objects or a hash of
22
+ * arrays that can be used with the SetCookie
23
+ * constructor
24
+ */
25
+ public function __construct($strictMode = false, $cookieArray = [])
26
+ {
27
+ $this->strictMode = $strictMode;
28
+
29
+ foreach ($cookieArray as $cookie) {
30
+ if (!($cookie instanceof SetCookie)) {
31
+ $cookie = new SetCookie($cookie);
32
+ }
33
+ $this->setCookie($cookie);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Create a new Cookie jar from an associative array and domain.
39
+ *
40
+ * @param array $cookies Cookies to create the jar from
41
+ * @param string $domain Domain to set the cookies to
42
+ *
43
+ * @return self
44
+ */
45
+ public static function fromArray(array $cookies, $domain)
46
+ {
47
+ $cookieJar = new self();
48
+ foreach ($cookies as $name => $value) {
49
+ $cookieJar->setCookie(new SetCookie([
50
+ 'Domain' => $domain,
51
+ 'Name' => $name,
52
+ 'Value' => $value,
53
+ 'Discard' => true
54
+ ]));
55
+ }
56
+
57
+ return $cookieJar;
58
+ }
59
+
60
+ /**
61
+ * Quote the cookie value if it is not already quoted and it contains
62
+ * problematic characters.
63
+ *
64
+ * @param string $value Value that may or may not need to be quoted
65
+ *
66
+ * @return string
67
+ */
68
+ public static function getCookieValue($value)
69
+ {
70
+ if (substr($value, 0, 1) !== '"' &&
71
+ substr($value, -1, 1) !== '"' &&
72
+ strpbrk($value, ';,=')
73
+ ) {
74
+ $value = '"' . $value . '"';
75
+ }
76
+
77
+ return $value;
78
+ }
79
+
80
+ /**
81
+ * Evaluate if this cookie should be persisted to storage
82
+ * that survives between requests.
83
+ *
84
+ * @param SetCookie $cookie Being evaluated.
85
+ * @param bool $allowSessionCookies If we should persist session cookies
86
+ * @return bool
87
+ */
88
+ public static function shouldPersist(
89
+ SetCookie $cookie,
90
+ $allowSessionCookies = false
91
+ ) {
92
+ if ($cookie->getExpires() || $allowSessionCookies) {
93
+ if (!$cookie->getDiscard()) {
94
+ return true;
95
+ }
96
+ }
97
+
98
+ return false;
99
+ }
100
+
101
+ public function toArray()
102
+ {
103
+ return array_map(function (SetCookie $cookie) {
104
+ return $cookie->toArray();
105
+ }, $this->getIterator()->getArrayCopy());
106
+ }
107
+
108
+ public function clear($domain = null, $path = null, $name = null)
109
+ {
110
+ if (!$domain) {
111
+ $this->cookies = [];
112
+ return;
113
+ } elseif (!$path) {
114
+ $this->cookies = array_filter(
115
+ $this->cookies,
116
+ function (SetCookie $cookie) use ($path, $domain) {
117
+ return !$cookie->matchesDomain($domain);
118
+ }
119
+ );
120
+ } elseif (!$name) {
121
+ $this->cookies = array_filter(
122
+ $this->cookies,
123
+ function (SetCookie $cookie) use ($path, $domain) {
124
+ return !($cookie->matchesPath($path) &&
125
+ $cookie->matchesDomain($domain));
126
+ }
127
+ );
128
+ } else {
129
+ $this->cookies = array_filter(
130
+ $this->cookies,
131
+ function (SetCookie $cookie) use ($path, $domain, $name) {
132
+ return !($cookie->getName() == $name &&
133
+ $cookie->matchesPath($path) &&
134
+ $cookie->matchesDomain($domain));
135
+ }
136
+ );
137
+ }
138
+ }
139
+
140
+ public function clearSessionCookies()
141
+ {
142
+ $this->cookies = array_filter(
143
+ $this->cookies,
144
+ function (SetCookie $cookie) {
145
+ return !$cookie->getDiscard() && $cookie->getExpires();
146
+ }
147
+ );
148
+ }
149
+
150
+ public function setCookie(SetCookie $cookie)
151
+ {
152
+ // If the name string is empty (but not 0), ignore the set-cookie
153
+ // string entirely.
154
+ $name = $cookie->getName();
155
+ if (!$name && $name !== '0') {
156
+ return false;
157
+ }
158
+
159
+ // Only allow cookies with set and valid domain, name, value
160
+ $result = $cookie->validate();
161
+ if ($result !== true) {
162
+ if ($this->strictMode) {
163
+ throw new \RuntimeException('Invalid cookie: ' . $result);
164
+ } else {
165
+ $this->removeCookieIfEmpty($cookie);
166
+ return false;
167
+ }
168
+ }
169
+
170
+ // Resolve conflicts with previously set cookies
171
+ foreach ($this->cookies as $i => $c) {
172
+
173
+ // Two cookies are identical, when their path, and domain are
174
+ // identical.
175
+ if ($c->getPath() != $cookie->getPath() ||
176
+ $c->getDomain() != $cookie->getDomain() ||
177
+ $c->getName() != $cookie->getName()
178
+ ) {
179
+ continue;
180
+ }
181
+
182
+ // The previously set cookie is a discard cookie and this one is
183
+ // not so allow the new cookie to be set
184
+ if (!$cookie->getDiscard() && $c->getDiscard()) {
185
+ unset($this->cookies[$i]);
186
+ continue;
187
+ }
188
+
189
+ // If the new cookie's expiration is further into the future, then
190
+ // replace the old cookie
191
+ if ($cookie->getExpires() > $c->getExpires()) {
192
+ unset($this->cookies[$i]);
193
+ continue;
194
+ }
195
+
196
+ // If the value has changed, we better change it
197
+ if ($cookie->getValue() !== $c->getValue()) {
198
+ unset($this->cookies[$i]);
199
+ continue;
200
+ }
201
+
202
+ // The cookie exists, so no need to continue
203
+ return false;
204
+ }
205
+
206
+ $this->cookies[] = $cookie;
207
+
208
+ return true;
209
+ }
210
+
211
+ public function count()
212
+ {
213
+ return count($this->cookies);
214
+ }
215
+
216
+ public function getIterator()
217
+ {
218
+ return new \ArrayIterator(array_values($this->cookies));
219
+ }
220
+
221
+ public function extractCookies(
222
+ RequestInterface $request,
223
+ ResponseInterface $response
224
+ ) {
225
+ if ($cookieHeader = $response->getHeader('Set-Cookie')) {
226
+ foreach ($cookieHeader as $cookie) {
227
+ $sc = SetCookie::fromString($cookie);
228
+ if (!$sc->getDomain()) {
229
+ $sc->setDomain($request->getUri()->getHost());
230
+ }
231
+ $this->setCookie($sc);
232
+ }
233
+ }
234
+ }
235
+
236
+ public function withCookieHeader(RequestInterface $request)
237
+ {
238
+ $values = [];
239
+ $uri = $request->getUri();
240
+ $scheme = $uri->getScheme();
241
+ $host = $uri->getHost();
242
+ $path = $uri->getPath() ?: '/';
243
+
244
+ foreach ($this->cookies as $cookie) {
245
+ if ($cookie->matchesPath($path) &&
246
+ $cookie->matchesDomain($host) &&
247
+ !$cookie->isExpired() &&
248
+ (!$cookie->getSecure() || $scheme == 'https')
249
+ ) {
250
+ $values[] = $cookie->getName() . '='
251
+ . self::getCookieValue($cookie->getValue());
252
+ }
253
+ }
254
+
255
+ return $values
256
+ ? $request->withHeader('Cookie', implode('; ', $values))
257
+ : $request;
258
+ }
259
+
260
+ /**
261
+ * If a cookie already exists and the server asks to set it again with a
262
+ * null value, the cookie must be deleted.
263
+ *
264
+ * @param SetCookie $cookie
265
+ */
266
+ private function removeCookieIfEmpty(SetCookie $cookie)
267
+ {
268
+ $cookieValue = $cookie->getValue();
269
+ if ($cookieValue === null || $cookieValue === '') {
270
+ $this->clear(
271
+ $cookie->getDomain(),
272
+ $cookie->getPath(),
273
+ $cookie->getName()
274
+ );
275
+ }
276
+ }
277
+ }
includes/aws/GuzzleHttp/Cookie/CookieJarInterface.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+ use Psr\Http\Message\ResponseInterface;
6
+
7
+ /**
8
+ * Stores HTTP cookies.
9
+ *
10
+ * It extracts cookies from HTTP requests, and returns them in HTTP responses.
11
+ * CookieJarInterface instances automatically expire contained cookies when
12
+ * necessary. Subclasses are also responsible for storing and retrieving
13
+ * cookies from a file, database, etc.
14
+ *
15
+ * @link http://docs.python.org/2/library/cookielib.html Inspiration
16
+ */
17
+ interface CookieJarInterface extends \Countable, \IteratorAggregate
18
+ {
19
+ /**
20
+ * Create a request with added cookie headers.
21
+ *
22
+ * If no matching cookies are found in the cookie jar, then no Cookie
23
+ * header is added to the request and the same request is returned.
24
+ *
25
+ * @param RequestInterface $request Request object to modify.
26
+ *
27
+ * @return RequestInterface returns the modified request.
28
+ */
29
+ public function withCookieHeader(RequestInterface $request);
30
+
31
+ /**
32
+ * Extract cookies from an HTTP response and store them in the CookieJar.
33
+ *
34
+ * @param RequestInterface $request Request that was sent
35
+ * @param ResponseInterface $response Response that was received
36
+ */
37
+ public function extractCookies(
38
+ RequestInterface $request,
39
+ ResponseInterface $response
40
+ );
41
+
42
+ /**
43
+ * Sets a cookie in the cookie jar.
44
+ *
45
+ * @param SetCookie $cookie Cookie to set.
46
+ *
47
+ * @return bool Returns true on success or false on failure
48
+ */
49
+ public function setCookie(SetCookie $cookie);
50
+
51
+ /**
52
+ * Remove cookies currently held in the cookie jar.
53
+ *
54
+ * Invoking this method without arguments will empty the whole cookie jar.
55
+ * If given a $domain argument only cookies belonging to that domain will
56
+ * be removed. If given a $domain and $path argument, cookies belonging to
57
+ * the specified path within that domain are removed. If given all three
58
+ * arguments, then the cookie with the specified name, path and domain is
59
+ * removed.
60
+ *
61
+ * @param string $domain Clears cookies matching a domain
62
+ * @param string $path Clears cookies matching a domain and path
63
+ * @param string $name Clears cookies matching a domain, path, and name
64
+ *
65
+ * @return CookieJarInterface
66
+ */
67
+ public function clear($domain = null, $path = null, $name = null);
68
+
69
+ /**
70
+ * Discard all sessions cookies.
71
+ *
72
+ * Removes cookies that don't have an expire field or a have a discard
73
+ * field set to true. To be called when the user agent shuts down according
74
+ * to RFC 2965.
75
+ */
76
+ public function clearSessionCookies();
77
+
78
+ /**
79
+ * Converts the cookie jar to an array.
80
+ *
81
+ * @return array
82
+ */
83
+ public function toArray();
84
+ }
includes/aws/GuzzleHttp/Cookie/FileCookieJar.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ /**
5
+ * Persists non-session cookies using a JSON formatted file
6
+ */
7
+ class FileCookieJar extends CookieJar
8
+ {
9
+ /** @var string filename */
10
+ private $filename;
11
+
12
+ /** @var bool Control whether to persist session cookies or not. */
13
+ private $storeSessionCookies;
14
+
15
+ /**
16
+ * Create a new FileCookieJar object
17
+ *
18
+ * @param string $cookieFile File to store the cookie data
19
+ * @param bool $storeSessionCookies Set to true to store session cookies
20
+ * in the cookie jar.
21
+ *
22
+ * @throws \RuntimeException if the file cannot be found or created
23
+ */
24
+ public function __construct($cookieFile, $storeSessionCookies = false)
25
+ {
26
+ $this->filename = $cookieFile;
27
+ $this->storeSessionCookies = $storeSessionCookies;
28
+
29
+ if (file_exists($cookieFile)) {
30
+ $this->load($cookieFile);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Saves the file when shutting down
36
+ */
37
+ public function __destruct()
38
+ {
39
+ $this->save($this->filename);
40
+ }
41
+
42
+ /**
43
+ * Saves the cookies to a file.
44
+ *
45
+ * @param string $filename File to save
46
+ * @throws \RuntimeException if the file cannot be found or created
47
+ */
48
+ public function save($filename)
49
+ {
50
+ $json = [];
51
+ foreach ($this as $cookie) {
52
+ /** @var SetCookie $cookie */
53
+ if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
54
+ $json[] = $cookie->toArray();
55
+ }
56
+ }
57
+
58
+ if (false === file_put_contents($filename, json_encode($json))) {
59
+ throw new \RuntimeException("Unable to save file {$filename}");
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Load cookies from a JSON formatted file.
65
+ *
66
+ * Old cookies are kept unless overwritten by newly loaded ones.
67
+ *
68
+ * @param string $filename Cookie file to load.
69
+ * @throws \RuntimeException if the file cannot be loaded.
70
+ */
71
+ public function load($filename)
72
+ {
73
+ $json = file_get_contents($filename);
74
+ if (false === $json) {
75
+ throw new \RuntimeException("Unable to load file {$filename}");
76
+ }
77
+
78
+ $data = json_decode($json, true);
79
+ if (is_array($data)) {
80
+ foreach (json_decode($json, true) as $cookie) {
81
+ $this->setCookie(new SetCookie($cookie));
82
+ }
83
+ } elseif (strlen($data)) {
84
+ throw new \RuntimeException("Invalid cookie file: {$filename}");
85
+ }
86
+ }
87
+ }
includes/aws/GuzzleHttp/Cookie/SessionCookieJar.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ /**
5
+ * Persists cookies in the client session
6
+ */
7
+ class SessionCookieJar extends CookieJar
8
+ {
9
+ /** @var string session key */
10
+ private $sessionKey;
11
+
12
+ /** @var bool Control whether to persist session cookies or not. */
13
+ private $storeSessionCookies;
14
+
15
+ /**
16
+ * Create a new SessionCookieJar object
17
+ *
18
+ * @param string $sessionKey Session key name to store the cookie
19
+ * data in session
20
+ * @param bool $storeSessionCookies Set to true to store session cookies
21
+ * in the cookie jar.
22
+ */
23
+ public function __construct($sessionKey, $storeSessionCookies = false)
24
+ {
25
+ $this->sessionKey = $sessionKey;
26
+ $this->storeSessionCookies = $storeSessionCookies;
27
+ $this->load();
28
+ }
29
+
30
+ /**
31
+ * Saves cookies to session when shutting down
32
+ */
33
+ public function __destruct()
34
+ {
35
+ $this->save();
36
+ }
37
+
38
+ /**
39
+ * Save cookies to the client session
40
+ */
41
+ public function save()
42
+ {
43
+ $json = [];
44
+ foreach ($this as $cookie) {
45
+ /** @var SetCookie $cookie */
46
+ if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
47
+ $json[] = $cookie->toArray();
48
+ }
49
+ }
50
+
51
+ $_SESSION[$this->sessionKey] = json_encode($json);
52
+ }
53
+
54
+ /**
55
+ * Load the contents of the client session into the data array
56
+ */
57
+ protected function load()
58
+ {
59
+ $cookieJar = isset($_SESSION[$this->sessionKey])
60
+ ? $_SESSION[$this->sessionKey]
61
+ : null;
62
+
63
+ $data = json_decode($cookieJar, true);
64
+ if (is_array($data)) {
65
+ foreach ($data as $cookie) {
66
+ $this->setCookie(new SetCookie($cookie));
67
+ }
68
+ } elseif (strlen($data)) {
69
+ throw new \RuntimeException("Invalid cookie data");
70
+ }
71
+ }
72
+ }
includes/aws/GuzzleHttp/Cookie/SetCookie.php ADDED
@@ -0,0 +1,404 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ /**
5
+ * Set-Cookie object
6
+ */
7
+ class SetCookie
8
+ {
9
+ /** @var array */
10
+ private static $defaults = [
11
+ 'Name' => null,
12
+ 'Value' => null,
13
+ 'Domain' => null,
14
+ 'Path' => '/',
15
+ 'Max-Age' => null,
16
+ 'Expires' => null,
17
+ 'Secure' => false,
18
+ 'Discard' => false,
19
+ 'HttpOnly' => false
20
+ ];
21
+
22
+ /** @var array Cookie data */
23
+ private $data;
24
+
25
+ /**
26
+ * Create a new SetCookie object from a string
27
+ *
28
+ * @param string $cookie Set-Cookie header string
29
+ *
30
+ * @return self
31
+ */
32
+ public static function fromString($cookie)
33
+ {
34
+ // Create the default return array
35
+ $data = self::$defaults;
36
+ // Explode the cookie string using a series of semicolons
37
+ $pieces = array_filter(array_map('trim', explode(';', $cookie)));
38
+ // The name of the cookie (first kvp) must include an equal sign.
39
+ if (empty($pieces) || !strpos($pieces[0], '=')) {
40
+ return new self($data);
41
+ }
42
+
43
+ // Add the cookie pieces into the parsed data array
44
+ foreach ($pieces as $part) {
45
+
46
+ $cookieParts = explode('=', $part, 2);
47
+ $key = trim($cookieParts[0]);
48
+ $value = isset($cookieParts[1])
49
+ ? trim($cookieParts[1], " \n\r\t\0\x0B")
50
+ : true;
51
+
52
+ // Only check for non-cookies when cookies have been found
53
+ if (empty($data['Name'])) {
54
+ $data['Name'] = $key;
55
+ $data['Value'] = $value;
56
+ } else {
57
+ foreach (array_keys(self::$defaults) as $search) {
58
+ if (!strcasecmp($search, $key)) {
59
+ $data[$search] = $value;
60
+ continue 2;
61
+ }
62
+ }
63
+ $data[$key] = $value;
64
+ }
65
+ }
66
+
67
+ return new self($data);
68
+ }
69
+
70
+ /**
71
+ * @param array $data Array of cookie data provided by a Cookie parser
72
+ */
73
+ public function __construct(array $data = [])
74
+ {
75
+ $this->data = array_replace(self::$defaults, $data);
76
+ // Extract the Expires value and turn it into a UNIX timestamp if needed
77
+ if (!$this->getExpires() && $this->getMaxAge()) {
78
+ // Calculate the Expires date
79
+ $this->setExpires(time() + $this->getMaxAge());
80
+ } elseif ($this->getExpires() && !is_numeric($this->getExpires())) {
81
+ $this->setExpires($this->getExpires());
82
+ }
83
+ }
84
+
85
+ public function __toString()
86
+ {
87
+ $str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
88
+ foreach ($this->data as $k => $v) {
89
+ if ($k != 'Name' && $k != 'Value' && $v !== null && $v !== false) {
90
+ if ($k == 'Expires') {
91
+ $str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
92
+ } else {
93
+ $str .= ($v === true ? $k : "{$k}={$v}") . '; ';
94
+ }
95
+ }
96
+ }
97
+
98
+ return rtrim($str, '; ');
99
+ }
100
+
101
+ public function toArray()
102
+ {
103
+ return $this->data;
104
+ }
105
+
106
+ /**
107
+ * Get the cookie name
108
+ *
109
+ * @return string
110
+ */
111
+ public function getName()
112
+ {
113
+ return $this->data['Name'];
114
+ }
115
+
116
+ /**
117
+ * Set the cookie name
118
+ *
119
+ * @param string $name Cookie name
120
+ */
121
+ public function setName($name)
122
+ {
123
+ $this->data['Name'] = $name;
124
+ }
125
+
126
+ /**
127
+ * Get the cookie value
128
+ *
129
+ * @return string
130
+ */
131
+ public function getValue()
132
+ {
133
+ return $this->data['Value'];
134
+ }
135
+
136
+ /**
137
+ * Set the cookie value
138
+ *
139
+ * @param string $value Cookie value
140
+ */
141
+ public function setValue($value)
142
+ {
143
+ $this->data['Value'] = $value;
144
+ }
145
+
146
+ /**
147
+ * Get the domain
148
+ *
149
+ * @return string|null
150
+ */
151
+ public function getDomain()
152
+ {
153
+ return $this->data['Domain'];
154
+ }
155
+
156
+ /**
157
+ * Set the domain of the cookie
158
+ *
159
+ * @param string $domain
160
+ */
161
+ public function setDomain($domain)
162
+ {
163
+ $this->data['Domain'] = $domain;
164
+ }
165
+
166
+ /**
167
+ * Get the path
168
+ *
169
+ * @return string
170
+ */
171
+ public function getPath()
172
+ {
173
+ return $this->data['Path'];
174
+ }
175
+
176
+ /**
177
+ * Set the path of the cookie
178
+ *
179
+ * @param string $path Path of the cookie
180
+ */
181
+ public function setPath($path)
182
+ {
183
+ $this->data['Path'] = $path;
184
+ }
185
+
186
+ /**
187
+ * Maximum lifetime of the cookie in seconds
188
+ *
189
+ * @return int|null
190
+ */
191
+ public function getMaxAge()
192
+ {
193
+ return $this->data['Max-Age'];
194
+ }
195
+
196
+ /**
197
+ * Set the max-age of the cookie
198
+ *
199
+ * @param int $maxAge Max age of the cookie in seconds
200
+ */
201
+ public function setMaxAge($maxAge)
202
+ {
203
+ $this->data['Max-Age'] = $maxAge;
204
+ }
205
+
206
+ /**
207
+ * The UNIX timestamp when the cookie Expires
208
+ *
209
+ * @return mixed
210
+ */
211
+ public function getExpires()
212
+ {
213
+ return $this->data['Expires'];
214
+ }
215
+
216
+ /**
217
+ * Set the unix timestamp for which the cookie will expire
218
+ *
219
+ * @param int $timestamp Unix timestamp
220
+ */
221
+ public function setExpires($timestamp)
222
+ {
223
+ $this->data['Expires'] = is_numeric($timestamp)
224
+ ? (int) $timestamp
225
+ : strtotime($timestamp);
226
+ }
227
+
228
+ /**
229
+ * Get whether or not this is a secure cookie
230
+ *
231
+ * @return null|bool
232
+ */
233
+ public function getSecure()
234
+ {
235
+ return $this->data['Secure'];
236
+ }
237
+
238
+ /**
239
+ * Set whether or not the cookie is secure
240
+ *
241
+ * @param bool $secure Set to true or false if secure
242
+ */
243
+ public function setSecure($secure)
244
+ {
245
+ $this->data['Secure'] = $secure;
246
+ }
247
+
248
+ /**
249
+ * Get whether or not this is a session cookie
250
+ *
251
+ * @return null|bool
252
+ */
253
+ public function getDiscard()
254
+ {
255
+ return $this->data['Discard'];
256
+ }
257
+
258
+ /**
259
+ * Set whether or not this is a session cookie
260
+ *
261
+ * @param bool $discard Set to true or false if this is a session cookie
262
+ */
263
+ public function setDiscard($discard)
264
+ {
265
+ $this->data['Discard'] = $discard;
266
+ }
267
+
268
+ /**
269
+ * Get whether or not this is an HTTP only cookie
270
+ *
271
+ * @return bool
272
+ */
273
+ public function getHttpOnly()
274
+ {
275
+ return $this->data['HttpOnly'];
276
+ }
277
+
278
+ /**
279
+ * Set whether or not this is an HTTP only cookie
280
+ *
281
+ * @param bool $httpOnly Set to true or false if this is HTTP only
282
+ */
283
+ public function setHttpOnly($httpOnly)
284
+ {
285
+ $this->data['HttpOnly'] = $httpOnly;
286
+ }
287
+
288
+ /**
289
+ * Check if the cookie matches a path value.
290
+ *
291
+ * A request-path path-matches a given cookie-path if at least one of
292
+ * the following conditions holds:
293
+ *
294
+ * - The cookie-path and the request-path are identical.
295
+ * - The cookie-path is a prefix of the request-path, and the last
296
+ * character of the cookie-path is %x2F ("/").
297
+ * - The cookie-path is a prefix of the request-path, and the first
298
+ * character of the request-path that is not included in the cookie-
299
+ * path is a %x2F ("/") character.
300
+ *
301
+ * @param string $requestPath Path to check against
302
+ *
303
+ * @return bool
304
+ */
305
+ public function matchesPath($requestPath)
306
+ {
307
+ $cookiePath = $this->getPath();
308
+
309
+ // Match on exact matches or when path is the default empty "/"
310
+ if ($cookiePath == '/' || $cookiePath == $requestPath) {
311
+ return true;
312
+ }
313
+
314
+ // Ensure that the cookie-path is a prefix of the request path.
315
+ if (0 !== strpos($requestPath, $cookiePath)) {
316
+ return false;
317
+ }
318
+
319
+ // Match if the last character of the cookie-path is "/"
320
+ if (substr($cookiePath, -1, 1) == '/') {
321
+ return true;
322
+ }
323
+
324
+ // Match if the first character not included in cookie path is "/"
325
+ return substr($requestPath, strlen($cookiePath), 1) == '/';
326
+ }
327
+
328
+ /**
329
+ * Check if the cookie matches a domain value
330
+ *
331
+ * @param string $domain Domain to check against
332
+ *
333
+ * @return bool
334
+ */
335
+ public function matchesDomain($domain)
336
+ {
337
+ // Remove the leading '.' as per spec in RFC 6265.
338
+ // http://tools.ietf.org/html/rfc6265#section-5.2.3
339
+ $cookieDomain = ltrim($this->getDomain(), '.');
340
+
341
+ // Domain not set or exact match.
342
+ if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) {
343
+ return true;
344
+ }
345
+
346
+ // Matching the subdomain according to RFC 6265.
347
+ // http://tools.ietf.org/html/rfc6265#section-5.1.3
348
+ if (filter_var($domain, FILTER_VALIDATE_IP)) {
349
+ return false;
350
+ }
351
+
352
+ return (bool) preg_match('/\.' . preg_quote($cookieDomain) . '$/', $domain);
353
+ }
354
+
355
+ /**
356
+ * Check if the cookie is expired
357
+ *
358
+ * @return bool
359
+ */
360
+ public function isExpired()
361
+ {
362
+ return $this->getExpires() && time() > $this->getExpires();
363
+ }
364
+
365
+ /**
366
+ * Check if the cookie is valid according to RFC 6265
367
+ *
368
+ * @return bool|string Returns true if valid or an error message if invalid
369
+ */
370
+ public function validate()
371
+ {
372
+ // Names must not be empty, but can be 0
373
+ $name = $this->getName();
374
+ if (empty($name) && !is_numeric($name)) {
375
+ return 'The cookie name must not be empty';
376
+ }
377
+
378
+ // Check if any of the invalid characters are present in the cookie name
379
+ if (preg_match(
380
+ '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
381
+ $name)
382
+ ) {
383
+ return 'Cookie name must not contain invalid characters: ASCII '
384
+ . 'Control characters (0-31;127), space, tab and the '
385
+ . 'following characters: ()<>@,;:\"/?={}';
386
+ }
387
+
388
+ // Value must not be empty, but can be 0
389
+ $value = $this->getValue();
390
+ if (empty($value) && !is_numeric($value)) {
391
+ return 'The cookie value must not be empty';
392
+ }
393
+
394
+ // Domains must not be empty, but can be 0
395
+ // A "0" is not a valid internet domain, but may be used as server name
396
+ // in a private network.
397
+ $domain = $this->getDomain();
398
+ if (empty($domain) && !is_numeric($domain)) {
399
+ return 'The cookie domain must not be empty';
400
+ }
401
+
402
+ return true;
403
+ }
404
+ }
includes/aws/GuzzleHttp/Exception/BadResponseException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ /**
5
+ * Exception when an HTTP error occurs (4xx or 5xx error)
6
+ */
7
+ class BadResponseException extends RequestException {}
includes/aws/GuzzleHttp/Exception/ClientException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ /**
5
+ * Exception when a client error is encountered (4xx codes)
6
+ */
7
+ class ClientException extends BadResponseException {}
includes/aws/GuzzleHttp/Exception/ConnectException.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+
6
+ /**
7
+ * Exception thrown when a connection cannot be established.
8
+ *
9
+ * Note that no response is present for a ConnectException
10
+ */
11
+ class ConnectException extends RequestException
12
+ {
13
+ public function __construct(
14
+ $message,
15
+ RequestInterface $request,
16
+ \Exception $previous = null,
17
+ array $handlerContext = []
18
+ ) {
19
+ parent::__construct($message, $request, null, $previous, $handlerContext);
20
+ }
21
+
22
+ /**
23
+ * @return null
24
+ */
25
+ public function getResponse()
26
+ {
27
+ return null;
28
+ }
29
+
30
+ /**
31
+ * @return bool
32
+ */
33
+ public function hasResponse()
34
+ {
35
+ return false;
36
+ }
37
+ }
includes/aws/GuzzleHttp/Exception/GuzzleException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ interface GuzzleException {}
includes/aws/GuzzleHttp/Exception/RequestException.php ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+ use Psr\Http\Message\ResponseInterface;
6
+ use GuzzleHttp\Promise\PromiseInterface;
7
+
8
+ /**
9
+ * HTTP Request exception
10
+ */
11
+ class RequestException extends TransferException
12
+ {
13
+ /** @var RequestInterface */
14
+ private $request;
15
+
16
+ /** @var ResponseInterface */
17
+ private $response;
18
+
19
+ /** @var array */
20
+ private $handlerContext;
21
+
22
+ public function __construct(
23
+ $message,
24
+ RequestInterface $request,
25
+ ResponseInterface $response = null,
26
+ \Exception $previous = null,
27
+ array $handlerContext = []
28
+ ) {
29
+ // Set the code of the exception if the response is set and not future.
30
+ $code = $response && !($response instanceof PromiseInterface)
31
+ ? $response->getStatusCode()
32
+ : 0;
33
+ parent::__construct($message, $code, $previous);
34
+ $this->request = $request;
35
+ $this->response = $response;
36
+ $this->handlerContext = $handlerContext;
37
+ }
38
+
39
+ /**
40
+ * Wrap non-RequestExceptions with a RequestException
41
+ *
42
+ * @param RequestInterface $request
43
+ * @param \Exception $e
44
+ *
45
+ * @return RequestException
46
+ */
47
+ public static function wrapException(RequestInterface $request, \Exception $e)
48
+ {
49
+ return $e instanceof RequestException
50
+ ? $e
51
+ : new RequestException($e->getMessage(), $request, null, $e);
52
+ }
53
+
54
+ /**
55
+ * Factory method to create a new exception with a normalized error message
56
+ *
57
+ * @param RequestInterface $request Request
58
+ * @param ResponseInterface $response Response received
59
+ * @param \Exception $previous Previous exception
60
+ * @param array $ctx Optional handler context.
61
+ *
62
+ * @return self
63
+ */
64
+ public static function create(
65
+ RequestInterface $request,
66
+ ResponseInterface $response = null,
67
+ \Exception $previous = null,
68
+ array $ctx = []
69
+ ) {
70
+ if (!$response) {
71
+ return new self(
72
+ 'Error completing request',
73
+ $request,
74
+ null,
75
+ $previous,
76
+ $ctx
77
+ );
78
+ }
79
+
80
+ $level = floor($response->getStatusCode() / 100);
81
+ if ($level == '4') {
82
+ $label = 'Client error';
83
+ $className = __NAMESPACE__ . '\\ClientException';
84
+ } elseif ($level == '5') {
85
+ $label = 'Server error';
86
+ $className = __NAMESPACE__ . '\\ServerException';
87
+ } else {
88
+ $label = 'Unsuccessful request';
89
+ $className = __CLASS__;
90
+ }
91
+
92
+ // Server Error: `GET /` resulted in a `404 Not Found` response:
93
+ // <html> ... (truncated)
94
+ $message = sprintf(
95
+ '%s: `%s` resulted in a `%s` response',
96
+ $label,
97
+ $request->getMethod() . ' ' . $request->getUri(),
98
+ $response->getStatusCode() . ' ' . $response->getReasonPhrase()
99
+ );
100
+
101
+ $summary = static::getResponseBodySummary($response);
102
+
103
+ if ($summary !== null) {
104
+ $message .= ":\n{$summary}\n";
105
+ }
106
+
107
+ return new $className($message, $request, $response, $previous, $ctx);
108
+ }
109
+
110
+ /**
111
+ * Get a short summary of the response
112
+ *
113
+ * Will return `null` if the response is not printable.
114
+ *
115
+ * @param ResponseInterface $response
116
+ *
117
+ * @return string|null
118
+ */
119
+ public static function getResponseBodySummary(ResponseInterface $response)
120
+ {
121
+ $body = $response->getBody();
122
+
123
+ if (!$body->isSeekable()) {
124
+ return null;
125
+ }
126
+
127
+ $size = $body->getSize();
128
+ $summary = $body->read(120);
129
+ $body->rewind();
130
+
131
+ if ($size > 120) {
132
+ $summary .= ' (truncated...)';
133
+ }
134
+
135
+ // Matches any printable character, including unicode characters:
136
+ // letters, marks, numbers, punctuation, spacing, and separators.
137
+ if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
138
+ return null;
139
+ }
140
+
141
+ return $summary;
142
+ }
143
+
144
+ /**
145
+ * Get the request that caused the exception
146
+ *
147
+ * @return RequestInterface
148
+ */
149
+ public function getRequest()
150
+ {
151
+ return $this->request;
152
+ }
153
+
154
+ /**
155
+ * Get the associated response
156
+ *
157
+ * @return ResponseInterface|null
158
+ */
159
+ public function getResponse()
160
+ {
161
+ return $this->response;
162
+ }
163
+
164
+ /**
165
+ * Check if a response was received
166
+ *
167
+ * @return bool
168
+ */
169
+ public function hasResponse()
170
+ {
171
+ return $this->response !== null;
172
+ }
173
+
174
+ /**
175
+ * Get contextual information about the error from the underlying handler.
176
+ *
177
+ * The contents of this array will vary depending on which handler you are
178
+ * using. It may also be just an empty array. Relying on this data will
179
+ * couple you to a specific handler, but can give more debug information
180
+ * when needed.
181
+ *
182
+ * @return array
183
+ */
184
+ public function getHandlerContext()
185
+ {
186
+ return $this->handlerContext;
187
+ }
188
+ }
includes/aws/GuzzleHttp/Exception/SeekException.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Exception thrown when a seek fails on a stream.
8
+ */
9
+ class SeekException extends \RuntimeException implements GuzzleException
10
+ {
11
+ private $stream;
12
+
13
+ public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
14
+ {
15
+ $this->stream = $stream;
16
+ $msg = $msg ?: 'Could not seek the stream to position ' . $pos;
17
+ parent::__construct($msg);
18
+ }
19
+
20
+ /**
21
+ * @return StreamInterface
22
+ */
23
+ public function getStream()
24
+ {
25
+ return $this->stream;
26
+ }
27
+ }
includes/aws/GuzzleHttp/Exception/ServerException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ /**
5
+ * Exception when a server error is encountered (5xx codes)
6
+ */
7
+ class ServerException extends BadResponseException {}
includes/aws/GuzzleHttp/Exception/TooManyRedirectsException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class TooManyRedirectsException extends RequestException {}
includes/aws/GuzzleHttp/Exception/TransferException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class TransferException extends \RuntimeException implements GuzzleException {}
includes/aws/GuzzleHttp/Handler/CurlFactory.php ADDED
@@ -0,0 +1,531 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Exception\RequestException;
5
+ use GuzzleHttp\Exception\ConnectException;
6
+ use GuzzleHttp\Promise\FulfilledPromise;
7
+ use GuzzleHttp\Promise\RejectedPromise;
8
+ use GuzzleHttp\Psr7;
9
+ use GuzzleHttp\Psr7\LazyOpenStream;
10
+ use GuzzleHttp\TransferStats;
11
+ use Psr\Http\Message\RequestInterface;
12
+
13
+ /**
14
+ * Creates curl resources from a request
15
+ */
16
+ class CurlFactory implements CurlFactoryInterface
17
+ {
18
+ /** @var array */
19
+ private $handles;
20
+
21
+ /** @var int Total number of idle handles to keep in cache */
22
+ private $maxHandles;
23
+
24
+ /**
25
+ * @param int $maxHandles Maximum number of idle handles.
26
+ */
27
+ public function __construct($maxHandles)
28
+ {
29
+ $this->maxHandles = $maxHandles;
30
+ }
31
+
32
+ public function create(RequestInterface $request, array $options)
33
+ {
34
+ if (isset($options['curl']['body_as_string'])) {
35
+ $options['_body_as_string'] = $options['curl']['body_as_string'];
36
+ unset($options['curl']['body_as_string']);
37
+ }
38
+
39
+ $easy = new EasyHandle;
40
+ $easy->request = $request;
41
+ $easy->options = $options;
42
+ $conf = $this->getDefaultConf($easy);
43
+ $this->applyMethod($easy, $conf);
44
+ $this->applyHandlerOptions($easy, $conf);
45
+ $this->applyHeaders($easy, $conf);
46
+ unset($conf['_headers']);
47
+
48
+ // Add handler options from the request configuration options
49
+ if (isset($options['curl'])) {
50
+ $conf = array_replace($conf, $options['curl']);
51
+ }
52
+
53
+ $conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
54
+ $easy->handle = $this->handles
55
+ ? array_pop($this->handles)
56
+ : curl_init();
57
+ curl_setopt_array($easy->handle, $conf);
58
+
59
+ return $easy;
60
+ }
61
+
62
+ public function release(EasyHandle $easy)
63
+ {
64
+ $resource = $easy->handle;
65
+ unset($easy->handle);
66
+
67
+ if (count($this->handles) >= $this->maxHandles) {
68
+ curl_close($resource);
69
+ } else {
70
+ // Remove all callback functions as they can hold onto references
71
+ // and are not cleaned up by curl_reset. Using curl_setopt_array
72
+ // does not work for some reason, so removing each one
73
+ // individually.
74
+ curl_setopt($resource, CURLOPT_HEADERFUNCTION, null);
75
+ curl_setopt($resource, CURLOPT_READFUNCTION, null);
76
+ curl_setopt($resource, CURLOPT_WRITEFUNCTION, null);
77
+ curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null);
78
+ curl_reset($resource);
79
+ $this->handles[] = $resource;
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Completes a cURL transaction, either returning a response promise or a
85
+ * rejected promise.
86
+ *
87
+ * @param callable $handler
88
+ * @param EasyHandle $easy
89
+ * @param CurlFactoryInterface $factory Dictates how the handle is released
90
+ *
91
+ * @return \GuzzleHttp\Promise\PromiseInterface
92
+ */
93
+ public static function finish(
94
+ callable $handler,
95
+ EasyHandle $easy,
96
+ CurlFactoryInterface $factory
97
+ ) {
98
+ if (isset($easy->options['on_stats'])) {
99
+ self::invokeStats($easy);
100
+ }
101
+
102
+ if (!$easy->response || $easy->errno) {
103
+ return self::finishError($handler, $easy, $factory);
104
+ }
105
+
106
+ // Return the response if it is present and there is no error.
107
+ $factory->release($easy);
108
+
109
+ // Rewind the body of the response if possible.
110
+ $body = $easy->response->getBody();
111
+ if ($body->isSeekable()) {
112
+ $body->rewind();
113
+ }
114
+
115
+ return new FulfilledPromise($easy->response);
116
+ }
117
+
118
+ private static function invokeStats(EasyHandle $easy)
119
+ {
120
+ $curlStats = curl_getinfo($easy->handle);
121
+ $stats = new TransferStats(
122
+ $easy->request,
123
+ $easy->response,
124
+ $curlStats['total_time'],
125
+ $easy->errno,
126
+ $curlStats
127
+ );
128
+ call_user_func($easy->options['on_stats'], $stats);
129
+ }
130
+
131
+ private static function finishError(
132
+ callable $handler,
133
+ EasyHandle $easy,
134
+ CurlFactoryInterface $factory
135
+ ) {
136
+ // Get error information and release the handle to the factory.
137
+ $ctx = [
138
+ 'errno' => $easy->errno,
139
+ 'error' => curl_error($easy->handle),
140
+ ] + curl_getinfo($easy->handle);
141
+ $factory->release($easy);
142
+
143
+ // Retry when nothing is present or when curl failed to rewind.
144
+ if (empty($easy->options['_err_message'])
145
+ && (!$easy->errno || $easy->errno == 65)
146
+ ) {
147
+ return self::retryFailedRewind($handler, $easy, $ctx);
148
+ }
149
+
150
+ return self::createRejection($easy, $ctx);
151
+ }
152
+
153
+ private static function createRejection(EasyHandle $easy, array $ctx)
154
+ {
155
+ static $connectionErrors = [
156
+ CURLE_OPERATION_TIMEOUTED => true,
157
+ CURLE_COULDNT_RESOLVE_HOST => true,
158
+ CURLE_COULDNT_CONNECT => true,
159
+ CURLE_SSL_CONNECT_ERROR => true,
160
+ CURLE_GOT_NOTHING => true,
161
+ ];
162
+
163
+ // If an exception was encountered during the onHeaders event, then
164
+ // return a rejected promise that wraps that exception.
165
+ if ($easy->onHeadersException) {
166
+ return new RejectedPromise(
167
+ new RequestException(
168
+ 'An error was encountered during the on_headers event',
169
+ $easy->request,
170
+ $easy->response,
171
+ $easy->onHeadersException,
172
+ $ctx
173
+ )
174
+ );
175
+ }
176
+
177
+ $message = sprintf(
178
+ 'cURL error %s: %s (%s)',
179
+ $ctx['errno'],
180
+ $ctx['error'],
181
+ 'see http://curl.haxx.se/libcurl/c/libcurl-errors.html'
182
+ );
183
+
184
+ // Create a connection exception if it was a specific error code.
185
+ $error = isset($connectionErrors[$easy->errno])
186
+ ? new ConnectException($message, $easy->request, null, $ctx)
187
+ : new RequestException($message, $easy->request, $easy->response, null, $ctx);
188
+
189
+ return new RejectedPromise($error);
190
+ }
191
+
192
+ private function getDefaultConf(EasyHandle $easy)
193
+ {
194
+ $conf = [
195
+ '_headers' => $easy->request->getHeaders(),
196
+ CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
197
+ CURLOPT_URL => (string) $easy->request->getUri(),
198
+ CURLOPT_RETURNTRANSFER => false,
199
+ CURLOPT_HEADER => false,
200
+ CURLOPT_CONNECTTIMEOUT => 150,
201
+ ];
202
+
203
+ if (defined('CURLOPT_PROTOCOLS')) {
204
+ $conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
205
+ }
206
+
207
+ $version = $easy->request->getProtocolVersion();
208
+ if ($version == 1.1) {
209
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
210
+ } elseif ($version == 2.0) {
211
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
212
+ } else {
213
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
214
+ }
215
+
216
+ return $conf;
217
+ }
218
+
219
+ private function applyMethod(EasyHandle $easy, array &$conf)
220
+ {
221
+ $body = $easy->request->getBody();
222
+ $size = $body->getSize();
223
+
224
+ if ($size === null || $size > 0) {
225
+ $this->applyBody($easy->request, $easy->options, $conf);
226
+ return;
227
+ }
228
+
229
+ $method = $easy->request->getMethod();
230
+ if ($method === 'PUT' || $method === 'POST') {
231
+ // See http://tools.ietf.org/html/rfc7230#section-3.3.2
232
+ if (!$easy->request->hasHeader('Content-Length')) {
233
+ $conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
234
+ }
235
+ } elseif ($method === 'HEAD') {
236
+ $conf[CURLOPT_NOBODY] = true;
237
+ unset(
238
+ $conf[CURLOPT_WRITEFUNCTION],
239
+ $conf[CURLOPT_READFUNCTION],
240
+ $conf[CURLOPT_FILE],
241
+ $conf[CURLOPT_INFILE]
242
+ );
243
+ }
244
+ }
245
+
246
+ private function applyBody(RequestInterface $request, array $options, array &$conf)
247
+ {
248
+ $size = $request->hasHeader('Content-Length')
249
+ ? (int) $request->getHeaderLine('Content-Length')
250
+ : null;
251
+
252
+ // Send the body as a string if the size is less than 1MB OR if the
253
+ // [curl][body_as_string] request value is set.
254
+ if (($size !== null && $size < 1000000) ||
255
+ !empty($options['_body_as_string'])
256
+ ) {
257
+ $conf[CURLOPT_POSTFIELDS] = (string) $request->getBody();
258
+ // Don't duplicate the Content-Length header
259
+ $this->removeHeader('Content-Length', $conf);
260
+ $this->removeHeader('Transfer-Encoding', $conf);
261
+ } else {
262
+ $conf[CURLOPT_UPLOAD] = true;
263
+ if ($size !== null) {
264
+ $conf[CURLOPT_INFILESIZE] = $size;
265
+ $this->removeHeader('Content-Length', $conf);
266
+ }
267
+ $body = $request->getBody();
268
+ $conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
269
+ return $body->read($length);
270
+ };
271
+ }
272
+
273
+ // If the Expect header is not present, prevent curl from adding it
274
+ if (!$request->hasHeader('Expect')) {
275
+ $conf[CURLOPT_HTTPHEADER][] = 'Expect:';
276
+ }
277
+
278
+ // cURL sometimes adds a content-type by default. Prevent this.
279
+ if (!$request->hasHeader('Content-Type')) {
280
+ $conf[CURLOPT_HTTPHEADER][] = 'Content-Type:';
281
+ }
282
+ }
283
+
284
+ private function applyHeaders(EasyHandle $easy, array &$conf)
285
+ {
286
+ foreach ($conf['_headers'] as $name => $values) {
287
+ foreach ($values as $value) {
288
+ $conf[CURLOPT_HTTPHEADER][] = "$name: $value";
289
+ }
290
+ }
291
+
292
+ // Remove the Accept header if one was not set
293
+ if (!$easy->request->hasHeader('Accept')) {
294
+ $conf[CURLOPT_HTTPHEADER][] = 'Accept:';
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Remove a header from the options array.
300
+ *
301
+ * @param string $name Case-insensitive header to remove
302
+ * @param array $options Array of options to modify
303
+ */
304
+ private function removeHeader($name, array &$options)
305
+ {
306
+ foreach (array_keys($options['_headers']) as $key) {
307
+ if (!strcasecmp($key, $name)) {
308
+ unset($options['_headers'][$key]);
309
+ return;
310
+ }
311
+ }
312
+ }
313
+
314
+ private function applyHandlerOptions(EasyHandle $easy, array &$conf)
315
+ {
316
+ $options = $easy->options;
317
+ if (isset($options['verify'])) {
318
+ if ($options['verify'] === false) {
319
+ unset($conf[CURLOPT_CAINFO]);
320
+ $conf[CURLOPT_SSL_VERIFYHOST] = 0;
321
+ $conf[CURLOPT_SSL_VERIFYPEER] = false;
322
+ } else {
323
+ $conf[CURLOPT_SSL_VERIFYHOST] = 2;
324
+ $conf[CURLOPT_SSL_VERIFYPEER] = true;
325
+ if (is_string($options['verify'])) {
326
+ $conf[CURLOPT_CAINFO] = $options['verify'];
327
+ if (!file_exists($options['verify'])) {
328
+ throw new \InvalidArgumentException(
329
+ "SSL CA bundle not found: {$options['verify']}"
330
+ );
331
+ }
332
+ }
333
+ }
334
+ }
335
+
336
+ if (!empty($options['decode_content'])) {
337
+ $accept = $easy->request->getHeaderLine('Accept-Encoding');
338
+ if ($accept) {
339
+ $conf[CURLOPT_ENCODING] = $accept;
340
+ } else {
341
+ $conf[CURLOPT_ENCODING] = '';
342
+ // Don't let curl send the header over the wire
343
+ $conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
344
+ }
345
+ }
346
+
347
+ if (isset($options['sink'])) {
348
+ $sink = $options['sink'];
349
+ if (!is_string($sink)) {
350
+ $sink = \GuzzleHttp\Psr7\stream_for($sink);
351
+ } elseif (!is_dir(dirname($sink))) {
352
+ // Ensure that the directory exists before failing in curl.
353
+ throw new \RuntimeException(sprintf(
354
+ 'Directory %s does not exist for sink value of %s',
355
+ dirname($sink),
356
+ $sink
357
+ ));
358
+ } else {
359
+ $sink = new LazyOpenStream($sink, 'w+');
360
+ }
361
+ $easy->sink = $sink;
362
+ $conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) {
363
+ return $sink->write($write);
364
+ };
365
+ } else {
366
+ // Use a default temp stream if no sink was set.
367
+ $conf[CURLOPT_FILE] = fopen('php://temp', 'w+');
368
+ $easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]);
369
+ }
370
+
371
+ if (isset($options['timeout'])) {
372
+ $conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
373
+ }
374
+
375
+ if (isset($options['connect_timeout'])) {
376
+ $conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
377
+ }
378
+
379
+ if (isset($options['proxy'])) {
380
+ if (!is_array($options['proxy'])) {
381
+ $conf[CURLOPT_PROXY] = $options['proxy'];
382
+ } else {
383
+ $scheme = $easy->request->getUri()->getScheme();
384
+ if (isset($options['proxy'][$scheme])) {
385
+ $host = $easy->request->getUri()->getHost();
386
+ if (!isset($options['proxy']['no']) ||
387
+ !\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])
388
+ ) {
389
+ $conf[CURLOPT_PROXY] = $options['proxy'][$scheme];
390
+ }
391
+ }
392
+ }
393
+ }
394
+
395
+ if (isset($options['cert'])) {
396
+ $cert = $options['cert'];
397
+ if (is_array($cert)) {
398
+ $conf[CURLOPT_SSLCERTPASSWD] = $cert[1];
399
+ $cert = $cert[0];
400
+ }
401
+ if (!file_exists($cert)) {
402
+ throw new \InvalidArgumentException(
403
+ "SSL certificate not found: {$cert}"
404
+ );
405
+ }
406
+ $conf[CURLOPT_SSLCERT] = $cert;
407
+ }
408
+
409
+ if (isset($options['ssl_key'])) {
410
+ $sslKey = $options['ssl_key'];
411
+ if (is_array($sslKey)) {
412
+ $conf[CURLOPT_SSLKEYPASSWD] = $sslKey[1];
413
+ $sslKey = $sslKey[0];
414
+ }
415
+ if (!file_exists($sslKey)) {
416
+ throw new \InvalidArgumentException(
417
+ "SSL private key not found: {$sslKey}"
418
+ );
419
+ }
420
+ $conf[CURLOPT_SSLKEY] = $sslKey;
421
+ }
422
+
423
+ if (isset($options['progress'])) {
424
+ $progress = $options['progress'];
425
+ if (!is_callable($progress)) {
426
+ throw new \InvalidArgumentException(
427
+ 'progress client option must be callable'
428
+ );
429
+ }
430
+ $conf[CURLOPT_NOPROGRESS] = false;
431
+ $conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) {
432
+ $args = func_get_args();
433
+ // PHP 5.5 pushed the handle onto the start of the args
434
+ if (is_resource($args[0])) {
435
+ array_shift($args);
436
+ }
437
+ call_user_func_array($progress, $args);
438
+ };
439
+ }
440
+
441
+ if (!empty($options['debug'])) {
442
+ $conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']);
443
+ $conf[CURLOPT_VERBOSE] = true;
444
+ }
445
+ }
446
+
447
+ /**
448
+ * This function ensures that a response was set on a transaction. If one
449
+ * was not set, then the request is retried if possible. This error
450
+ * typically means you are sending a payload, curl encountered a
451
+ * "Connection died, retrying a fresh connect" error, tried to rewind the
452
+ * stream, and then encountered a "necessary data rewind wasn't possible"
453
+ * error, causing the request to be sent through curl_multi_info_read()
454
+ * without an error status.
455
+ */
456
+ private static function retryFailedRewind(
457
+ callable $handler,
458
+ EasyHandle $easy,
459
+ array $ctx
460
+ ) {
461
+ try {
462
+ // Only rewind if the body has been read from.
463
+ $body = $easy->request->getBody();
464
+ if ($body->tell() > 0) {
465
+ $body->rewind();
466
+ }
467
+ } catch (\RuntimeException $e) {
468
+ $ctx['error'] = 'The connection unexpectedly failed without '
469
+ . 'providing an error. The request would have been retried, '
470
+ . 'but attempting to rewind the request body failed. '
471
+ . 'Exception: ' . $e;
472
+ return self::createRejection($easy, $ctx);
473
+ }
474
+
475
+ // Retry no more than 3 times before giving up.
476
+ if (!isset($easy->options['_curl_retries'])) {
477
+ $easy->options['_curl_retries'] = 1;
478
+ } elseif ($easy->options['_curl_retries'] == 2) {
479
+ $ctx['error'] = 'The cURL request was retried 3 times '
480
+ . 'and did not succeed. The most likely reason for the failure '
481
+ . 'is that cURL was unable to rewind the body of the request '
482
+ . 'and subsequent retries resulted in the same error. Turn on '
483
+ . 'the debug option to see what went wrong. See '
484
+ . 'https://bugs.php.net/bug.php?id=47204 for more information.';
485
+ return self::createRejection($easy, $ctx);
486
+ } else {
487
+ $easy->options['_curl_retries']++;
488
+ }
489
+
490
+ return $handler($easy->request, $easy->options);
491
+ }
492
+
493
+ private function createHeaderFn(EasyHandle $easy)
494
+ {
495
+ if (!isset($easy->options['on_headers'])) {
496
+ $onHeaders = null;
497
+ } elseif (!is_callable($easy->options['on_headers'])) {
498
+ throw new \InvalidArgumentException('on_headers must be callable');
499
+ } else {
500
+ $onHeaders = $easy->options['on_headers'];
501
+ }
502
+
503
+ return function ($ch, $h) use (
504
+ $onHeaders,
505
+ $easy,
506
+ &$startingResponse
507
+ ) {
508
+ $value = trim($h);
509
+ if ($value === '') {
510
+ $startingResponse = true;
511
+ $easy->createResponse();
512
+ if ($onHeaders) {
513
+ try {
514
+ $onHeaders($easy->response);
515
+ } catch (\Exception $e) {
516
+ // Associate the exception with the handle and trigger
517
+ // a curl header write error by returning 0.
518
+ $easy->onHeadersException = $e;
519
+ return -1;
520
+ }
521
+ }
522
+ } elseif ($startingResponse) {
523
+ $startingResponse = false;
524
+ $easy->headers = [$value];
525
+ } else {
526
+ $easy->headers[] = $value;
527
+ }
528
+ return strlen($h);
529
+ };
530
+ }
531
+ }
includes/aws/GuzzleHttp/Handler/CurlFactoryInterface.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+
6
+ interface CurlFactoryInterface
7
+ {
8
+ /**
9
+ * Creates a cURL handle resource.
10
+ *
11
+ * @param RequestInterface $request Request
12
+ * @param array $options Transfer options
13
+ *
14
+ * @return EasyHandle
15
+ * @throws \RuntimeException when an option cannot be applied
16
+ */
17
+ public function create(RequestInterface $request, array $options);
18
+
19
+ /**
20
+ * Release an easy handle, allowing it to be reused or closed.
21
+ *
22
+ * This function must call unset on the easy handle's "handle" property.
23
+ *
24
+ * @param EasyHandle $easy
25
+ */
26
+ public function release(EasyHandle $easy);
27
+ }
includes/aws/GuzzleHttp/Handler/CurlHandler.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Psr7;
5
+ use Psr\Http\Message\RequestInterface;
6
+
7
+ /**
8
+ * HTTP handler that uses cURL easy handles as a transport layer.
9
+ *
10
+ * When using the CurlHandler, custom curl options can be specified as an
11
+ * associative array of curl option constants mapping to values in the
12
+ * **curl** key of the "client" key of the request.
13
+ */
14
+ class CurlHandler
15
+ {
16
+ /** @var CurlFactoryInterface */
17
+ private $factory;
18
+
19
+ /**
20
+ * Accepts an associative array of options:
21
+ *
22
+ * - factory: Optional curl factory used to create cURL handles.
23
+ *
24
+ * @param array $options Array of options to use with the handler
25
+ */
26
+ public function __construct(array $options = [])
27
+ {
28
+ $this->factory = isset($options['handle_factory'])
29
+ ? $options['handle_factory']
30
+ : new CurlFactory(3);
31
+ }
32
+
33
+ public function __invoke(RequestInterface $request, array $options)
34
+ {
35
+ if (isset($options['delay'])) {
36
+ usleep($options['delay'] * 1000);
37
+ }
38
+
39
+ $easy = $this->factory->create($request, $options);
40
+ curl_exec($easy->handle);
41
+ $easy->errno = curl_errno($easy->handle);
42
+
43
+ return CurlFactory::finish($this, $easy, $this->factory);
44
+ }
45
+ }
includes/aws/GuzzleHttp/Handler/CurlMultiHandler.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Promise as P;
5
+ use GuzzleHttp\Promise\Promise;
6
+ use GuzzleHttp\Psr7;
7
+ use Psr\Http\Message\RequestInterface;
8
+
9
+ /**
10
+ * Returns an asynchronous response using curl_multi_* functions.
11
+ *
12
+ * When using the CurlMultiHandler, custom curl options can be specified as an
13
+ * associative array of curl option constants mapping to values in the
14
+ * **curl** key of the provided request options.
15
+ *
16
+ * @property resource $_mh Internal use only. Lazy loaded multi-handle.
17
+ */
18
+ class CurlMultiHandler
19
+ {
20
+ /** @var CurlFactoryInterface */
21
+ private $factory;
22
+ private $selectTimeout;
23
+ private $active;
24
+ private $handles = [];
25
+ private $delays = [];
26
+
27
+ /**
28
+ * This handler accepts the following options:
29
+ *
30
+ * - handle_factory: An optional factory used to create curl handles
31
+ * - select_timeout: Optional timeout (in seconds) to block before timing
32
+ * out while selecting curl handles. Defaults to 1 second.
33
+ *
34
+ * @param array $options
35
+ */
36
+ public function __construct(array $options = [])
37
+ {
38
+ $this->factory = isset($options['handle_factory'])
39
+ ? $options['handle_factory'] : new CurlFactory(50);
40
+ $this->selectTimeout = isset($options['select_timeout'])
41
+ ? $options['select_timeout'] : 1;
42
+ }
43
+
44
+ public function __get($name)
45
+ {
46
+ if ($name === '_mh') {
47
+ return $this->_mh = curl_multi_init();
48
+ }
49
+
50
+ throw new \BadMethodCallException();
51
+ }
52
+
53
+ public function __destruct()
54
+ {
55
+ if (isset($this->_mh)) {
56
+ curl_multi_close($this->_mh);
57
+ unset($this->_mh);
58
+ }
59
+ }
60
+
61
+ public function __invoke(RequestInterface $request, array $options)
62
+ {
63
+ $easy = $this->factory->create($request, $options);
64
+ $id = (int) $easy->handle;
65
+
66
+ $promise = new Promise(
67
+ [$this, 'execute'],
68
+ function () use ($id) { return $this->cancel($id); }
69
+ );
70
+
71
+ $this->addRequest(['easy' => $easy, 'deferred' => $promise]);
72
+
73
+ return $promise;
74
+ }
75
+
76
+ /**
77
+ * Ticks the curl event loop.
78
+ */
79
+ public function tick()
80
+ {
81
+ // Add any delayed handles if needed.
82
+ if ($this->delays) {
83
+ $currentTime = microtime(true);
84
+ foreach ($this->delays as $id => $delay) {
85
+ if ($currentTime >= $delay) {
86
+ unset($this->delays[$id]);
87
+ curl_multi_add_handle(
88
+ $this->_mh,
89
+ $this->handles[$id]['easy']->handle
90
+ );
91
+ }
92
+ }
93
+ }
94
+
95
+ // Step through the task queue which may add additional requests.
96
+ P\queue()->run();
97
+
98
+ if ($this->active &&
99
+ curl_multi_select($this->_mh, $this->selectTimeout) === -1
100
+ ) {
101
+ // Perform a usleep if a select returns -1.
102
+ // See: https://bugs.php.net/bug.php?id=61141
103
+ usleep(250);
104
+ }
105
+
106
+ while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM);
107
+
108
+ $this->processMessages();
109
+ }
110
+
111
+ /**
112
+ * Runs until all outstanding connections have completed.
113
+ */
114
+ public function execute()
115
+ {
116
+ $queue = P\queue();
117
+
118
+ while ($this->handles || !$queue->isEmpty()) {
119
+ // If there are no transfers, then sleep for the next delay
120
+ if (!$this->active && $this->delays) {
121
+ usleep($this->timeToNext());
122
+ }
123
+ $this->tick();
124
+ }
125
+ }
126
+
127
+ private function addRequest(array $entry)
128
+ {
129
+ $easy = $entry['easy'];
130
+ $id = (int) $easy->handle;
131
+ $this->handles[$id] = $entry;
132
+ if (empty($easy->options['delay'])) {
133
+ curl_multi_add_handle($this->_mh, $easy->handle);
134
+ } else {
135
+ $this->delays[$id] = microtime(true) + ($easy->options['delay'] / 1000);
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Cancels a handle from sending and removes references to it.
141
+ *
142
+ * @param int $id Handle ID to cancel and remove.
143
+ *
144
+ * @return bool True on success, false on failure.
145
+ */
146
+ private function cancel($id)
147
+ {
148
+ // Cannot cancel if it has been processed.
149
+ if (!isset($this->handles[$id])) {
150
+ return false;
151
+ }
152
+
153
+ $handle = $this->handles[$id]['easy']->handle;
154
+ unset($this->delays[$id], $this->handles[$id]);
155
+ curl_multi_remove_handle($this->_mh, $handle);
156
+ curl_close($handle);
157
+
158
+ return true;
159
+ }
160
+
161
+ private function processMessages()
162
+ {
163
+ while ($done = curl_multi_info_read($this->_mh)) {
164
+ $id = (int) $done['handle'];
165
+ curl_multi_remove_handle($this->_mh, $done['handle']);
166
+
167
+ if (!isset($this->handles[$id])) {
168
+ // Probably was cancelled.
169
+ continue;
170
+ }
171
+
172
+ $entry = $this->handles[$id];
173
+ unset($this->handles[$id], $this->delays[$id]);
174
+ $entry['easy']->errno = $done['result'];
175
+ $entry['deferred']->resolve(
176
+ CurlFactory::finish(
177
+ $this,
178
+ $entry['easy'],
179
+ $this->factory
180
+ )
181
+ );
182
+ }
183
+ }
184
+
185
+ private function timeToNext()
186
+ {
187
+ $currentTime = microtime(true);
188
+ $nextTime = PHP_INT_MAX;
189
+ foreach ($this->delays as $time) {
190
+ if ($time < $nextTime) {
191
+ $nextTime = $time;
192
+ }
193
+ }
194
+
195
+ return max(0, $currentTime - $nextTime);
196
+ }
197
+ }
includes/aws/GuzzleHttp/Handler/EasyHandle.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Psr7\Response;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use Psr\Http\Message\ResponseInterface;
7
+ use Psr\Http\Message\StreamInterface;
8
+
9
+ /**
10
+ * Represents a cURL easy handle and the data it populates.
11
+ *
12
+ * @internal
13
+ */
14
+ final class EasyHandle
15
+ {
16
+ /** @var resource cURL resource */
17
+ public $handle;
18
+
19
+ /** @var StreamInterface Where data is being written */
20
+ public $sink;
21
+
22
+ /** @var array Received HTTP headers so far */
23
+ public $headers = [];
24
+
25
+ /** @var ResponseInterface Received response (if any) */
26
+ public $response;
27
+
28
+ /** @var RequestInterface Request being sent */
29
+ public $request;
30
+
31
+ /** @var array Request options */
32
+ public $options = [];
33
+
34
+ /** @var int cURL error number (if any) */
35
+ public $errno = 0;
36
+
37
+ /** @var \Exception Exception during on_headers (if any) */
38
+ public $onHeadersException;
39
+
40
+ /**
41
+ * Attach a response to the easy handle based on the received headers.
42
+ *
43
+ * @throws \RuntimeException if no headers have been received.
44
+ */
45
+ public function createResponse()
46
+ {
47
+ if (empty($this->headers)) {
48
+ throw new \RuntimeException('No headers have been received');
49
+ }
50
+
51
+ // HTTP-version SP status-code SP reason-phrase
52
+ $startLine = explode(' ', array_shift($this->headers), 3);
53
+ $headers = \GuzzleHttp\headers_from_lines($this->headers);
54
+ $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
55
+
56
+ if (!empty($this->options['decode_content'])
57
+ && isset($normalizedKeys['content-encoding'])
58
+ ) {
59
+ unset($headers[$normalizedKeys['content-encoding']]);
60
+ if (isset($normalizedKeys['content-length'])) {
61
+ $bodyLength = (int) $this->sink->getSize();
62
+ if ($bodyLength) {
63
+ $headers[$normalizedKeys['content-length']] = $bodyLength;
64
+ } else {
65
+ unset($headers[$normalizedKeys['content-length']]);
66
+ }
67
+ }
68
+ }
69
+
70
+ // Attach a response to the easy handle with the parsed headers.
71
+ $this->response = new Response(
72
+ $startLine[1],
73
+ $headers,
74
+ $this->sink,
75
+ substr($startLine[0], 5),
76
+ isset($startLine[2]) ? (string) $startLine[2] : null
77
+ );
78
+ }
79
+
80
+ public function __get($name)
81
+ {
82
+ $msg = $name === 'handle'
83
+ ? 'The EasyHandle has been released'
84
+ : 'Invalid property: ' . $name;
85
+ throw new \BadMethodCallException($msg);
86
+ }
87
+ }
includes/aws/GuzzleHttp/Handler/MockHandler.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\HandlerStack;
5
+ use GuzzleHttp\Promise\PromiseInterface;
6
+ use GuzzleHttp\Promise\RejectedPromise;
7
+ use GuzzleHttp\TransferStats;
8
+ use Psr\Http\Message\RequestInterface;
9
+ use Psr\Http\Message\ResponseInterface;
10
+
11
+ /**
12
+ * Handler that returns responses or throw exceptions from a queue.
13
+ */
14
+ class MockHandler implements \Countable
15
+ {
16
+ private $queue;
17
+ private $lastRequest;
18
+ private $lastOptions;
19
+ private $onFulfilled;
20
+ private $onRejected;
21
+
22
+ /**
23
+ * Creates a new MockHandler that uses the default handler stack list of
24
+ * middlewares.
25
+ *
26
+ * @param array $queue Array of responses, callables, or exceptions.
27
+ * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
28
+ * @param callable $onRejected Callback to invoke when the return value is rejected.
29
+ *
30
+ * @return MockHandler
31
+ */
32
+ public static function createWithMiddleware(
33
+ array $queue = null,
34
+ callable $onFulfilled = null,
35
+ callable $onRejected = null
36
+ ) {
37
+ return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
38
+ }
39
+
40
+ /**
41
+ * The passed in value must be an array of
42
+ * {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
43
+ * callables, or Promises.
44
+ *
45
+ * @param array $queue
46
+ * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
47
+ * @param callable $onRejected Callback to invoke when the return value is rejected.
48
+ */
49
+ public function __construct(
50
+ array $queue = null,
51
+ callable $onFulfilled = null,
52
+ callable $onRejected = null
53
+ ) {
54
+ $this->onFulfilled = $onFulfilled;
55
+ $this->onRejected = $onRejected;
56
+
57
+ if ($queue) {
58
+ call_user_func_array([$this, 'append'], $queue);
59
+ }
60
+ }
61
+
62
+ public function __invoke(RequestInterface $request, array $options)
63
+ {
64
+ if (!$this->queue) {
65
+ throw new \OutOfBoundsException('Mock queue is empty');
66
+ }
67
+
68
+ if (isset($options['delay'])) {
69
+ usleep($options['delay'] * 1000);
70
+ }
71
+
72
+ $this->lastRequest = $request;
73
+ $this->lastOptions = $options;
74
+ $response = array_shift($this->queue);
75
+
76
+ if (is_callable($response)) {
77
+ $response = $response($request, $options);
78
+ }
79
+
80
+ $response = $response instanceof \Exception
81
+ ? new RejectedPromise($response)
82
+ : \GuzzleHttp\Promise\promise_for($response);
83
+
84
+ return $response->then(
85
+ function ($value) use ($request, $options) {
86
+ $this->invokeStats($request, $options, $value);
87
+ if ($this->onFulfilled) {
88
+ call_user_func($this->onFulfilled, $value);
89
+ }
90
+ if (isset($options['sink'])) {
91
+ $contents = (string) $value->getBody();
92
+ $sink = $options['sink'];
93
+
94
+ if (is_resource($sink)) {
95
+ fwrite($sink, $contents);
96
+ } elseif (is_string($sink)) {
97
+ file_put_contents($sink, $contents);
98
+ } elseif ($sink instanceof \Psr\Http\Message\StreamInterface) {
99
+ $sink->write($contents);
100
+ }
101
+ }
102
+
103
+ return $value;
104
+ },
105
+ function ($reason) use ($request, $options) {
106
+ $this->invokeStats($request, $options, null, $reason);
107
+ if ($this->onRejected) {
108
+ call_user_func($this->onRejected, $reason);
109
+ }
110
+ return new RejectedPromise($reason);
111
+ }
112
+ );
113
+ }
114
+
115
+ /**
116
+ * Adds one or more variadic requests, exceptions, callables, or promises
117
+ * to the queue.
118
+ */
119
+ public function append()
120
+ {
121
+ foreach (func_get_args() as $value) {
122
+ if ($value instanceof ResponseInterface
123
+ || $value instanceof \Exception
124
+ || $value instanceof PromiseInterface
125
+ || is_callable($value)
126
+ ) {
127
+ $this->queue[] = $value;
128
+ } else {
129
+ throw new \InvalidArgumentException('Expected a response or '
130
+ . 'exception. Found ' . \GuzzleHttp\describe_type($value));
131
+ }
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Get the last received request.
137
+ *
138
+ * @return RequestInterface
139
+ */
140
+ public function getLastRequest()
141
+ {
142
+ return $this->lastRequest;
143
+ }
144
+
145
+ /**
146
+ * Get the last received request options.
147
+ *
148
+ * @return RequestInterface
149
+ */
150
+ public function getLastOptions()
151
+ {
152
+ return $this->lastOptions;
153
+ }
154
+
155
+ /**
156
+ * Returns the number of remaining items in the queue.
157
+ *
158
+ * @return int
159
+ */
160
+ public function count()
161
+ {
162
+ return count($this->queue);
163
+ }
164
+
165
+ private function invokeStats(
166
+ RequestInterface $request,
167
+ array $options,
168
+ ResponseInterface $response = null,
169
+ $reason = null
170
+ ) {
171
+ if (isset($options['on_stats'])) {
172
+ $stats = new TransferStats($request, $response, 0, $reason);
173
+ call_user_func($options['on_stats'], $stats);
174
+ }
175
+ }
176
+ }
includes/aws/GuzzleHttp/Handler/Proxy.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\RequestOptions;
5
+ use Psr\Http\Message\RequestInterface;
6
+
7
+ /**
8
+ * Provides basic proxies for handlers.
9
+ */
10
+ class Proxy
11
+ {
12
+ /**
13
+ * Sends synchronous requests to a specific handler while sending all other
14
+ * requests to another handler.
15
+ *
16
+ * @param callable $default Handler used for normal responses
17
+ * @param callable $sync Handler used for synchronous responses.
18
+ *
19
+ * @return callable Returns the composed handler.
20
+ */
21
+ public static function wrapSync(
22
+ callable $default,
23
+ callable $sync
24
+ ) {
25
+ return function (RequestInterface $request, array $options) use ($default, $sync) {
26
+ return empty($options[RequestOptions::SYNCHRONOUS])
27
+ ? $default($request, $options)
28
+ : $sync($request, $options);
29
+ };
30
+ }
31
+
32
+ /**
33
+ * Sends streaming requests to a streaming compatible handler while sending
34
+ * all other requests to a default handler.
35
+ *
36
+ * This, for example, could be useful for taking advantage of the
37
+ * performance benefits of curl while still supporting true streaming
38
+ * through the StreamHandler.
39
+ *
40
+ * @param callable $default Handler used for non-streaming responses
41
+ * @param callable $streaming Handler used for streaming responses
42
+ *
43
+ * @return callable Returns the composed handler.
44
+ */
45
+ public static function wrapStreaming(
46
+ callable $default,
47
+ callable $streaming
48
+ ) {
49
+ return function (RequestInterface $request, array $options) use ($default, $streaming) {
50
+ return empty($options['stream'])
51
+ ? $default($request, $options)
52
+ : $streaming($request, $options);
53
+ };
54
+ }
55
+ }
includes/aws/GuzzleHttp/Handler/StreamHandler.php ADDED
@@ -0,0 +1,458 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Exception\RequestException;
5
+ use GuzzleHttp\Exception\ConnectException;
6
+ use GuzzleHttp\Promise\FulfilledPromise;
7
+ use GuzzleHttp\Promise\RejectedPromise;
8
+ use GuzzleHttp\Promise\PromiseInterface;
9
+ use GuzzleHttp\Psr7;
10
+ use GuzzleHttp\TransferStats;
11
+ use Psr\Http\Message\RequestInterface;
12
+ use Psr\Http\Message\ResponseInterface;
13
+ use Psr\Http\Message\StreamInterface;
14
+
15
+ /**
16
+ * HTTP handler that uses PHP's HTTP stream wrapper.
17
+ */
18
+ class StreamHandler
19
+ {
20
+ private $lastHeaders = [];
21
+
22
+ /**
23
+ * Sends an HTTP request.
24
+ *
25
+ * @param RequestInterface $request Request to send.
26
+ * @param array $options Request transfer options.
27
+ *
28
+ * @return PromiseInterface
29
+ */
30
+ public function __invoke(RequestInterface $request, array $options)
31
+ {
32
+ // Sleep if there is a delay specified.
33
+ if (isset($options['delay'])) {
34
+ usleep($options['delay'] * 1000);
35
+ }
36
+
37
+ $startTime = isset($options['on_stats']) ? microtime(true) : null;
38
+
39
+ try {
40
+ // Does not support the expect header.
41
+ $request = $request->withoutHeader('Expect');
42
+
43
+ // Append a content-length header if body size is zero to match
44
+ // cURL's behavior.
45
+ if (0 === $request->getBody()->getSize()) {
46
+ $request = $request->withHeader('Content-Length', 0);
47
+ }
48
+
49
+ return $this->createResponse(
50
+ $request,
51
+ $options,
52
+ $this->createStream($request, $options),
53
+ $startTime
54
+ );
55
+ } catch (\InvalidArgumentException $e) {
56
+ throw $e;
57
+ } catch (\Exception $e) {
58
+ // Determine if the error was a networking error.
59
+ $message = $e->getMessage();
60
+ // This list can probably get more comprehensive.
61
+ if (strpos($message, 'getaddrinfo') // DNS lookup failed
62
+ || strpos($message, 'Connection refused')
63
+ || strpos($message, "couldn't connect to host") // error on HHVM
64
+ ) {
65
+ $e = new ConnectException($e->getMessage(), $request, $e);
66
+ }
67
+ $e = RequestException::wrapException($request, $e);
68
+ $this->invokeStats($options, $request, $startTime, null, $e);
69
+
70
+ return new RejectedPromise($e);
71
+ }
72
+ }
73
+
74
+ private function invokeStats(
75
+ array $options,
76
+ RequestInterface $request,
77
+ $startTime,
78
+ ResponseInterface $response = null,
79
+ $error = null
80
+ ) {
81
+ if (isset($options['on_stats'])) {
82
+ $stats = new TransferStats(
83
+ $request,
84
+ $response,
85
+ microtime(true) - $startTime,
86
+ $error,
87
+ []
88
+ );
89
+ call_user_func($options['on_stats'], $stats);
90
+ }
91
+ }
92
+
93
+ private function createResponse(
94
+ RequestInterface $request,
95
+ array $options,
96
+ $stream,
97
+ $startTime
98
+ ) {
99
+ $hdrs = $this->lastHeaders;
100
+ $this->lastHeaders = [];
101
+ $parts = explode(' ', array_shift($hdrs), 3);
102
+ $ver = explode('/', $parts[0])[1];
103
+ $status = $parts[1];
104
+ $reason = isset($parts[2]) ? $parts[2] : null;
105
+ $headers = \GuzzleHttp\headers_from_lines($hdrs);
106
+ list ($stream, $headers) = $this->checkDecode($options, $headers, $stream);
107
+ $stream = Psr7\stream_for($stream);
108
+ $sink = $this->createSink($stream, $options);
109
+ $response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
110
+
111
+ if (isset($options['on_headers'])) {
112
+ try {
113
+ $options['on_headers']($response);
114
+ } catch (\Exception $e) {
115
+ $msg = 'An error was encountered during the on_headers event';
116
+ $ex = new RequestException($msg, $request, $response, $e);
117
+ return new RejectedPromise($ex);
118
+ }
119
+ }
120
+
121
+ if ($sink !== $stream) {
122
+ $this->drain($stream, $sink);
123
+ }
124
+
125
+ $this->invokeStats($options, $request, $startTime, $response, null);
126
+
127
+ return new FulfilledPromise($response);
128
+ }
129
+
130
+ private function createSink(StreamInterface $stream, array $options)
131
+ {
132
+ if (!empty($options['stream'])) {
133
+ return $stream;
134
+ }
135
+
136
+ $sink = isset($options['sink'])
137
+ ? $options['sink']
138
+ : fopen('php://temp', 'r+');
139
+
140
+ return is_string($sink)
141
+ ? new Psr7\Stream(Psr7\try_fopen($sink, 'r+'))
142
+ : Psr7\stream_for($sink);
143
+ }
144
+
145
+ private function checkDecode(array $options, array $headers, $stream)
146
+ {
147
+ // Automatically decode responses when instructed.
148
+ if (!empty($options['decode_content'])) {
149
+ $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
150
+ if (isset($normalizedKeys['content-encoding'])) {
151
+ $encoding = $headers[$normalizedKeys['content-encoding']];
152
+ if ($encoding[0] == 'gzip' || $encoding[0] == 'deflate') {
153
+ $stream = new Psr7\InflateStream(
154
+ Psr7\stream_for($stream)
155
+ );
156
+ // Remove content-encoding header
157
+ unset($headers[$normalizedKeys['content-encoding']]);
158
+ // Fix content-length header
159
+ if (isset($normalizedKeys['content-length'])) {
160
+ $length = (int) $stream->getSize();
161
+ if ($length == 0) {
162
+ unset($headers[$normalizedKeys['content-length']]);
163
+ } else {
164
+ $headers[$normalizedKeys['content-length']] = [$length];
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+
171
+ return [$stream, $headers];
172
+ }
173
+
174
+ /**
175
+ * Drains the source stream into the "sink" client option.
176
+ *
177
+ * @param StreamInterface $source
178
+ * @param StreamInterface $sink
179
+ *
180
+ * @return StreamInterface
181
+ * @throws \RuntimeException when the sink option is invalid.
182
+ */
183
+ private function drain(StreamInterface $source, StreamInterface $sink)
184
+ {
185
+ Psr7\copy_to_stream($source, $sink);
186
+ $sink->seek(0);
187
+ $source->close();
188
+
189
+ return $sink;
190
+ }
191
+
192
+ /**
193
+ * Create a resource and check to ensure it was created successfully
194
+ *
195
+ * @param callable $callback Callable that returns stream resource
196
+ *
197
+ * @return resource
198
+ * @throws \RuntimeException on error
199
+ */
200
+ private function createResource(callable $callback)
201
+ {
202
+ $errors = null;
203
+ set_error_handler(function ($_, $msg, $file, $line) use (&$errors) {
204
+ $errors[] = [
205
+ 'message' => $msg,
206
+ 'file' => $file,
207
+ 'line' => $line
208
+ ];
209
+ return true;
210
+ });
211
+
212
+ $resource = $callback();
213
+ restore_error_handler();
214
+
215
+ if (!$resource) {
216
+ $message = 'Error creating resource: ';
217
+ foreach ($errors as $err) {
218
+ foreach ($err as $key => $value) {
219
+ $message .= "[$key] $value" . PHP_EOL;
220
+ }
221
+ }
222
+ throw new \RuntimeException(trim($message));
223
+ }
224
+
225
+ return $resource;
226
+ }
227
+
228
+ private function createStream(RequestInterface $request, array $options)
229
+ {
230
+ static $methods;
231
+ if (!$methods) {
232
+ $methods = array_flip(get_class_methods(__CLASS__));
233
+ }
234
+
235
+ // HTTP/1.1 streams using the PHP stream wrapper require a
236
+ // Connection: close header
237
+ if ($request->getProtocolVersion() == '1.1'
238
+ && !$request->hasHeader('Connection')
239
+ ) {
240
+ $request = $request->withHeader('Connection', 'close');
241
+ }
242
+
243
+ // Ensure SSL is verified by default
244
+ if (!isset($options['verify'])) {
245
+ $options['verify'] = true;
246
+ }
247
+
248
+ $params = [];
249
+ $context = $this->getDefaultContext($request, $options);
250
+
251
+ if (isset($options['on_headers']) && !is_callable($options['on_headers'])) {
252
+ throw new \InvalidArgumentException('on_headers must be callable');
253
+ }
254
+
255
+ if (!empty($options)) {
256
+ foreach ($options as $key => $value) {
257
+ $method = "add_{$key}";
258
+ if (isset($methods[$method])) {
259
+ $this->{$method}($request, $context, $value, $params);
260
+ }
261
+ }
262
+ }
263
+
264
+ if (isset($options['stream_context'])) {
265
+ if (!is_array($options['stream_context'])) {
266
+ throw new \InvalidArgumentException('stream_context must be an array');
267
+ }
268
+ $context = array_replace_recursive(
269
+ $context,
270
+ $options['stream_context']
271
+ );
272
+ }
273
+
274
+ $context = $this->createResource(
275
+ function () use ($context, $params) {
276
+ return stream_context_create($context, $params);
277
+ }
278
+ );
279
+
280
+ return $this->createResource(
281
+ function () use ($request, &$http_response_header, $context) {
282
+ $resource = fopen($request->getUri(), 'r', null, $context);
283
+ $this->lastHeaders = $http_response_header;
284
+ return $resource;
285
+ }
286
+ );
287
+ }
288
+
289
+ private function getDefaultContext(RequestInterface $request)
290
+ {
291
+ $headers = '';
292
+ foreach ($request->getHeaders() as $name => $value) {
293
+ foreach ($value as $val) {
294
+ $headers .= "$name: $val\r\n";
295
+ }
296
+ }
297
+
298
+ $context = [
299
+ 'http' => [
300
+ 'method' => $request->getMethod(),
301
+ 'header' => $headers,
302
+ 'protocol_version' => $request->getProtocolVersion(),
303
+ 'ignore_errors' => true,
304
+ 'follow_location' => 0,
305
+ ],
306
+ ];
307
+
308
+ $body = (string) $request->getBody();
309
+
310
+ if (!empty($body)) {
311
+ $context['http']['content'] = $body;
312
+ // Prevent the HTTP handler from adding a Content-Type header.
313
+ if (!$request->hasHeader('Content-Type')) {
314
+ $context['http']['header'] .= "Content-Type:\r\n";
315
+ }
316
+ }
317
+
318
+ $context['http']['header'] = rtrim($context['http']['header']);
319
+
320
+ return $context;
321
+ }
322
+
323
+ private function add_proxy(RequestInterface $request, &$options, $value, &$params)
324
+ {
325
+ if (!is_array($value)) {
326
+ $options['http']['proxy'] = $value;
327
+ } else {
328
+ $scheme = $request->getUri()->getScheme();
329
+ if (isset($value[$scheme])) {
330
+ if (!isset($value['no'])
331
+ || !\GuzzleHttp\is_host_in_noproxy(
332
+ $request->getUri()->getHost(),
333
+ $value['no']
334
+ )
335
+ ) {
336
+ $options['http']['proxy'] = $value[$scheme];
337
+ }
338
+ }
339
+ }
340
+ }
341
+
342
+ private function add_timeout(RequestInterface $request, &$options, $value, &$params)
343
+ {
344
+ $options['http']['timeout'] = $value;
345
+ }
346
+
347
+ private function add_verify(RequestInterface $request, &$options, $value, &$params)
348
+ {
349
+ if ($value === true) {
350
+ // PHP 5.6 or greater will find the system cert by default. When
351
+ // < 5.6, use the Guzzle bundled cacert.
352
+ if (PHP_VERSION_ID < 50600) {
353
+ $options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle();
354
+ }
355
+ } elseif (is_string($value)) {
356
+ $options['ssl']['cafile'] = $value;
357
+ if (!file_exists($value)) {
358
+ throw new \RuntimeException("SSL CA bundle not found: $value");
359
+ }
360
+ } elseif ($value === false) {
361
+ $options['ssl']['verify_peer'] = false;
362
+ $options['ssl']['verify_peer_name'] = false;
363
+ return;
364
+ } else {
365
+ throw new \InvalidArgumentException('Invalid verify request option');
366
+ }
367
+
368
+ $options['ssl']['verify_peer'] = true;
369
+ $options['ssl']['verify_peer_name'] = true;
370
+ $options['ssl']['allow_self_signed'] = false;
371
+ }
372
+
373
+ private function add_cert(RequestInterface $request, &$options, $value, &$params)
374
+ {
375
+ if (is_array($value)) {
376
+ $options['ssl']['passphrase'] = $value[1];
377
+ $value = $value[0];
378
+ }
379
+
380
+ if (!file_exists($value)) {
381
+ throw new \RuntimeException("SSL certificate not found: {$value}");
382
+ }
383
+
384
+ $options['ssl']['local_cert'] = $value;
385
+ }
386
+
387
+ private function add_progress(RequestInterface $request, &$options, $value, &$params)
388
+ {
389
+ $this->addNotification(
390
+ $params,
391
+ function ($code, $a, $b, $c, $transferred, $total) use ($value) {
392
+ if ($code == STREAM_NOTIFY_PROGRESS) {
393
+ $value($total, $transferred, null, null);
394
+ }
395
+ }
396
+ );
397
+ }
398
+
399
+ private function add_debug(RequestInterface $request, &$options, $value, &$params)
400
+ {
401
+ if ($value === false) {
402
+ return;
403
+ }
404
+
405
+ static $map = [
406
+ STREAM_NOTIFY_CONNECT => 'CONNECT',
407
+ STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
408
+ STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
409
+ STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
410
+ STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
411
+ STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
412
+ STREAM_NOTIFY_PROGRESS => 'PROGRESS',
413
+ STREAM_NOTIFY_FAILURE => 'FAILURE',
414
+ STREAM_NOTIFY_COMPLETED => 'COMPLETED',
415
+ STREAM_NOTIFY_RESOLVE => 'RESOLVE',
416
+ ];
417
+ static $args = ['severity', 'message', 'message_code',
418
+ 'bytes_transferred', 'bytes_max'];
419
+
420
+ $value = \GuzzleHttp\debug_resource($value);
421
+ $ident = $request->getMethod() . ' ' . $request->getUri();
422
+ $this->addNotification(
423
+ $params,
424
+ function () use ($ident, $value, $map, $args) {
425
+ $passed = func_get_args();
426
+ $code = array_shift($passed);
427
+ fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
428
+ foreach (array_filter($passed) as $i => $v) {
429
+ fwrite($value, $args[$i] . ': "' . $v . '" ');
430
+ }
431
+ fwrite($value, "\n");
432
+ }
433
+ );
434
+ }
435
+
436
+ private function addNotification(array &$params, callable $notify)
437
+ {
438
+ // Wrap the existing function if needed.
439
+ if (!isset($params['notification'])) {
440
+ $params['notification'] = $notify;
441
+ } else {
442
+ $params['notification'] = $this->callArray([
443
+ $params['notification'],
444
+ $notify
445
+ ]);
446
+ }
447
+ }
448
+
449
+ private function callArray(array $functions)
450
+ {
451
+ return function () use ($functions) {
452
+ $args = func_get_args();
453
+ foreach ($functions as $fn) {
454
+ call_user_func_array($fn, $args);
455
+ }
456
+ };
457
+ }
458
+ }
includes/aws/GuzzleHttp/HandlerStack.php ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+
6
+ /**
7
+ * Creates a composed Guzzle handler function by stacking middlewares on top of
8
+ * an HTTP handler function.
9
+ */
10
+ class HandlerStack
11
+ {
12
+ /** @var callable */
13
+ private $handler;
14
+
15
+ /** @var array */
16
+ private $stack = [];
17
+
18
+ /** @var callable|null */
19
+ private $cached;
20
+
21
+ /**
22
+ * Creates a default handler stack that can be used by clients.
23
+ *
24
+ * The returned handler will wrap the provided handler or use the most
25
+ * appropriate default handler for you system. The returned HandlerStack has
26
+ * support for cookies, redirects, HTTP error exceptions, and preparing a body
27
+ * before sending.
28
+ *
29
+ * The returned handler stack can be passed to a client in the "handler"
30
+ * option.
31
+ *
32
+ * @param callable $handler HTTP handler function to use with the stack. If no
33
+ * handler is provided, the best handler for your
34
+ * system will be utilized.
35
+ *
36
+ * @return HandlerStack
37
+ */
38
+ public static function create(callable $handler = null)
39
+ {
40
+ $stack = new self($handler ?: choose_handler());
41
+ $stack->push(Middleware::httpErrors(), 'http_errors');
42
+ $stack->push(Middleware::redirect(), 'allow_redirects');
43
+ $stack->push(Middleware::cookies(), 'cookies');
44
+ $stack->push(Middleware::prepareBody(), 'prepare_body');
45
+
46
+ return $stack;
47
+ }
48
+
49
+ /**
50
+ * @param callable $handler Underlying HTTP handler.
51
+ */
52
+ public function __construct(callable $handler = null)
53
+ {
54
+ $this->handler = $handler;
55
+ }
56
+
57
+ /**
58
+ * Invokes the handler stack as a composed handler
59
+ *
60
+ * @param RequestInterface $request
61
+ * @param array $options
62
+ */
63
+ public function __invoke(RequestInterface $request, array $options)
64
+ {
65
+ $handler = $this->resolve();
66
+
67
+ return $handler($request, $options);
68
+ }
69
+
70
+ /**
71
+ * Dumps a string representation of the stack.
72
+ *
73
+ * @return string
74
+ */
75
+ public function __toString()
76
+ {
77
+ $depth = 0;
78
+ $stack = [];
79
+ if ($this->handler) {
80
+ $stack[] = "0) Handler: " . $this->debugCallable($this->handler);
81
+ }
82
+
83
+ $result = '';
84
+ foreach (array_reverse($this->stack) as $tuple) {
85
+ $depth++;
86
+ $str = "{$depth}) Name: '{$tuple[1]}', ";
87
+ $str .= "Function: " . $this->debugCallable($tuple[0]);
88
+ $result = "> {$str}\n{$result}";
89
+ $stack[] = $str;
90
+ }
91
+
92
+ foreach (array_keys($stack) as $k) {
93
+ $result .= "< {$stack[$k]}\n";
94
+ }
95
+
96
+ return $result;
97
+ }
98
+
99
+ /**
100
+ * Set the HTTP handler that actually returns a promise.
101
+ *
102
+ * @param callable $handler Accepts a request and array of options and
103
+ * returns a Promise.
104
+ */
105
+ public function setHandler(callable $handler)
106
+ {
107
+ $this->handler = $handler;
108
+ $this->cached = null;
109
+ }
110
+
111
+ /**
112
+ * Returns true if the builder has a handler.
113
+ *
114
+ * @return bool
115
+ */
116
+ public function hasHandler()
117
+ {
118
+ return (bool) $this->handler;
119
+ }
120
+
121
+ /**
122
+ * Unshift a middleware to the bottom of the stack.
123
+ *
124
+ * @param callable $middleware Middleware function
125
+ * @param string $name Name to register for this middleware.
126
+ */
127
+ public function unshift(callable $middleware, $name = null)
128
+ {
129
+ array_unshift($this->stack, [$middleware, $name]);
130
+ $this->cached = null;
131
+ }
132
+
133
+ /**
134
+ * Push a middleware to the top of the stack.
135
+ *
136
+ * @param callable $middleware Middleware function
137
+ * @param string $name Name to register for this middleware.
138
+ */
139
+ public function push(callable $middleware, $name = '')
140
+ {
141
+ $this->stack[] = [$middleware, $name];
142
+ $this->cached = null;
143
+ }
144
+
145
+ /**
146
+ * Add a middleware before another middleware by name.
147
+ *
148
+ * @param string $findName Middleware to find
149
+ * @param callable $middleware Middleware function
150
+ * @param string $withName Name to register for this middleware.
151
+ */
152
+ public function before($findName, callable $middleware, $withName = '')
153
+ {
154
+ $this->splice($findName, $withName, $middleware, true);
155
+ }
156
+
157
+ /**
158
+ * Add a middleware after another middleware by name.
159
+ *
160
+ * @param string $findName Middleware to find
161
+ * @param callable $middleware Middleware function
162
+ * @param string $withName Name to register for this middleware.
163
+ */
164
+ public function after($findName, callable $middleware, $withName = '')
165
+ {
166
+ $this->splice($findName, $withName, $middleware, false);
167
+ }
168
+
169
+ /**
170
+ * Remove a middleware by instance or name from the stack.
171
+ *
172
+ * @param callable|string $remove Middleware to remove by instance or name.
173
+ */
174
+ public function remove($remove)
175
+ {
176
+ $this->cached = null;
177
+ $idx = is_callable($remove) ? 0 : 1;
178
+ $this->stack = array_values(array_filter(
179
+ $this->stack,
180
+ function ($tuple) use ($idx, $remove) {
181
+ return $tuple[$idx] !== $remove;
182
+ }
183
+ ));
184
+ }
185
+
186
+ /**
187
+ * Compose the middleware and handler into a single callable function.
188
+ *
189
+ * @return callable
190
+ */
191
+ public function resolve()
192
+ {
193
+ if (!$this->cached) {
194
+ if (!($prev = $this->handler)) {
195
+ throw new \LogicException('No handler has been specified');
196
+ }
197
+
198
+ foreach (array_reverse($this->stack) as $fn) {
199
+ $prev = $fn[0]($prev);
200
+ }
201
+
202
+ $this->cached = $prev;
203
+ }
204
+
205
+ return $this->cached;
206
+ }
207
+
208
+ /**
209
+ * @param $name
210
+ * @return int
211
+ */
212
+ private function findByName($name)
213
+ {
214
+ foreach ($this->stack as $k => $v) {
215
+ if ($v[1] === $name) {
216
+ return $k;
217
+ }
218
+ }
219
+
220
+ throw new \InvalidArgumentException("Middleware not found: $name");
221
+ }
222
+
223
+ /**
224
+ * Splices a function into the middleware list at a specific position.
225
+ *
226
+ * @param $findName
227
+ * @param $withName
228
+ * @param callable $middleware
229
+ * @param $before
230
+ */
231
+ private function splice($findName, $withName, callable $middleware, $before)
232
+ {
233
+ $this->cached = null;
234
+ $idx = $this->findByName($findName);
235
+ $tuple = [$middleware, $withName];
236
+
237
+ if ($before) {
238
+ if ($idx === 0) {
239
+ array_unshift($this->stack, $tuple);
240
+ } else {
241
+ $replacement = [$tuple, $this->stack[$idx]];
242
+ array_splice($this->stack, $idx, 1, $replacement);
243
+ }
244
+ } elseif ($idx === count($this->stack) - 1) {
245
+ $this->stack[] = $tuple;
246
+ } else {
247
+ $replacement = [$this->stack[$idx], $tuple];
248
+ array_splice($this->stack, $idx, 1, $replacement);
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Provides a debug string for a given callable.
254
+ *
255
+ * @param array|callable $fn Function to write as a string.
256
+ *
257
+ * @return string
258
+ */
259
+ private function debugCallable($fn)
260
+ {
261
+ if (is_string($fn)) {
262
+ return "callable({$fn})";
263
+ }
264
+
265
+ if (is_array($fn)) {
266
+ return is_string($fn[0])
267
+ ? "callable({$fn[0]}::{$fn[1]})"
268
+ : "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])";
269
+ }
270
+
271
+ return 'callable(' . spl_object_hash($fn) . ')';
272
+ }
273
+ }
includes/aws/GuzzleHttp/MessageFormatter.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use Psr\Http\Message\MessageInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use Psr\Http\Message\ResponseInterface;
7
+
8
+ /**
9
+ * Formats log messages using variable substitutions for requests, responses,
10
+ * and other transactional data.
11
+ *
12
+ * The following variable substitutions are supported:
13
+ *
14
+ * - {request}: Full HTTP request message
15
+ * - {response}: Full HTTP response message
16
+ * - {ts}: ISO 8601 date in GMT
17
+ * - {date_iso_8601} ISO 8601 date in GMT
18
+ * - {date_common_log} Apache common log date using the configured timezone.
19
+ * - {host}: Host of the request
20
+ * - {method}: Method of the request
21
+ * - {uri}: URI of the request
22
+ * - {host}: Host of the request
23
+ * - {version}: Protocol version
24
+ * - {target}: Request target of the request (path + query + fragment)
25
+ * - {hostname}: Hostname of the machine that sent the request
26
+ * - {code}: Status code of the response (if available)
27
+ * - {phrase}: Reason phrase of the response (if available)
28
+ * - {error}: Any error messages (if available)
29
+ * - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message
30
+ * - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message
31
+ * - {req_headers}: Request headers
32
+ * - {res_headers}: Response headers
33
+ * - {req_body}: Request body
34
+ * - {res_body}: Response body
35
+ */
36
+ class MessageFormatter
37
+ {
38
+ /**
39
+ * Apache Common Log Format.
40
+ * @link http://httpd.apache.org/docs/2.4/logs.html#common
41
+ * @var string
42
+ */
43
+ const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
44
+ const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
45
+ const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
46
+
47
+ /** @var string Template used to format log messages */
48
+ private $template;
49
+
50
+ /**
51
+ * @param string $template Log message template
52
+ */
53
+ public function __construct($template = self::CLF)
54
+ {
55
+ $this->template = $template ?: self::CLF;
56
+ }
57
+
58
+ /**
59
+ * Returns a formatted message string.
60
+ *
61
+ * @param RequestInterface $request Request that was sent
62
+ * @param ResponseInterface $response Response that was received
63
+ * @param \Exception $error Exception that was received
64
+ *
65
+ * @return string
66
+ */
67
+ public function format(
68
+ RequestInterface $request,
69
+ ResponseInterface $response = null,
70
+ \Exception $error = null
71
+ ) {
72
+ $cache = [];
73
+
74
+ return preg_replace_callback(
75
+ '/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
76
+ function (array $matches) use ($request, $response, $error, &$cache) {
77
+
78
+ if (isset($cache[$matches[1]])) {
79
+ return $cache[$matches[1]];
80
+ }
81
+
82
+ $result = '';
83
+ switch ($matches[1]) {
84
+ case 'request':
85
+ $result = Psr7\str($request);
86
+ break;
87
+ case 'response':
88
+ $result = $response ? Psr7\str($response) : '';
89
+ break;
90
+ case 'req_headers':
91
+ $result = trim($request->getMethod()
92
+ . ' ' . $request->getRequestTarget())
93
+ . ' HTTP/' . $request->getProtocolVersion() . "\r\n"
94
+ . $this->headers($request);
95
+ break;
96
+ case 'res_headers':
97
+ $result = $response ?
98
+ sprintf(
99
+ 'HTTP/%s %d %s',
100
+ $response->getProtocolVersion(),
101
+ $response->getStatusCode(),
102
+ $response->getReasonPhrase()
103
+ ) . "\r\n" . $this->headers($response)
104
+ : 'NULL';
105
+ break;
106
+ case 'req_body':
107
+ $result = $request->getBody();
108
+ break;
109
+ case 'res_body':
110
+ $result = $response ? $response->getBody() : 'NULL';
111
+ break;
112
+ case 'ts':
113
+ case 'date_iso_8601':
114
+ $result = gmdate('c');
115
+ break;
116
+ case 'date_common_log':
117
+ $result = date('d/M/Y:H:i:s O');
118
+ break;
119
+ case 'method':
120
+ $result = $request->getMethod();
121
+ break;
122
+ case 'version':
123
+ $result = $request->getProtocolVersion();
124
+ break;
125
+ case 'uri':
126
+ case 'url':
127
+ $result = $request->getUri();
128
+ break;
129
+ case 'target':
130
+ $result = $request->getRequestTarget();
131
+ break;
132
+ case 'req_version':
133
+ $result = $request->getProtocolVersion();
134
+ break;
135
+ case 'res_version':
136
+ $result = $response
137
+ ? $response->getProtocolVersion()
138
+ : 'NULL';
139
+ break;
140
+ case 'host':
141
+ $result = $request->getHeaderLine('Host');
142
+ break;
143
+ case 'hostname':
144
+ $result = gethostname();
145
+ break;
146
+ case 'code':
147
+ $result = $response ? $response->getStatusCode() : 'NULL';
148
+ break;
149
+ case 'phrase':
150
+ $result = $response ? $response->getReasonPhrase() : 'NULL';
151
+ break;
152
+ case 'error':
153
+ $result = $error ? $error->getMessage() : 'NULL';
154
+ break;
155
+ default:
156
+ // handle prefixed dynamic headers
157
+ if (strpos($matches[1], 'req_header_') === 0) {
158
+ $result = $request->getHeaderLine(substr($matches[1], 11));
159
+ } elseif (strpos($matches[1], 'res_header_') === 0) {
160
+ $result = $response
161
+ ? $response->getHeaderLine(substr($matches[1], 11))
162
+ : 'NULL';
163
+ }
164
+ }
165
+
166
+ $cache[$matches[1]] = $result;
167
+ return $result;
168
+ },
169
+ $this->template
170
+ );
171
+ }
172
+
173
+ private function headers(MessageInterface $message)
174
+ {
175
+ $result = '';
176
+ foreach ($message->getHeaders() as $name => $values) {
177
+ $result .= $name . ': ' . implode(', ', $values) . "\r\n";
178
+ }
179
+
180
+ return trim($result);
181
+ }
182
+ }
includes/aws/GuzzleHttp/Middleware.php ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Cookie\CookieJarInterface;
5
+ use GuzzleHttp\Exception\RequestException;
6
+ use GuzzleHttp\Promise\RejectedPromise;
7
+ use GuzzleHttp\Psr7;
8
+ use Psr\Http\Message\ResponseInterface;
9
+ use Psr\Log\LoggerInterface;
10
+ use Psr\Log\LogLevel;
11
+
12
+ /**
13
+ * Functions used to create and wrap handlers with handler middleware.
14
+ */
15
+ final class Middleware
16
+ {
17
+ /**
18
+ * Middleware that adds cookies to requests.
19
+ *
20
+ * The options array must be set to a CookieJarInterface in order to use
21
+ * cookies. This is typically handled for you by a client.
22
+ *
23
+ * @return callable Returns a function that accepts the next handler.
24
+ */
25
+ public static function cookies()
26
+ {
27
+ return function (callable $handler) {
28
+ return function ($request, array $options) use ($handler) {
29
+ if (empty($options['cookies'])) {
30
+ return $handler($request, $options);
31
+ } elseif (!($options['cookies'] instanceof CookieJarInterface)) {
32
+ throw new \InvalidArgumentException('cookies must be an instance of GuzzleHttp\Cookie\CookieJarInterface');
33
+ }
34
+ $cookieJar = $options['cookies'];
35
+ $request = $cookieJar->withCookieHeader($request);
36
+ return $handler($request, $options)
37
+ ->then(function ($response) use ($cookieJar, $request) {
38
+ $cookieJar->extractCookies($request, $response);
39
+ return $response;
40
+ }
41
+ );
42
+ };
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Middleware that throws exceptions for 4xx or 5xx responses when the
48
+ * "http_error" request option is set to true.
49
+ *
50
+ * @return callable Returns a function that accepts the next handler.
51
+ */
52
+ public static function httpErrors()
53
+ {
54
+ return function (callable $handler) {
55
+ return function ($request, array $options) use ($handler) {
56
+ if (empty($options['http_errors'])) {
57
+ return $handler($request, $options);
58
+ }
59
+ return $handler($request, $options)->then(
60
+ function (ResponseInterface $response) use ($request, $handler) {
61
+ $code = $response->getStatusCode();
62
+ if ($code < 400) {
63
+ return $response;
64
+ }
65
+ throw RequestException::create($request, $response);
66
+ }
67
+ );
68
+ };
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Middleware that pushes history data to an ArrayAccess container.
74
+ *
75
+ * @param array $container Container to hold the history (by reference).
76
+ *
77
+ * @return callable Returns a function that accepts the next handler.
78
+ */
79
+ public static function history(array &$container)
80
+ {
81
+ return function (callable $handler) use (&$container) {
82
+ return function ($request, array $options) use ($handler, &$container) {
83
+ return $handler($request, $options)->then(
84
+ function ($value) use ($request, &$container, $options) {
85
+ $container[] = [
86
+ 'request' => $request,
87
+ 'response' => $value,
88
+ 'error' => null,
89
+ 'options' => $options
90
+ ];
91
+ return $value;
92
+ },
93
+ function ($reason) use ($request, &$container, $options) {
94
+ $container[] = [
95
+ 'request' => $request,
96
+ 'response' => null,
97
+ 'error' => $reason,
98
+ 'options' => $options
99
+ ];
100
+ return new RejectedPromise($reason);
101
+ }
102
+ );
103
+ };
104
+ };
105
+ }
106
+
107
+ /**
108
+ * Middleware that invokes a callback before and after sending a request.
109
+ *
110
+ * The provided listener cannot modify or alter the response. It simply
111
+ * "taps" into the chain to be notified before returning the promise. The
112
+ * before listener accepts a request and options array, and the after
113
+ * listener accepts a request, options array, and response promise.
114
+ *
115
+ * @param callable $before Function to invoke before forwarding the request.
116
+ * @param callable $after Function invoked after forwarding.
117
+ *
118
+ * @return callable Returns a function that accepts the next handler.
119
+ */
120
+ public static function tap(callable $before = null, callable $after = null)
121
+ {
122
+ return function (callable $handler) use ($before, $after) {
123
+ return function ($request, array $options) use ($handler, $before, $after) {
124
+ if ($before) {
125
+ $before($request, $options);
126
+ }
127
+ $response = $handler($request, $options);
128
+ if ($after) {
129
+ $after($request, $options, $response);
130
+ }
131
+ return $response;
132
+ };
133
+ };
134
+ }
135
+
136
+ /**
137
+ * Middleware that handles request redirects.
138
+ *
139
+ * @return callable Returns a function that accepts the next handler.
140
+ */
141
+ public static function redirect()
142
+ {
143
+ return function (callable $handler) {
144
+ return new RedirectMiddleware($handler);
145
+ };
146
+ }
147
+
148
+ /**
149
+ * Middleware that retries requests based on the boolean result of
150
+ * invoking the provided "decider" function.
151
+ *
152
+ * If no delay function is provided, a simple implementation of exponential
153
+ * backoff will be utilized.
154
+ *
155
+ * @param callable $decider Function that accepts the number of retries,
156
+ * a request, [response], and [exception] and
157
+ * returns true if the request is to be retried.
158
+ * @param callable $delay Function that accepts the number of retries and
159
+ * returns the number of milliseconds to delay.
160
+ *
161
+ * @return callable Returns a function that accepts the next handler.
162
+ */
163
+ public static function retry(callable $decider, callable $delay = null)
164
+ {
165
+ return function (callable $handler) use ($decider, $delay) {
166
+ return new RetryMiddleware($decider, $handler, $delay);
167
+ };
168
+ }
169
+
170
+ /**
171
+ * Middleware that logs requests, responses, and errors using a message
172
+ * formatter.
173
+ *
174
+ * @param LoggerInterface $logger Logs messages.
175
+ * @param MessageFormatter $formatter Formatter used to create message strings.
176
+ * @param string $logLevel Level at which to log requests.
177
+ *
178
+ * @return callable Returns a function that accepts the next handler.
179
+ */
180
+ public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO)
181
+ {
182
+ return function (callable $handler) use ($logger, $formatter, $logLevel) {
183
+ return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
184
+ return $handler($request, $options)->then(
185
+ function ($response) use ($logger, $request, $formatter, $logLevel) {
186
+ $message = $formatter->format($request, $response);
187
+ $logger->log($logLevel, $message);
188
+ return $response;
189
+ },
190
+ function ($reason) use ($logger, $request, $formatter) {
191
+ $response = $reason instanceof RequestException
192
+ ? $reason->getResponse()
193
+ : null;
194
+ $message = $formatter->format($request, $response, $reason);
195
+ $logger->notice($message);
196
+ return \GuzzleHttp\Promise\rejection_for($reason);
197
+ }
198
+ );
199
+ };
200
+ };
201
+ }
202
+
203
+ /**
204
+ * This middleware adds a default content-type if possible, a default
205
+ * content-length or transfer-encoding header, and the expect header.
206
+ *
207
+ * @return callable
208
+ */
209
+ public static function prepareBody()
210
+ {
211
+ return function (callable $handler) {
212
+ return new PrepareBodyMiddleware($handler);
213
+ };
214
+ }
215
+
216
+ /**
217
+ * Middleware that applies a map function to the request before passing to
218
+ * the next handler.
219
+ *
220
+ * @param callable $fn Function that accepts a RequestInterface and returns
221
+ * a RequestInterface.
222
+ * @return callable
223
+ */
224
+ public static function mapRequest(callable $fn)
225
+ {
226
+ return function (callable $handler) use ($fn) {
227
+ return function ($request, array $options) use ($handler, $fn) {
228
+ return $handler($fn($request), $options);
229
+ };
230
+ };
231
+ }
232
+
233
+ /**
234
+ * Middleware that applies a map function to the resolved promise's
235
+ * response.
236
+ *
237
+ * @param callable $fn Function that accepts a ResponseInterface and
238
+ * returns a ResponseInterface.
239
+ * @return callable
240
+ */
241
+ public static function mapResponse(callable $fn)
242
+ {
243
+ return function (callable $handler) use ($fn) {
244
+ return function ($request, array $options) use ($handler, $fn) {
245
+ return $handler($request, $options)->then($fn);
246
+ };
247
+ };
248
+ }
249
+ }
includes/aws/GuzzleHttp/Pool.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Promise\PromisorInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use GuzzleHttp\Promise\EachPromise;
7
+
8
+ /**
9
+ * Sends and iterator of requests concurrently using a capped pool size.
10
+ *
11
+ * The pool will read from an iterator until it is cancelled or until the
12
+ * iterator is consumed. When a request is yielded, the request is sent after
13
+ * applying the "request_options" request options (if provided in the ctor).
14
+ *
15
+ * When a function is yielded by the iterator, the function is provided the
16
+ * "request_options" array that should be merged on top of any existing
17
+ * options, and the function MUST then return a wait-able promise.
18
+ */
19
+ class Pool implements PromisorInterface
20
+ {
21
+ /** @var EachPromise */
22
+ private $each;
23
+
24
+ /**
25
+ * @param ClientInterface $client Client used to send the requests.
26
+ * @param array|\Iterator $requests Requests or functions that return
27
+ * requests to send concurrently.
28
+ * @param array $config Associative array of options
29
+ * - concurrency: (int) Maximum number of requests to send concurrently
30
+ * - options: Array of request options to apply to each request.
31
+ * - fulfilled: (callable) Function to invoke when a request completes.
32
+ * - rejected: (callable) Function to invoke when a request is rejected.
33
+ */
34
+ public function __construct(
35
+ ClientInterface $client,
36
+ $requests,
37
+ array $config = []
38
+ ) {
39
+ // Backwards compatibility.
40
+ if (isset($config['pool_size'])) {
41
+ $config['concurrency'] = $config['pool_size'];
42
+ } elseif (!isset($config['concurrency'])) {
43
+ $config['concurrency'] = 25;
44
+ }
45
+
46
+ if (isset($config['options'])) {
47
+ $opts = $config['options'];
48
+ unset($config['options']);
49
+ } else {
50
+ $opts = [];
51
+ }
52
+
53
+ $iterable = \GuzzleHttp\Promise\iter_for($requests);
54
+ $requests = function () use ($iterable, $client, $opts) {
55
+ foreach ($iterable as $key => $rfn) {
56
+ if ($rfn instanceof RequestInterface) {
57
+ yield $key => $client->sendAsync($rfn, $opts);
58
+ } elseif (is_callable($rfn)) {
59
+ yield $key => $rfn($opts);
60
+ } else {
61
+ throw new \InvalidArgumentException('Each value yielded by '
62
+ . 'the iterator must be a Psr7\Http\Message\RequestInterface '
63
+ . 'or a callable that returns a promise that fulfills '
64
+ . 'with a Psr7\Message\Http\ResponseInterface object.');
65
+ }
66
+ }
67
+ };
68
+
69
+ $this->each = new EachPromise($requests(), $config);
70
+ }
71
+
72
+ public function promise()
73
+ {
74
+ return $this->each->promise();
75
+ }
76
+
77
+ /**
78
+ * Sends multiple requests concurrently and returns an array of responses
79
+ * and exceptions that uses the same ordering as the provided requests.
80
+ *
81
+ * IMPORTANT: This method keeps every request and response in memory, and
82
+ * as such, is NOT recommended when sending a large number or an
83
+ * indeterminate number of requests concurrently.
84
+ *
85
+ * @param ClientInterface $client Client used to send the requests
86
+ * @param array|\Iterator $requests Requests to send concurrently.
87
+ * @param array $options Passes through the options available in
88
+ * {@see GuzzleHttp\Pool::__construct}
89
+ *
90
+ * @return array Returns an array containing the response or an exception
91
+ * in the same order that the requests were sent.
92
+ * @throws \InvalidArgumentException if the event format is incorrect.
93
+ */
94
+ public static function batch(
95
+ ClientInterface $client,
96
+ $requests,
97
+ array $options = []
98
+ ) {
99
+ $res = [];
100
+ self::cmpCallback($options, 'fulfilled', $res);
101
+ self::cmpCallback($options, 'rejected', $res);
102
+ $pool = new static($client, $requests, $options);
103
+ $pool->promise()->wait();
104
+ ksort($res);
105
+
106
+ return $res;
107
+ }
108
+
109
+ private static function cmpCallback(array &$options, $name, array &$results)
110
+ {
111
+ if (!isset($options[$name])) {
112
+ $options[$name] = function ($v, $k) use (&$results) {
113
+ $results[$k] = $v;
114
+ };
115
+ } else {
116
+ $currentFn = $options[$name];
117
+ $options[$name] = function ($v, $k) use (&$results, $currentFn) {
118
+ $currentFn($v, $k);
119
+ $results[$k] = $v;
120
+ };
121
+ }
122
+ }
123
+ }
includes/aws/GuzzleHttp/PrepareBodyMiddleware.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Promise\PromiseInterface;
5
+ use GuzzleHttp\Psr7;
6
+ use Psr\Http\Message\RequestInterface;
7
+
8
+ /**
9
+ * Prepares requests that contain a body, adding the Content-Length,
10
+ * Content-Type, and Expect headers.
11
+ */
12
+ class PrepareBodyMiddleware
13
+ {
14
+ /** @var callable */
15
+ private $nextHandler;
16
+
17
+ /** @var array */
18
+ private static $skipMethods = ['GET' => true, 'HEAD' => true];
19
+
20
+ /**
21
+ * @param callable $nextHandler Next handler to invoke.
22
+ */
23
+ public function __construct(callable $nextHandler)
24
+ {
25
+ $this->nextHandler = $nextHandler;
26
+ }
27
+
28
+ /**
29
+ * @param RequestInterface $request
30
+ * @param array $options
31
+ *
32
+ * @return PromiseInterface
33
+ */
34
+ public function __invoke(RequestInterface $request, array $options)
35
+ {
36
+ $fn = $this->nextHandler;
37
+
38
+ // Don't do anything if the request has no body.
39
+ if (isset(self::$skipMethods[$request->getMethod()])
40
+ || $request->getBody()->getSize() === 0
41
+ ) {
42
+ return $fn($request, $options);
43
+ }
44
+
45
+ $modify = [];
46
+
47
+ // Add a default content-type if possible.
48
+ if (!$request->hasHeader('Content-Type')) {
49
+ if ($uri = $request->getBody()->getMetadata('uri')) {
50
+