WP Offload S3 Lite - Version 2.4

Version Description

= 2.3 = This is a major upgrade that switches to using a custom table for storing data about offloaded Media Library items. Once upgraded you will not be able to downgrade without restoring data from a backup.

= 2.0 = This is a major upgrade that introduces support for DigitalOcean Spaces, renames the plugin to WP Offload Media Lite, and coincidentally upgrades some of its database settings. You may not be able to downgrade to WP Offload S3 Lite 1.x after upgrading to WP Offload Media Lite 2.0+.

= 1.1 = This is a major change, which ensures S3 URLs are no longer saved in post content. Instead, local URLs are filtered on page generation and replaced with the S3 version. If you depend on the S3 URLs being stored in post content you will need to make modifications to support this version.

= 0.6 = This version requires PHP 5.3.3+ and the Amazon Web Services plugin

Download this release

Release Info

Developer deliciousbrains
Plugin Icon 128x128 WP Offload S3 Lite
Version 2.4
Comparing to
See all releases

Code changes from version 2.3.2 to 2.4

Files changed (147) hide show
  1. README.md +31 -3
  2. assets/css/delivery-provider.css +1 -0
  3. assets/css/media.css +1 -1
  4. assets/css/styles.css +1 -1
  5. assets/js/delivery-provider.js +89 -0
  6. assets/js/delivery-provider.min.js +1 -0
  7. assets/js/script.js +174 -14
  8. assets/js/script.min.js +1 -1
  9. assets/sass/delivery-provider.scss +28 -0
  10. assets/sass/media.scss +93 -1
  11. assets/sass/styles.scss +209 -14
  12. classes/amazon-s3-and-cloudfront.php +1031 -444
  13. classes/as3cf-filter.php +6 -6
  14. classes/as3cf-notices.php +1 -2
  15. classes/as3cf-plugin-base.php +38 -0
  16. classes/as3cf-plugin-compatibility.php +20 -17
  17. classes/as3cf-utils.php +140 -6
  18. classes/filters/as3cf-local-to-s3.php +64 -29
  19. classes/filters/as3cf-s3-to-local.php +21 -1
  20. classes/items/item.php +33 -8
  21. classes/items/media-library-item.php +96 -27
  22. classes/providers/delivery/another-cdn.php +49 -0
  23. classes/providers/delivery/aws-cloudfront.php +112 -0
  24. classes/providers/delivery/cloudflare.php +62 -0
  25. classes/providers/delivery/delivery-provider.php +428 -0
  26. classes/providers/delivery/digitalocean-spaces-cdn.php +85 -0
  27. classes/providers/delivery/gcp-cdn.php +75 -0
  28. classes/providers/delivery/keycdn.php +62 -0
  29. classes/providers/delivery/other.php +61 -0
  30. classes/providers/delivery/stackpath.php +62 -0
  31. classes/providers/delivery/storage.php +103 -0
  32. classes/providers/provider.php +38 -865
  33. classes/providers/{aws-provider.php → storage/aws-provider.php} +178 -79
  34. classes/providers/{digitalocean-provider.php → storage/digitalocean-provider.php} +17 -1
  35. classes/providers/{gcp-provider.php → storage/gcp-provider.php} +91 -50
  36. classes/providers/{null-provider.php → storage/null-provider.php} +1 -1
  37. classes/providers/storage/storage-provider.php +958 -0
  38. classes/providers/{streams → storage/streams}/aws-s3-stream-wrapper.php +30 -12
  39. classes/providers/{streams → storage/streams}/gcp-gcs-stream-wrapper.php +1 -2
  40. classes/upgrades/upgrade-filter-post.php +4 -4
  41. classes/upgrades/upgrade-items-table.php +2 -2
  42. classes/upgrades/upgrade.php +25 -0
  43. include/functions.php +34 -10
  44. languages/amazon-s3-and-cloudfront-en.pot +436 -183
  45. readme.txt +31 -3
  46. vendor/Aws3/Aws/AbstractConfigurationProvider.php +133 -0
  47. vendor/Aws3/Aws/Api/ApiProvider.php +1 -1
  48. vendor/Aws3/Aws/Api/DocModel.php +1 -1
  49. vendor/Aws3/Aws/Api/ErrorParser/AbstractErrorParser.php +69 -0
  50. vendor/Aws3/Aws/Api/ErrorParser/JsonParserTrait.php +8 -0
  51. vendor/Aws3/Aws/Api/ErrorParser/JsonRpcErrorParser.php +12 -2
  52. vendor/Aws3/Aws/Api/ErrorParser/RestJsonErrorParser.php +15 -2
  53. vendor/Aws3/Aws/Api/ErrorParser/XmlErrorParser.php +34 -14
  54. vendor/Aws3/Aws/Api/Parser/AbstractRestParser.php +13 -3
  55. vendor/Aws3/Aws/Api/Parser/DecodingEventStreamIterator.php +1 -1
  56. vendor/Aws3/Aws/Api/Parser/Exception/ParserException.php +23 -0
  57. vendor/Aws3/Aws/Api/Parser/MetadataParserTrait.php +74 -0
  58. vendor/Aws3/Aws/Api/Parser/PayloadParserTrait.php +1 -1
  59. vendor/Aws3/Aws/Api/Parser/XmlParser.php +16 -0
  60. vendor/Aws3/Aws/Api/Serializer/RestJsonSerializer.php +1 -1
  61. vendor/Aws3/Aws/Api/Serializer/RestSerializer.php +5 -0
  62. vendor/Aws3/Aws/Api/Serializer/XmlBody.php +1 -1
  63. vendor/Aws3/Aws/Api/Service.php +20 -2
  64. vendor/Aws3/Aws/Api/ShapeMap.php +3 -1
  65. vendor/Aws3/Aws/Api/Validator.php +11 -1
  66. vendor/Aws3/Aws/Arn/AccessPointArn.php +67 -0
  67. vendor/Aws3/Aws/Arn/Arn.php +112 -0
  68. vendor/Aws3/Aws/Arn/ArnInterface.php +30 -0
  69. vendor/Aws3/Aws/Arn/ArnParser.php +39 -0
  70. vendor/Aws3/Aws/Arn/Exception/InvalidArnException.php +10 -0
  71. vendor/Aws3/Aws/Arn/ResourceTypeAndIdTrait.php +32 -0
  72. vendor/Aws3/Aws/Arn/S3/AccessPointArn.php +25 -0
  73. vendor/Aws3/Aws/AwsClient.php +63 -6
  74. vendor/Aws3/Aws/AwsClientTrait.php +9 -2
  75. vendor/Aws3/Aws/ClientResolver.php +49 -4
  76. vendor/Aws3/Aws/ClientSideMonitoring/AbstractMonitoringMiddleware.php +12 -3
  77. vendor/Aws3/Aws/ClientSideMonitoring/Configuration.php +12 -2
  78. vendor/Aws3/Aws/ClientSideMonitoring/ConfigurationInterface.php +7 -1
  79. vendor/Aws3/Aws/ClientSideMonitoring/ConfigurationProvider.php +33 -124
  80. vendor/Aws3/Aws/CloudFront/CloudFrontClient.php +171 -0
  81. vendor/Aws3/Aws/CloudFront/CookieSigner.php +57 -0
  82. vendor/Aws3/Aws/CloudFront/Exception/CloudFrontException.php +11 -0
  83. vendor/Aws3/Aws/CloudFront/Signer.php +99 -0
  84. vendor/Aws3/Aws/CloudFront/UrlSigner.php +95 -0
  85. vendor/Aws3/Aws/Command.php +3 -0
  86. vendor/Aws3/Aws/ConfigurationProviderInterface.php +14 -0
  87. vendor/Aws3/Aws/Credentials/AssumeRoleWithWebIdentityCredentialProvider.php +100 -0
  88. vendor/Aws3/Aws/Credentials/CredentialProvider.php +218 -35
  89. vendor/Aws3/Aws/Credentials/EcsCredentialProvider.php +4 -1
  90. vendor/Aws3/Aws/Credentials/InstanceProfileProvider.php +109 -10
  91. vendor/Aws3/Aws/Crypto/DecryptionTrait.php +4 -3
  92. vendor/Aws3/Aws/Crypto/EncryptionTrait.php +1 -1
  93. vendor/Aws3/Aws/Endpoint/Partition.php +43 -5
  94. vendor/Aws3/Aws/Endpoint/PartitionEndpointProvider.php +22 -3
  95. vendor/Aws3/Aws/EndpointDiscovery/Configuration.php +39 -0
  96. vendor/Aws3/Aws/EndpointDiscovery/ConfigurationInterface.php +29 -0
  97. vendor/Aws3/Aws/EndpointDiscovery/ConfigurationProvider.php +170 -0
  98. vendor/Aws3/Aws/EndpointDiscovery/EndpointDiscoveryMiddleware.php +240 -0
  99. vendor/Aws3/Aws/EndpointDiscovery/EndpointList.php +80 -0
  100. vendor/Aws3/Aws/EndpointDiscovery/Exception/ConfigurationException.php +13 -0
  101. vendor/Aws3/Aws/EndpointParameterMiddleware.php +4 -0
  102. vendor/Aws3/Aws/Exception/AwsException.php +19 -3
  103. vendor/Aws3/Aws/Exception/IncalculablePayloadException.php +10 -0
  104. vendor/Aws3/Aws/Exception/InvalidJsonException.php +10 -0
  105. vendor/Aws3/Aws/Exception/InvalidRegionException.php +10 -0
  106. vendor/Aws3/Aws/Handler/GuzzleV5/GuzzleHandler.php +4 -4
  107. vendor/Aws3/Aws/MultiRegionClient.php +2 -0
  108. vendor/Aws3/Aws/Multipart/AbstractUploadManager.php +21 -7
  109. vendor/Aws3/Aws/Psr16CacheAdapter.php +26 -0
  110. vendor/Aws3/Aws/ResponseContainerInterface.php +1 -0
  111. vendor/Aws3/Aws/RetryMiddleware.php +6 -0
  112. vendor/Aws3/Aws/S3/BucketEndpointArnMiddleware.php +200 -0
  113. vendor/Aws3/Aws/S3/MultipartCopy.php +7 -1
  114. vendor/Aws3/Aws/S3/MultipartUploader.php +1 -1
  115. vendor/Aws3/Aws/S3/ObjectCopier.php +9 -0
  116. vendor/Aws3/Aws/S3/ObjectUploader.php +3 -2
  117. vendor/Aws3/Aws/S3/PutObjectUrlMiddleware.php +1 -1
  118. vendor/Aws3/Aws/S3/RegionalEndpoint/Configuration.php +29 -0
  119. vendor/Aws3/Aws/S3/RegionalEndpoint/ConfigurationInterface.php +22 -0
  120. vendor/Aws3/Aws/S3/RegionalEndpoint/ConfigurationProvider.php +158 -0
  121. vendor/Aws3/Aws/S3/RegionalEndpoint/Exception/ConfigurationException.php +13 -0
  122. vendor/Aws3/Aws/S3/S3Client.php +85 -4
  123. vendor/Aws3/Aws/S3/S3ClientInterface.php +2 -2
  124. vendor/Aws3/Aws/S3/S3EndpointMiddleware.php +1 -1
  125. vendor/Aws3/Aws/S3/S3MultiRegionClient.php +1 -1
  126. vendor/Aws3/Aws/S3/S3UriParser.php +20 -1
  127. vendor/Aws3/Aws/S3/StreamWrapper.php +13 -6
  128. vendor/Aws3/Aws/S3/Transfer.php +5 -2
  129. vendor/Aws3/Aws/S3/UseArnRegion/Configuration.php +31 -0
  130. vendor/Aws3/Aws/S3/UseArnRegion/ConfigurationInterface.php +19 -0
  131. vendor/Aws3/Aws/S3/UseArnRegion/ConfigurationProvider.php +141 -0
  132. vendor/Aws3/Aws/S3/UseArnRegion/Exception/ConfigurationException.php +13 -0
  133. vendor/Aws3/Aws/Sdk.php +113 -1
  134. vendor/Aws3/Aws/Signature/AnonymousSignature.php +1 -1
  135. vendor/Aws3/Aws/Signature/SignatureInterface.php +1 -1
  136. vendor/Aws3/Aws/StreamRequestPayloadMiddleware.php +67 -0
  137. vendor/Aws3/Aws/WrappedHttpHandler.php +1 -1
  138. vendor/Aws3/Aws/data/accessanalyzer/2019-11-01/api-2.json.php +4 -0
  139. vendor/Aws3/Aws/data/accessanalyzer/2019-11-01/paginators-1.json.php +4 -0
  140. vendor/Aws3/Aws/data/acm-pca/2017-08-22/api-2.json.php +1 -1
  141. vendor/Aws3/Aws/data/acm-pca/2017-08-22/paginators-1.json.php +1 -1
  142. vendor/Aws3/Aws/data/acm-pca/2017-08-22/waiters-2.json.php +1 -1
  143. vendor/Aws3/Aws/data/acm/2015-12-08/api-2.json.php +1 -1
  144. vendor/Aws3/Aws/data/alexaforbusiness/2017-11-09/api-2.json.php +1 -1
  145. vendor/Aws3/Aws/data/alexaforbusiness/2017-11-09/paginators-1.json.php +1 -1
  146. vendor/Aws3/Aws/data/aliases.json.php +4 -0
  147. vendor/Aws3/Aws/data/amplify/2017-07-25/api-2.json.php +1 -1
README.md CHANGED
@@ -2,9 +2,9 @@
2
  **Contributors:** bradt, deliciousbrains, ianmjones
3
  **Tags:** uploads, amazon, s3, amazon s3, digitalocean, digitalocean spaces, google cloud storage, gcs, mirror, admin, media, cdn, cloudfront
4
  **Requires at least:** 4.9
5
- **Tested up to:** 5.4
6
  **Requires PHP:** 5.5
7
- **Stable tag:** 2.3.2
8
  **License:** GPLv3
9
 
10
  Copies files to Amazon S3, DigitalOcean Spaces or Google Cloud Storage as they are uploaded to the Media Library. Optionally configure Amazon CloudFront or another CDN for faster delivery.
@@ -32,7 +32,7 @@ Although WP Offload Media doesn't include image optimization features, we work c
32
  * [Assets Pull addon](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=assets%2Baddon#addons) - Serve your CSS, JS and fonts via CloudFront or another CDN
33
  * [WooCommerce integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=woocommerce%2Baddon#integrations)
34
  * [Easy Digital Downloads integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=edd%2Baddon#integrations)
35
- * PriorityExpert™ email support
36
 
37
  [Compare pro vs free →](https://deliciousbrains.com/wp-offload-media/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
38
 
@@ -89,6 +89,34 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
89
 
90
  ## Changelog ##
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  ### WP Offload Media Lite 2.3.2 - 2019-12-09 ###
93
  * Improvement: Reduced database queries when external object cache available
94
  * Bug fix: Uncaught Error: Call to undefined function DeliciousBrains\WP_Offload_Media\Gcp\GuzzleHttp\choose_handler()
2
  **Contributors:** bradt, deliciousbrains, ianmjones
3
  **Tags:** uploads, amazon, s3, amazon s3, digitalocean, digitalocean spaces, google cloud storage, gcs, mirror, admin, media, cdn, cloudfront
4
  **Requires at least:** 4.9
5
+ **Tested up to:** 5.5
6
  **Requires PHP:** 5.5
7
+ **Stable tag:** 2.4
8
  **License:** GPLv3
9
 
10
  Copies files to Amazon S3, DigitalOcean Spaces or Google Cloud Storage as they are uploaded to the Media Library. Optionally configure Amazon CloudFront or another CDN for faster delivery.
32
  * [Assets Pull addon](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=assets%2Baddon#addons) - Serve your CSS, JS and fonts via CloudFront or another CDN
33
  * [WooCommerce integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=woocommerce%2Baddon#integrations)
34
  * [Easy Digital Downloads integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=edd%2Baddon#integrations)
35
+ * Priority email support
36
 
37
  [Compare pro vs free →](https://deliciousbrains.com/wp-offload-media/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
38
 
89
 
90
  ## Changelog ##
91
 
92
+ ### WP Offload Media Lite 2.4 - 2020-07-14 ###
93
+ * [Release Summary Blog Post](https://deliciousbrains.com/wp-offload-media-2-4-released/?utm_campaign=changelogs&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
94
+ * New: Setting to choose a Delivery Provider (i.e. S3, CloudFront, another CDN)
95
+ * New: Support for Block All Public Access setting on S3 buckets
96
+ * New: Raw S3 URLs use bucket in domain rather than path where possible as per changes required by AWS
97
+ * New: Raw S3 URLs use dot rather than dash between s3 and region name as per changes required by AWS
98
+ * New: Added S3 regions for Africa (Cape Town), Asia Pacific (Hong Kong), EU (Milan), EU (Stockholm), and Middle East (Bahrain)
99
+ * New: Added GCS regions for Salt Lake City, Las Vegas, Zürich, Osaka, Seoul, EUR4 (dual-region), and NAM4 (dual-region)
100
+ * Improvement: Updated AWS PHP SDK to v3.133.40
101
+ * Improvement: Updated Google Cloud Storage SDK to v1.18.0
102
+ * Improvement: S3 regions for China no longer hidden (configuration via AWS Console still required)
103
+ * Bug fix: Private images not showing in grid mode Media page overlay
104
+ * Bug fix: Public image thumbnails not showing in grid mode Media page when original is private
105
+ * Bug fix: URL rewriting sometimes fails for sites hosted on Windows
106
+ * Bug fix: URL rewrite fails for image when original upload has size in file name
107
+ * Bug fix: External URLs rewritten to local URLs when they shouldn't
108
+ * Bug fix: StreamWrappers don't work with private buckets
109
+ * Bug fix: Database error when inserting media library item and using HyperDB
110
+ * Bug fix: S3 bucket link in settings no longer goes direct to bucket contents
111
+ * Bug fix: New uploads slow with very large Media Library
112
+ * Bug fix: Migration to custom table very slow with large postmeta tables
113
+ * Bug fix: Signed GCS URLs have incorrect expires value
114
+ * Bug fix: The use-server-roles AS3CF_SETTINGS value is not properly reflected in Diagnostic Info
115
+ * Bug fix: Unknown column '2019/12/some-file-name.pdf' in 'where clause' when using managed MySQL on DigitalOcean
116
+ * Bug fix: WordPress database error Expression #1 of ORDER BY clause is not in SELECT list when using MySQL8
117
+ * Bug fix: WordPress forces HTTP in Edit Media page if site is not HTTPS, breaking remote URLs that require HTTPS
118
+ * Tested: WordPress 5.5
119
+
120
  ### WP Offload Media Lite 2.3.2 - 2019-12-09 ###
121
  * Improvement: Reduced database queries when external object cache available
122
  * Bug fix: Uncaught Error: Call to undefined function DeliciousBrains\WP_Offload_Media\Gcp\GuzzleHttp\choose_handler()
assets/css/delivery-provider.css ADDED
@@ -0,0 +1 @@
 
1
+ .as3cf-delivery-provider-select .as3cf-delivery-provider-select-options{margin-bottom:30px}.as3cf-delivery-provider-select .as3cf-delivery-provider-select-options .as3cf-delivery-provider-sub-option{margin-left:25px}.as3cf-delivery-provider-select .as3cf-delivery-provider-select-options .as3cf-delivery-provider-sub-option .as3cf-setting{display:none;margin-left:25px}.as3cf-delivery-provider-select .as3cf-delivery-provider-select-options .as3cf-delivery-provider-sub-option.selected .as3cf-setting{display:block}.as3cf-delivery-provider-select .as3cf-delivery-provider-select-options .as3cf-delivery-provider-sub-option-container>.as3cf-delivery-provider-sub-option{display:none}.as3cf-delivery-provider-select .as3cf-delivery-provider-select-options .as3cf-delivery-provider-sub-option-container.selected>.as3cf-delivery-provider-sub-option{display:block}
assets/css/media.css CHANGED
@@ -1 +1 @@
1
- body.as3cf-pro .attachments-browser .media-toolbar-secondary{max-width:100%}.as3cfpro_remove a.local-warning{color:#a00}.as3cfpro_remove a.local-warning:hover{color:#f00;text-decoration:none;border:none}.media-modal a.local-warning{color:#bc0b0b}.media-modal a.local-warning:hover{color:red}.attachment-info .attachment-s3-details{font-weight:bold;margin-bottom:5px}
1
+ body.as3cf-pro .media-toolbar-mode-select{overflow:visible}body.as3cf-pro .attachments-browser .media-toolbar-secondary{max-width:100%}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons{margin-right:10px;position:relative;display:none !important}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons.visible{display:inline-block !important}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons .button{margin:0;text-align:left}@media screen and (max-width: 782px){body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons .button{min-height:40px}}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__action-default{width:-webkit-calc(100% - 32px);width:calc(100% - 32px);position:relative;z-index:2}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__toggle{width:32px;position:relative;border-left:1px solid rgba(255,255,255,0.2);z-index:2}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__toggle:focus{-webkit-box-shadow:none;box-shadow:none}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__toggle::after{content:'';display:inline-block;width:0;height:0;vertical-align:0.255em;border-top:0.3em solid;border-right:0.3em solid transparent;border-bottom:0;border-left:0.3em solid transparent;-webkit-transition:0.2s all ease;transition:0.2s all ease}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__toggle.opened::after{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__submenu{position:absolute;left:0;top:0;z-index:1;-webkit-transform:translateY(33px);-ms-transform:translateY(33px);transform:translateY(33px);border-radius:3px;overflow:hidden;-webkit-box-shadow:0 2px 5px 2px rgba(0,0,0,0.3);box-shadow:0 2px 5px 2px rgba(0,0,0,0.3)}@media screen and (max-width: 782px){body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__submenu{-webkit-transform:translateY(41px);-ms-transform:translateY(41px);transform:translateY(41px)}}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__action{display:block;width:100%;margin:0;border-radius:0;-moz-text-align-last:left;text-align-last:left;border:none;border-bottom:1px solid rgba(255,255,255,0.2)}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__action:last-child{border:none}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__action:focus{-webkit-box-shadow:none;box-shadow:none}.as3cfpro_remove a.local-warning{color:#a00}.as3cfpro_remove a.local-warning:hover{color:#f00;text-decoration:none;border:none}.media-modal a.local-warning{color:#bc0b0b}.media-modal a.local-warning:hover{color:red}.attachment-info .attachment-s3-details{font-weight:bold;margin-bottom:5px}
assets/css/styles.css CHANGED
@@ -1 +1 @@
1
- .as3cf-content,.as3cf-updated,.as3cf-compatibility-notice{-webkit-box-sizing:border-box;box-sizing:border-box;max-width:650px}.settings_page_amazon-s3-and-cloudfront .error,.settings_page_amazon-s3-and-cloudfront .notice,.settings_page_amazon-s3-and-cloudfront .updated{-webkit-box-sizing:border-box;box-sizing:border-box;max-width:650px}.as3cf-main.wrap{position:relative}.as3cf-main.wrap>h1{float:left}.as3cf-main.wrap .as3cf-notice,.as3cf-main.wrap .as3cf-updated,.as3cf-main.wrap .as3cf-error{-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-main.wrap .as3cf-error.fatal{clear:both}.as3cf-main.wrap h2.nav-tab-wrapper{float:none;margin-bottom:15px;width:650px;margin-top:10px;padding:9px 0 0 5px}.as3cf-main.wrap h2.nav-tab-wrapper .nav-tab-container{float:right}.as3cf-main.wrap h2.nav-tab-wrapper .nav-tab-container :last-child{margin-right:5px}.as3cf-main.wrap h2.nav-tab-wrapper a.nav-tab-active{color:#464646;cursor:default}.as3cf-main.wrap h2.nav-tab-wrapper a:focus{-webkit-box-shadow:none;box-shadow:none}.as3cf-main.wrap .more-info{white-space:nowrap}.as3cf-main.wrap .error pre{background:#eaeaea;background:rgba(0,0,0,0.07);display:block;padding:10px 15px}.as3cf-main.wrap .error pre code{padding:0;background:none}.as3cf-main.wrap[data-tab="support"] .as3cf-notice,.as3cf-main.wrap[data-tab="support"] .error,.as3cf-main.wrap[data-tab="support"] .updated,.as3cf-main.wrap[data-tab="support"] .updated.show{display:none}.as3cf-main.wrap[data-tab="support"] .fatal .error,.as3cf-main.wrap[data-tab="support"] .as3cf-notice.important,.as3cf-main.wrap[data-tab="support"] .dbrains-api-down{display:block}.as3cf-main.wrap .as3cf-notice,.as3cf-main.wrap .error,.as3cf-main.wrap .updated{max-width:650px;margin-top:15px;-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-main.wrap .as3cf-updated{display:none}.as3cf-main.wrap .as3cf-updated.as3cf-notice,.as3cf-main.wrap .as3cf-updated.show{display:block}.as3cf-main.wrap .alignleft{margin-right:20px;margin-bottom:20px}.as3cf-main.wrap .spinner{min-width:20px}.as3cf-tab .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab .as3cf-main-settings .as3cf-bucket-container a.as3cf-change-provider{display:none}.as3cf-tab .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-can-write-error,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-provider-select{display:block}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-bucket-container,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-media-settings,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-can-write-error,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-bucket-container,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-bucket-container{display:block}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-media-settings,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket) .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket) .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket) .as3cf-main-settings .as3cf-media-settings{display:block}.as3cf-content>section{margin-bottom:20px}.as3cf-content>section+section.as3cf-access-keys{padding-top:20px;border-top:1px solid #d3d3d3}.as3cf-content>section+section.as3cf-access-keys .as3cf-section-heading{margin-top:0}.as3cf-tab{display:none;position:relative;width:650px}.as3cf-tab .as3cf-main-settings p{font-size:13px}.as3cf-tab .as3cf-main-settings p a{color:#444}.as3cf-tab .object-prefix-desc em{white-space:nowrap}.as3cf-tab .as3cf-url-preview-wrap{background:#fff;text-align:center;padding:20px 0 0;max-width:650px;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-tab .as3cf-url-preview-wrap .as3cf-url-preview{margin-top:10px;padding:0 20px 10px;overflow-x:scroll}.as3cf-tab .as3cf-url-preview-wrap span{color:#aaa;text-transform:uppercase;font-weight:bold}.as3cf-tab .as3cf-radio-group label{display:block;margin-bottom:10px}.as3cf-tab .as3cf-radio-group label.disabled,.as3cf-tab .as3cf-radio-group label.disabled p{color:#bbb;cursor:default}.as3cf-tab .as3cf-radio-group p{padding-left:25px;color:#6b6b6b;margin:0;font-size:12px}.as3cf-tab .as3cf-radio-group p.as3cf-setting{margin-top:5px}.as3cf-tab .as3cf-switch{position:relative;display:inline-block;padding:2px;overflow:hidden;border-radius:2px;background-color:#d4d3d3;cursor:pointer}.as3cf-tab .as3cf-switch.on{background-color:#ade7b5}.as3cf-tab .as3cf-switch span{visibility:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;float:left;display:inline-block;height:100%;font-size:12px;line-height:20px;border-radius:2px;font-weight:bold;padding:4px 8px;background:#fff;color:#8d8d8d;z-index:1}.as3cf-tab .as3cf-switch span.on{color:#82d78b}.as3cf-tab .as3cf-switch span.checked{visibility:visible}.as3cf-tab .as3cf-switch.disabled{cursor:default;background:#e6e6e6}.as3cf-tab .as3cf-switch.disabled span{background:#f1f1f1;color:#d6d6d6}.as3cf-tab .as3cf-switch input[type="checkbox"]{position:absolute !important;top:0;left:0;opacity:0;filter:alpha(opacity=0);z-index:-1}.as3cf-tab .as3cf-setting.hide{display:none}.as3cf-tab div.as3cf-setting{margin-top:4px}.as3cf-tab h3{font-weight:normal;text-transform:uppercase}.as3cf-tab .form-table{margin:0}.as3cf-tab .form-table tr.as3cf-border-bottom td{border-bottom:1px solid #ddd;padding:20px 0px}.as3cf-tab .form-table tr.as3cf-setting-title td{padding-bottom:0}.as3cf-tab .form-table tr.as3cf-setting-title:first-child td{padding-top:20px}.as3cf-tab .form-table tr.configure-url:first-child td{padding-top:5px;padding-bottom:0}.as3cf-tab .form-table tr td{padding:15px 0}.as3cf-tab .form-table tr td:first-child{vertical-align:top;min-width:120px;padding-top:20px}.as3cf-tab .form-table tr td .as3cf-notice:last-child{margin-bottom:0}.as3cf-tab .form-table tr td>p:first-child{margin-top:0}.as3cf-tab .form-table h3{padding:0;margin:0}.as3cf-tab .form-table h4{margin:0}.as3cf-tab .as3cf-active-region{font-style:italic}.as3cf-tab .as3cf-view-bucket{color:#444;text-decoration:none;margin-right:10px}.as3cf-tab .as3cf-view-bucket:hover,.as3cf-tab .as3cf-view-bucket:active{color:#00a0d2}.as3cf-tab .as3cf-view-bucket:focus{-webkit-box-shadow:none;box-shadow:none}.as3cf-tab .as3cf-view-bucket .dashicons-external{margin-top:-2px}.as3cf-tab .tooltip{position:relative;z-index:2;cursor:pointer}.as3cf-tab .tooltip:before,.as3cf-tab .tooltip:after{visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;pointer-events:none}.as3cf-tab .tooltip:before{position:absolute;bottom:150%;left:50%;margin-bottom:5px;margin-left:-250px;padding:10px;width:500px;border-radius:3px;background-color:#000;background-color:rgba(51,51,51,0.9);color:#fff;content:attr(data-tooltip);text-align:center;font-size:14px;line-height:1.3}.as3cf-tab .tooltip:after{position:absolute;bottom:150%;left:50%;margin-left:-5px;width:0;border-top:5px solid #000;border-top:5px solid rgba(51,51,51,0.9);border-right:5px solid transparent;border-left:5px solid transparent;content:" ";font-size:0;line-height:0}.as3cf-tab .tooltip:hover:before,.as3cf-tab .tooltip:hover:after{visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}.as3cf-tab .as3cf-defined-in-config{background:#ccc;color:#fff;padding:2px 5px;margin:0 0 5px 5px;float:right;white-space:nowrap}.as3cf-tab .as3cf-defined-setting{color:#bbb}.as3cf-tab .as3cf-defined-setting label{cursor:default}.as3cf-tab .as3cf-defined-setting p .more-info a{color:#bbb}.as3cf-tab .as3cf-defined-setting .as3cf-radio-group p{color:#bbb}.as3cf-tab .as3cf-defined-setting .as3cf-notice{display:none !important}.as3cf-tab p.actions{margin:20px -30px -30px;padding:20px 30px;border-top:none;overflow:hidden}.as3cf-tab p.actions .right{margin-left:15px}.as3cf-tab p.actions .right:last-of-type{margin-left:0}.as3cf-tab p.actions button{min-width:90px}#tab-media{display:block}#tab-media .as3cf-provider-setting td{padding-top:20px;padding-bottom:5px}#tab-media .as3cf-bucket-setting td{padding:5px 0}.as3cf-bucket-container h3{line-height:1.3;text-transform:none}.as3cf-bucket-container a:focus{-webkit-box-shadow:none;box-shadow:none;outline:none}.as3cf-bucket-container input[type=text]{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.as3cf-bucket-container select{-webkit-box-sizing:border-box;box-sizing:border-box;width:50%}.as3cf-bucket-container .form-table .as3cf-provider-setting h4{font-weight:inherit;margin:0}.as3cf-bucket-container .form-table .as3cf-bucket-list{margin:5px 0 0 0}.as3cf-bucket-container .form-table td{padding:5px 0}.as3cf-bucket-container .form-table td:first-child{width:100px;line-height:30px;vertical-align:top}.as3cf-bucket-container .bucket-actions{margin:15px 0;border-top:1px solid #ccc;padding-top:15px;overflow:hidden}.as3cf-bucket-container .bucket-actions button,.as3cf-bucket-container .bucket-actions .right{float:right;margin-right:0}.as3cf-bucket-container .bucket-actions span{display:inline-block;margin-right:20px;line-height:28px}.as3cf-bucket-container .as3cf-bucket-list{padding:15px;max-height:200px;overflow-x:hidden;overflow-y:auto;background-color:#fff;font-size:14px}.as3cf-bucket-container .as3cf-bucket-list li:last-of-type{margin-bottom:0}.as3cf-bucket-container .as3cf-bucket-list a{color:#444;text-decoration:none}.as3cf-bucket-container .as3cf-bucket-list a:hover{color:#0074a2}.as3cf-bucket-container .as3cf-bucket-list a.selected{font-weight:bold;color:#0074a2}.as3cf-bucket-container .as3cf-bucket-list a .dashicons{margin-right:5px}#tab-media{display:block}#tab-support{min-height:900px}#tab-support .as3cf-sidebar{top:11px}#tab-support .support-section{border-bottom:1px solid #ccc;padding-bottom:20px;margin-bottom:20px}#tab-support .support-section h3{font-size:20px}#tab-support .debug textarea{width:100%;min-height:200px;font-family:Consolas, Monaco, monospace;margin-bottom:5px}.as3cf-sidebar{position:absolute;top:9px;left:670px;width:292px}.as3cf-sidebar .block{padding:20px;border:1px solid #ccc}.as3cf-sidebar .subscribe{border-top:none}.as3cf-sidebar .subscribe h2{padding:0;margin:0;margin-bottom:0.5em;color:#666;font-size:20px;line-height:1.2em;float:none}.as3cf-sidebar .subscribe h3{font-size:16px;margin:0}.as3cf-sidebar .subscribe p{margin:0}.as3cf-sidebar .subscribe .intro{margin-bottom:1em;line-height:1.4}.as3cf-sidebar .subscribe li{line-height:1.4}.as3cf-sidebar .subscribe .links{margin-bottom:2em}.as3cf-sidebar .subscribe .links a{text-decoration:none}.as3cf-sidebar .subscribe .promise{color:#999;font-size:12px;line-height:1.4em}.as3cf-sidebar .subscribe .field{margin-bottom:0.5em}.as3cf-sidebar .subscribe .field p{margin-bottom:0.3em}.as3cf-sidebar .subscribe .field input[type=text],.as3cf-sidebar .subscribe .field input[type=email]{width:100%}.as3cf-sidebar .subscribe .field.submit-button{margin-bottom:1em}.as3cf-sidebar .credits{border-top:0}.as3cf-sidebar .credits h4{font-size:16px;margin-top:0;margin-bottom:10px}.as3cf-sidebar .credits ul{margin:0}.as3cf-sidebar .credits li{overflow:hidden}.as3cf-sidebar .credits li:last-child{margin-bottom:0}.as3cf-sidebar .credits img{float:left;margin-right:10px}.as3cf-sidebar .credits span{float:left;display:block;line-height:32px}.as3cf-sidebar .credits a{display:block;text-decoration:none;color:#444;font-size:16px;text-align:center}.as3cf-sidebar .credits a:hover{color:#888}@media screen and (max-width: 1052px){.as3cf-sidebar{position:relative;top:auto;right:auto}}.as3cf-active-provider,.as3cf-active-bucket{font-weight:bold;margin-right:10px}.as3cf-banner{margin-top:35px;width:292px;height:200px;display:block;background:#f8cfae url(../img/os3-banner.svg) left bottom/220px 220px no-repeat}.as3cf-banner:focus{-webkit-box-shadow:none;box-shadow:none}.wrap .as3cf-upgrade-details{background-color:#4e0d33;padding:10px 20px 20px 20px;color:#eee;font-size:13px;margin:0;display:block;text-decoration:none}.wrap .as3cf-upgrade-details h1{font-size:28px;color:#eee;margin:0 0 15px 0;padding:0;text-decoration:none;font-weight:200;line-height:1}.wrap .as3cf-upgrade-details p{margin:0}.wrap .as3cf-upgrade-details a{color:#eee;font-weight:bold;text-decoration:none;font-size:16px;-webkit-box-shadow:none;box-shadow:none}.wrap .as3cf-upgrade-details a:hover{color:#fff}.wrap .as3cf-upgrade-details ul{margin-top:0;margin-left:16px;list-style-type:disc}.as3cf-compatibility-notice.error{clear:both;margin:5px 20px 5px 0}.as3cf-bucket-error span.title{font-weight:bold}.as3cf-invalid-bucket-name,.as3cf-validation-error{display:block;margin-top:2px;font-size:12px;color:#a00}.as3cf-notice-toggle-content{max-height:100px;overflow-y:scroll}.as3cf-notice-toggle-content .as3cf-notice-toggle-list{margin-top:0;margin-left:0;padding-left:40px;color:#dc3232}.as3cf-need-help{background-color:white;font-size:16px;font-weight:bold;padding:1em}.as3cf-need-help a{text-decoration:none}.as3cf-settings h3{font-size:20px}.as3cf-settings p{font-size:14px}.as3cf-addons,.as3cf-tab .as3cf-compatibility-notice{max-width:cover}textarea.as3cf-access-key-constants-snippet.code{width:100%;white-space:pre;overflow:hidden;font-size:12px;padding:10px;height:53px}.as3cf-addons .as3cf-addons-list{margin:20px 0 200px;padding-top:5px}.as3cf-addons .as3cf-addon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:20px;font-size:14px}.as3cf-addons .as3cf-addon-info{min-height:100px}.as3cf-addons .as3cf-addon-links{float:right}.as3cf-addons .as3cf-addon-links span{padding:4px 6px}.as3cf-addons .as3cf-addon-icon{float:left;margin-right:20px}.as3cf-addons .as3cf-addon-details{white-space:nowrap}.as3cf-addons .as3cf-addon-title,.as3cf-addons .as3cf-addon-description{font-weight:100}.as3cf-addons .as3cf-addon+.as3cf-addon{margin-top:20px}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull{background-color:#0769ad;color:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .as3cf-addon-title,.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .as3cf-addon-description,.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull a{color:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .extra{background:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .extra a{color:#0769ad;text-decoration:none}
1
+ .as3cf-content,.as3cf-updated,.as3cf-compatibility-notice{-webkit-box-sizing:border-box;box-sizing:border-box;max-width:650px}.settings_page_amazon-s3-and-cloudfront .error,.settings_page_amazon-s3-and-cloudfront .notice,.settings_page_amazon-s3-and-cloudfront .updated{-webkit-box-sizing:border-box;box-sizing:border-box;max-width:650px}.as3cf-main.wrap{position:relative}.as3cf-main.wrap>h1{float:left}.as3cf-main.wrap .as3cf-notice,.as3cf-main.wrap .as3cf-updated,.as3cf-main.wrap .as3cf-error{-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-main.wrap .as3cf-error.fatal{clear:both}.as3cf-main.wrap h2.nav-tab-wrapper{float:none;margin-bottom:15px;width:650px;margin-top:10px;padding:9px 0 0 5px}.as3cf-main.wrap h2.nav-tab-wrapper .nav-tab-container{float:right}.as3cf-main.wrap h2.nav-tab-wrapper .nav-tab-container :last-child{margin-right:5px}.as3cf-main.wrap h2.nav-tab-wrapper a.nav-tab-active{color:#464646;cursor:default}.as3cf-main.wrap h2.nav-tab-wrapper a:focus{-webkit-box-shadow:none;box-shadow:none}.as3cf-main.wrap .more-info{white-space:nowrap}.as3cf-main.wrap .error pre{background:#eaeaea;background:rgba(0,0,0,0.07);display:block;padding:10px 15px}.as3cf-main.wrap .error pre code{padding:0;background:none}.as3cf-main.wrap[data-tab="support"] .as3cf-notice,.as3cf-main.wrap[data-tab="support"] .error,.as3cf-main.wrap[data-tab="support"] .updated,.as3cf-main.wrap[data-tab="support"] .updated.show{display:none}.as3cf-main.wrap[data-tab="support"] .fatal .error,.as3cf-main.wrap[data-tab="support"] .as3cf-notice.important,.as3cf-main.wrap[data-tab="support"] .dbrains-api-down{display:block}.as3cf-main.wrap .as3cf-notice,.as3cf-main.wrap .error,.as3cf-main.wrap .updated{max-width:650px;margin-top:15px;-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-main.wrap .as3cf-updated{display:none}.as3cf-main.wrap .as3cf-updated.as3cf-notice,.as3cf-main.wrap .as3cf-updated.show{display:block}.as3cf-main.wrap .alignleft{margin-right:20px;margin-bottom:20px}.as3cf-main.wrap .spinner{min-width:20px}.as3cf-tab .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab .as3cf-main-settings .as3cf-bucket-container,.as3cf-tab .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:none}.as3cf-tab .as3cf-main-settings .as3cf-bucket-container h3,.as3cf-tab .as3cf-main-settings .as3cf-change-bucket-access-prompt h3{margin-bottom:-0.5em}.as3cf-tab .as3cf-main-settings a.as3cf-change-provider{display:none}.as3cf-tab .as3cf-main-settings .as3cf-delivery-provider-select{display:none}.as3cf-tab .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-can-write-error,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-provider-select{display:block}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-bucket-container,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-change-bucket-access-prompt,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-delivery-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-delivery-provider-select{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-media-settings,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-can-write-error,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-bucket-container,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-bucket-container{display:block}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-change-bucket-access-prompt,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-delivery-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-delivery-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-media-settings,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:block}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-main-settings .as3cf-delivery-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-main-settings .as3cf-delivery-provider-select{display:block}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) .as3cf-main-settings .as3cf-delivery-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) .as3cf-main-settings .as3cf-media-settings{display:block}.as3cf-content>section{margin-bottom:20px}.as3cf-content>section+section.as3cf-access-keys{padding-top:20px;border-top:1px solid #d3d3d3}.as3cf-content>section+section.as3cf-access-keys .as3cf-section-heading{margin-top:0}.as3cf-tab{display:none;position:relative;width:650px}.as3cf-tab .as3cf-main-settings p{font-size:13px}.as3cf-tab .as3cf-main-settings p a{color:#444}.as3cf-tab .object-prefix-desc em{white-space:nowrap}.as3cf-tab .as3cf-url-preview-wrap{background:#fff;text-align:center;padding:20px 0 0;max-width:650px;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-tab .as3cf-url-preview-wrap .as3cf-url-preview{margin-top:10px;padding:0 20px 10px;overflow-x:scroll}.as3cf-tab .as3cf-url-preview-wrap span{color:#aaa;text-transform:uppercase;font-weight:bold}.as3cf-tab .as3cf-radio-group label{display:block;margin-bottom:10px}.as3cf-tab .as3cf-radio-group label.disabled,.as3cf-tab .as3cf-radio-group label.disabled p{color:#bbb;cursor:default}.as3cf-tab .as3cf-radio-group p{padding-left:25px;color:#6b6b6b;margin:0;font-size:12px}.as3cf-tab .as3cf-radio-group p.as3cf-setting{margin-top:5px}.as3cf-tab .as3cf-switch{position:relative;display:inline-block;padding:2px;overflow:hidden;border-radius:2px;background-color:#d4d3d3;cursor:pointer}.as3cf-tab .as3cf-switch.on{background-color:#ade7b5}.as3cf-tab .as3cf-switch span{visibility:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;float:left;display:inline-block;height:100%;font-size:12px;line-height:20px;border-radius:2px;font-weight:bold;padding:4px 8px;background:#fff;color:#8d8d8d;z-index:1}.as3cf-tab .as3cf-switch span.on{color:#82d78b}.as3cf-tab .as3cf-switch span.checked{visibility:visible}.as3cf-tab .as3cf-switch.disabled{cursor:default;background:#e6e6e6}.as3cf-tab .as3cf-switch.disabled span{background:#f1f1f1;color:#d6d6d6}.as3cf-tab .as3cf-switch input[type="checkbox"]{position:absolute !important;top:0;left:0;opacity:0;filter:alpha(opacity=0);z-index:-1}.as3cf-tab .as3cf-setting.hide{display:none}.as3cf-tab .as3cf-setting .as3cf-sub-setting .as3cf-sub-setting-heading{padding-top:15px}.as3cf-tab .as3cf-setting .as3cf-sub-setting .as3cf-defined-in-config{margin-top:15px}.as3cf-tab div.as3cf-setting{margin-top:4px}.as3cf-tab h3{font-weight:normal;text-transform:uppercase}.as3cf-tab .form-table{margin:0}.as3cf-tab .form-table tr.as3cf-border-bottom td{border-bottom:1px solid #ddd;padding:20px 0px}.as3cf-tab .form-table tr.as3cf-setting-title td{padding-bottom:0}.as3cf-tab .form-table tr.as3cf-setting-title:first-child td{padding-top:20px}.as3cf-tab .form-table tr.configure-url:first-child td{padding-top:5px;padding-bottom:0}.as3cf-tab .form-table tr.hide{display:none}.as3cf-tab .form-table tr td{padding:15px 0}.as3cf-tab .form-table tr td:first-child{vertical-align:top;min-width:120px;padding-top:20px}.as3cf-tab .form-table tr td .as3cf-notice:last-child{margin-bottom:0}.as3cf-tab .form-table tr td>p:first-child{margin-top:0}.as3cf-tab .form-table h3{padding:0;margin:0}.as3cf-tab .form-table h4{margin:0}.as3cf-tab .as3cf-active-region{font-style:italic}.as3cf-tab .as3cf-view-bucket{color:#444;text-decoration:none;margin-right:10px}.as3cf-tab .as3cf-view-bucket:hover,.as3cf-tab .as3cf-view-bucket:active{color:#00a0d2}.as3cf-tab .as3cf-view-bucket:focus{-webkit-box-shadow:none;box-shadow:none}.as3cf-tab .as3cf-view-bucket .dashicons-external{margin-top:-2px}.as3cf-tab .tooltip{position:relative;z-index:2;cursor:pointer}.as3cf-tab .tooltip:before,.as3cf-tab .tooltip:after{visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;pointer-events:none}.as3cf-tab .tooltip:before{position:absolute;bottom:150%;left:50%;margin-bottom:5px;margin-left:-250px;padding:10px;width:500px;border-radius:3px;background-color:#000;background-color:rgba(51,51,51,0.9);color:#fff;content:attr(data-tooltip);text-align:center;font-size:14px;line-height:1.3}.as3cf-tab .tooltip:after{position:absolute;bottom:150%;left:50%;margin-left:-5px;width:0;border-top:5px solid #000;border-top:5px solid rgba(51,51,51,0.9);border-right:5px solid transparent;border-left:5px solid transparent;content:" ";font-size:0;line-height:0}.as3cf-tab .tooltip:hover:before,.as3cf-tab .tooltip:hover:after{visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}.as3cf-tab .as3cf-defined-in-config{background:#ccc;color:#fff;padding:2px 5px;margin:0 0 3px 5px;float:right;white-space:nowrap;clear:right}.as3cf-tab .as3cf-defined-setting,.as3cf-tab .as3cf-locked-setting{color:#bbb}.as3cf-tab .as3cf-defined-setting label,.as3cf-tab .as3cf-locked-setting label{cursor:default}.as3cf-tab .as3cf-defined-setting p .more-info a,.as3cf-tab .as3cf-locked-setting p .more-info a{color:#bbb}.as3cf-tab .as3cf-defined-setting .as3cf-radio-group p,.as3cf-tab .as3cf-locked-setting .as3cf-radio-group p{color:#bbb}.as3cf-tab .as3cf-defined-setting .as3cf-notice,.as3cf-tab .as3cf-locked-setting .as3cf-notice{display:none !important}.as3cf-tab p.actions{margin:30px 0;border-top:1px solid #ccc;padding-top:15px;overflow:hidden}.as3cf-tab p.actions button,.as3cf-tab p.actions .right{float:right;margin-left:15px;margin-right:0;min-width:90px}.as3cf-tab p.actions button:last-of-type,.as3cf-tab p.actions .right:last-of-type{margin-left:0}.as3cf-tab p.actions span{display:inline-block;margin-right:20px;line-height:28px}.as3cf-tab .locked .as3cf-radio-group label,.as3cf-tab .locked .as3cf-radio-group label p{color:#bbb;cursor:default}.as3cf-tab .locked .as3cf-switch{cursor:default;background:#e6e6e6}.as3cf-tab .locked .as3cf-switch span{background:#f1f1f1;color:#d6d6d6}#tab-media{display:block}#tab-media .as3cf-provider-setting td{padding-top:20px;padding-bottom:5px}#tab-media .as3cf-bucket-setting td{padding:5px 0}.as3cf-bucket-container h3{line-height:1.3;text-transform:none}.as3cf-bucket-container a:focus{-webkit-box-shadow:none;box-shadow:none;outline:none}.as3cf-bucket-container input[type=text]{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.as3cf-bucket-container select{-webkit-box-sizing:border-box;box-sizing:border-box;width:50%}.as3cf-bucket-container .form-table .as3cf-provider-setting h4{font-weight:inherit;margin:0}.as3cf-bucket-container .form-table .as3cf-bucket-list{margin:5px 0 0 0}.as3cf-bucket-container .form-table td{padding:5px 0}.as3cf-bucket-container .form-table td:first-child{width:100px;line-height:30px;vertical-align:top}.as3cf-bucket-container .form-table td .as3cf-defined-in-config{margin-top:-1.75em}.as3cf-bucket-container .as3cf-bucket-list{padding:15px;max-height:200px;overflow-x:hidden;overflow-y:auto;background-color:#fff;font-size:14px}.as3cf-bucket-container .as3cf-bucket-list li:last-of-type{margin-bottom:0}.as3cf-bucket-container .as3cf-bucket-list a{color:#444;text-decoration:none}.as3cf-bucket-container .as3cf-bucket-list a:hover{color:#0074a2}.as3cf-bucket-container .as3cf-bucket-list a.selected{font-weight:bold;color:#0074a2}.as3cf-bucket-container .as3cf-bucket-list a .dashicons{margin-right:5px}.as3cf-change-bucket-access-prompt h3{line-height:1.3;text-transform:none}.as3cf-change-bucket-access-prompt .as3cf-radio-group{margin-bottom:25px}.as3cf-change-bucket-access-prompt .note{color:#999}.as3cf-delivery-provider-select h3{line-height:1.3;text-transform:none}.as3cf-delivery-provider-select .note{color:#999}#tab-media{display:block}#tab-support{min-height:900px}#tab-support .as3cf-sidebar{top:11px}#tab-support .support-section{border-bottom:1px solid #ccc;padding-bottom:20px;margin-bottom:20px}#tab-support .support-section h3{font-size:20px}#tab-support .debug textarea{width:100%;min-height:200px;font-family:Consolas, Monaco, monospace;margin-bottom:5px}.as3cf-sidebar{position:absolute;top:9px;left:670px;width:292px}.as3cf-sidebar .block{padding:20px;border:1px solid #ccc}.as3cf-sidebar .subscribe{border-top:none}.as3cf-sidebar .subscribe h2{padding:0;margin:0;margin-bottom:0.5em;color:#666;font-size:20px;line-height:1.2em;float:none}.as3cf-sidebar .subscribe h3{font-size:16px;margin:0}.as3cf-sidebar .subscribe p{margin:0}.as3cf-sidebar .subscribe .intro{margin-bottom:1em;line-height:1.4}.as3cf-sidebar .subscribe li{line-height:1.4}.as3cf-sidebar .subscribe .links{margin-bottom:2em}.as3cf-sidebar .subscribe .links a{text-decoration:none}.as3cf-sidebar .subscribe .promise{color:#999;font-size:12px;line-height:1.4em}.as3cf-sidebar .subscribe .field{margin-bottom:0.5em}.as3cf-sidebar .subscribe .field p{margin-bottom:0.3em}.as3cf-sidebar .subscribe .field input[type=text],.as3cf-sidebar .subscribe .field input[type=email]{width:100%}.as3cf-sidebar .subscribe .field.submit-button{margin-bottom:1em}.as3cf-sidebar .credits{border-top:0}.as3cf-sidebar .credits h4{font-size:16px;margin-top:0;margin-bottom:10px}.as3cf-sidebar .credits ul{margin:0}.as3cf-sidebar .credits li{overflow:hidden}.as3cf-sidebar .credits li:last-child{margin-bottom:0}.as3cf-sidebar .credits img{float:left;margin-right:10px}.as3cf-sidebar .credits span{float:left;display:block;line-height:32px}.as3cf-sidebar .credits a{display:block;text-decoration:none;color:#444;font-size:16px;text-align:center}.as3cf-sidebar .credits a:hover{color:#888}@media screen and (max-width: 1052px){.as3cf-sidebar{position:relative;top:auto;right:auto}}.as3cf-active-provider,.as3cf-active-bucket{font-weight:bold;margin-right:10px}.as3cf-banner{margin-top:35px;width:292px;height:200px;display:block;background:#f8cfae url(../img/os3-banner.svg) left bottom/220px 220px no-repeat}.as3cf-banner:focus{-webkit-box-shadow:none;box-shadow:none}.wrap .as3cf-upgrade-details{background-color:#4e0d33;padding:10px 20px 20px 20px;color:#eee;font-size:13px;margin:0;display:block;text-decoration:none}.wrap .as3cf-upgrade-details h1{font-size:28px;color:#eee;margin:0 0 15px 0;padding:0;text-decoration:none;font-weight:200;line-height:1}.wrap .as3cf-upgrade-details p{margin:0}.wrap .as3cf-upgrade-details a{color:#eee;font-weight:bold;text-decoration:none;font-size:16px;-webkit-box-shadow:none;box-shadow:none}.wrap .as3cf-upgrade-details a:hover{color:#fff}.wrap .as3cf-upgrade-details ul{margin-top:0;margin-left:16px;list-style-type:disc}.as3cf-compatibility-notice.error{clear:both;margin:5px 20px 5px 0}.as3cf-bucket-error span.title{font-weight:bold}.as3cf-invalid-bucket-name,.as3cf-validation-error{display:block;margin-top:2px;font-size:12px;color:#a00}.as3cf-notice-toggle-content{max-height:100px;overflow-y:scroll}.as3cf-notice-toggle-content .as3cf-notice-toggle-list{margin-top:0;margin-left:0;padding-left:40px;color:#dc3232}.as3cf-need-help{background-color:white;font-size:16px;font-weight:bold;padding:1em}.as3cf-need-help a{text-decoration:none}.as3cf-settings h3{font-size:20px}.as3cf-settings p{font-size:14px}.as3cf-addons,.as3cf-tab .as3cf-compatibility-notice{max-width:cover}textarea.as3cf-access-key-constants-snippet.code{width:100%;white-space:pre;overflow:hidden;font-size:12px;padding:10px;height:53px}.as3cf-addons .as3cf-addons-list{margin:20px 0 200px;padding-top:5px}.as3cf-addons .as3cf-addon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:20px;font-size:14px}.as3cf-addons .as3cf-addon-info{min-height:100px}.as3cf-addons .as3cf-addon-links{float:right}.as3cf-addons .as3cf-addon-links span{padding:4px 6px}.as3cf-addons .as3cf-addon-icon{float:left;margin-right:20px}.as3cf-addons .as3cf-addon-details{white-space:nowrap}.as3cf-addons .as3cf-addon-title,.as3cf-addons .as3cf-addon-description{font-weight:100}.as3cf-addons .as3cf-addon+.as3cf-addon{margin-top:20px}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull{background-color:#0769ad;color:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .as3cf-addon-title,.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .as3cf-addon-description,.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull a{color:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .extra{background:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .extra a{color:#0769ad;text-decoration:none}
assets/js/delivery-provider.js ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function( $ ) {
2
+ var $body = $( 'body' );
3
+
4
+ var as3cf = as3cf || {};
5
+
6
+ /**
7
+ * Handle changes to the selected Delivery Provider.
8
+ */
9
+ as3cf.deliveryProvider = {
10
+ changed: function() {
11
+ var provider = $( 'input[name="delivery-provider"]:checked' ).val();
12
+ var parent = $( 'input[name="delivery-provider"]:checked' ).attr( 'data-delivery-provider-parent' );
13
+
14
+ // De-select all providers.
15
+ $( '.as3cf-delivery-provider' ).each( function() {
16
+ $( this ).removeClass( 'selected' );
17
+ } );
18
+
19
+ // De-select all sub option containers.
20
+ $( '.as3cf-delivery-provider-sub-option-container' ).each( function() {
21
+ $( this ).removeClass( 'selected' );
22
+ } );
23
+
24
+ // Select chosen provider.
25
+ $( '.as3cf-delivery-provider[data-delivery-provider="' + provider + '"]' ).each( function() {
26
+ $( this ).addClass( 'selected' );
27
+ } );
28
+
29
+ if ( 0 < parent.length ) {
30
+ // If switching sub options, re-select container and parent too.
31
+ $( '.as3cf-delivery-provider-sub-option-container[data-delivery-provider="' + parent + '"]' ).each( function() {
32
+ $( this ).addClass( 'selected' );
33
+ } );
34
+ $( '.as3cf-delivery-provider[data-delivery-provider="' + parent + '"]' ).each( function() {
35
+ $( this ).addClass( 'selected' );
36
+ } );
37
+ } else {
38
+ // Switching top level provider, de-select any sub option container...
39
+ $( '.as3cf-delivery-provider-sub-option-container' ).each( function() {
40
+ $( this ).removeClass( 'selected' );
41
+ } );
42
+
43
+ // ... and select the dummy hidden radio button.
44
+ $( 'input#as3cf-delivery-provider-dummy-parent[name="delivery-provider-sub-option-parent"]' ).each( function() {
45
+ $( this ).prop( 'checked', true );
46
+ $( this ).trigger( 'change' );
47
+ } );
48
+ }
49
+ },
50
+
51
+ subOptionParentChanged: function() {
52
+ var parent = $( 'input[name="delivery-provider-sub-option-parent"]:checked' ).val();
53
+
54
+ // De-select all other top level options.
55
+ $( '.as3cf-delivery-provider-option' ).each( function() {
56
+ $( this ).removeClass( 'selected' );
57
+ } );
58
+
59
+ // Select chosen sub option container.
60
+ $( '.as3cf-delivery-provider-sub-option-container[data-delivery-provider="' + parent + '"]' ).each( function() {
61
+ $( this ).addClass( 'selected' );
62
+ } );
63
+
64
+ // Select chosen sub option parent.
65
+ $( '.as3cf-delivery-provider-option[data-delivery-provider="' + parent + '"]' ).each( function() {
66
+ $( this ).addClass( 'selected' );
67
+ } );
68
+
69
+ // Find default sub option to select.
70
+ $( 'input[data-delivery-provider-parent="' + parent + '"]' ).first().each( function() {
71
+ $( this ).prop( 'checked', true );
72
+ $( this ).trigger( 'change' );
73
+ } );
74
+ }
75
+ };
76
+
77
+ $( document ).ready( function() {
78
+ // Switch displayed delivery provider content.
79
+ $body.on( 'change', 'input[name="delivery-provider"]', function( e ) {
80
+ e.preventDefault();
81
+ as3cf.deliveryProvider.changed();
82
+ } );
83
+ $body.on( 'change', 'input[name="delivery-provider-sub-option-parent"]', function( e ) {
84
+ e.preventDefault();
85
+ as3cf.deliveryProvider.subOptionParentChanged();
86
+ } );
87
+ } );
88
+
89
+ })( jQuery );
assets/js/delivery-provider.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(a){var b=a("body"),c=c||{};c.deliveryProvider={changed:function(){var b=a('input[name="delivery-provider"]:checked').val(),c=a('input[name="delivery-provider"]:checked').attr("data-delivery-provider-parent");a(".as3cf-delivery-provider").each(function(){a(this).removeClass("selected")}),a(".as3cf-delivery-provider-sub-option-container").each(function(){a(this).removeClass("selected")}),a('.as3cf-delivery-provider[data-delivery-provider="'+b+'"]').each(function(){a(this).addClass("selected")}),0<c.length?(a('.as3cf-delivery-provider-sub-option-container[data-delivery-provider="'+c+'"]').each(function(){a(this).addClass("selected")}),a('.as3cf-delivery-provider[data-delivery-provider="'+c+'"]').each(function(){a(this).addClass("selected")})):(a(".as3cf-delivery-provider-sub-option-container").each(function(){a(this).removeClass("selected")}),a('input#as3cf-delivery-provider-dummy-parent[name="delivery-provider-sub-option-parent"]').each(function(){a(this).prop("checked",!0),a(this).trigger("change")}))},subOptionParentChanged:function(){var b=a('input[name="delivery-provider-sub-option-parent"]:checked').val();a(".as3cf-delivery-provider-option").each(function(){a(this).removeClass("selected")}),a('.as3cf-delivery-provider-sub-option-container[data-delivery-provider="'+b+'"]').each(function(){a(this).addClass("selected")}),a('.as3cf-delivery-provider-option[data-delivery-provider="'+b+'"]').each(function(){a(this).addClass("selected")}),a('input[data-delivery-provider-parent="'+b+'"]').first().each(function(){a(this).prop("checked",!0),a(this).trigger("change")})}},a(document).ready(function(){b.on("change",'input[name="delivery-provider"]',function(a){a.preventDefault(),c.deliveryProvider.changed()}),b.on("change",'input[name="delivery-provider-sub-option-parent"]',function(a){a.preventDefault(),c.deliveryProvider.subOptionParentChanged()})})}(jQuery);
assets/js/script.js CHANGED
@@ -53,6 +53,63 @@
53
  }
54
  }
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  as3cf.tabs = {
57
  defaultTab: 'media',
58
  /**
@@ -376,6 +433,40 @@
376
  $( document ).trigger( 'wp-updates-notice-added' ); // Hack to run WP Core's makeNoticesDismissible() function.
377
  };
378
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  /**
380
  * Get the link to the bucket on the AWS Console and update the DOM
381
  *
@@ -538,7 +629,7 @@
538
  } );
539
 
540
  $( '.as3cf-switch' ).on( 'click', function( e ) {
541
- if ( ! $( this ).hasClass( 'disabled' ) ) {
542
  setCheckbox( $( this ).attr( 'id' ) );
543
  }
544
  } );
@@ -548,14 +639,6 @@
548
  $( '.as3cf-setting.' + setting ).toggleClass( 'hide' );
549
  } );
550
 
551
- $( '.as3cf-domain' ).on( 'change', 'input[type="radio"]', function( e ) {
552
- var $selected = $( this ).closest( 'input:radio[name="domain"]:checked' );
553
- var domain = $selected.val();
554
- var $cloudfront = $( this ).parents( '.as3cf-domain' ).find( '.as3cf-setting.cloudfront' );
555
- var cloudfrontSelected = ( 'cloudfront' === domain );
556
- $cloudfront.toggleClass( 'hide', ! cloudfrontSelected );
557
- } );
558
-
559
  $( '.url-preview' ).on( 'change', 'input', function( e ) {
560
  generateUrlPreview();
561
  } );
@@ -579,20 +662,87 @@
579
  }
580
  } );
581
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
582
  // Validate custom domain
583
- $( 'input[name="cloudfront"]' ).on( 'keyup', function( e ) {
584
  validateCustomDomain( $( this ) );
585
  } );
586
 
587
- // Re-enable submit button on domain change
588
- $( 'input[name="domain"]' ).on( 'change', function( e ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
589
  var $input = $( this );
590
  var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
591
 
592
- if ( 'cloudfront' !== $input.val() ) {
593
  $submit.prop( 'disabled', false );
594
  } else {
595
- validateCustomDomain( $input.next( '.as3cf-setting' ).find( 'input[name="cloudfront"]' ) );
596
  }
597
  } );
598
 
@@ -663,6 +813,16 @@
663
  return false;
664
  }
665
  } );
 
 
 
 
 
 
 
 
 
 
666
  } );
667
 
668
  } )( jQuery, as3cfModal );
53
  }
54
  }
55
 
56
+ /**
57
+ * Validate Signed URLs Key ID.
58
+ *
59
+ * @param {object} $input
60
+ */
61
+ function validateSignedUrlsKeyID( $input ) {
62
+ var $error = $input.next( '.as3cf-validation-error' );
63
+ var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
64
+ var pattern = /[^a-zA-Z0-9]/; // Letters & Numbers only at present (CloudFront).
65
+
66
+ if ( pattern.test( $input.val() ) ) {
67
+ $error.show();
68
+ $submit.prop( 'disabled', true );
69
+ } else {
70
+ $error.hide();
71
+ $submit.prop( 'disabled', false );
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Validate Signed URLs Key File Path.
77
+ *
78
+ * @param {object} $input
79
+ */
80
+ function validateSignedUrlsKeyFilePath( $input ) {
81
+ var $error = $input.next( '.as3cf-validation-error' );
82
+ var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
83
+ var pattern = /[^a-zA-Z0-9\.\-\\:\/ ]/;
84
+
85
+ if ( pattern.test( $input.val() ) ) {
86
+ $error.show();
87
+ $submit.prop( 'disabled', true );
88
+ } else {
89
+ $error.hide();
90
+ $submit.prop( 'disabled', false );
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Validate Signed URLs Object Prefix.
96
+ *
97
+ * @param {object} $input
98
+ */
99
+ function validateSignedUrlsObjectPrefix( $input ) {
100
+ var $error = $input.next( '.as3cf-validation-error' );
101
+ var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
102
+ var pattern = /[^a-zA-Z0-9\-\/ ]/;
103
+
104
+ if ( pattern.test( $input.val() ) ) {
105
+ $error.show();
106
+ $submit.prop( 'disabled', true );
107
+ } else {
108
+ $error.hide();
109
+ $submit.prop( 'disabled', false );
110
+ }
111
+ }
112
+
113
  as3cf.tabs = {
114
  defaultTab: 'media',
115
  /**
433
  $( document ).trigger( 'wp-updates-notice-added' ); // Hack to run WP Core's makeNoticesDismissible() function.
434
  };
435
 
436
+ as3cf.Settings = as3cf.Settings ? as3cf.Settings : {};
437
+
438
+ /**
439
+ * The object that handles locking and unlocking the Media settings.
440
+ */
441
+ as3cf.Settings.Media = {
442
+ /**
443
+ * Lock settings.
444
+ */
445
+ lock: function( key ) {
446
+ $( '#as3cf-media-settings-locked-' + key ).show();
447
+ $( '.as3cf-media-settings' ).addClass( 'locked locked-' + key );
448
+ $( '.as3cf-media-settings.locked-' + key ).each( function() {
449
+ $( this ).find( 'input,button' ).prop( 'disabled', true );
450
+ $( this ).find( '.as3cf-settings-container' ).addClass( 'as3cf-locked-setting' );
451
+ $( this ).find( 'a.as3cf-change-settings' ).hide();
452
+ } );
453
+ },
454
+
455
+ /**
456
+ * Unlock settings.
457
+ */
458
+ unlock: function( key ) {
459
+ $( '.as3cf-media-settings.locked-' + key ).each( function() {
460
+ $( this ).find( 'input,button' ).filter( ':not(.disabled)' ).prop( 'disabled', false );
461
+ $( this ).find( '.as3cf-settings-container' ).removeClass( 'as3cf-locked-setting' );
462
+ $( this ).find( 'a.as3cf-change-settings' ).show();
463
+ $( this ).removeClass( 'locked locked-' + key );
464
+ } );
465
+ $( '#as3cf-media-settings-locked-' + key ).hide();
466
+ }
467
+
468
+ };
469
+
470
  /**
471
  * Get the link to the bucket on the AWS Console and update the DOM
472
  *
629
  } );
630
 
631
  $( '.as3cf-switch' ).on( 'click', function( e ) {
632
+ if ( ! $( this ).hasClass( 'disabled' ) && ! $( this ).parents().hasClass( 'locked' ) ) {
633
  setCheckbox( $( this ).attr( 'id' ) );
634
  }
635
  } );
639
  $( '.as3cf-setting.' + setting ).toggleClass( 'hide' );
640
  } );
641
 
 
 
 
 
 
 
 
 
642
  $( '.url-preview' ).on( 'change', 'input', function( e ) {
643
  generateUrlPreview();
644
  } );
662
  }
663
  } );
664
 
665
+ // Show or hide Custom Domain input and Enable Signed URLs section based on custom domain toggle switch.
666
+ $( '.as3cf-enable-delivery-domain-container' ).on( 'change', 'input[type="checkbox"]', function( e ) {
667
+ var deliveryDomainEnabled = $( this ).is( ':checked' );
668
+ var $deliveryDomain = $( this ).parents( '.as3cf-enable-delivery-domain-container' ).find( '.as3cf-setting.as3cf-delivery-domain' );
669
+ $deliveryDomain.toggleClass( 'hide', ! deliveryDomainEnabled );
670
+ var $signedUrlsEnabled = $( this ).parents( '.as3cf-enable-delivery-domain-container' ).siblings( '.as3cf-enable-signed-urls-container' );
671
+ $signedUrlsEnabled.toggleClass( 'hide', ! deliveryDomainEnabled );
672
+ } );
673
+
674
+ // Re-enable submit button on domain change
675
+ $( 'input[name="enable-delivery-domain"]' ).on( 'change', function( e ) {
676
+ var $input = $( this );
677
+ var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
678
+
679
+ if ( '1' !== $input.val() ) {
680
+ $submit.prop( 'disabled', false );
681
+ } else {
682
+ validateCustomDomain( $input.next( '.as3cf-setting' ).find( 'input[name="delivery-domain"]' ) );
683
+ }
684
+ } );
685
+
686
  // Validate custom domain
687
+ $( 'input[name="delivery-domain"]' ).on( 'keyup', function( e ) {
688
  validateCustomDomain( $( this ) );
689
  } );
690
 
691
+ // Show or hide Signed URLs fields based on Enable Signed URLs toggle switch.
692
+ $( '.as3cf-enable-signed-urls-container' ).on( 'change', 'input[type="checkbox"]', function( e ) {
693
+ var signedUrlsEnabled = $( this ).is( ':checked' );
694
+ var $signedUrls = $( this ).parents( '.as3cf-enable-signed-urls-container' ).find( '.as3cf-setting.as3cf-signed-urls' );
695
+ $signedUrls.toggleClass( 'hide', ! signedUrlsEnabled );
696
+ } );
697
+
698
+ // Validate Signed URLs Key ID.
699
+ $( 'input[name="signed-urls-key-id"]' ).on( 'keyup', function( e ) {
700
+ validateSignedUrlsKeyID( $( this ) );
701
+ } );
702
+
703
+ // Re-enable submit button on Signed URLs Key ID change
704
+ $( 'input[name="enable-signed-urls-key-id"]' ).on( 'change', function( e ) {
705
+ var $input = $( this );
706
+ var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
707
+
708
+ if ( '1' !== $input.val() ) {
709
+ $submit.prop( 'disabled', false );
710
+ } else {
711
+ validateSignedUrlsKeyID( $input.next( '.as3cf-setting' ).find( 'input[name="signed-urls-key-id"]' ) );
712
+ }
713
+ } );
714
+
715
+ // Validate Signed URLs Key File Path.
716
+ $( 'input[name="signed-urls-key-file-path"]' ).on( 'keyup', function( e ) {
717
+ validateSignedUrlsKeyFilePath( $( this ) );
718
+ } );
719
+
720
+ // Re-enable submit button on Signed URLs Key File Path change
721
+ $( 'input[name="enable-signed-urls-key-file-path"]' ).on( 'change', function( e ) {
722
+ var $input = $( this );
723
+ var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
724
+
725
+ if ( '1' !== $input.val() ) {
726
+ $submit.prop( 'disabled', false );
727
+ } else {
728
+ validateSignedUrlsKeyFilePath( $input.next( '.as3cf-setting' ).find( 'input[name="signed-urls-key-file-path"]' ) );
729
+ }
730
+ } );
731
+
732
+ // Validate Signed URLs Object Prefix.
733
+ $( 'input[name="signed-urls-object-prefix"]' ).on( 'keyup', function( e ) {
734
+ validateSignedUrlsObjectPrefix( $( this ) );
735
+ } );
736
+
737
+ // Re-enable submit button on Signed URLs Object Prefix change
738
+ $( 'input[name="enable-signed-urls-object-prefix"]' ).on( 'change', function( e ) {
739
  var $input = $( this );
740
  var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
741
 
742
+ if ( '1' !== $input.val() ) {
743
  $submit.prop( 'disabled', false );
744
  } else {
745
+ validateSignedUrlsObjectPrefix( $input.next( '.as3cf-setting' ).find( 'input[name="signed-urls-object-prefix"]' ) );
746
  }
747
  } );
748
 
813
  return false;
814
  }
815
  } );
816
+
817
+ // Enable/Disable Block All Public Access button during setup depending on checkbox.
818
+ $( '.as3cf-change-bucket-access-prompt' ).on( 'change', '#origin-access-identity-confirmation', function( e ) {
819
+ $( '#block-public-access-confirmed' ).prop( 'disabled', ! $( this ).prop( 'checked' ) );
820
+ } );
821
+
822
+ // If there's an upgrade in progress when the page loads, ensure settings are locked.
823
+ $( '.as3cf-media-settings.locked.locked-upgrade' ).each( function() {
824
+ as3cf.Settings.Media.lock( 'upgrade' );
825
+ } );
826
  } );
827
 
828
  } )( jQuery, as3cfModal );
assets/js/script.min.js CHANGED
@@ -1 +1 @@
1
- !function(a,b){function c(b){return a("#"+b+" .as3cf-main-settings form").find("input:not(.no-compare)").serialize()}function d(a){var b=l.find("#"+a),c=b.find("input[type=checkbox]");b.toggleClass("on").find("span").toggleClass("checked");var d=b.find("span.on").hasClass("checked");c.prop("checked",d).trigger("change")}function e(b){var c=b.next(".as3cf-validation-error"),d=a("#"+l.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9\.\-]/;e.test(b.val())?(c.show(),d.prop("disabled",!0)):(c.hide(),d.prop("disabled",!1))}function f(){var c=a("#"+b.prefix+"-bucket").val(),d=l.find('input[name="object-prefix"]'),e=d.val();""!==e&&(e=as3cf.provider_console_url_prefix_param+encodeURIComponent(e));var f=as3cf.provider_console_url+c+e;a("#"+b.prefix+"-view-bucket").attr("href",f)}function g(){a("#as3cf-remove-local-file").is(":checked")&&a("#as3cf-serve-from-s3").is(":not(:checked)")?a("#as3cf-lost-files-notice").show():a("#as3cf-lost-files-notice").hide()}function h(){a("#as3cf-remove-local-file").is(":checked")?a("#as3cf-remove-local-notice").show():a("#as3cf-remove-local-notice").hide()}function i(b){!0!==b?a("#as3cf-seo-friendly-url-notice").show():a("#as3cf-seo-friendly-url-notice").hide()}function j(){a(".as3cf-url-preview").html("Generating...");var b={_nonce:as3cf.nonces.get_url_preview};a.each(a("#tab-"+as3cf.tabs.defaultTab+" .as3cf-main-settings form").serializeArray(),function(c,d){var e=d.name,f=d.value;e=e.replace("[]",""),b[e]=void 0===b[e]?f:a.isArray(b[e])?b[e].concat(f):[b[e],f]}),b.action="as3cf-get-url-preview",a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:b,error:function(a,b,c){alert(as3cf.strings.get_url_preview_error+c)},success:function(b,c,d){"undefined"!=typeof b.success?(a(".as3cf-url-preview").html(b.url),i(b.seo_friendly)):alert(as3cf.strings.get_url_preview_error+b.error)}})}function k(){return"#"+as3cf.tabs.defaultTab===location.hash?void(location.hash=""):(as3cf.tabs.toggle(location.hash.replace("#",""),!0),void a(document).trigger("as3cf.tabRendered",[location.hash.replace("#","")]))}var l,m={},n=/[^a-z0-9.-]/,o=a("body"),p=a(".as3cf-tab");a(".as3cf-settings");as3cf.tabs={defaultTab:"media",toggle:function(c,d){c=as3cf.tabs.sanitizeHash(c),p.hide(),l=a("#tab-"+c),l.show(),a(".nav-tab").removeClass("nav-tab-active"),a('a.nav-tab[data-tab="'+c+'"]').addClass("nav-tab-active"),a(".as3cf-main").data("tab",c),l.data("prefix")&&(b.prefix=l.data("prefix")),d||a(".as3cf-updated").removeClass("show"),"support"===c&&as3cf.tabs.getDiagnosticInfo()},getDiagnosticInfo:function(){var b=a(".debug-log-textarea");b.html(as3cf.strings.get_diagnostic_info);var c={action:"as3cf-get-diagnostic-info",_nonce:as3cf.nonces.get_diagnostic_info};a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:c,error:function(a,c,d){b.html(d)},success:function(a,c,d){"undefined"!=typeof a.success?b.html(a.diagnostic_info):(b.html(as3cf.strings.get_diagnostic_info_error),b.append(a.error))}})},sanitizeHash:function(b){var c=a("#tab-"+b);return 0===c.length&&(b=as3cf.tabs.defaultTab),b}},as3cf.buckets={validLength:3,bucketSelectLock:!1,loadList:function(c){"undefined"==typeof c&&(c=!1);var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select"),e=d.find(".bucket-select-region"),f=d.find(".as3cf-bucket-list"),g=a("#"+b.prefix+"-bucket").val();if(!1===c&&f.find("li").length>1)return a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+g+'"]').addClass("selected"),void this.scrollToSelected();f.html('<li class="loading">'+f.data("working")+"</li>"),this.disabledButtons();var h={action:b.prefix+"-get-buckets",_nonce:window[b.prefix.replace(/-/g,"_")].nonces.get_buckets};e.val()&&(h.region=e.val());var i=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:h,error:function(a,b,c){f.html(""),i.showError(as3cf.strings.get_buckets_error,c,"as3cf-bucket-select")},success:function(b,c,d){f.html(""),"undefined"!=typeof b.success?(a(".as3cf-bucket-error").hide(),0===b.buckets.length?f.html('<li class="loading">'+f.data("nothing-found")+"</li>"):(a(b.buckets).each(function(a,b){var c=b.Name===g?"selected":"";f.append('<li><a class="'+c+'" href="#" data-bucket="'+b.Name+'"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> '+b.Name+'</span><span class="spinner"></span></span></a></li>')}),i.scrollToSelected(),i.disabledButtons())):i.showError(as3cf.strings.get_buckets_error,b.error,"as3cf-bucket-select")}})},scrollToSelected:function(){if(a(".as3cf-bucket-list a.selected").length){var b=a("ul.as3cf-bucket-list li").first().position().top+150;a(".as3cf-bucket-list").animate({scrollTop:a("ul.as3cf-bucket-list li a.selected").position().top-b})}},setSelected:function(c){a(".as3cf-bucket-list a").removeClass("selected"),c.addClass("selected"),a("#"+b.prefix+"-bucket-select-name").val(c.data("bucket"))},disabledButtons:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create"),d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual"),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select");0===c.length&&0===d.length&&0===e.length||(0<c.length&&this.isValidName(c.find(".as3cf-bucket-name").val())?c.find("button[type=submit]").prop("disabled",!1):c.find("button[type=submit]").prop("disabled",!0),0<d.length&&this.isValidName(d.find(".as3cf-bucket-name").val())?d.find("button[type=submit]").prop("disabled",!1):d.find("button[type=submit]").prop("disabled",!0),0<e.length&&1===e.find(".as3cf-bucket-list a.selected").length?e.find("button[type=submit]").prop("disabled",!1):e.find("button[type=submit]").prop("disabled",!0))},showError:function(b,c,d){var e=a(".as3cf-bucket-container").children(":visible"),f=e.find(".as3cf-bucket-error");d="undefined"==typeof d?null:d,d&&!e.hasClass(d)||(f.find("span.title").html(b+" &mdash;"),f.find("span.message").html(c),f.show(),this.bucketSelectLock=!1)},isValidName:function(a){return!(a.length<3||a.length>63)&&!0!==n.test(a)},updateNameNotice:function(b){var c=null;!0===n.test(b)?c=as3cf.strings.create_bucket_invalid_chars:b.length<3?c=as3cf.strings.create_bucket_name_short:b.length>63&&(c=as3cf.strings.create_bucket_name_long),c&&b.length>0?a(".as3cf-invalid-bucket-name").html(c):a(".as3cf-invalid-bucket-name").html("")}},as3cf.reloadUpdated=function(){var a=location.pathname+location.search;location.search.match(/[?&]updated=/)||(a+="&updated=1"),a+=location.hash,location.assign(a)},as3cf.showSettingsSavedNotice=function(){if(!(0<a("#setting-error-settings_updated:visible").length||0<a("#as3cf-settings_updated:visible").length)){var b='<div id="as3cf-settings_updated" class="updated settings-error notice is-dismissible"><p><strong>'+as3cf.strings.settings_saved+"</strong></p></div>";a("h2.nav-tab-wrapper").after(b),a(document).trigger("wp-updates-notice-added")}},a(document).ready(function(){k(),window.onhashchange=function(a){"function"==typeof history.replaceState&&"#"===location.href.slice(-1)&&history.replaceState({},"",location.href.slice(0,-1)),k()};var i=a(".as3cf-main .nav-tab-wrapper");a(".as3cf-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(i),p.length&&p.each(function(a,b){m[b.id]=c(b.id)}),a(window).on("beforeunload.as3cf-settings",function(){if(!a.isEmptyObject(m)){var b=l.attr("id");return c(b)!==m[b]?as3cf.strings.save_alert:void 0}}),a(document).on("submit",".as3cf-main-settings form",function(b){a(window).off("beforeunload.as3cf-settings")}),a(".as3cf-switch").on("click",function(b){a(this).hasClass("disabled")||d(a(this).attr("id"))}),p.on("change",".sub-toggle",function(b){var c=a(this).attr("id");a(".as3cf-setting."+c).toggleClass("hide")}),a(".as3cf-domain").on("change",'input[type="radio"]',function(b){var c=a(this).closest('input:radio[name="domain"]:checked'),d=c.val(),e=a(this).parents(".as3cf-domain").find(".as3cf-setting.cloudfront"),f="cloudfront"===d;e.toggleClass("hide",!f)}),a(".url-preview").on("change","input",function(a){j()}),g(),a("#as3cf-serve-from-s3,#as3cf-remove-local-file").on("change",function(a){g()}),h(),a("#as3cf-remove-local-file").on("change",function(a){h()}),a('.as3cf-setting input[type="text"]').keypress(function(a){if(13===a.which)return a.preventDefault(),!1}),a('input[name="cloudfront"]').on("keyup",function(b){e(a(this))}),a('input[name="domain"]').on("change",function(b){var c=a(this),d=a("#"+l.attr("id")+' form button[type="submit"]');"cloudfront"!==c.val()?d.prop("disabled",!1):e(c.next(".as3cf-setting").find('input[name="cloudfront"]'))}),a('input[name="object-prefix"]').on("change",function(a){f()}),a("#tab-media > .as3cf-bucket-error").detach().insertAfter(".as3cf-bucket-container h3"),as3cf.buckets.disabledButtons(),o.on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),o.on("change",".bucket-select-region",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),0<a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").length&&as3cf.buckets.loadList(!0),o.on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.setSelected(a(this)),as3cf.buckets.disabledButtons()}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),o.on("input keyup",".as3cf-bucket-create .as3cf-bucket-name",function(b){var c=a(this).val();as3cf.buckets.updateNameNotice(c),as3cf.buckets.disabledButtons()}),o.on("input keyup",".as3cf-bucket-manual .as3cf-bucket-name",function(b){var c=a(this).val();as3cf.buckets.updateNameNotice(c),as3cf.buckets.disabledButtons()}),a('.as3cf-bucket-container input[type="text"]').keypress(function(a){if(13===a.which)return a.preventDefault(),!1})})}(jQuery,as3cfModal);
1
+ !function(a,b){function c(b){return a("#"+b+" .as3cf-main-settings form").find("input:not(.no-compare)").serialize()}function d(a){var b=o.find("#"+a),c=b.find("input[type=checkbox]");b.toggleClass("on").find("span").toggleClass("checked");var d=b.find("span.on").hasClass("checked");c.prop("checked",d).trigger("change")}function e(b){var c=b.next(".as3cf-validation-error"),d=a("#"+o.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9\.\-]/;e.test(b.val())?(c.show(),d.prop("disabled",!0)):(c.hide(),d.prop("disabled",!1))}function f(b){var c=b.next(".as3cf-validation-error"),d=a("#"+o.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9]/;e.test(b.val())?(c.show(),d.prop("disabled",!0)):(c.hide(),d.prop("disabled",!1))}function g(b){var c=b.next(".as3cf-validation-error"),d=a("#"+o.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9\.\-\\:\/ ]/;e.test(b.val())?(c.show(),d.prop("disabled",!0)):(c.hide(),d.prop("disabled",!1))}function h(b){var c=b.next(".as3cf-validation-error"),d=a("#"+o.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9\-\/ ]/;e.test(b.val())?(c.show(),d.prop("disabled",!0)):(c.hide(),d.prop("disabled",!1))}function i(){var c=a("#"+b.prefix+"-bucket").val(),d=o.find('input[name="object-prefix"]'),e=d.val();""!==e&&(e=as3cf.provider_console_url_prefix_param+encodeURIComponent(e));var f=as3cf.provider_console_url+c+e;a("#"+b.prefix+"-view-bucket").attr("href",f)}function j(){a("#as3cf-remove-local-file").is(":checked")&&a("#as3cf-serve-from-s3").is(":not(:checked)")?a("#as3cf-lost-files-notice").show():a("#as3cf-lost-files-notice").hide()}function k(){a("#as3cf-remove-local-file").is(":checked")?a("#as3cf-remove-local-notice").show():a("#as3cf-remove-local-notice").hide()}function l(b){!0!==b?a("#as3cf-seo-friendly-url-notice").show():a("#as3cf-seo-friendly-url-notice").hide()}function m(){a(".as3cf-url-preview").html("Generating...");var b={_nonce:as3cf.nonces.get_url_preview};a.each(a("#tab-"+as3cf.tabs.defaultTab+" .as3cf-main-settings form").serializeArray(),function(c,d){var e=d.name,f=d.value;e=e.replace("[]",""),b[e]=void 0===b[e]?f:a.isArray(b[e])?b[e].concat(f):[b[e],f]}),b.action="as3cf-get-url-preview",a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:b,error:function(a,b,c){alert(as3cf.strings.get_url_preview_error+c)},success:function(b,c,d){"undefined"!=typeof b.success?(a(".as3cf-url-preview").html(b.url),l(b.seo_friendly)):alert(as3cf.strings.get_url_preview_error+b.error)}})}function n(){return"#"+as3cf.tabs.defaultTab===location.hash?void(location.hash=""):(as3cf.tabs.toggle(location.hash.replace("#",""),!0),void a(document).trigger("as3cf.tabRendered",[location.hash.replace("#","")]))}var o,p={},q=/[^a-z0-9.-]/,r=a("body"),s=a(".as3cf-tab");a(".as3cf-settings");as3cf.tabs={defaultTab:"media",toggle:function(c,d){c=as3cf.tabs.sanitizeHash(c),s.hide(),o=a("#tab-"+c),o.show(),a(".nav-tab").removeClass("nav-tab-active"),a('a.nav-tab[data-tab="'+c+'"]').addClass("nav-tab-active"),a(".as3cf-main").data("tab",c),o.data("prefix")&&(b.prefix=o.data("prefix")),d||a(".as3cf-updated").removeClass("show"),"support"===c&&as3cf.tabs.getDiagnosticInfo()},getDiagnosticInfo:function(){var b=a(".debug-log-textarea");b.html(as3cf.strings.get_diagnostic_info);var c={action:"as3cf-get-diagnostic-info",_nonce:as3cf.nonces.get_diagnostic_info};a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:c,error:function(a,c,d){b.html(d)},success:function(a,c,d){"undefined"!=typeof a.success?b.html(a.diagnostic_info):(b.html(as3cf.strings.get_diagnostic_info_error),b.append(a.error))}})},sanitizeHash:function(b){var c=a("#tab-"+b);return 0===c.length&&(b=as3cf.tabs.defaultTab),b}},as3cf.buckets={validLength:3,bucketSelectLock:!1,loadList:function(c){"undefined"==typeof c&&(c=!1);var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select"),e=d.find(".bucket-select-region"),f=d.find(".as3cf-bucket-list"),g=a("#"+b.prefix+"-bucket").val();if(!1===c&&f.find("li").length>1)return a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+g+'"]').addClass("selected"),void this.scrollToSelected();f.html('<li class="loading">'+f.data("working")+"</li>"),this.disabledButtons();var h={action:b.prefix+"-get-buckets",_nonce:window[b.prefix.replace(/-/g,"_")].nonces.get_buckets};e.val()&&(h.region=e.val());var i=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:h,error:function(a,b,c){f.html(""),i.showError(as3cf.strings.get_buckets_error,c,"as3cf-bucket-select")},success:function(b,c,d){f.html(""),"undefined"!=typeof b.success?(a(".as3cf-bucket-error").hide(),0===b.buckets.length?f.html('<li class="loading">'+f.data("nothing-found")+"</li>"):(a(b.buckets).each(function(a,b){var c=b.Name===g?"selected":"";f.append('<li><a class="'+c+'" href="#" data-bucket="'+b.Name+'"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> '+b.Name+'</span><span class="spinner"></span></span></a></li>')}),i.scrollToSelected(),i.disabledButtons())):i.showError(as3cf.strings.get_buckets_error,b.error,"as3cf-bucket-select")}})},scrollToSelected:function(){if(a(".as3cf-bucket-list a.selected").length){var b=a("ul.as3cf-bucket-list li").first().position().top+150;a(".as3cf-bucket-list").animate({scrollTop:a("ul.as3cf-bucket-list li a.selected").position().top-b})}},setSelected:function(c){a(".as3cf-bucket-list a").removeClass("selected"),c.addClass("selected"),a("#"+b.prefix+"-bucket-select-name").val(c.data("bucket"))},disabledButtons:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create"),d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual"),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select");0===c.length&&0===d.length&&0===e.length||(0<c.length&&this.isValidName(c.find(".as3cf-bucket-name").val())?c.find("button[type=submit]").prop("disabled",!1):c.find("button[type=submit]").prop("disabled",!0),0<d.length&&this.isValidName(d.find(".as3cf-bucket-name").val())?d.find("button[type=submit]").prop("disabled",!1):d.find("button[type=submit]").prop("disabled",!0),0<e.length&&1===e.find(".as3cf-bucket-list a.selected").length?e.find("button[type=submit]").prop("disabled",!1):e.find("button[type=submit]").prop("disabled",!0))},showError:function(b,c,d){var e=a(".as3cf-bucket-container").children(":visible"),f=e.find(".as3cf-bucket-error");d="undefined"==typeof d?null:d,d&&!e.hasClass(d)||(f.find("span.title").html(b+" &mdash;"),f.find("span.message").html(c),f.show(),this.bucketSelectLock=!1)},isValidName:function(a){return!(a.length<3||a.length>63)&&!0!==q.test(a)},updateNameNotice:function(b){var c=null;!0===q.test(b)?c=as3cf.strings.create_bucket_invalid_chars:b.length<3?c=as3cf.strings.create_bucket_name_short:b.length>63&&(c=as3cf.strings.create_bucket_name_long),c&&b.length>0?a(".as3cf-invalid-bucket-name").html(c):a(".as3cf-invalid-bucket-name").html("")}},as3cf.reloadUpdated=function(){var a=location.pathname+location.search;location.search.match(/[?&]updated=/)||(a+="&updated=1"),a+=location.hash,location.assign(a)},as3cf.showSettingsSavedNotice=function(){if(!(0<a("#setting-error-settings_updated:visible").length||0<a("#as3cf-settings_updated:visible").length)){var b='<div id="as3cf-settings_updated" class="updated settings-error notice is-dismissible"><p><strong>'+as3cf.strings.settings_saved+"</strong></p></div>";a("h2.nav-tab-wrapper").after(b),a(document).trigger("wp-updates-notice-added")}},as3cf.Settings=as3cf.Settings?as3cf.Settings:{},as3cf.Settings.Media={lock:function(b){a("#as3cf-media-settings-locked-"+b).show(),a(".as3cf-media-settings").addClass("locked locked-"+b),a(".as3cf-media-settings.locked-"+b).each(function(){a(this).find("input,button").prop("disabled",!0),a(this).find(".as3cf-settings-container").addClass("as3cf-locked-setting"),a(this).find("a.as3cf-change-settings").hide()})},unlock:function(b){a(".as3cf-media-settings.locked-"+b).each(function(){a(this).find("input,button").filter(":not(.disabled)").prop("disabled",!1),a(this).find(".as3cf-settings-container").removeClass("as3cf-locked-setting"),a(this).find("a.as3cf-change-settings").show(),a(this).removeClass("locked locked-"+b)}),a("#as3cf-media-settings-locked-"+b).hide()}},a(document).ready(function(){n(),window.onhashchange=function(a){"function"==typeof history.replaceState&&"#"===location.href.slice(-1)&&history.replaceState({},"",location.href.slice(0,-1)),n()};var l=a(".as3cf-main .nav-tab-wrapper");a(".as3cf-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(l),s.length&&s.each(function(a,b){p[b.id]=c(b.id)}),a(window).on("beforeunload.as3cf-settings",function(){if(!a.isEmptyObject(p)){var b=o.attr("id");return c(b)!==p[b]?as3cf.strings.save_alert:void 0}}),a(document).on("submit",".as3cf-main-settings form",function(b){a(window).off("beforeunload.as3cf-settings")}),a(".as3cf-switch").on("click",function(b){a(this).hasClass("disabled")||a(this).parents().hasClass("locked")||d(a(this).attr("id"))}),s.on("change",".sub-toggle",function(b){var c=a(this).attr("id");a(".as3cf-setting."+c).toggleClass("hide")}),a(".url-preview").on("change","input",function(a){m()}),j(),a("#as3cf-serve-from-s3,#as3cf-remove-local-file").on("change",function(a){j()}),k(),a("#as3cf-remove-local-file").on("change",function(a){k()}),a('.as3cf-setting input[type="text"]').keypress(function(a){if(13===a.which)return a.preventDefault(),!1}),a(".as3cf-enable-delivery-domain-container").on("change",'input[type="checkbox"]',function(b){var c=a(this).is(":checked"),d=a(this).parents(".as3cf-enable-delivery-domain-container").find(".as3cf-setting.as3cf-delivery-domain");d.toggleClass("hide",!c);var e=a(this).parents(".as3cf-enable-delivery-domain-container").siblings(".as3cf-enable-signed-urls-container");e.toggleClass("hide",!c)}),a('input[name="enable-delivery-domain"]').on("change",function(b){var c=a(this),d=a("#"+o.attr("id")+' form button[type="submit"]');"1"!==c.val()?d.prop("disabled",!1):e(c.next(".as3cf-setting").find('input[name="delivery-domain"]'))}),a('input[name="delivery-domain"]').on("keyup",function(b){e(a(this))}),a(".as3cf-enable-signed-urls-container").on("change",'input[type="checkbox"]',function(b){var c=a(this).is(":checked"),d=a(this).parents(".as3cf-enable-signed-urls-container").find(".as3cf-setting.as3cf-signed-urls");d.toggleClass("hide",!c)}),a('input[name="signed-urls-key-id"]').on("keyup",function(b){f(a(this))}),a('input[name="enable-signed-urls-key-id"]').on("change",function(b){var c=a(this),d=a("#"+o.attr("id")+' form button[type="submit"]');"1"!==c.val()?d.prop("disabled",!1):f(c.next(".as3cf-setting").find('input[name="signed-urls-key-id"]'))}),a('input[name="signed-urls-key-file-path"]').on("keyup",function(b){g(a(this))}),a('input[name="enable-signed-urls-key-file-path"]').on("change",function(b){var c=a(this),d=a("#"+o.attr("id")+' form button[type="submit"]');"1"!==c.val()?d.prop("disabled",!1):g(c.next(".as3cf-setting").find('input[name="signed-urls-key-file-path"]'))}),a('input[name="signed-urls-object-prefix"]').on("keyup",function(b){h(a(this))}),a('input[name="enable-signed-urls-object-prefix"]').on("change",function(b){var c=a(this),d=a("#"+o.attr("id")+' form button[type="submit"]');"1"!==c.val()?d.prop("disabled",!1):h(c.next(".as3cf-setting").find('input[name="signed-urls-object-prefix"]'))}),a('input[name="object-prefix"]').on("change",function(a){i()}),a("#tab-media > .as3cf-bucket-error").detach().insertAfter(".as3cf-bucket-container h3"),as3cf.buckets.disabledButtons(),r.on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),r.on("change",".bucket-select-region",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),0<a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").length&&as3cf.buckets.loadList(!0),r.on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.setSelected(a(this)),as3cf.buckets.disabledButtons()}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),r.on("input keyup",".as3cf-bucket-create .as3cf-bucket-name",function(b){var c=a(this).val();as3cf.buckets.updateNameNotice(c),as3cf.buckets.disabledButtons()}),r.on("input keyup",".as3cf-bucket-manual .as3cf-bucket-name",function(b){var c=a(this).val();as3cf.buckets.updateNameNotice(c),as3cf.buckets.disabledButtons()}),a('.as3cf-bucket-container input[type="text"]').keypress(function(a){if(13===a.which)return a.preventDefault(),!1}),a(".as3cf-change-bucket-access-prompt").on("change","#origin-access-identity-confirmation",function(b){a("#block-public-access-confirmed").prop("disabled",!a(this).prop("checked"))}),a(".as3cf-media-settings.locked.locked-upgrade").each(function(){as3cf.Settings.Media.lock("upgrade")})})}(jQuery,as3cfModal);
assets/sass/delivery-provider.scss ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .as3cf-delivery-provider-select {
2
+ .as3cf-delivery-provider-select-options {
3
+ margin-bottom: 30px;
4
+
5
+ .as3cf-delivery-provider-sub-option {
6
+ margin-left: 25px;
7
+
8
+ .as3cf-setting {
9
+ display: none;
10
+ margin-left: 25px;
11
+ }
12
+
13
+ &.selected {
14
+ .as3cf-setting {
15
+ display: block;
16
+ }
17
+ }
18
+ }
19
+
20
+ .as3cf-delivery-provider-sub-option-container > .as3cf-delivery-provider-sub-option {
21
+ display: none;
22
+ }
23
+
24
+ .as3cf-delivery-provider-sub-option-container.selected > .as3cf-delivery-provider-sub-option {
25
+ display: block;
26
+ }
27
+ }
28
+ }
assets/sass/media.scss CHANGED
@@ -1,6 +1,98 @@
1
  body.as3cf-pro {
 
 
 
 
2
  .attachments-browser .media-toolbar-secondary {
3
  max-width: 100%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  }
5
  }
6
 
@@ -23,4 +115,4 @@ body.as3cf-pro {
23
  .attachment-info .attachment-s3-details {
24
  font-weight: bold;
25
  margin-bottom: 5px;
26
- }
1
  body.as3cf-pro {
2
+ .media-toolbar-mode-select {
3
+ overflow: visible;
4
+ }
5
+
6
  .attachments-browser .media-toolbar-secondary {
7
  max-width: 100%;
8
+
9
+ .offload-buttons {
10
+ margin-right: 10px;
11
+ position: relative;
12
+ display: none !important;
13
+
14
+ &.visible {
15
+ display: inline-block !important;
16
+ }
17
+
18
+ .button {
19
+ margin: 0;
20
+ text-align: left;
21
+
22
+ @media screen and (max-width: 782px) {
23
+ min-height: 40px;
24
+ }
25
+ }
26
+ }
27
+
28
+ .offload-buttons__action-default {
29
+ width: calc(100% - 32px);
30
+ position: relative;
31
+ z-index: 2;
32
+ }
33
+
34
+ .offload-buttons__toggle {
35
+ width: 32px;
36
+ position: relative;
37
+ border-left: 1px solid rgba(255, 255, 255, 0.2);
38
+ z-index: 2;
39
+
40
+ &:focus {
41
+ box-shadow: none;
42
+ }
43
+
44
+ &::after {
45
+ content: '';
46
+ display: inline-block;
47
+ width: 0;
48
+ height: 0;
49
+ vertical-align: 0.255em;
50
+ border-top: 0.3em solid;
51
+ border-right: 0.3em solid transparent;
52
+ border-bottom: 0;
53
+ border-left: 0.3em solid transparent;
54
+ transition: 0.2s all ease;
55
+ }
56
+
57
+ &.opened {
58
+ &::after {
59
+ transform: rotate(180deg);
60
+ }
61
+ }
62
+ }
63
+
64
+ .offload-buttons__submenu {
65
+ position: absolute;
66
+ left: 0;
67
+ top: 0;
68
+ z-index: 1;
69
+ transform: translateY(33px);
70
+ border-radius: 3px;
71
+ overflow: hidden;
72
+ box-shadow: 0 2px 5px 2px rgba(0, 0, 0, 0.3);
73
+
74
+ @media screen and (max-width: 782px) {
75
+ transform: translateY(41px);
76
+ }
77
+ }
78
+
79
+ .offload-buttons__action {
80
+ display: block;
81
+ width: 100%;
82
+ margin: 0;
83
+ border-radius: 0;
84
+ text-align-last: left;
85
+ border: none;
86
+ border-bottom: 1px solid rgba(255, 255, 255, 0.2);
87
+
88
+ &:last-child {
89
+ border: none;
90
+ }
91
+
92
+ &:focus {
93
+ box-shadow: none;
94
+ }
95
+ }
96
  }
97
  }
98
 
115
  .attachment-info .attachment-s3-details {
116
  font-weight: bold;
117
  margin-bottom: 5px;
118
+ }
assets/sass/styles.scss CHANGED
@@ -78,10 +78,12 @@ $as3cf_assets: #0769ad;
78
  .as3cf-notice, .error, .updated, .updated.show {
79
  display: none;
80
  }
 
81
  .fatal .error, .as3cf-notice.important, .dbrains-api-down {
82
  display: block;
83
  }
84
  }
 
85
  .as3cf-notice, .error, .updated {
86
  max-width: 650px;
87
  margin-top: 15px;
@@ -90,6 +92,7 @@ $as3cf_assets: #0769ad;
90
 
91
  .as3cf-updated {
92
  display: none;
 
93
  &.as3cf-notice, &.show {
94
  display: block;
95
  }
@@ -106,27 +109,38 @@ $as3cf_assets: #0769ad;
106
  }
107
 
108
  /**
109
- * Show Storage Provider / Bucket Select / media Settings
110
  */
111
  .as3cf-tab {
 
112
  .as3cf-main-settings {
113
  .as3cf-provider-select {
114
  display: none;
115
  }
116
 
117
- .as3cf-bucket-container {
 
118
  display: none;
119
 
120
- a.as3cf-change-provider {
121
- display: none;
122
  }
123
  }
124
 
 
 
 
 
 
 
 
 
125
  .as3cf-media-settings {
126
  display: none;
127
  }
128
  }
129
 
 
130
  &.as3cf-needs-access-keys, &.as3cf-has-access-keys.as3cf-change-provider {
131
  .as3cf-can-write-error {
132
  display: none;
@@ -141,12 +155,21 @@ $as3cf_assets: #0769ad;
141
  display: none;
142
  }
143
 
 
 
 
 
 
 
 
 
144
  .as3cf-media-settings {
145
  display: none;
146
  }
147
  }
148
  }
149
 
 
150
  &.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider), &.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) {
151
  .as3cf-can-write-error {
152
  display: none;
@@ -161,13 +184,55 @@ $as3cf_assets: #0769ad;
161
  display: block;
162
  }
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  .as3cf-media-settings {
165
  display: none;
166
  }
167
  }
168
  }
169
 
170
- &.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket) {
 
 
 
 
 
171
  .as3cf-main-settings {
172
  .as3cf-provider-select {
173
  display: none;
@@ -177,6 +242,39 @@ $as3cf_assets: #0769ad;
177
  display: none;
178
  }
179
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  .as3cf-media-settings {
181
  display: block;
182
  }
@@ -210,6 +308,7 @@ $as3cf_assets: #0769ad;
210
  .as3cf-main-settings {
211
  p {
212
  font-size: 13px;
 
213
  a {
214
  color: #444;
215
  }
@@ -235,6 +334,7 @@ $as3cf_assets: #0769ad;
235
  padding: 0 20px 10px;
236
  overflow-x: scroll;
237
  }
 
238
  span {
239
  color: #aaa;
240
  text-transform: uppercase;
@@ -246,6 +346,7 @@ $as3cf_assets: #0769ad;
246
  label {
247
  display: block;
248
  margin-bottom: 10px;
 
249
  &.disabled, &.disabled p {
250
  color: #bbb;
251
  cursor: default;
@@ -257,6 +358,7 @@ $as3cf_assets: #0769ad;
257
  color: #6b6b6b;
258
  margin: 0;
259
  font-size: 12px;
 
260
  &.as3cf-setting {
261
  margin-top: 5px;
262
  }
@@ -324,6 +426,16 @@ $as3cf_assets: #0769ad;
324
  &.hide {
325
  display: none;
326
  }
 
 
 
 
 
 
 
 
 
 
327
  }
328
 
329
  div.as3cf-setting {
@@ -343,18 +455,27 @@ $as3cf_assets: #0769ad;
343
  border-bottom: 1px solid #ddd;
344
  padding: 20px 0px;
345
  }
 
346
  &.as3cf-setting-title td {
347
  padding-bottom: 0;
348
  }
 
349
  &.as3cf-setting-title:first-child td {
350
  padding-top: 20px;
351
  }
 
352
  &.configure-url:first-child td {
353
  padding-top: 5px;
354
  padding-bottom: 0;
355
  }
 
 
 
 
 
356
  td {
357
  padding: 15px 0;
 
358
  &:first-child {
359
  vertical-align: top;
360
  min-width: 120px;
@@ -375,6 +496,7 @@ $as3cf_assets: #0769ad;
375
  padding: 0;
376
  margin: 0;
377
  }
 
378
  h4 {
379
  margin: 0;
380
  }
@@ -388,12 +510,15 @@ $as3cf_assets: #0769ad;
388
  color: #444;
389
  text-decoration: none;
390
  margin-right: 10px;
 
391
  &:hover, &:active {
392
  color: #00a0d2;
393
  }
 
394
  &:focus {
395
  box-shadow: none;
396
  }
 
397
  .dashicons-external {
398
  margin-top: -2px;
399
  }
@@ -463,12 +588,13 @@ $as3cf_assets: #0769ad;
463
  background: #ccc;
464
  color: #fff;
465
  padding: 2px 5px;
466
- margin: 0 0 5px 5px;
467
  float: right;
468
  white-space: nowrap;
 
469
  }
470
 
471
- .as3cf-defined-setting {
472
  color: #bbb;
473
 
474
  label {
@@ -489,21 +615,50 @@ $as3cf_assets: #0769ad;
489
  }
490
 
491
  p.actions {
492
- margin: 20px -30px -30px;
493
- padding: 20px 30px;
494
- border-top: none;
 
495
  overflow: hidden;
496
 
 
497
  .right {
 
498
  margin-left: 15px;
 
 
499
 
500
  &:last-of-type {
501
  margin-left: 0;
502
  }
503
  }
504
 
505
- button {
506
- min-width: 90px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
507
  }
508
  }
509
  }
@@ -555,9 +710,11 @@ $as3cf_assets: #0769ad;
555
  margin: 0;
556
  }
557
  }
 
558
  .as3cf-bucket-list {
559
  margin: 5px 0 0 0;
560
  }
 
561
  td {
562
  padding: 5px 0;
563
 
@@ -566,10 +723,14 @@ $as3cf_assets: #0769ad;
566
  line-height: 30px;
567
  vertical-align: top;
568
  }
 
 
 
 
569
  }
570
  }
571
 
572
- .bucket-actions {
573
  margin: 15px 0;
574
  border-top: 1px solid #ccc;
575
  padding-top: 15px;
@@ -586,7 +747,7 @@ $as3cf_assets: #0769ad;
586
  margin-right: 20px;
587
  line-height: 28px;
588
  }
589
- }
590
 
591
  .as3cf-bucket-list {
592
  padding: 15px;
@@ -620,12 +781,45 @@ $as3cf_assets: #0769ad;
620
  }
621
  }
622
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
623
  #tab-media {
624
  display: block;
625
  }
626
 
627
  #tab-support {
628
  min-height: 900px;
 
629
  .as3cf-sidebar {
630
  top: 11px;
631
  }
@@ -962,6 +1156,7 @@ textarea.as3cf-access-key-constants-snippet.code {
962
 
963
  .extra {
964
  background: white;
 
965
  a {
966
  color: $as3cf_assets;
967
  text-decoration: none;
78
  .as3cf-notice, .error, .updated, .updated.show {
79
  display: none;
80
  }
81
+
82
  .fatal .error, .as3cf-notice.important, .dbrains-api-down {
83
  display: block;
84
  }
85
  }
86
+
87
  .as3cf-notice, .error, .updated {
88
  max-width: 650px;
89
  margin-top: 15px;
92
 
93
  .as3cf-updated {
94
  display: none;
95
+
96
  &.as3cf-notice, &.show {
97
  display: block;
98
  }
109
  }
110
 
111
  /**
112
+ * Show Storage Provider / Bucket Select / Delivery Provider Select / media Settings
113
  */
114
  .as3cf-tab {
115
+ /* Initial State: Show Nothing (overridden below) */
116
  .as3cf-main-settings {
117
  .as3cf-provider-select {
118
  display: none;
119
  }
120
 
121
+ .as3cf-bucket-container,
122
+ .as3cf-change-bucket-access-prompt {
123
  display: none;
124
 
125
+ h3 {
126
+ margin-bottom: -0.5em;
127
  }
128
  }
129
 
130
+ a.as3cf-change-provider {
131
+ display: none;
132
+ }
133
+
134
+ .as3cf-delivery-provider-select {
135
+ display: none;
136
+ }
137
+
138
  .as3cf-media-settings {
139
  display: none;
140
  }
141
  }
142
 
143
+ /* Need/Change Storage Provider */
144
  &.as3cf-needs-access-keys, &.as3cf-has-access-keys.as3cf-change-provider {
145
  .as3cf-can-write-error {
146
  display: none;
155
  display: none;
156
  }
157
 
158
+ .as3cf-change-bucket-access-prompt {
159
+ display: none;
160
+ }
161
+
162
+ .as3cf-delivery-provider-select {
163
+ display: none;
164
+ }
165
+
166
  .as3cf-media-settings {
167
  display: none;
168
  }
169
  }
170
  }
171
 
172
+ /* Need/Change Bucket */
173
  &.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider), &.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) {
174
  .as3cf-can-write-error {
175
  display: none;
184
  display: block;
185
  }
186
 
187
+ .as3cf-change-bucket-access-prompt {
188
+ display: none;
189
+ }
190
+
191
+ .as3cf-delivery-provider-select {
192
+ display: none;
193
+ }
194
+
195
+ .as3cf-media-settings {
196
+ display: none;
197
+ }
198
+ }
199
+ }
200
+
201
+ /* Change Bucket Access */
202
+ &.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access {
203
+ .as3cf-can-write-error {
204
+ display: none;
205
+ }
206
+
207
+ .as3cf-main-settings {
208
+ .as3cf-provider-select {
209
+ display: none;
210
+ }
211
+
212
+ .as3cf-bucket-container {
213
+ display: none;
214
+ }
215
+
216
+ .as3cf-change-bucket-access-prompt {
217
+ display: block;
218
+ }
219
+
220
+ .as3cf-delivery-provider-select {
221
+ display: none;
222
+ }
223
+
224
  .as3cf-media-settings {
225
  display: none;
226
  }
227
  }
228
  }
229
 
230
+ /* Change Delivery Provider */
231
+ &.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider {
232
+ .as3cf-can-write-error {
233
+ display: none;
234
+ }
235
+
236
  .as3cf-main-settings {
237
  .as3cf-provider-select {
238
  display: none;
242
  display: none;
243
  }
244
 
245
+ .as3cf-change-bucket-access-prompt {
246
+ display: none;
247
+ }
248
+
249
+ .as3cf-delivery-provider-select {
250
+ display: block;
251
+ }
252
+
253
+ .as3cf-media-settings {
254
+ display: none;
255
+ }
256
+ }
257
+ }
258
+
259
+ /* Normal Media Settings */
260
+ &.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) {
261
+ .as3cf-main-settings {
262
+ .as3cf-provider-select {
263
+ display: none;
264
+ }
265
+
266
+ .as3cf-bucket-container {
267
+ display: none;
268
+ }
269
+
270
+ .as3cf-change-bucket-access-prompt {
271
+ display: none;
272
+ }
273
+
274
+ .as3cf-delivery-provider-select {
275
+ display: none;
276
+ }
277
+
278
  .as3cf-media-settings {
279
  display: block;
280
  }
308
  .as3cf-main-settings {
309
  p {
310
  font-size: 13px;
311
+
312
  a {
313
  color: #444;
314
  }
334
  padding: 0 20px 10px;
335
  overflow-x: scroll;
336
  }
337
+
338
  span {
339
  color: #aaa;
340
  text-transform: uppercase;
346
  label {
347
  display: block;
348
  margin-bottom: 10px;
349
+
350
  &.disabled, &.disabled p {
351
  color: #bbb;
352
  cursor: default;
358
  color: #6b6b6b;
359
  margin: 0;
360
  font-size: 12px;
361
+
362
  &.as3cf-setting {
363
  margin-top: 5px;
364
  }
426
  &.hide {
427
  display: none;
428
  }
429
+
430
+ .as3cf-sub-setting {
431
+ .as3cf-sub-setting-heading {
432
+ padding-top: 15px;
433
+ }
434
+
435
+ .as3cf-defined-in-config {
436
+ margin-top: 15px;
437
+ }
438
+ }
439
  }
440
 
441
  div.as3cf-setting {
455
  border-bottom: 1px solid #ddd;
456
  padding: 20px 0px;
457
  }
458
+
459
  &.as3cf-setting-title td {
460
  padding-bottom: 0;
461
  }
462
+
463
  &.as3cf-setting-title:first-child td {
464
  padding-top: 20px;
465
  }
466
+
467
  &.configure-url:first-child td {
468
  padding-top: 5px;
469
  padding-bottom: 0;
470
  }
471
+
472
+ &.hide {
473
+ display: none;
474
+ }
475
+
476
  td {
477
  padding: 15px 0;
478
+
479
  &:first-child {
480
  vertical-align: top;
481
  min-width: 120px;
496
  padding: 0;
497
  margin: 0;
498
  }
499
+
500
  h4 {
501
  margin: 0;
502
  }
510
  color: #444;
511
  text-decoration: none;
512
  margin-right: 10px;
513
+
514
  &:hover, &:active {
515
  color: #00a0d2;
516
  }
517
+
518
  &:focus {
519
  box-shadow: none;
520
  }
521
+
522
  .dashicons-external {
523
  margin-top: -2px;
524
  }
588
  background: #ccc;
589
  color: #fff;
590
  padding: 2px 5px;
591
+ margin: 0 0 3px 5px;
592
  float: right;
593
  white-space: nowrap;
594
+ clear: right;
595
  }
596
 
597
+ .as3cf-defined-setting, .as3cf-locked-setting {
598
  color: #bbb;
599
 
600
  label {
615
  }
616
 
617
  p.actions {
618
+ margin: 30px 0;
619
+ border-top: 1px solid #ccc;
620
+ //padding: 20px 30px;
621
+ padding-top: 15px;
622
  overflow: hidden;
623
 
624
+ button,
625
  .right {
626
+ float: right;
627
  margin-left: 15px;
628
+ margin-right: 0;
629
+ min-width: 90px;
630
 
631
  &:last-of-type {
632
  margin-left: 0;
633
  }
634
  }
635
 
636
+ span {
637
+ display: inline-block;
638
+ margin-right: 20px;
639
+ line-height: 28px;
640
+ }
641
+ }
642
+
643
+ /**
644
+ * When entire tab's settings are locked.
645
+ */
646
+ .locked {
647
+ .as3cf-radio-group {
648
+ label, label p {
649
+ color: #bbb;
650
+ cursor: default;
651
+ }
652
+ }
653
+
654
+ .as3cf-switch {
655
+ cursor: default;
656
+ background: #e6e6e6;
657
+
658
+ span {
659
+ background: #f1f1f1;
660
+ color: #d6d6d6;
661
+ }
662
  }
663
  }
664
  }
710
  margin: 0;
711
  }
712
  }
713
+
714
  .as3cf-bucket-list {
715
  margin: 5px 0 0 0;
716
  }
717
+
718
  td {
719
  padding: 5px 0;
720
 
723
  line-height: 30px;
724
  vertical-align: top;
725
  }
726
+
727
+ .as3cf-defined-in-config {
728
+ margin-top: -1.75em;
729
+ }
730
  }
731
  }
732
 
733
+ /*.bucket-actions {
734
  margin: 15px 0;
735
  border-top: 1px solid #ccc;
736
  padding-top: 15px;
747
  margin-right: 20px;
748
  line-height: 28px;
749
  }
750
+ }*/
751
 
752
  .as3cf-bucket-list {
753
  padding: 15px;
781
  }
782
  }
783
 
784
+ /**
785
+ * Change Bucket Access
786
+ */
787
+ .as3cf-change-bucket-access-prompt {
788
+ h3 {
789
+ line-height: 1.3;
790
+ text-transform: none;
791
+ }
792
+
793
+ .as3cf-radio-group {
794
+ margin-bottom: 25px;
795
+ }
796
+
797
+ .note {
798
+ color: #999;
799
+ }
800
+ }
801
+
802
+ /**
803
+ * Change Delivery Provider
804
+ */
805
+ .as3cf-delivery-provider-select {
806
+ h3 {
807
+ line-height: 1.3;
808
+ text-transform: none;
809
+ }
810
+
811
+ .note {
812
+ color: #999;
813
+ }
814
+ }
815
+
816
  #tab-media {
817
  display: block;
818
  }
819
 
820
  #tab-support {
821
  min-height: 900px;
822
+
823
  .as3cf-sidebar {
824
  top: 11px;
825
  }
1156
 
1157
  .extra {
1158
  background: white;
1159
+
1160
  a {
1161
  color: $as3cf_assets;
1162
  text-decoration: none;
classes/amazon-s3-and-cloudfront.php CHANGED
@@ -1,11 +1,23 @@
1
  <?php
2
 
3
  use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
4
- use DeliciousBrains\WP_Offload_Media\Providers\AWS_Provider;
5
- use DeliciousBrains\WP_Offload_Media\Providers\DigitalOcean_Provider;
6
- use DeliciousBrains\WP_Offload_Media\Providers\GCP_Provider;
7
- use DeliciousBrains\WP_Offload_Media\Providers\Null_Provider;
 
 
 
 
 
 
8
  use DeliciousBrains\WP_Offload_Media\Providers\Provider;
 
 
 
 
 
 
9
  use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_Content_Replace_URLs;
10
  use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_EDD_Replace_URLs;
11
  use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_File_Sizes;
@@ -18,12 +30,12 @@ use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_WPOS3_To_AS3CF;
18
  class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
19
 
20
  /**
21
- * @var Provider
22
  */
23
- private $provider;
24
 
25
  /**
26
- * @var Provider
27
  */
28
  private $provider_client;
29
 
@@ -32,6 +44,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
32
  */
33
  private $provider_client_region;
34
 
 
 
 
 
 
35
  /**
36
  * @var array
37
  */
@@ -85,12 +102,22 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
85
  /**
86
  * @var string
87
  */
88
- protected static $default_provider = 'aws';
 
 
 
 
 
 
 
 
 
 
89
 
90
  /**
91
- * @var array Known provider classes.
92
  */
93
- protected static $provider_classes = array();
94
 
95
  /**
96
  * @var AS3CF_Plugin_Compatibility
@@ -138,15 +165,30 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
138
  $this->plugin_title = __( 'Offload Media Lite', 'amazon-s3-and-cloudfront' );
139
  $this->plugin_menu_title = __( 'Offload Media Lite', 'amazon-s3-and-cloudfront' );
140
 
141
- static::$provider_classes = array(
142
- AWS_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\AWS_Provider',
143
- DigitalOcean_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\DigitalOcean_Provider',
144
- GCP_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\GCP_Provider',
145
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
  Media_Library_Item::init_cache();
148
 
149
- $this->set_provider();
 
150
 
151
  // Bundled SDK may require AWS setup before data migrations.
152
  $this->handle_aws_access_key_migration();
@@ -184,6 +226,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
184
 
185
  // Rewriting URLs, doesn't depend on plugin being setup
186
  add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 99, 2 );
 
187
  add_filter( 'get_image_tag', array( $this, 'maybe_encode_get_image_tag' ), 99, 6 );
188
  add_filter( 'wp_get_attachment_image_src', array( $this, 'maybe_encode_wp_get_attachment_image_src' ), 99, 4 );
189
  add_filter( 'wp_prepare_attachment_for_js', array( $this, 'maybe_encode_wp_prepare_attachment_for_js', ), 99, 3 );
@@ -217,50 +260,114 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
217
 
218
  // Register storage provider scripts and styles
219
  $this->register_storage_provider_assets();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  }
221
 
222
  /**
223
- * @return Provider
224
  */
225
- public function get_provider() {
226
- return $this->provider;
227
  }
228
 
229
  /**
230
- * @param Provider|string|null $provider
231
  *
232
  * @throws Exception
233
  */
234
- public function set_provider( $provider = null ) {
235
- if ( empty( $provider ) ) {
236
- $provider = $this->get_core_setting( 'provider', static::$default_provider );
 
 
 
 
 
237
  }
238
 
239
- if ( is_string( $provider ) ) {
240
- $provider = new self::$provider_classes[ $provider ]( $this );
241
  }
242
 
243
- $this->provider = $provider;
 
 
 
 
 
244
  }
245
 
246
  /**
247
  * Returns the currently supported Providers.
248
  *
 
 
249
  * @return array
250
  */
251
- public function get_provider_classes() {
252
- return self::$provider_classes;
 
 
 
 
 
 
 
 
 
 
 
253
  }
254
 
255
  /**
256
  * Returns provider class name for given key.
257
  *
258
  * @param string $key_name
 
259
  *
260
- * @return mixed|null
261
  */
262
- public function get_provider_class( $key_name ) {
263
- $classes = $this->get_provider_classes();
 
 
 
264
 
265
  return empty( $classes[ $key_name ] ) ? null : $classes[ $key_name ];
266
  }
@@ -269,12 +376,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
269
  * Provider name for given key.
270
  *
271
  * @param string $key_name
 
272
  *
273
  * @return string
274
  */
275
- public function get_provider_name( $key_name ) {
276
- /** @var Provider $class */
277
- $class = $this->get_provider_class( $key_name );
 
 
278
 
279
  return empty( $class ) ? __( 'Unknown', 'amazon-s3-and-cloudfront' ) : $class::get_provider_name();
280
  }
@@ -283,12 +393,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
283
  * Provider & Service name for given key.
284
  *
285
  * @param string $key_name
 
286
  *
287
  * @return string
288
  */
289
- public function get_provider_service_name( $key_name ) {
290
- /** @var Provider $class */
291
- $class = $this->get_provider_class( $key_name );
 
 
292
 
293
  return empty( $class ) ? __( 'Unknown', 'amazon-s3-and-cloudfront' ) : $class::get_provider_service_name();
294
  }
@@ -352,7 +465,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
352
  'key' => $key,
353
  'disabled' => false,
354
  'disabled_attr' => '',
355
- 'tr_class' => str_replace( '_', '-', $this->get_plugin_prefix() . '-' . $key . '-container' ),
356
  'setting_msg' => '',
357
  'is_defined' => false,
358
  );
@@ -520,6 +633,52 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
520
  return $aws_secret_access_key;
521
  }
522
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
523
  $value = parent::get_setting( $key, $default );
524
 
525
  // Provider
@@ -532,6 +691,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
532
  return $bucket;
533
  }
534
 
 
 
 
 
 
535
  return apply_filters( 'as3cf_setting_' . $key, $value );
536
  }
537
 
@@ -589,14 +753,14 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
589
 
590
  // Region of bucket translation
591
  if ( 'region' === $key && isset( $settings['region'] ) ) {
592
- return $this->get_provider()->sanitize_region( $settings['region'] );
593
  }
594
 
595
  return false;
596
  }
597
 
598
  /**
599
- * Get the bucket and if a constant save to database and clear region
600
  *
601
  * @param string $key
602
  * @param string $value
@@ -646,9 +810,58 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
646
  */
647
  public function bucket_changed() {
648
  $this->remove_setting( 'region' );
 
649
  $this->save_settings();
650
  }
651
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
652
  /**
653
  * Filter in defined settings with sensible defaults.
654
  *
@@ -734,10 +947,18 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
734
  $defined_settings = ! empty( $defined_settings ) ? $defined_settings : $this->get_defined_settings();
735
  $whitelisted_settings = $this->get_settings_whitelist();
736
  $settings_to_skip = array(
 
 
 
 
 
737
  'bucket',
738
  'region',
739
- 'permissions',
 
740
  'virtual-host',
 
 
741
  );
742
 
743
  foreach ( $whitelisted_settings as $setting ) {
@@ -745,16 +966,41 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
745
  continue;
746
  }
747
 
748
- if ( 'object-prefix' === $setting ) {
749
- if ( isset( $defined_settings['enable-object-prefix'] ) && '0' === $defined_settings['enable-object-prefix'] ) {
750
- continue;
751
- }
 
 
752
  }
753
 
754
- if ( 'cloudfront' === $setting ) {
755
- if ( isset( $defined_settings['domain'] ) && 'cloudfront' !== $defined_settings['domain'] ) {
756
- continue;
757
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
758
  }
759
 
760
  if ( ! isset( $defined_settings[ $setting ] ) ) {
@@ -867,17 +1113,21 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
867
  * @return string
868
  */
869
  function get_url_preview( $escape = true, $suffix = 'photo.jpg' ) {
870
- $scheme = $this->get_url_scheme();
871
- $bucket = $this->get_setting( 'bucket' );
872
- $path = $this->maybe_update_cloudfront_path( $this->get_file_prefix() );
873
- $region = $this->get_setting( 'region' );
874
- if ( is_wp_error( $region ) ) {
875
- $region = '';
876
- }
 
 
877
 
878
- $domain = $this->get_provider()->get_url_domain( $bucket, $region, null, array(), true );
879
 
880
- $url = $scheme . '://' . $domain . '/' . $path . $suffix;
 
 
881
 
882
  // Replace hyphens with non breaking hyphens for formatting
883
  if ( $escape ) {
@@ -982,9 +1232,10 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
982
  * to cope with possible different regions
983
  */
984
  function remove_attachment_files_from_provider( $post_id, Media_Library_Item $as3cf_item, $include_backups = true, $log_error = false, $return_on_error = false, $force_new_provider_client = false ) {
985
- $prefix = $as3cf_item->normalized_path_dir();
986
- $paths = AS3CF_Utils::get_attachment_file_paths( $post_id, false, false, $include_backups );
987
- $paths = apply_filters( 'as3cf_remove_attachment_paths', $paths, $post_id, $as3cf_item, $include_backups );
 
988
 
989
  // If another item in current site shares full size *local* paths, only remove remote files not referenced by duplicates.
990
  // We reference local paths as they should be reflected one way or another remotely, including backups.
@@ -1009,9 +1260,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1009
 
1010
  $objects_to_remove = array();
1011
 
1012
- foreach ( $paths as $path ) {
1013
  $objects_to_remove[] = array(
1014
- 'Key' => $prefix . wp_basename( $path ),
1015
  );
1016
  }
1017
 
@@ -1178,7 +1429,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1178
  $post_id,
1179
  $duplicate_item->source_path(),
1180
  wp_basename( $duplicate_item->original_source_path() ),
1181
- $duplicate_item->private_sizes()
1182
  );
1183
 
1184
  $old_item->save();
@@ -1235,7 +1486,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1235
  return $this->return_upload_error( $error_msg, $return_metadata );
1236
  }
1237
 
1238
- $acl = $this->get_provider()->get_default_acl();
1239
 
1240
  // check the attachment already exists in provider, eg. edit or restore image
1241
  if ( $old_item ) {
@@ -1246,11 +1497,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1246
 
1247
  // Use private ACL if existing offload is already private.
1248
  if ( $old_item->is_private() ) {
1249
- $acl = $this->get_provider()->get_private_acl();
1250
  }
1251
 
1252
  // use existing prefix
1253
  $prefix = $old_item->normalized_path_dir();
 
 
1254
  // use existing bucket
1255
  $bucket = $old_item->bucket();
1256
  // get existing region
@@ -1259,8 +1512,14 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1259
  $original_filename = wp_basename( $old_item->original_source_path() );
1260
  } else {
1261
  // derive prefix from various settings
1262
- $time = $this->get_attachment_folder_year_month( $post_id, $data );
1263
- $prefix = $this->get_file_prefix( $time );
 
 
 
 
 
 
1264
 
1265
  // use bucket from settings
1266
  $bucket = $this->get_setting( 'bucket' );
@@ -1273,19 +1532,26 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1273
  $original_filename = empty( $data['original_image'] ) ? null : $data['original_image'];
1274
  }
1275
 
1276
- $acl = apply_filters( 'wps3_upload_acl', $acl, $type, $data, $post_id, $this ); // Old naming convention, will be deprecated soon
1277
- $acl = apply_filters( 'as3cf_upload_acl', $acl, $data, $post_id );
 
1278
 
1279
  $args = array(
1280
  'Bucket' => $bucket,
1281
  'Key' => $prefix . $file_name,
1282
  'SourceFile' => $file_path,
1283
- 'ACL' => $acl,
1284
  'ContentType' => $type,
1285
  'CacheControl' => 'max-age=31536000',
1286
  'Expires' => date( 'D, d M Y H:i:s O', time() + 31536000 ),
1287
  );
1288
 
 
 
 
 
 
 
 
1289
  // TODO: Remove GZIP functionality.
1290
  // Handle gzip on supported items
1291
  if ( $this->should_gzip_file( $file_path, $type ) && false !== ( $gzip_body = gzencode( file_get_contents( $file_path ) ) ) ) {
@@ -1295,18 +1561,26 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1295
  $args['ContentEncoding'] = 'gzip';
1296
  }
1297
 
1298
- $image_size = wp_attachment_is_image( $post_id ) ? 'full' : '';
1299
- $args = apply_filters( 'as3cf_object_meta', $args, $post_id, $image_size, false );
 
 
 
 
 
 
 
 
 
 
1300
 
1301
- $provider = $this->get_provider()->get_provider_key_name();
1302
- $region = $bucket !== $args['Bucket'] ? $this->get_bucket_region( $args['Bucket'], true ) : $region;
1303
- $is_private = $this->get_provider()->get_private_acl() === $args['ACL'] ? true : false;
1304
- $private_sizes = empty( $old_item ) ? array() : $old_item->private_sizes();
1305
- $item_id = empty( $old_item ) ? null : $old_item->id();
1306
 
1307
- $as3cf_item = new Media_Library_Item( $provider, $region, $args['Bucket'], $args['Key'], $is_private, $post_id, $file_path, $original_filename, $private_sizes, $item_id );
 
 
1308
 
1309
- do_action( 'as3cf_upload_attachment_pre_remove', $post_id, $as3cf_item, $prefix, $args );
1310
 
1311
  $new_offloads = array();
1312
  $files_to_remove = array();
@@ -1335,17 +1609,22 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1335
 
1336
  foreach ( $file_paths as $size => $file_path ) {
1337
  if ( ! in_array( $file_path, $files_to_remove ) ) {
1338
- $acl = apply_filters( 'as3cf_upload_acl_sizes', $this->get_provider()->get_default_acl(), $size, $post_id, $data );
1339
 
 
 
 
 
 
1340
  $additional_images[ $size ] = array(
1341
- 'Key' => $prefix . wp_basename( $file_path ),
1342
  'SourceFile' => $file_path,
1343
- 'ACL' => $acl,
1344
  'ContentType' => $this->get_mime_type( $file_path ),
1345
  );
1346
 
1347
- if ( $this->get_provider()->get_private_acl() === $acl ) {
1348
- $private_sizes[] = $size;
 
1349
  }
1350
  }
1351
  }
@@ -1360,6 +1639,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1360
 
1361
  $args = apply_filters( 'as3cf_object_meta', array_merge( $args, $image ), $post_id, $size, false );
1362
 
 
 
 
 
 
 
 
 
 
1363
  if ( ! file_exists( $args['SourceFile'] ) ) {
1364
  if ( ! $duplicate ) {
1365
  $upload_errors[] = $this->return_upload_error( sprintf( __( 'File %s does not exist', 'amazon-s3-and-cloudfront' ), $args['SourceFile'] ) );
@@ -1390,7 +1678,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1390
  $as3cf_item->source_id(),
1391
  $as3cf_item->source_path(),
1392
  wp_basename( $image['SourceFile'] ),
1393
- $as3cf_item->private_sizes(),
1394
  $as3cf_item->id()
1395
  );
1396
  }
@@ -1430,6 +1718,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1430
 
1431
  // Additional image sizes have custom ACLs, record them.
1432
  if ( ! empty( $private_sizes ) ) {
 
 
 
1433
  $as3cf_item = new Media_Library_Item(
1434
  $as3cf_item->provider(),
1435
  $as3cf_item->region(),
@@ -1439,7 +1730,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1439
  $as3cf_item->source_id(),
1440
  $as3cf_item->source_path(),
1441
  wp_basename( $as3cf_item->original_source_path() ),
1442
- $private_sizes,
1443
  $as3cf_item->id()
1444
  );
1445
  }
@@ -1875,7 +2166,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1875
  * TODO: Performance - cache / static var by param.
1876
  */
1877
  function is_plugin_setup( $with_credentials = false ) {
1878
- if ( $with_credentials && $this->get_provider()->needs_access_keys() ) {
1879
  // AWS not configured
1880
  return false;
1881
  }
@@ -1904,7 +2195,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1904
  * @param array $headers Header overrides for request
1905
  * @param bool $skip_rewrite_check
1906
  *
1907
- * @return mixed|WP_Error
1908
  */
1909
  public function get_secure_attachment_url( $post_id, $expires = null, $size = null, $headers = array(), $skip_rewrite_check = false ) {
1910
  if ( is_null( $expires ) ) {
@@ -1988,18 +2279,35 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1988
  }
1989
 
1990
  /**
1991
- * Get the url of the file from Amazon provider
1992
  *
1993
- * @param int $post_id Post ID of the attachment
1994
- * @param int|null $expires Seconds for the link to live
1995
- * @param string|null $size Size of the image to get
1996
- * @param array|null $meta Pre retrieved _wp_attachment_metadata for the attachment
1997
- * @param array $headers Header overrides for request
1998
- * @param bool $skip_rewrite_check Always return the URL regardless of the 'Rewrite File URLs' setting.
1999
- * Useful for the EDD and Woo addons to not break download URLs when the
2000
- * option is disabled.
2001
  *
2002
- * @return bool|mixed|WP_Error
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2003
  */
2004
  public function get_attachment_url( $post_id, $expires = null, $size = null, $meta = null, $headers = array(), $skip_rewrite_check = false ) {
2005
  if ( ! ( $as3cf_item = $this->is_attachment_served_by_provider( $post_id, $skip_rewrite_check ) ) ) {
@@ -2089,17 +2397,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2089
  * @return string|WP_Error
2090
  */
2091
  public function get_attachment_provider_url( $post_id, Media_Library_Item $as3cf_item, $expires = null, $size = null, $meta = null, $headers = array() ) {
2092
- $item_path = $as3cf_item->path();
2093
 
2094
- if ( ! empty( $as3cf_item->region() ) && ( $this->get_provider()->region_required() || $this->get_provider()->get_default_region() !== $as3cf_item->region() ) ) {
2095
- $region = $this->get_provider()->sanitize_region( $as3cf_item->region() );
2096
- } else {
2097
- $region = '';
2098
- }
2099
-
2100
- $size = $this->maybe_convert_size_to_string( $post_id, $size );
2101
-
2102
- // Force use of secured URL when ACL has been set to private
2103
  if ( is_null( $expires ) ) {
2104
  if ( is_null( $size ) && $as3cf_item->is_private() ) {
2105
  // Full size URL private
@@ -2112,6 +2412,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2112
  }
2113
  }
2114
 
 
 
2115
  if ( ! is_null( $size ) ) {
2116
  if ( is_null( $meta ) ) {
2117
  $meta = get_post_meta( $post_id, '_wp_attachment_metadata', true );
@@ -2129,32 +2431,40 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2129
  }
2130
  }
2131
 
2132
- $scheme = $this->get_url_scheme();
2133
- $domain = $this->get_provider()->get_url_domain( $as3cf_item->bucket(), $region, $expires );
2134
- $base_url = $scheme . '://' . $domain;
 
 
 
 
 
 
 
 
 
 
 
 
2135
 
2136
  if ( ! is_null( $expires ) && $this->is_plugin_setup( true ) ) {
2137
  try {
2138
- if ( $this->get_provider()->get_domain() !== $domain ) {
2139
- $headers['BaseURL'] = $base_url;
2140
- }
2141
 
2142
- $expires = time() + apply_filters( 'as3cf_expires', $expires );
2143
- $secure_url = $this->get_provider_client( $region )
2144
- ->get_object_url( $as3cf_item->bucket(), $item_path, $expires, $headers );
 
 
 
 
2145
 
2146
- return apply_filters( 'as3cf_get_attachment_secure_url', $secure_url, $as3cf_item, $post_id, $expires, $headers );
2147
  } catch ( Exception $e ) {
2148
  return new WP_Error( 'exception', $e->getMessage() );
2149
  }
2150
  }
2151
-
2152
- $item_path = $this->maybe_update_cloudfront_path( $item_path );
2153
-
2154
- $file = $this->encode_filename_in_path( $item_path );
2155
- $url = $base_url . '/' . $file;
2156
-
2157
- return apply_filters( 'as3cf_get_attachment_url', $url, $as3cf_item, $post_id, $expires, $headers );
2158
  }
2159
 
2160
  /**
@@ -2182,6 +2492,39 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2182
  return $new_url;
2183
  }
2184
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2185
  /**
2186
  * Maybe encode attachment URLs when retrieving the image tag
2187
  *
@@ -2213,7 +2556,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2213
 
2214
  $img_src = $matches[1];
2215
  $new_img_src = $this->maybe_sign_intermediate_size( $img_src, $id, $size, $as3cf_item );
2216
- $new_img_src = $this->encode_filename_in_path( $new_img_src );
2217
 
2218
  return str_replace( $img_src, $new_img_src, $html );
2219
  }
@@ -2236,7 +2579,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2236
 
2237
  if ( isset( $image[0] ) ) {
2238
  $url = $this->maybe_sign_intermediate_size( $image[0], $attachment_id, $size, $as3cf_item );
2239
- $url = $this->encode_filename_in_path( $url );
2240
 
2241
  $image[0] = $url;
2242
  }
@@ -2260,13 +2603,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2260
  }
2261
 
2262
  if ( isset( $response['url'] ) ) {
2263
- $response['url'] = $this->encode_filename_in_path( $response['url'] );
2264
  }
2265
 
2266
  if ( isset( $response['sizes'] ) && is_array( $response['sizes'] ) ) {
2267
  foreach ( $response['sizes'] as $size => $value ) {
2268
- $url = $this->maybe_sign_intermediate_size( $value['url'], $attachment->ID, $size, $as3cf_item );
2269
- $url = $this->encode_filename_in_path( $url );
2270
 
2271
  $response['sizes'][ $size ]['url'] = $url;
2272
  }
@@ -2292,7 +2635,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2292
 
2293
  if ( isset( $data['url'] ) ) {
2294
  $url = $this->maybe_sign_intermediate_size( $data['url'], $post_id, $size, $as3cf_item );
2295
- $url = $this->encode_filename_in_path( $url );
2296
 
2297
  $data['url'] = $url;
2298
  }
@@ -2307,17 +2650,18 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2307
  * @param int $attachment_id
2308
  * @param string|array $size
2309
  * @param bool|Media_Library_Item $as3cf_item
 
2310
  *
2311
  * @return string|WP_Error
2312
  */
2313
- protected function maybe_sign_intermediate_size( $url, $attachment_id, $size, $as3cf_item = false ) {
2314
  if ( ! $as3cf_item ) {
2315
  $as3cf_item = Media_Library_Item::get_by_source_id( $attachment_id );
2316
  }
2317
 
2318
- $size = $this->maybe_convert_size_to_string( $attachment_id, $size );
2319
 
2320
- if ( $as3cf_item->is_private_size( $size ) ) {
2321
  // Private file, add AWS signature if required
2322
  return $this->get_attachment_provider_url( $attachment_id, $as3cf_item, null, $size );
2323
  }
@@ -2325,81 +2669,17 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2325
  return $url;
2326
  }
2327
 
2328
- /**
2329
- * Convert dimensions to size
2330
- *
2331
- * @param int $attachment_id
2332
- * @param array $dimensions
2333
- *
2334
- * @return null|string
2335
- */
2336
- protected function convert_dimensions_to_size_name( $attachment_id, $dimensions ) {
2337
- $w = ( isset( $dimensions[0] ) && $dimensions[0] > 0 ) ? $dimensions[0] : 1;
2338
- $h = ( isset( $dimensions[1] ) && $dimensions[1] > 0 ) ? $dimensions[1] : 1;
2339
- $original_aspect_ratio = $w / $h;
2340
- $meta = wp_get_attachment_metadata( $attachment_id );
2341
-
2342
- if ( ! isset( $meta['sizes'] ) || empty( $meta['sizes'] ) ) {
2343
- return null;
2344
- }
2345
-
2346
- $sizes = $meta['sizes'];
2347
- uasort( $sizes, function ( $a, $b ) {
2348
- // Order by image area
2349
- return ( $a['width'] * $a['height'] ) - ( $b['width'] * $b['height'] );
2350
- } );
2351
-
2352
- $nearest_matches = array();
2353
-
2354
- foreach ( $sizes as $size => $value ) {
2355
- if ( $w > $value['width'] || $h > $value['height'] ) {
2356
- continue;
2357
- }
2358
-
2359
- $aspect_ratio = $value['width'] / $value['height'];
2360
-
2361
- if ( $aspect_ratio === $original_aspect_ratio ) {
2362
- return $size;
2363
- }
2364
-
2365
- $nearest_matches[] = $size;
2366
- }
2367
-
2368
- // Return nearest match
2369
- if ( ! empty( $nearest_matches ) ) {
2370
- return $nearest_matches[0];
2371
- }
2372
-
2373
- return null;
2374
- }
2375
-
2376
- /**
2377
- * Maybe convert size to string
2378
- *
2379
- * @param int $attachment_id
2380
- * @param mixed $size
2381
- *
2382
- * @return null|string
2383
- */
2384
- protected function maybe_convert_size_to_string( $attachment_id, $size ) {
2385
- if ( is_array( $size ) ) {
2386
- return $this->convert_dimensions_to_size_name( $attachment_id, $size );
2387
- }
2388
-
2389
- return $size;
2390
- }
2391
-
2392
  /**
2393
  * Is attachment served by provider.
2394
  *
2395
- * @param int $attachment_id
2396
- * @param bool $skip_rewrite_check Still check if offloaded even if not currently rewriting URLs? Default: false
2397
- * @param bool $skip_current_provider_check Skip checking if offloaded to current provider. Default: false, negated if $provider supplied
2398
- * @param Provider|null $provider Provider where attachment expected to be offloaded to. Default: currently configured provider
2399
  *
2400
  * @return bool|Media_Library_Item
2401
  */
2402
- public function is_attachment_served_by_provider( $attachment_id, $skip_rewrite_check = false, $skip_current_provider_check = false, Provider $provider = null ) {
2403
  if ( ! $skip_rewrite_check && ! $this->get_setting( 'serve-from-s3' ) ) {
2404
  // Not serving provider URLs
2405
  return false;
@@ -2413,7 +2693,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2413
  }
2414
 
2415
  if ( ! $skip_current_provider_check && empty( $provider ) ) {
2416
- $provider = $this->get_provider();
2417
  }
2418
 
2419
  if ( ! empty( $provider ) && $provider::get_provider_key_name() !== $as3cf_item->provider() ) {
@@ -2424,44 +2704,6 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2424
  return $as3cf_item;
2425
  }
2426
 
2427
- /**
2428
- * Encode file names according to RFC 3986 when generating urls
2429
- * As per Amazon https://forums.aws.amazon.com/thread.jspa?threadID=55746#jive-message-244233
2430
- *
2431
- * @param string $file
2432
- *
2433
- * @return string Encoded filename
2434
- */
2435
- public function encode_filename_in_path( $file ) {
2436
- $url = parse_url( $file );
2437
-
2438
- if ( ! isset( $url['path'] ) ) {
2439
- // Can't determine path, return original
2440
- return $file;
2441
- }
2442
-
2443
- if ( isset( $url['query'] ) ) {
2444
- // Manually strip query string, as passing $url['path'] to basename results in corrupt � characters
2445
- $file_name = wp_basename( str_replace( '?' . $url['query'], '', $file ) );
2446
- } else {
2447
- $file_name = wp_basename( $file );
2448
- }
2449
-
2450
- if ( false !== strpos( $file_name, '%' ) ) {
2451
- // File name already encoded, return original
2452
- return $file;
2453
- }
2454
-
2455
- $encoded_file_name = rawurlencode( $file_name );
2456
-
2457
- if ( $file_name === $encoded_file_name ) {
2458
- // File name doesn't need encoding, return original
2459
- return $file;
2460
- }
2461
-
2462
- return str_replace( $file_name, $encoded_file_name, $file );
2463
- }
2464
-
2465
  /**
2466
  * Allow processes to update the file on provider via update_attached_file()
2467
  *
@@ -2488,8 +2730,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2488
 
2489
  /**
2490
  * Return the provider URL when the local file is missing
2491
- * unless we know the calling process is and we are happy
2492
- * to copy the file back to the server to be used
2493
  *
2494
  * @param string $file
2495
  * @param int $attachment_id
@@ -2497,8 +2739,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2497
  * @return string
2498
  */
2499
  function get_attached_file( $file, $attachment_id ) {
2500
- if ( file_exists( $file ) || ! ( $as3cf_item = $this->is_attachment_served_by_provider( $attachment_id ) ) ) {
2501
- return $file;
 
 
 
 
 
 
 
2502
  }
2503
 
2504
  $url = $this->get_attachment_url( $attachment_id );
@@ -2610,7 +2859,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2610
  $region = AS3CF_REGION;
2611
  }
2612
 
2613
- if ( ! is_null( $region ) && $this->get_provider()->get_default_region() !== $region ) {
2614
  $args['LocationConstraint'] = $region;
2615
  }
2616
 
@@ -2670,6 +2919,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2670
 
2671
  $this->set_setting( 'bucket', $bucket_name );
2672
 
 
 
 
2673
  if ( empty( $region ) ) {
2674
  // retrieve the bucket region if not supplied
2675
  $region = $this->get_bucket_region( $bucket_name );
@@ -2678,7 +2930,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2678
  }
2679
  }
2680
 
2681
- if ( ! $this->get_provider()->region_required() && $this->get_provider()->get_default_region() === $region ) {
2682
  $region = '';
2683
  }
2684
 
@@ -2718,27 +2970,59 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2718
  }
2719
 
2720
  /**
2721
- * Add the settings page to the top-level AWS menu item for backwards compatibility.
2722
  *
2723
- * @param \Amazon_Web_Services $aws Plugin class instance from the amazon-web-services plugin.
 
 
2724
  */
2725
- public function aws_admin_menu( $aws ) {
2726
- $aws->add_page(
2727
- $this->get_plugin_page_title(),
2728
- $this->get_plugin_menu_title(),
2729
- 'manage_options',
2730
- $this->plugin_slug,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2731
  array( $this, 'render_page' )
2732
  );
2733
  }
2734
 
2735
  /**
2736
- * What is the default provider for legacy data?
 
 
 
 
 
 
 
 
 
2737
  *
2738
  * @return string
2739
  */
2740
- public static function get_default_provider() {
2741
- return static::$default_provider;
2742
  }
2743
 
2744
  /**
@@ -2747,7 +3031,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2747
  * @return string
2748
  */
2749
  public function get_default_region() {
2750
- return $this->get_provider()->get_default_region();
2751
  }
2752
 
2753
  /**
@@ -2756,7 +3040,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2756
  * @param bool|string $region specify region to client for signature
2757
  * @param bool $force force return of new provider client when swapping regions
2758
  *
2759
- * @return Provider|Null_Provider
2760
  * @throws Exception
2761
  */
2762
  public function get_provider_client( $region = false, $force = false ) {
@@ -2767,17 +3051,17 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2767
  $args = array();
2768
 
2769
  if ( $force ) {
2770
- $this->set_provider();
2771
  }
2772
 
2773
  if ( $region ) {
2774
- $args['region'] = $this->get_provider()->sanitize_region( $region );
2775
  }
2776
 
2777
  $provider_client_region = isset( $args['region'] ) ? $args['region'] : $region;
2778
 
2779
  try {
2780
- $this->set_client( $this->get_provider()->get_client( $args ), $provider_client_region );
2781
  } catch ( Exception $e ) {
2782
  AS3CF_Error::log( $e->getMessage() );
2783
  $this->set_client( new Null_Provider );
@@ -2790,8 +3074,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2790
  /**
2791
  * Setter for Provider client
2792
  *
2793
- * @param Provider|Null_Provider $client
2794
- * @param bool|string $region
2795
  */
2796
  public function set_client( $client, $region = false ) {
2797
  $this->provider_client = $client;
@@ -2830,7 +3114,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2830
  return new WP_Error( 'exception', $error_msg_title . $error_msg );
2831
  }
2832
 
2833
- $region = $this->get_provider()->sanitize_region( $region );
2834
 
2835
  if ( is_string( $region ) ) {
2836
  $regions[ $bucket ] = $region;
@@ -2847,7 +3131,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2847
  $this->verify_ajax_request();
2848
 
2849
  $region = empty( $_POST['region'] ) ? '' : $_POST['region'];
2850
- $region = $this->check_region( $region, $this->get_provider()->region_required() );
2851
 
2852
  $result = $this->get_buckets( $region );
2853
 
@@ -2896,14 +3180,14 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2896
  * @throws Exception
2897
  */
2898
  function check_write_permission( $bucket = null, $region = null ) {
2899
- if ( $this->get_provider()->needs_access_keys() ) {
2900
  // If no access keys set then no need check.
2901
  return false;
2902
  }
2903
 
2904
  if ( is_null( $bucket ) ) {
2905
  // If changing provider or bucket don't bother to test saved bucket permissions.
2906
- if ( ! empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'change-provider', 'change-bucket' ) ) ) {
2907
  return false;
2908
  }
2909
 
@@ -2992,6 +3276,20 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2992
  wp_register_script( 'as3cf-storage-provider', $src, array( 'jquery' ), $version, true );
2993
  }
2994
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2995
  /**
2996
  * On plugin load.
2997
  */
@@ -3008,8 +3306,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3008
 
3009
  add_action( 'network_admin_notices', array( $this, 'settings_saved_notice' ) );
3010
 
3011
- $this->enqueue_style( 'as3cf-styles', 'assets/css/styles', array( 'as3cf-modal', 'as3cf-storage-provider' ) );
3012
- $this->enqueue_script( 'as3cf-script', 'assets/js/script', array( 'jquery', 'underscore', 'as3cf-modal', 'as3cf-storage-provider' ) );
3013
 
3014
  wp_localize_script( 'as3cf-script',
3015
  'as3cf',
@@ -3040,8 +3338,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3040
  'aws_keys_remove' => wp_create_nonce( 'as3cf-aws-keys-remove' ),
3041
  ),
3042
  'is_pro' => $this->is_pro(),
3043
- 'provider_console_url' => $this->get_provider()->get_console_url(),
3044
- 'provider_console_url_prefix_param' => $this->get_provider()->get_console_url_prefix_param(),
3045
  )
3046
  );
3047
 
@@ -3059,6 +3357,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3059
  */
3060
  function get_settings_whitelist() {
3061
  return array(
 
3062
  'provider',
3063
  'access-key-id',
3064
  'secret-access-key',
@@ -3067,18 +3366,28 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3067
  'use-server-roles',
3068
  'bucket',
3069
  'region',
3070
- 'domain',
3071
- 'virtual-host',
3072
- 'permissions',
3073
- 'cloudfront',
3074
  'object-prefix',
3075
- 'copy-to-s3',
3076
- 'serve-from-s3',
3077
- 'remove-local-file',
3078
- 'force-https',
3079
- 'object-versioning',
3080
  'use-yearmonth-folders',
3081
- 'enable-object-prefix',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3082
  );
3083
  }
3084
 
@@ -3104,6 +3413,26 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3104
  return array( 'key-file' );
3105
  }
3106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3107
  /**
3108
  * Handle the saving of the settings page
3109
  */
@@ -3121,14 +3450,23 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3121
  }
3122
 
3123
  // Keep track of original provider at start of settings change flow.
3124
- $orig_provider = empty( $_GET['orig_provider'] ) ? $this->get_setting( 'provider', false ) : $_GET['orig_provider'];
3125
 
3126
- if ( $this->get_provider()->needs_access_keys() || ( ! empty( $_GET['action'] ) && 'change-provider' === $_GET['action'] ) ) {
 
 
 
 
 
3127
  // Changing Provider currently doesn't need anything special over saving settings,
3128
  // but if not already set needs to be handled rather than change-bucket raising its hand.
3129
  $changed_keys = $this->handle_save_settings();
3130
  } elseif ( empty( $this->get_setting( 'bucket' ) ) || ( ! empty( $_GET['action'] ) && 'change-bucket' === $_GET['action'] ) ) {
3131
  $changed_keys = $this->handle_change_bucket();
 
 
 
 
3132
  } elseif ( ! empty( $_GET['action'] ) ) {
3133
  $changed_keys = apply_filters( 'as3cf_handle_post_request', array() );
3134
  } else {
@@ -3147,17 +3485,45 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3147
  if ( ! empty( $changed_keys ) ) {
3148
  $action = null;
3149
 
3150
- foreach ( $changed_keys as $key ) {
3151
- // If anything about the Provider has changed then we need to verify the bucket selection.
3152
- // Otherwise we can let the filter decide whether there is an action to take.
3153
- // Last implementer will win, but the above handlers take care of grouping things appropriately.
3154
- if ( in_array( $key, array( 'provider', 'access-key-id', 'secret-access-key', 'key-file', 'use-server-roles' ) ) && ! $this->get_defined_setting( 'bucket', false ) ) {
3155
- $action = 'change-bucket';
3156
- break;
 
 
 
3157
  } else {
3158
- $action = apply_filters( 'as3cf_action_for_changed_settings_key', $action, $key );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3159
  }
3160
  }
 
 
3161
  }
3162
 
3163
  // Stash which step we're on in possibly multi-step config.
@@ -3165,14 +3531,28 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3165
 
3166
  // Depending on the step we're on, we may need another step if not already determined by newly saved settings.
3167
  if ( empty( $action ) && ! empty( $prev_action ) ) {
3168
- // After change-provider we always want the user to confirm the bucket is still ok.
3169
- // This gets round the change-provider => change-bucket => "back" problem.
3170
- // but then no change in provider settings problem.
3171
  if ( 'change-provider' === $prev_action && ! $this->get_defined_setting( 'bucket', false ) ) {
 
 
 
3172
  $action = 'change-bucket';
 
 
 
3173
  }
3174
  }
3175
 
 
 
 
 
 
 
 
 
 
 
 
3176
  if ( ! empty( $action ) ) {
3177
  $url_args['action'] = $action;
3178
 
@@ -3183,6 +3563,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3183
  if ( ! empty( $orig_provider ) ) {
3184
  $url_args['orig_provider'] = $orig_provider;
3185
  }
 
 
 
 
 
 
 
 
 
3186
  }
3187
 
3188
  $url = $this->get_plugin_page_url( $url_args );
@@ -3197,6 +3586,10 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3197
  * @throws Exception
3198
  */
3199
  private function handle_change_bucket() {
 
 
 
 
3200
  // Quick check that bucket name actually given.
3201
  $bucket = empty( $_POST['bucket_name'] ) ? false : $_POST['bucket_name'];
3202
 
@@ -3219,7 +3612,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3219
 
3220
  // Check and set region.
3221
  $region = empty( $_POST['region_name'] ) ? '' : $_POST['region_name'];
3222
- $region_required = 'create' === $bucket_mode ? true : $this->get_provider()->region_required();
3223
  $region = $this->check_region( $region, $region_required );
3224
 
3225
  if ( false === $region ) {
@@ -3285,6 +3678,109 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3285
  return $changed_keys;
3286
  }
3287
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3288
  /**
3289
  * Handle saving settings submitted by user.
3290
  *
@@ -3333,10 +3829,42 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3333
  continue;
3334
  }
3335
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3336
  $this->set_setting( $var, $value );
3337
 
3338
  // Some setting changes might have knock-on effects that require confirmation of secondary settings.
3339
- if ( isset( $old_settings[ $var ] ) && $old_settings[ $var ] !== $value ) {
3340
  $changed_keys[] = $var;
3341
  }
3342
  }
@@ -3518,7 +4046,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3518
 
3519
  foreach ( $blogs as $blog ) {
3520
  $blog = (array) $blog;
3521
- $blog_ids[] = $blog['blog_id'];
3522
  }
3523
 
3524
  return $blog_ids;
@@ -3537,58 +4065,6 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3537
  return true;
3538
  }
3539
 
3540
- /**
3541
- * Apply ACL to an attachment and associated files
3542
- *
3543
- * @param int $post_id
3544
- * @param Media_Library_Item $as3cf_item
3545
- * @param bool $private
3546
- *
3547
- * @return Media_Library_Item|bool|WP_Error
3548
- */
3549
- public function set_attachment_acl_on_provider( $post_id, Media_Library_Item $as3cf_item, $private ) {
3550
- // Return early if already set to the desired ACL
3551
- if ( $as3cf_item->is_private() === $private ) {
3552
- return false;
3553
- }
3554
-
3555
- $acl = $private ? $this->get_provider()->get_private_acl() : $this->get_provider()->get_default_acl();
3556
-
3557
- $args = array(
3558
- 'ACL' => $acl,
3559
- 'Bucket' => $as3cf_item->bucket(),
3560
- 'Key' => $as3cf_item->path(),
3561
- );
3562
-
3563
- $region = empty( $as3cf_item->region() ) ? false : $as3cf_item->region();
3564
-
3565
- try {
3566
- $provider_client = $this->get_provider_client( $region, true );
3567
- $provider_client->update_object_acl( $args );
3568
-
3569
- $as3cf_item = new Media_Library_Item(
3570
- $as3cf_item->provider(),
3571
- $as3cf_item->region(),
3572
- $as3cf_item->bucket(),
3573
- $as3cf_item->path(),
3574
- $private,
3575
- $as3cf_item->source_id(),
3576
- $as3cf_item->source_path(),
3577
- wp_basename( $as3cf_item->original_source_path() ),
3578
- $as3cf_item->private_sizes(),
3579
- $as3cf_item->id()
3580
- );
3581
- $as3cf_item->save();
3582
- } catch ( Exception $e ) {
3583
- $msg = 'Error setting ACL to ' . $acl . ' for ' . $as3cf_item->path() . ': ' . $e->getMessage();
3584
- AS3CF_Error::log( $msg );
3585
-
3586
- return new WP_Error( 'acl_exception', $msg );
3587
- }
3588
-
3589
- return $as3cf_item;
3590
- }
3591
-
3592
  /**
3593
  * Make admin notice for when object ACL has changed
3594
  *
@@ -3596,7 +4072,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3596
  */
3597
  function make_acl_admin_notice( Media_Library_Item $as3cf_item ) {
3598
  $filename = wp_basename( $as3cf_item->path() );
3599
- $acl = $as3cf_item->is_private() ? $this->get_provider()->get_private_acl() : $this->get_provider()->get_default_acl();
3600
  $acl_name = $this->get_acl_display_name( $acl );
3601
  $text = sprintf( __( '<strong>WP Offload Media</strong> &mdash; The file %s has been given %s permissions in the bucket.', 'amazon-s3-and-cloudfront' ), "<strong>{$filename}</strong>", "<strong>{$acl_name}</strong>" );
3602
 
@@ -3867,17 +4343,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3867
  $media_counts = $this->media_counts();
3868
 
3869
  $output .= 'Media Files: ';
3870
- $output .= number_format_i18n( $media_counts['total'] ) . ' (paths ' . number_format_i18n( $media_counts['total_paths'] ) . ')';
3871
  $output .= "\r\n";
3872
 
3873
  $output .= 'Offloaded Media Files: ';
3874
- $output .= number_format_i18n( $media_counts['offloaded'] ) . ' (paths ' . number_format_i18n( $media_counts['offloaded_paths'] ) . ')';
3875
  $output .= "\r\n";
3876
 
3877
  $output .= 'Not Offloaded Media Files: ';
3878
- $output .= number_format_i18n( $media_counts['not_offloaded'] ) . ' (paths ' . number_format_i18n( $media_counts['not_offloaded_paths'] ) . ')';
3879
- $output .= "\r\n";
3880
- $output .= 'Note: Approximate values, paths *try* and discard duplicates.';
3881
  $output .= "\r\n\r\n";
3882
 
3883
  $output .= 'Number of Image Sizes: ';
@@ -3962,42 +4436,47 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3962
  $output .= "\r\n";
3963
  $output .= "\r\n";
3964
 
3965
- $provider = $this->get_provider();
 
 
 
 
3966
 
3967
- if ( empty( $provider ) ) {
3968
- $output .= 'Provider: Not configured';
3969
  $output .= "\r\n";
3970
  } else {
3971
- $output .= 'Provider: ' . $provider::get_provider_name();
3972
  $output .= "\r\n";
3973
 
3974
- if ( $provider::use_server_roles_allowed() ) {
3975
- $output .= 'Use Server Roles: ' . $this->on_off( $provider->use_server_roles() );
 
3976
  } else {
3977
  $output .= 'Use Server Roles: N/A';
3978
  }
3979
  $output .= "\r\n";
3980
 
3981
- if ( $provider::use_key_file_allowed() ) {
3982
  $output .= 'Key File Path: ';
3983
- $output .= empty( $provider->get_key_file_path() ) ? 'None' : esc_html( $provider->get_key_file_path() );
3984
  $output .= "\r\n";
3985
  $output .= 'Key File Path Define: ';
3986
- $output .= $provider::key_file_path_constant() ? $provider::key_file_path_constant() : 'Not defined';
3987
  } else {
3988
  $output .= 'Key File Path: N/A';
3989
  }
3990
  $output .= "\r\n";
3991
 
3992
- if ( $provider::use_access_keys_allowed() ) {
3993
  $output .= 'Access Keys Set: ';
3994
- $output .= $provider->are_access_keys_set() ? 'Yes' : 'No';
3995
  $output .= "\r\n";
3996
  $output .= 'Access Key ID Define: ';
3997
- $output .= $provider::access_key_id_constant() ? $provider::access_key_id_constant() : 'Not defined';
3998
  $output .= "\r\n";
3999
  $output .= 'Secret Access Key Define: ';
4000
- $output .= $provider::secret_access_key_constant() ? $provider::secret_access_key_constant() : 'Not defined';
4001
  } else {
4002
  $output .= 'Access Keys Set: N/A';
4003
  }
@@ -4005,15 +4484,41 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4005
  }
4006
  $output .= "\r\n";
4007
 
 
4008
  $output .= 'Bucket: ';
4009
- $output .= esc_html( $this->get_setting( 'bucket' ) );
4010
  $output .= "\r\n";
 
4011
  $output .= 'Region: ';
4012
- $region = esc_html( $this->get_setting( 'region' ) );
4013
- if ( ! is_wp_error( $region ) ) {
4014
- $output .= $region;
 
 
 
4015
  }
4016
  $output .= "\r\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4017
  $output .= "\r\n";
4018
 
4019
  $output .= 'Copy Files to Bucket: ';
@@ -4022,8 +4527,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4022
  $output .= 'Enable Path: ';
4023
  $output .= $this->on_off( 'enable-object-prefix' );
4024
  $output .= "\r\n";
 
4025
  $output .= 'Custom Path: ';
4026
- $output .= esc_html( $this->get_setting( 'object-prefix' ) );
4027
  $output .= "\r\n";
4028
  $output .= 'Use Year/Month: ';
4029
  $output .= $this->on_off( 'use-yearmonth-folders' );
@@ -4033,15 +4539,47 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4033
  $output .= "\r\n";
4034
  $output .= "\r\n";
4035
 
4036
- $output .= 'Rewrite Media URLs: ';
4037
- $output .= $this->on_off( 'serve-from-s3' );
4038
- $output .= "\r\n";
4039
- $output .= 'Enable Custom Domain (CDN): ';
4040
- $output .= 'cloudfront' === $this->get_setting( 'domain' ) ? 'On' : 'Off';
4041
- $output .= "\r\n";
4042
- $output .= 'Custom Domain (CDN): ';
4043
- $output .= esc_html( $this->get_setting( 'cloudfront' ) );
4044
- $output .= "\r\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4045
  $output .= 'Force HTTPS: ';
4046
  $output .= $this->on_off( 'force-https' );
4047
  $output .= "\r\n";
@@ -4206,6 +4744,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4206
  * @return string
4207
  */
4208
  function get_acl_display_name( $acl ) {
 
4209
  $acl = ( 'public-read' === $acl ) ? 'public' : $acl;
4210
 
4211
  return ucwords( str_replace( '-', ' ', $acl ) );
@@ -4335,7 +4874,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4335
  * @return string
4336
  */
4337
  function get_access_denied_notice_message( $single = true ) {
4338
- if ( $this->get_provider()->needs_access_keys() ) {
4339
  return sprintf( __( '<a href="%s">Define your access keys</a> to enable write access to the bucket', 'amazon-s3-and-cloudfront' ), '#settings' );
4340
  }
4341
 
@@ -4439,38 +4978,29 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4439
  */
4440
  public function media_counts( $skip_transient = false, $force = false ) {
4441
  if ( $skip_transient || false === ( $attachment_counts = get_site_transient( 'as3cf_attachment_counts' ) ) ) {
4442
- $table_prefixes = $this->get_all_blog_table_prefixes();
4443
- $total = 0;
4444
- $total_paths = 0;
4445
- $offloaded = 0;
4446
- $offloaded_paths = 0;
4447
- $not_offloaded = 0;
4448
- $not_offloaded_paths = 0;
4449
 
4450
  foreach ( $table_prefixes as $blog_id => $table_prefix ) {
4451
  $this->switch_to_blog( $blog_id );
4452
 
4453
- $counts = Media_Library_Item::count_attachments( $skip_transient, $force );
4454
- $total += $counts['total'];
4455
- $total_paths += $counts['total_paths'];
4456
- $offloaded += $counts['offloaded'];
4457
- $offloaded_paths += $counts['offloaded_paths'];
4458
- $not_offloaded += $counts['not_offloaded'];
4459
- $not_offloaded_paths += $counts['not_offloaded_paths'];
4460
 
4461
  $this->restore_current_blog();
4462
  }
4463
 
4464
  $attachment_counts = array(
4465
- 'total' => $total,
4466
- 'total_paths' => $total_paths,
4467
- 'offloaded' => $offloaded,
4468
- 'offloaded_paths' => $offloaded_paths,
4469
- 'not_offloaded' => $not_offloaded,
4470
- 'not_offloaded_paths' => $not_offloaded_paths,
4471
  );
4472
 
4473
- set_site_transient( 'as3cf_attachment_counts', $attachment_counts, 2 * MINUTE_IN_SECONDS );
4474
  }
4475
 
4476
  return $attachment_counts;
@@ -4581,25 +5111,6 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4581
  exit( $exit_code );
4582
  }
4583
 
4584
- /**
4585
- * Show the deprecated Domain option setting?
4586
- *
4587
- * @param null|string $domain
4588
- *
4589
- * @return bool
4590
- */
4591
- public function show_deprecated_domain_setting( $domain = null ) {
4592
- if ( is_null( $domain ) ) {
4593
- $domain = $this->get_setting( 'domain' );
4594
- }
4595
-
4596
- if ( ! in_array( $domain, array( 'path', 'cloudfront' ) ) ) {
4597
- return true;
4598
- }
4599
-
4600
- return apply_filters( 'as3cf_show_deprecated_domain_setting', false );
4601
- }
4602
-
4603
  /**
4604
  * Upgrade the 'virtual host' / 'bucket as domain' setting to the
4605
  * new CloudFront / Domain setting
@@ -4642,15 +5153,20 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4642
  }
4643
 
4644
  /**
4645
- * Potentially update path for CloudFront URLs.
4646
  *
4647
- * @param string $path
 
 
4648
  *
4649
  * @return string
 
 
4650
  */
4651
- public function maybe_update_cloudfront_path( $path ) {
4652
- if ( 'cloudfront' === $this->get_setting( 'domain' ) ) {
4653
- $path_parts = apply_filters( 'as3cf_cloudfront_path_parts', explode( '/', $path ), $this->get_setting( 'cloudfront' ) );
 
4654
 
4655
  if ( ! empty( $path_parts ) ) {
4656
  $path = implode( '/', $path_parts );
@@ -4744,7 +5260,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4744
  $provider_object['key'] = $provider_object['path'];
4745
  $provider_object['url'] = $this->get_attachment_provider_url( $id, $as3cf_item );
4746
 
4747
- $acl = $as3cf_item->is_private() ? $this->get_provider()->get_private_acl() : $this->get_provider()->get_default_acl();
4748
  $acl_info = array(
4749
  'acl' => $acl,
4750
  'name' => $this->get_acl_display_name( $acl ),
@@ -4756,7 +5272,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4756
  }
4757
 
4758
  $provider_object['acl'] = $acl_info;
4759
- $provider_object['region'] = $this->get_provider()->get_region_name( $provider_object['region'] );
4760
  $provider_object['provider_name'] = $this->get_provider_service_name( $provider_object['provider'] );
4761
 
4762
  return $provider_object;
@@ -4838,7 +5354,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4838
  *
4839
  * @return array
4840
  */
4841
- function add_media_row_actions( Array $actions, $post ) {
4842
  return $actions;
4843
  }
4844
 
@@ -4927,19 +5443,64 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4927
  /**
4928
  * Get ACL for intermediate size.
4929
  *
4930
- * @param int $attachment_id
4931
- * @param string $size
 
 
4932
  *
4933
- * @return string
4934
  */
4935
- public function get_acl_for_intermediate_size( $attachment_id, $size ) {
4936
- $as3cf_item = Media_Library_Item::get_by_source_id( $attachment_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4937
 
4938
- if ( ! empty( $as3cf_item ) ) {
4939
- return $as3cf_item->is_private_size( $size ) ? $this->get_provider()->get_private_acl() : $this->get_provider()->get_default_acl();
 
4940
  }
4941
 
4942
- return $this->get_provider()->get_default_acl();
 
4943
  }
4944
 
4945
  /**
@@ -5046,7 +5607,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
5046
  );
5047
  $this->notices->add_notice( $message, $args );
5048
 
5049
- if ( is_a( $this->get_provider(), '\DeliciousBrains\WP_Offload_Media\Providers\AWS_Provider' ) && $this->get_provider()->needs_access_keys() ) {
5050
  // Have access keys been defined in still active AWS plugin's database settings?
5051
  $aws_settings = get_site_option( 'aws_settings' );
5052
 
@@ -5115,4 +5676,30 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
5115
 
5116
  return $data;
5117
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5118
  }
1
  <?php
2
 
3
  use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
4
+ use DeliciousBrains\WP_Offload_Media\Providers\Delivery\Another_CDN;
5
+ use DeliciousBrains\WP_Offload_Media\Providers\Delivery\AWS_CloudFront;
6
+ use DeliciousBrains\WP_Offload_Media\Providers\Delivery\Cloudflare;
7
+ use DeliciousBrains\WP_Offload_Media\Providers\Delivery\Delivery_Provider;
8
+ use DeliciousBrains\WP_Offload_Media\Providers\Delivery\DigitalOcean_Spaces_CDN;
9
+ use DeliciousBrains\WP_Offload_Media\Providers\Delivery\GCP_CDN;
10
+ use DeliciousBrains\WP_Offload_Media\Providers\Delivery\KeyCDN;
11
+ use DeliciousBrains\WP_Offload_Media\Providers\Delivery\Other;
12
+ use DeliciousBrains\WP_Offload_Media\Providers\Delivery\StackPath;
13
+ use DeliciousBrains\WP_Offload_Media\Providers\Delivery\Storage;
14
  use DeliciousBrains\WP_Offload_Media\Providers\Provider;
15
+ use DeliciousBrains\WP_Offload_Media\Providers\Storage\AWS_Provider;
16
+ use DeliciousBrains\WP_Offload_Media\Providers\Storage\DigitalOcean_Provider;
17
+ use DeliciousBrains\WP_Offload_Media\Providers\Storage\GCP_Provider;
18
+ use DeliciousBrains\WP_Offload_Media\Providers\Storage\Null_Provider;
19
+ use DeliciousBrains\WP_Offload_Media\Providers\Storage\Storage_Provider;
20
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade;
21
  use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_Content_Replace_URLs;
22
  use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_EDD_Replace_URLs;
23
  use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_File_Sizes;
30
  class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
31
 
32
  /**
33
+ * @var Storage_Provider
34
  */
35
+ private $storage_provider;
36
 
37
  /**
38
+ * @var Storage_Provider
39
  */
40
  private $provider_client;
41
 
44
  */
45
  private $provider_client_region;
46
 
47
+ /**
48
+ * @var Delivery_Provider
49
+ */
50
+ private $delivery_provider;
51
+
52
  /**
53
  * @var array
54
  */
102
  /**
103
  * @var string
104
  */
105
+ protected static $default_storage_provider = 'aws';
106
+
107
+ /**
108
+ * @var string
109
+ */
110
+ protected static $default_delivery_provider = 'storage';
111
+
112
+ /**
113
+ * @var array Known storage provider classes.
114
+ */
115
+ protected static $storage_provider_classes = array();
116
 
117
  /**
118
+ * @var array Known delivery provider classes.
119
  */
120
+ protected static $delivery_provider_classes = array();
121
 
122
  /**
123
  * @var AS3CF_Plugin_Compatibility
165
  $this->plugin_title = __( 'Offload Media Lite', 'amazon-s3-and-cloudfront' );
166
  $this->plugin_menu_title = __( 'Offload Media Lite', 'amazon-s3-and-cloudfront' );
167
 
168
+ static::$storage_provider_classes = apply_filters( 'as3cf_storage_provider_classes', array(
169
+ AWS_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Storage\AWS_Provider',
170
+ DigitalOcean_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Storage\DigitalOcean_Provider',
171
+ GCP_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Storage\GCP_Provider',
172
+ ) );
173
+
174
+ static::$delivery_provider_classes = apply_filters( 'as3cf_delivery_provider_classes', array(
175
+ AWS_CloudFront::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\AWS_CloudFront',
176
+ DigitalOcean_Spaces_CDN::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\DigitalOcean_Spaces_CDN',
177
+ GCP_CDN::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\GCP_CDN',
178
+ Another_CDN::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\Another_CDN',
179
+ // Sub Options of Another CDN.
180
+ Cloudflare::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\Cloudflare',
181
+ KeyCDN::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\KeyCDN',
182
+ StackPath::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\StackPath',
183
+ Other::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\Other',
184
+ // Fallback to raw storage URLs.
185
+ Storage::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\Storage',
186
+ ) );
187
 
188
  Media_Library_Item::init_cache();
189
 
190
+ $this->set_storage_provider();
191
+ $this->set_delivery_provider();
192
 
193
  // Bundled SDK may require AWS setup before data migrations.
194
  $this->handle_aws_access_key_migration();
226
 
227
  // Rewriting URLs, doesn't depend on plugin being setup
228
  add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 99, 2 );
229
+ add_filter( 'wp_get_attachment_image_attributes', array( $this, 'wp_get_attachment_image_attributes' ), 99, 3 );
230
  add_filter( 'get_image_tag', array( $this, 'maybe_encode_get_image_tag' ), 99, 6 );
231
  add_filter( 'wp_get_attachment_image_src', array( $this, 'maybe_encode_wp_get_attachment_image_src' ), 99, 4 );
232
  add_filter( 'wp_prepare_attachment_for_js', array( $this, 'maybe_encode_wp_prepare_attachment_for_js', ), 99, 3 );
260
 
261
  // Register storage provider scripts and styles
262
  $this->register_storage_provider_assets();
263
+
264
+ // Register delivery provider scripts and styles
265
+ $this->register_delivery_provider_assets();
266
+ }
267
+
268
+ /**
269
+ * @return Storage_Provider
270
+ */
271
+ public function get_storage_provider() {
272
+ return $this->storage_provider;
273
+ }
274
+
275
+ /**
276
+ * @param Storage_Provider|string|null $storage_provider
277
+ *
278
+ * @throws Exception
279
+ */
280
+ public function set_storage_provider( $storage_provider = null ) {
281
+ if ( empty( $storage_provider ) ) {
282
+ $storage_provider = $this->get_core_setting( 'provider', static::get_default_storage_provider() );
283
+ }
284
+
285
+ // Specified provider does not exist, fall back to default.
286
+ if ( is_string( $storage_provider ) && empty( self::$storage_provider_classes[ $storage_provider ] ) ) {
287
+ $storage_provider = static::get_default_storage_provider();
288
+ }
289
+
290
+ if ( is_string( $storage_provider ) && ! empty( self::$storage_provider_classes[ $storage_provider ] ) ) {
291
+ $storage_provider = new self::$storage_provider_classes[ $storage_provider ]( $this );
292
+ }
293
+
294
+ if ( ! empty( $storage_provider ) && ! is_string( $storage_provider ) ) {
295
+ $this->storage_provider = $storage_provider;
296
+ } else {
297
+ // We really tried, we really did, but we're going to have to let things fail.
298
+ $this->storage_provider = null;
299
+ }
300
  }
301
 
302
  /**
303
+ * @return Delivery_Provider
304
  */
305
+ public function get_delivery_provider() {
306
+ return $this->delivery_provider;
307
  }
308
 
309
  /**
310
+ * @param Delivery_Provider|string|null $delivery_provider
311
  *
312
  * @throws Exception
313
  */
314
+ public function set_delivery_provider( $delivery_provider = null ) {
315
+ if ( empty( $delivery_provider ) ) {
316
+ $delivery_provider = $this->get_core_setting( 'delivery-provider', static::get_default_delivery_provider() );
317
+ }
318
+
319
+ // Specified provider does not exist, fall back to default.
320
+ if ( is_string( $delivery_provider ) && empty( self::$delivery_provider_classes[ $delivery_provider ] ) ) {
321
+ $delivery_provider = static::get_default_delivery_provider();
322
  }
323
 
324
+ if ( is_string( $delivery_provider ) && ! empty( self::$delivery_provider_classes[ $delivery_provider ] ) ) {
325
+ $delivery_provider = new self::$delivery_provider_classes[ $delivery_provider ]( $this );
326
  }
327
 
328
+ if ( ! empty( $delivery_provider ) && ! is_string( $delivery_provider ) ) {
329
+ $this->delivery_provider = $delivery_provider;
330
+ } else {
331
+ // We really tried, we really did, but we're going to have to let things fail.
332
+ $this->delivery_provider = null;
333
+ }
334
  }
335
 
336
  /**
337
  * Returns the currently supported Providers.
338
  *
339
+ * @param string $type Which type of provider, "storage" or "delivery".
340
+ *
341
  * @return array
342
  */
343
+ public function get_provider_classes( $type ) {
344
+ switch ( $type ) {
345
+ case 'storage':
346
+ $providers = self::$storage_provider_classes;
347
+ break;
348
+ case 'delivery':
349
+ $providers = self::$delivery_provider_classes;
350
+ break;
351
+ default:
352
+ $providers = array(); // Error.
353
+ }
354
+
355
+ return $providers;
356
  }
357
 
358
  /**
359
  * Returns provider class name for given key.
360
  *
361
  * @param string $key_name
362
+ * @param string $type
363
  *
364
+ * @return Provider|null
365
  */
366
+ public function get_provider_class( $key_name, $type = 'storage' ) {
367
+ if ( empty( $type ) ) {
368
+ $type = 'storage';
369
+ }
370
+ $classes = $this->get_provider_classes( $type );
371
 
372
  return empty( $classes[ $key_name ] ) ? null : $classes[ $key_name ];
373
  }
376
  * Provider name for given key.
377
  *
378
  * @param string $key_name
379
+ * @param string $type
380
  *
381
  * @return string
382
  */
383
+ public function get_provider_name( $key_name, $type = 'storage' ) {
384
+ if ( empty( $type ) ) {
385
+ $type = 'storage';
386
+ }
387
+ $class = $this->get_provider_class( $key_name, $type );
388
 
389
  return empty( $class ) ? __( 'Unknown', 'amazon-s3-and-cloudfront' ) : $class::get_provider_name();
390
  }
393
  * Provider & Service name for given key.
394
  *
395
  * @param string $key_name
396
+ * @param string $type
397
  *
398
  * @return string
399
  */
400
+ public function get_provider_service_name( $key_name, $type = 'storage' ) {
401
+ if ( empty( $type ) ) {
402
+ $type = 'storage';
403
+ }
404
+ $class = $this->get_provider_class( $key_name, $type );
405
 
406
  return empty( $class ) ? __( 'Unknown', 'amazon-s3-and-cloudfront' ) : $class::get_provider_service_name();
407
  }
465
  'key' => $key,
466
  'disabled' => false,
467
  'disabled_attr' => '',
468
+ 'tr_class' => 'as3cf-settings-container ' . str_replace( '_', '-', $this->get_plugin_prefix() . '-' . $key . '-container' ),
469
  'setting_msg' => '',
470
  'is_defined' => false,
471
  );
633
  return $aws_secret_access_key;
634
  }
635
 
636
+ // Delivery Provider since 2.4.
637
+ if ( 'delivery-provider' === $key && ! isset( $settings['delivery-provider'] ) ) {
638
+ if ( ! empty( $this->get_setting( 'delivery-domain' ) ) ) {
639
+ // Try and guess delivery provider from delivery domain, default to "other" if domain unknown.
640
+ $delivery_provider = 'other';
641
+ $domain = $this->get_setting( 'cloudfront' );
642
+
643
+ if ( strstr( $domain, '.cloudfront.net' ) ) {
644
+ $delivery_provider = AWS_CloudFront::get_provider_key_name();
645
+ } elseif ( strstr( $domain, '.cdn.digitaloceanspaces.com' ) ) {
646
+ $delivery_provider = DigitalOcean_Spaces_CDN::get_provider_key_name();
647
+ } elseif (
648
+ 'gcp' === $this->get_storage_provider()->get_provider_key_name() &&
649
+ false === strstr( $domain, $this->get_storage_provider()->get_domain() )
650
+ ) {
651
+ $delivery_provider = GCP_CDN::get_provider_key_name();
652
+ }
653
+ } else {
654
+ // No delivery provider, fallback to default, which should equate to delivery via storage provider's defaults.
655
+ $delivery_provider = $default;
656
+ }
657
+
658
+ return $delivery_provider;
659
+ }
660
+
661
+ // Delivery Domain since 2.4.
662
+ if ( 'enable-delivery-domain' === $key && ! isset( $settings['enable-delivery-domain'] ) ) {
663
+ if ( ! empty( $this->get_setting( 'delivery-domain' ) ) ) {
664
+ return true;
665
+ }
666
+
667
+ return false;
668
+ }
669
+
670
+ // Delivery Domain since 2.4.
671
+ if ( 'delivery-domain' === $key && ! isset( $settings['delivery-domain'] ) ) {
672
+ if ( 'cloudfront' === $this->get_setting( 'domain' ) && ! empty( $this->get_setting( 'cloudfront' ) ) ) {
673
+ $delivery_domain = $this->get_setting( 'cloudfront' );
674
+ } else {
675
+ // No delivery domain, fallback to storage provider's default domain.
676
+ $delivery_domain = '';
677
+ }
678
+
679
+ return $delivery_domain;
680
+ }
681
+
682
  $value = parent::get_setting( $key, $default );
683
 
684
  // Provider
691
  return $bucket;
692
  }
693
 
694
+ // Use Bucket ACLs
695
+ if ( null !== ( $use_bucket_acls = $this->get_setting_use_bucket_acls( $settings, $key, null ) ) ) {
696
+ return $use_bucket_acls;
697
+ }
698
+
699
  return apply_filters( 'as3cf_setting_' . $key, $value );
700
  }
701
 
753
 
754
  // Region of bucket translation
755
  if ( 'region' === $key && isset( $settings['region'] ) ) {
756
+ return $this->get_storage_provider()->sanitize_region( $settings['region'] );
757
  }
758
 
759
  return false;
760
  }
761
 
762
  /**
763
+ * Get the bucket and if a constant remove from database and clear region
764
  *
765
  * @param string $key
766
  * @param string $value
810
  */
811
  public function bucket_changed() {
812
  $this->remove_setting( 'region' );
813
+ $this->remove_setting( 'use-bucket-acls' );
814
  $this->save_settings();
815
  }
816
 
817
+ /**
818
+ * Get the derived use-bucket-acls setting
819
+ *
820
+ * @param array $settings
821
+ * @param string $key
822
+ * @param mixed $default
823
+ *
824
+ * @return bool|null
825
+ */
826
+ public function get_setting_use_bucket_acls( $settings, $key, $default ) {
827
+ if ( 'use-bucket-acls' === $key && isset( $settings['use-bucket-acls'] ) ) {
828
+ return $settings['use-bucket-acls'];
829
+ }
830
+
831
+ if ( 'use-bucket-acls' === $key && ! isset( $settings['use-bucket-acls'] ) ) {
832
+ if ( ! $this->get_storage_provider()->block_public_access_allowed() ) {
833
+ // Got no choice, must use ACLs.
834
+ parent::set_setting( 'use-bucket-acls', true );
835
+ $this->save_settings();
836
+
837
+ return true;
838
+ }
839
+
840
+ $bucket = $this->get_setting( 'bucket' );
841
+ $region = $this->get_setting( 'region' );
842
+
843
+ try {
844
+ $public_access_blocked = $this->get_provider_client( $region )->public_access_blocked( $bucket );
845
+ } catch ( Exception $e ) {
846
+ $public_access_blocked = null;
847
+ }
848
+
849
+ // At present, we default to using ACLs if public access to bucket status unknown.
850
+ if ( empty( $public_access_blocked ) || true !== $public_access_blocked ) {
851
+ $use_bucket_acls = true;
852
+ } else {
853
+ $use_bucket_acls = false;
854
+ }
855
+
856
+ parent::set_setting( 'use-bucket-acls', $use_bucket_acls );
857
+ $this->save_settings();
858
+
859
+ return $use_bucket_acls;
860
+ }
861
+
862
+ return $default;
863
+ }
864
+
865
  /**
866
  * Filter in defined settings with sensible defaults.
867
  *
947
  $defined_settings = ! empty( $defined_settings ) ? $defined_settings : $this->get_defined_settings();
948
  $whitelisted_settings = $this->get_settings_whitelist();
949
  $settings_to_skip = array(
950
+ 'access-key-id',
951
+ 'secret-access-key',
952
+ 'key-file-path',
953
+ 'key-file',
954
+ 'use-server-roles',
955
  'bucket',
956
  'region',
957
+ 'delivery-provider-service-name',
958
+ 'use-bucket-acls',
959
  'virtual-host',
960
+ 'domain', // Legacy
961
+ 'cloudfront', // Legacy
962
  );
963
 
964
  foreach ( $whitelisted_settings as $setting ) {
966
  continue;
967
  }
968
 
969
+ if (
970
+ 'object-prefix' === $setting &&
971
+ isset( $defined_settings['enable-object-prefix'] ) &&
972
+ empty( $defined_settings['enable-object-prefix'] )
973
+ ) {
974
+ continue;
975
  }
976
 
977
+ if (
978
+ in_array( $setting, array( 'enable-delivery-domain', 'delivery-domain' ) ) &&
979
+ ! $this->get_delivery_provider()->delivery_domain_allowed()
980
+ ) {
981
+ continue;
982
+ }
983
+
984
+ if (
985
+ 'delivery-domain' === $setting &&
986
+ isset( $defined_settings['enable-delivery-domain'] ) &&
987
+ empty( $defined_settings['enable-delivery-domain'] )
988
+ ) {
989
+ continue;
990
+ }
991
+
992
+ if (
993
+ in_array( $setting, array( 'enable-signed-urls', 'signed-urls-key-id', 'signed-urls-key-file-path', 'signed-urls-object-prefix' ) ) &&
994
+ ! $this->get_delivery_provider()->use_signed_urls_key_file_allowed()
995
+ ) {
996
+ continue;
997
+ }
998
+
999
+ if (
1000
+ in_array( $setting, array( 'signed-urls-key-id', 'signed-urls-key-file-path', 'signed-urls-object-prefix' ) ) &&
1001
+ isset( $defined_settings['enable-signed-urls'] ) && empty( $defined_settings['enable-signed-urls'] )
1002
+ ) {
1003
+ continue;
1004
  }
1005
 
1006
  if ( ! isset( $defined_settings[ $setting ] ) ) {
1113
  * @return string
1114
  */
1115
  function get_url_preview( $escape = true, $suffix = 'photo.jpg' ) {
1116
+ $as3cf_item = new Media_Library_Item(
1117
+ $this->get_storage_provider()->get_provider_key_name(),
1118
+ $this->get_setting( 'region' ),
1119
+ $this->get_setting( 'bucket' ),
1120
+ AS3CF_Utils::trailingslash_prefix( $this->get_file_prefix() ) . $suffix,
1121
+ false,
1122
+ null,
1123
+ null
1124
+ );
1125
 
1126
+ $url = $this->get_attachment_provider_url( null, $as3cf_item );
1127
 
1128
+ if ( is_wp_error( $url ) ) {
1129
+ return '';
1130
+ }
1131
 
1132
  // Replace hyphens with non breaking hyphens for formatting
1133
  if ( $escape ) {
1232
  * to cope with possible different regions
1233
  */
1234
  function remove_attachment_files_from_provider( $post_id, Media_Library_Item $as3cf_item, $include_backups = true, $log_error = false, $return_on_error = false, $force_new_provider_client = false ) {
1235
+ $prefix = $as3cf_item->normalized_path_dir();
1236
+ $private_prefix = $as3cf_item->private_prefix();
1237
+ $paths = AS3CF_Utils::get_attachment_file_paths( $post_id, false, false, $include_backups );
1238
+ $paths = apply_filters( 'as3cf_remove_attachment_paths', $paths, $post_id, $as3cf_item, $include_backups );
1239
 
1240
  // If another item in current site shares full size *local* paths, only remove remote files not referenced by duplicates.
1241
  // We reference local paths as they should be reflected one way or another remotely, including backups.
1260
 
1261
  $objects_to_remove = array();
1262
 
1263
+ foreach ( $paths as $size => $path ) {
1264
  $objects_to_remove[] = array(
1265
+ 'Key' => $as3cf_item->key( wp_basename( $path ) ),
1266
  );
1267
  }
1268
 
1429
  $post_id,
1430
  $duplicate_item->source_path(),
1431
  wp_basename( $duplicate_item->original_source_path() ),
1432
+ $duplicate_item->extra_info()
1433
  );
1434
 
1435
  $old_item->save();
1486
  return $this->return_upload_error( $error_msg, $return_metadata );
1487
  }
1488
 
1489
+ $acl = $this->get_storage_provider()->get_default_acl();
1490
 
1491
  // check the attachment already exists in provider, eg. edit or restore image
1492
  if ( $old_item ) {
1497
 
1498
  // Use private ACL if existing offload is already private.
1499
  if ( $old_item->is_private() ) {
1500
+ $acl = $this->get_storage_provider()->get_private_acl();
1501
  }
1502
 
1503
  // use existing prefix
1504
  $prefix = $old_item->normalized_path_dir();
1505
+ // use existing private prefix
1506
+ $private_prefix = $old_item->private_prefix();
1507
  // use existing bucket
1508
  $bucket = $old_item->bucket();
1509
  // get existing region
1512
  $original_filename = wp_basename( $old_item->original_source_path() );
1513
  } else {
1514
  // derive prefix from various settings
1515
+ $prefix = $this->get_new_attachment_prefix( $post_id, $data );
1516
+
1517
+ // maybe set a private prefix.
1518
+ if ( $this->private_prefix_enabled() ) {
1519
+ $private_prefix = AS3CF_Utils::trailingslash_prefix( $this->get_setting( 'signed-urls-object-prefix', '' ) );
1520
+ } else {
1521
+ $private_prefix = '';
1522
+ }
1523
 
1524
  // use bucket from settings
1525
  $bucket = $this->get_setting( 'bucket' );
1532
  $original_filename = empty( $data['original_image'] ) ? null : $data['original_image'];
1533
  }
1534
 
1535
+ $acl = apply_filters( 'wps3_upload_acl', $acl, $type, $data, $post_id, $this ); // Old naming convention, will be deprecated soon
1536
+ $acl = apply_filters( 'as3cf_upload_acl', $acl, $data, $post_id );
1537
+ $is_private = ( ! empty( $acl ) && $this->get_storage_provider()->get_private_acl() === $acl ) ? true : false;
1538
 
1539
  $args = array(
1540
  'Bucket' => $bucket,
1541
  'Key' => $prefix . $file_name,
1542
  'SourceFile' => $file_path,
 
1543
  'ContentType' => $type,
1544
  'CacheControl' => 'max-age=31536000',
1545
  'Expires' => date( 'D, d M Y H:i:s O', time() + 31536000 ),
1546
  );
1547
 
1548
+ $image_size = wp_attachment_is_image( $post_id ) ? 'full' : '';
1549
+
1550
+ // Only set ACL if actually required, some storage provider and bucket settings disable changing ACL.
1551
+ if ( ! empty( $acl ) && $this->use_acl_for_intermediate_size( $post_id, $image_size, $bucket ) ) {
1552
+ $args['ACL'] = $acl;
1553
+ }
1554
+
1555
  // TODO: Remove GZIP functionality.
1556
  // Handle gzip on supported items
1557
  if ( $this->should_gzip_file( $file_path, $type ) && false !== ( $gzip_body = gzencode( file_get_contents( $file_path ) ) ) ) {
1561
  $args['ContentEncoding'] = 'gzip';
1562
  }
1563
 
1564
+ $args = apply_filters( 'as3cf_object_meta', $args, $post_id, $image_size, false );
1565
+
1566
+ $provider = $this->get_storage_provider()->get_provider_key_name();
1567
+ $region = $bucket !== $args['Bucket'] ? $this->get_bucket_region( $args['Bucket'], true ) : $region;
1568
+ $is_private = ( ! empty( $args['ACL'] ) && $this->get_storage_provider()->get_private_acl() === $args['ACL'] ) ? true : $is_private;
1569
+ $extra_info = empty( $old_item ) ? array( 'private_prefix' => $private_prefix ) : $old_item->extra_info();
1570
+ $item_id = empty( $old_item ) ? null : $old_item->id();
1571
+
1572
+ // Protect against filter use and only set ACL if actually required, some storage provider and bucket settings disable changing ACL.
1573
+ if ( isset( $args['ACL'] ) && ! $this->use_acl_for_intermediate_size( $post_id, $image_size, $bucket ) ) {
1574
+ unset( $args['ACL'] );
1575
+ }
1576
 
1577
+ $as3cf_item = new Media_Library_Item( $provider, $region, $args['Bucket'], $args['Key'], $is_private, $post_id, $file_path, $original_filename, $extra_info, $item_id );
 
 
 
 
1578
 
1579
+ // With public path and private prefix now in place, we can set the final path for the full sized file.
1580
+ $size_private_prefix = $as3cf_item->is_private() ? $as3cf_item->private_prefix() : '';
1581
+ $args['Key'] = $size_private_prefix . $args['Key'];
1582
 
1583
+ do_action( 'as3cf_upload_attachment_pre_remove', $post_id, $as3cf_item, $as3cf_item->normalized_path_dir(), $args );
1584
 
1585
  $new_offloads = array();
1586
  $files_to_remove = array();
1609
 
1610
  foreach ( $file_paths as $size => $file_path ) {
1611
  if ( ! in_array( $file_path, $files_to_remove ) ) {
1612
+ $acl = apply_filters( 'as3cf_upload_acl_sizes', $this->get_storage_provider()->get_default_acl(), $size, $post_id, $data );
1613
 
1614
+ if ( ! empty( $acl ) && $this->get_storage_provider()->get_private_acl() === $acl ) {
1615
+ $private_sizes[] = $size;
1616
+ }
1617
+
1618
+ // Public path, modified to private in next block as needed.
1619
  $additional_images[ $size ] = array(
1620
+ 'Key' => $as3cf_item->normalized_path_dir() . wp_basename( $file_path ),
1621
  'SourceFile' => $file_path,
 
1622
  'ContentType' => $this->get_mime_type( $file_path ),
1623
  );
1624
 
1625
+ // Only set ACL if actually required, some storage provider and bucket settings disable changing ACL.
1626
+ if ( ! empty( $acl ) && $this->use_acl_for_intermediate_size( $post_id, $size, $bucket, $as3cf_item ) ) {
1627
+ $additional_images[ $size ]['ACL'] = $acl;
1628
  }
1629
  }
1630
  }
1639
 
1640
  $args = apply_filters( 'as3cf_object_meta', array_merge( $args, $image ), $post_id, $size, false );
1641
 
1642
+ // Is size private and therefore needs to be in private prefix?
1643
+ $size_private_prefix = in_array( $size, $private_sizes ) ? $as3cf_item->private_prefix() : '';
1644
+ $args['Key'] = $size_private_prefix . $args['Key'];
1645
+
1646
+ // Protect against filter use and only set ACL if actually required, some storage provider and bucket settings disable changing ACL.
1647
+ if ( isset( $args['ACL'] ) && ! $this->use_acl_for_intermediate_size( $post_id, $size, $bucket, $as3cf_item ) ) {
1648
+ unset( $args['ACL'] );
1649
+ }
1650
+
1651
  if ( ! file_exists( $args['SourceFile'] ) ) {
1652
  if ( ! $duplicate ) {
1653
  $upload_errors[] = $this->return_upload_error( sprintf( __( 'File %s does not exist', 'amazon-s3-and-cloudfront' ), $args['SourceFile'] ) );
1678
  $as3cf_item->source_id(),
1679
  $as3cf_item->source_path(),
1680
  wp_basename( $image['SourceFile'] ),
1681
+ $as3cf_item->extra_info(),
1682
  $as3cf_item->id()
1683
  );
1684
  }
1718
 
1719
  // Additional image sizes have custom ACLs, record them.
1720
  if ( ! empty( $private_sizes ) ) {
1721
+ $extra_info = $as3cf_item->extra_info();
1722
+ $extra_info['private_sizes'] = $private_sizes;
1723
+
1724
  $as3cf_item = new Media_Library_Item(
1725
  $as3cf_item->provider(),
1726
  $as3cf_item->region(),
1730
  $as3cf_item->source_id(),
1731
  $as3cf_item->source_path(),
1732
  wp_basename( $as3cf_item->original_source_path() ),
1733
+ $extra_info,
1734
  $as3cf_item->id()
1735
  );
1736
  }
2166
  * TODO: Performance - cache / static var by param.
2167
  */
2168
  function is_plugin_setup( $with_credentials = false ) {
2169
+ if ( $with_credentials && $this->get_storage_provider()->needs_access_keys() ) {
2170
  // AWS not configured
2171
  return false;
2172
  }
2195
  * @param array $headers Header overrides for request
2196
  * @param bool $skip_rewrite_check
2197
  *
2198
+ * @return string|bool|WP_Error
2199
  */
2200
  public function get_secure_attachment_url( $post_id, $expires = null, $size = null, $headers = array(), $skip_rewrite_check = false ) {
2201
  if ( is_null( $expires ) ) {
2279
  }
2280
 
2281
  /**
2282
+ * Get attachment's new public prefix path for current settings.
2283
  *
2284
+ * @param int $post_id Attachment ID
2285
+ * @param array $metadata Optional attachment metadata
 
 
 
 
 
 
2286
  *
2287
+ * @return string
2288
+ */
2289
+ public function get_new_attachment_prefix( $post_id, $metadata = null ) {
2290
+ if ( empty( $metadata ) ) {
2291
+ $metadata = wp_get_attachment_metadata( $post_id, true );
2292
+ }
2293
+
2294
+ $time = $this->get_attachment_folder_year_month( $post_id, $metadata );
2295
+
2296
+ return $this->get_file_prefix( $time );
2297
+ }
2298
+
2299
+ /**
2300
+ * Get the url of the file from provider
2301
+ *
2302
+ * @param int $post_id Post ID of the attachment, required.
2303
+ * @param int|null $expires Seconds for the link to live, optional.
2304
+ * @param string|null $size Size of the image to get, optional.
2305
+ * @param array|null $meta Pre retrieved _wp_attachment_metadata for the attachment, optional.
2306
+ * @param array $headers Header overrides for request, optional.
2307
+ * @param bool $skip_rewrite_check Always return the URL regardless of the 'Rewrite File URLs' setting, optional, default: false.
2308
+ * Useful for the EDD and Woo addons to not break download URLs when the option is disabled.
2309
+ *
2310
+ * @return string|bool|WP_Error
2311
  */
2312
  public function get_attachment_url( $post_id, $expires = null, $size = null, $meta = null, $headers = array(), $skip_rewrite_check = false ) {
2313
  if ( ! ( $as3cf_item = $this->is_attachment_served_by_provider( $post_id, $skip_rewrite_check ) ) ) {
2397
  * @return string|WP_Error
2398
  */
2399
  public function get_attachment_provider_url( $post_id, Media_Library_Item $as3cf_item, $expires = null, $size = null, $meta = null, $headers = array() ) {
2400
+ $size = AS3CF_Utils::maybe_convert_size_to_string( $post_id, $size );
2401
 
2402
+ // Is a signed expiring URL required for the requested object?
 
 
 
 
 
 
 
 
2403
  if ( is_null( $expires ) ) {
2404
  if ( is_null( $size ) && $as3cf_item->is_private() ) {
2405
  // Full size URL private
2412
  }
2413
  }
2414
 
2415
+ $item_path = $as3cf_item->path();
2416
+
2417
  if ( ! is_null( $size ) ) {
2418
  if ( is_null( $meta ) ) {
2419
  $meta = get_post_meta( $post_id, '_wp_attachment_metadata', true );
2431
  }
2432
  }
2433
 
2434
+ $scheme = $this->get_url_scheme();
2435
+ $enable_delivery_domain = $this->get_delivery_provider()->delivery_domain_allowed() ? $this->get_setting( 'enable-delivery-domain' ) : false;
2436
+ $delivery_domain = $this->get_setting( 'delivery-domain' );
2437
+
2438
+ if ( ! $enable_delivery_domain || empty( $delivery_domain ) ) {
2439
+ $region = $as3cf_item->region();
2440
+
2441
+ if ( is_wp_error( $region ) ) {
2442
+ return $region;
2443
+ }
2444
+
2445
+ $delivery_domain = $this->get_storage_provider()->get_url_domain( $as3cf_item->bucket(), $region, $expires );
2446
+ } else {
2447
+ $delivery_domain = AS3CF_Utils::sanitize_custom_domain( $delivery_domain );
2448
+ }
2449
 
2450
  if ( ! is_null( $expires ) && $this->is_plugin_setup( true ) ) {
2451
  try {
2452
+ $timestamp = time() + apply_filters( 'as3cf_expires', $expires );
2453
+ $url = $this->get_delivery_provider()->get_signed_url( $as3cf_item, $item_path, $delivery_domain, $scheme, $timestamp, $headers );
 
2454
 
2455
+ return apply_filters( 'as3cf_get_attachment_secure_url', $url, $as3cf_item, $post_id, $timestamp, $headers );
2456
+ } catch ( Exception $e ) {
2457
+ return new WP_Error( 'exception', $e->getMessage() );
2458
+ }
2459
+ } else {
2460
+ try {
2461
+ $url = $this->get_delivery_provider()->get_url( $as3cf_item, $item_path, $delivery_domain, $scheme, $headers );
2462
 
2463
+ return apply_filters( 'as3cf_get_attachment_url', $url, $as3cf_item, $post_id, $expires, $headers );
2464
  } catch ( Exception $e ) {
2465
  return new WP_Error( 'exception', $e->getMessage() );
2466
  }
2467
  }
 
 
 
 
 
 
 
2468
  }
2469
 
2470
  /**
2492
  return $new_url;
2493
  }
2494
 
2495
+ /**
2496
+ * Filters the list of attachment image attributes.
2497
+ *
2498
+ * @param array $attr Attributes for the image markup.
2499
+ * @param WP_Post $attachment Image attachment post.
2500
+ * @param string|array $size Requested size. Image size or array of width and height values (in that order).
2501
+ *
2502
+ * @return array
2503
+ */
2504
+ public function wp_get_attachment_image_attributes( $attr, $attachment, $size ) {
2505
+ if ( ! ( $as3cf_item = $this->is_attachment_served_by_provider( $attachment->ID ) ) ) {
2506
+ return $attr;
2507
+ }
2508
+
2509
+ $size = AS3CF_Utils::maybe_convert_size_to_string( $attachment->ID, $size );
2510
+
2511
+ // image_downsize incorrectly substitutes size filename into full URL for src attribute instead of clobbering.
2512
+ // So we need to fix up the src attribute if a size is being used.
2513
+ if ( ! empty( $size ) && ! empty( $attr['src'] ) ) {
2514
+ $attr['src'] = $this->get_attachment_provider_url( $attachment->ID, $as3cf_item, null, $size );
2515
+ }
2516
+
2517
+ /**
2518
+ * Filtered list of attachment image attributes.
2519
+ *
2520
+ * @param array $attr Attributes for the image markup.
2521
+ * @param WP_Post $attachment Image attachment post.
2522
+ * @param string $size Requested size.
2523
+ * @param Media_Library_Item $as3cf_item
2524
+ */
2525
+ return apply_filters( 'as3cf_wp_get_attachment_image_attributes', $attr, $attachment, $size, $as3cf_item );
2526
+ }
2527
+
2528
  /**
2529
  * Maybe encode attachment URLs when retrieving the image tag
2530
  *
2556
 
2557
  $img_src = $matches[1];
2558
  $new_img_src = $this->maybe_sign_intermediate_size( $img_src, $id, $size, $as3cf_item );
2559
+ $new_img_src = AS3CF_Utils::encode_filename_in_path( $new_img_src );
2560
 
2561
  return str_replace( $img_src, $new_img_src, $html );
2562
  }
2579
 
2580
  if ( isset( $image[0] ) ) {
2581
  $url = $this->maybe_sign_intermediate_size( $image[0], $attachment_id, $size, $as3cf_item );
2582
+ $url = AS3CF_Utils::encode_filename_in_path( $url );
2583
 
2584
  $image[0] = $url;
2585
  }
2603
  }
2604
 
2605
  if ( isset( $response['url'] ) ) {
2606
+ $response['url'] = AS3CF_Utils::encode_filename_in_path( $response['url'] );
2607
  }
2608
 
2609
  if ( isset( $response['sizes'] ) && is_array( $response['sizes'] ) ) {
2610
  foreach ( $response['sizes'] as $size => $value ) {
2611
+ $url = $this->maybe_sign_intermediate_size( $value['url'], $attachment->ID, $size, $as3cf_item, true );
2612
+ $url = AS3CF_Utils::encode_filename_in_path( $url );
2613
 
2614
  $response['sizes'][ $size ]['url'] = $url;
2615
  }
2635
 
2636
  if ( isset( $data['url'] ) ) {
2637
  $url = $this->maybe_sign_intermediate_size( $data['url'], $post_id, $size, $as3cf_item );
2638
+ $url = AS3CF_Utils::encode_filename_in_path( $url );
2639
 
2640
  $data['url'] = $url;
2641
  }
2650
  * @param int $attachment_id
2651
  * @param string|array $size
2652
  * @param bool|Media_Library_Item $as3cf_item
2653
+ * @param bool $force_rewrite If size not signed, make sure correct URL is being used anyway.
2654
  *
2655
  * @return string|WP_Error
2656
  */
2657
+ protected function maybe_sign_intermediate_size( $url, $attachment_id, $size, $as3cf_item = false, $force_rewrite = false ) {
2658
  if ( ! $as3cf_item ) {
2659
  $as3cf_item = Media_Library_Item::get_by_source_id( $attachment_id );
2660
  }
2661
 
2662
+ $size = AS3CF_Utils::maybe_convert_size_to_string( $attachment_id, $size );
2663
 
2664
+ if ( $force_rewrite || $as3cf_item->is_private_size( $size ) ) {
2665
  // Private file, add AWS signature if required
2666
  return $this->get_attachment_provider_url( $attachment_id, $as3cf_item, null, $size );
2667
  }
2669
  return $url;
2670
  }
2671
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2672
  /**
2673
  * Is attachment served by provider.
2674
  *
2675
+ * @param int $attachment_id
2676
+ * @param bool $skip_rewrite_check Still check if offloaded even if not currently rewriting URLs? Default: false
2677
+ * @param bool $skip_current_provider_check Skip checking if offloaded to current provider. Default: false, negated if $provider supplied
2678
+ * @param Storage_Provider|null $provider Provider where attachment expected to be offloaded to. Default: currently configured provider
2679
  *
2680
  * @return bool|Media_Library_Item
2681
  */
2682
+ public function is_attachment_served_by_provider( $attachment_id, $skip_rewrite_check = false, $skip_current_provider_check = false, Storage_Provider $provider = null ) {
2683
  if ( ! $skip_rewrite_check && ! $this->get_setting( 'serve-from-s3' ) ) {
2684
  // Not serving provider URLs
2685
  return false;
2693
  }
2694
 
2695
  if ( ! $skip_current_provider_check && empty( $provider ) ) {
2696
+ $provider = $this->get_storage_provider();
2697
  }
2698
 
2699
  if ( ! empty( $provider ) && $provider::get_provider_key_name() !== $as3cf_item->provider() ) {
2704
  return $as3cf_item;
2705
  }
2706
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2707
  /**
2708
  * Allow processes to update the file on provider via update_attached_file()
2709
  *
2730
 
2731
  /**
2732
  * Return the provider URL when the local file is missing
2733
+ * unless we know who the calling process is and we are happy
2734
+ * to copy the file back to the server to be used.
2735
  *
2736
  * @param string $file
2737
  * @param int $attachment_id
2739
  * @return string
2740
  */
2741
  function get_attached_file( $file, $attachment_id ) {
2742
+ $as3cf_item = $this->is_attachment_served_by_provider( $attachment_id );
2743
+
2744
+ if ( file_exists( $file ) || ! $as3cf_item ) {
2745
+ if ( $as3cf_item ) {
2746
+ // Although we have a local file, give filter implementors a chance to override or copy back siblings.
2747
+ return apply_filters( 'as3cf_get_attached_file_noop', $file, $file, $attachment_id, $as3cf_item );
2748
+ } else {
2749
+ return $file;
2750
+ }
2751
  }
2752
 
2753
  $url = $this->get_attachment_url( $attachment_id );
2859
  $region = AS3CF_REGION;
2860
  }
2861
 
2862
+ if ( ! is_null( $region ) && $this->get_storage_provider()->get_default_region() !== $region ) {
2863
  $args['LocationConstraint'] = $region;
2864
  }
2865
 
2919
 
2920
  $this->set_setting( 'bucket', $bucket_name );
2921
 
2922
+ // Ensure Use Bucket ACLs is refreshed.
2923
+ $this->remove_setting( 'use-bucket-acls' );
2924
+
2925
  if ( empty( $region ) ) {
2926
  // retrieve the bucket region if not supplied
2927
  $region = $this->get_bucket_region( $bucket_name );
2930
  }
2931
  }
2932
 
2933
+ if ( ! $this->get_storage_provider()->region_required() && $this->get_storage_provider()->get_default_region() === $region ) {
2934
  $region = '';
2935
  }
2936
 
2970
  }
2971
 
2972
  /**
2973
+ * In our settings screen?
2974
  *
2975
+ * @param WP_Screen|null $screen
2976
+ *
2977
+ * @return bool
2978
  */
2979
+ public function our_screen( WP_Screen $screen = null ) {
2980
+ if ( ! is_admin() || empty( $this->hook_suffix ) ) {
2981
+ return false;
2982
+ }
2983
+
2984
+ if ( empty( $screen ) ) {
2985
+ $screen = get_current_screen();
2986
+ }
2987
+
2988
+ if ( false === strpos( $screen->id, $this->hook_suffix ) ) {
2989
+ return false;
2990
+ }
2991
+
2992
+ return true;
2993
+ }
2994
+
2995
+ /**
2996
+ * Add the settings page to the top-level AWS menu item for backwards compatibility.
2997
+ *
2998
+ * @param \Amazon_Web_Services $aws Plugin class instance from the amazon-web-services plugin.
2999
+ */
3000
+ public function aws_admin_menu( $aws ) {
3001
+ $aws->add_page(
3002
+ $this->get_plugin_page_title(),
3003
+ $this->get_plugin_menu_title(),
3004
+ 'manage_options',
3005
+ $this->plugin_slug,
3006
  array( $this, 'render_page' )
3007
  );
3008
  }
3009
 
3010
  /**
3011
+ * What is the default storage provider for legacy data?
3012
+ *
3013
+ * @return string
3014
+ */
3015
+ public static function get_default_storage_provider() {
3016
+ return static::$default_storage_provider;
3017
+ }
3018
+
3019
+ /**
3020
+ * What is the default delivery provider for legacy data?
3021
  *
3022
  * @return string
3023
  */
3024
+ public static function get_default_delivery_provider() {
3025
+ return static::$default_delivery_provider;
3026
  }
3027
 
3028
  /**
3031
  * @return string
3032
  */
3033
  public function get_default_region() {
3034
+ return $this->get_storage_provider()->get_default_region();
3035
  }
3036
 
3037
  /**
3040
  * @param bool|string $region specify region to client for signature
3041
  * @param bool $force force return of new provider client when swapping regions
3042
  *
3043
+ * @return Storage_Provider|Null_Provider
3044
  * @throws Exception
3045
  */
3046
  public function get_provider_client( $region = false, $force = false ) {
3051
  $args = array();
3052
 
3053
  if ( $force ) {
3054
+ $this->set_storage_provider();
3055
  }
3056
 
3057
  if ( $region ) {
3058
+ $args['region'] = $this->get_storage_provider()->sanitize_region( $region );
3059
  }
3060
 
3061
  $provider_client_region = isset( $args['region'] ) ? $args['region'] : $region;
3062
 
3063
  try {
3064
+ $this->set_client( $this->get_storage_provider()->get_client( $args ), $provider_client_region );
3065
  } catch ( Exception $e ) {
3066
  AS3CF_Error::log( $e->getMessage() );
3067
  $this->set_client( new Null_Provider );
3074
  /**
3075
  * Setter for Provider client
3076
  *
3077
+ * @param Storage_Provider|Null_Provider $client
3078
+ * @param bool|string $region
3079
  */
3080
  public function set_client( $client, $region = false ) {
3081
  $this->provider_client = $client;
3114
  return new WP_Error( 'exception', $error_msg_title . $error_msg );
3115
  }
3116
 
3117
+ $region = $this->get_storage_provider()->sanitize_region( $region );
3118
 
3119
  if ( is_string( $region ) ) {
3120
  $regions[ $bucket ] = $region;
3131
  $this->verify_ajax_request();
3132
 
3133
  $region = empty( $_POST['region'] ) ? '' : $_POST['region'];
3134
+ $region = $this->check_region( $region, $this->get_storage_provider()->region_required() );
3135
 
3136
  $result = $this->get_buckets( $region );
3137
 
3180
  * @throws Exception
3181
  */
3182
  function check_write_permission( $bucket = null, $region = null ) {
3183
+ if ( $this->get_storage_provider()->needs_access_keys() ) {
3184
  // If no access keys set then no need check.
3185
  return false;
3186
  }
3187
 
3188
  if ( is_null( $bucket ) ) {
3189
  // If changing provider or bucket don't bother to test saved bucket permissions.
3190
+ if ( ! empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'change-provider', 'change-bucket', 'change-delivery-provider' ) ) ) {
3191
  return false;
3192
  }
3193
 
3276
  wp_register_script( 'as3cf-storage-provider', $src, array( 'jquery' ), $version, true );
3277
  }
3278
 
3279
+ /**
3280
+ * Register delivery provider scripts and styles so they can be enqueued later
3281
+ */
3282
+ function register_delivery_provider_assets() {
3283
+ $version = $this->get_asset_version();
3284
+ $suffix = $this->get_asset_suffix();
3285
+
3286
+ $src = plugins_url( 'assets/css/delivery-provider.css', $this->plugin_file_path );
3287
+ wp_register_style( 'as3cf-delivery-provider', $src, array(), $version );
3288
+
3289
+ $src = plugins_url( 'assets/js/delivery-provider' . $suffix . '.js', $this->plugin_file_path );
3290
+ wp_register_script( 'as3cf-delivery-provider', $src, array( 'jquery' ), $version, true );
3291
+ }
3292
+
3293
  /**
3294
  * On plugin load.
3295
  */
3306
 
3307
  add_action( 'network_admin_notices', array( $this, 'settings_saved_notice' ) );
3308
 
3309
+ $this->enqueue_style( 'as3cf-styles', 'assets/css/styles', array( 'as3cf-modal', 'as3cf-storage-provider', 'as3cf-delivery-provider' ) );
3310
+ $this->enqueue_script( 'as3cf-script', 'assets/js/script', array( 'jquery', 'underscore', 'as3cf-modal', 'as3cf-storage-provider', 'as3cf-delivery-provider' ) );
3311
 
3312
  wp_localize_script( 'as3cf-script',
3313
  'as3cf',
3338
  'aws_keys_remove' => wp_create_nonce( 'as3cf-aws-keys-remove' ),
3339
  ),
3340
  'is_pro' => $this->is_pro(),
3341
+ 'provider_console_url' => $this->get_storage_provider()->get_console_url(),
3342
+ 'provider_console_url_prefix_param' => $this->get_storage_provider()->get_console_url_prefix_param(),
3343
  )
3344
  );
3345
 
3357
  */
3358
  function get_settings_whitelist() {
3359
  return array(
3360
+ // Storage
3361
  'provider',
3362
  'access-key-id',
3363
  'secret-access-key',
3366
  'use-server-roles',
3367
  'bucket',
3368
  'region',
3369
+ 'use-bucket-acls',
3370
+ 'enable-object-prefix',
 
 
3371
  'object-prefix',
 
 
 
 
 
3372
  'use-yearmonth-folders',
3373
+ 'object-versioning',
3374
+ 'copy-to-s3', // TODO: Rename
3375
+ // Delivery
3376
+ 'delivery-provider',
3377
+ 'delivery-provider-service-name',
3378
+ 'enable-delivery-domain',
3379
+ 'delivery-domain',
3380
+ 'virtual-host', // Legacy
3381
+ 'domain', // Legacy
3382
+ 'cloudfront', // Legacy
3383
+ 'enable-signed-urls',
3384
+ 'signed-urls-key-id',
3385
+ 'signed-urls-key-file-path',
3386
+ 'signed-urls-object-prefix',
3387
+ 'force-https',
3388
+ 'serve-from-s3', // TODO: Rename
3389
+ // Advanced
3390
+ 'remove-local-file',
3391
  );
3392
  }
3393
 
3413
  return array( 'key-file' );
3414
  }
3415
 
3416
+ /**
3417
+ * @inheritDoc
3418
+ */
3419
+ function get_path_format_settings() {
3420
+ return array(
3421
+ 'key-file-path',
3422
+ 'signed-urls-key-file-path',
3423
+ );
3424
+ }
3425
+
3426
+ /**
3427
+ * @inheritDoc
3428
+ */
3429
+ function get_prefix_format_settings() {
3430
+ return array(
3431
+ 'object-prefix',
3432
+ 'signed-urls-object-prefix',
3433
+ );
3434
+ }
3435
+
3436
  /**
3437
  * Handle the saving of the settings page
3438
  */
3450
  }
3451
 
3452
  // Keep track of original provider at start of settings change flow.
3453
+ $orig_provider = isset( $_GET['orig_provider'] ) ? $_GET['orig_provider'] : '';
3454
 
3455
+ // If we already have a bucket, then we should keep track of the associated provider too.
3456
+ if ( empty( $orig_provider ) && $this->get_setting( 'bucket', false ) ) {
3457
+ $orig_provider = $this->get_setting( 'provider' );
3458
+ }
3459
+
3460
+ if ( $this->get_storage_provider()->needs_access_keys() || ( ! empty( $_GET['action'] ) && 'change-provider' === $_GET['action'] ) ) {
3461
  // Changing Provider currently doesn't need anything special over saving settings,
3462
  // but if not already set needs to be handled rather than change-bucket raising its hand.
3463
  $changed_keys = $this->handle_save_settings();
3464
  } elseif ( empty( $this->get_setting( 'bucket' ) ) || ( ! empty( $_GET['action'] ) && 'change-bucket' === $_GET['action'] ) ) {
3465
  $changed_keys = $this->handle_change_bucket();
3466
+ } elseif ( ! empty( $_GET['action'] ) && 'change-bucket-access' === $_GET['action'] ) {
3467
+ $changed_keys = $this->handle_change_bucket_access();
3468
+ } elseif ( ! empty( $_GET['action'] ) && 'change-delivery-provider' === $_GET['action'] ) {
3469
+ $changed_keys = $this->handle_save_settings();
3470
  } elseif ( ! empty( $_GET['action'] ) ) {
3471
  $changed_keys = apply_filters( 'as3cf_handle_post_request', array() );
3472
  } else {
3485
  if ( ! empty( $changed_keys ) ) {
3486
  $action = null;
3487
 
3488
+ // If anything about the Provider has changed then we need to verify the bucket selection.
3489
+ // If the bucket has changed, and provider allows blocking public access to bucket, verify bucket access requirement.
3490
+ // Otherwise we can let the filter decide whether there is an action to take.
3491
+ // Last implementer will win, but the above handlers take care of grouping things appropriately.
3492
+ if ( ! empty( array_intersect( $changed_keys, array( 'provider', 'access-key-id', 'secret-access-key', 'key-file', 'use-server-roles' ) ) ) && ! $this->get_defined_setting( 'bucket', false ) ) {
3493
+ $action = 'change-bucket';
3494
+ } elseif ( ! empty( array_intersect( $changed_keys, array( 'bucket', 'region' ) ) ) && $this->get_storage_provider()->block_public_access_allowed() ) {
3495
+ // Not initial setup, show change bucket access regardless if allowed.
3496
+ if ( ! empty( $_GET['orig_provider'] ) ) {
3497
+ $action = 'change-bucket-access';
3498
  } else {
3499
+ // Is Block All Public Access enabled?
3500
+ try {
3501
+ $public_access_blocked = $this->get_provider_client()->public_access_blocked( $this->get_setting( 'bucket' ) );
3502
+ } catch ( Exception $e ) {
3503
+ $public_access_blocked = null;
3504
+ }
3505
+
3506
+ if ( ! empty( $public_access_blocked ) && ! $this->get_delivery_provider()->use_signed_urls_key_file_allowed() ) {
3507
+ $action = 'change-bucket-access';
3508
+ }
3509
+ }
3510
+ } elseif ( in_array( 'delivery-provider', $changed_keys ) ) {
3511
+ // If delivery provider has just changed, there might be a masked change to enable-signed-urls.
3512
+ try {
3513
+ $this->set_delivery_provider();
3514
+
3515
+ if ( $this->get_setting( 'enable-signed-urls', false ) && ! $this->get_delivery_provider()->use_signed_urls_key_file_allowed() ) {
3516
+ $changed_keys[] = 'enable-signed-urls';
3517
+ $this->set_setting( 'enable-signed-urls', false );
3518
+ $this->save_settings();
3519
+ }
3520
+ } catch ( Exception $e ) {
3521
+ // Meh, no biggie, the move tool can always be run manually.
3522
+ AS3CF_Error::log( sprintf( __( 'Could not set new Delivery Provider: %s', 'amazon-s3-and-cloudfront' ), $e->getMessage() ) );
3523
  }
3524
  }
3525
+
3526
+ $action = empty( $action ) ? apply_filters( 'as3cf_action_for_changed_settings_key', $action, $changed_keys ) : $action;
3527
  }
3528
 
3529
  // Stash which step we're on in possibly multi-step config.
3531
 
3532
  // Depending on the step we're on, we may need another step if not already determined by newly saved settings.
3533
  if ( empty( $action ) && ! empty( $prev_action ) ) {
 
 
 
3534
  if ( 'change-provider' === $prev_action && ! $this->get_defined_setting( 'bucket', false ) ) {
3535
+ // After change-provider we always want the user to confirm the bucket is still ok.
3536
+ // This gets round the change-provider => change-bucket => "back" problem.
3537
+ // but then no change in provider settings problem.
3538
  $action = 'change-bucket';
3539
+ } elseif ( ! empty( $_GET['orig_provider'] ) && 'change-bucket' === $prev_action && $this->get_storage_provider()->block_public_access_allowed() ) {
3540
+ // If bucket didn't change, might want to update bucket access.
3541
+ $action = 'change-bucket-access';
3542
  }
3543
  }
3544
 
3545
+ // If no action set yet, but there were changes earlier, let filter implementors have a look at them.
3546
+ if ( ! empty( $_GET['changed'] ) ) {
3547
+ $changed = (array) $_GET['changed'];
3548
+ }
3549
+
3550
+ if ( empty( $action ) && ! empty( $changed ) ) {
3551
+ $action = null;
3552
+
3553
+ $action = apply_filters( 'as3cf_action_for_changed_settings_key', $action, $changed );
3554
+ }
3555
+
3556
  if ( ! empty( $action ) ) {
3557
  $url_args['action'] = $action;
3558
 
3563
  if ( ! empty( $orig_provider ) ) {
3564
  $url_args['orig_provider'] = $orig_provider;
3565
  }
3566
+
3567
+ if ( ! empty( $changed ) ) {
3568
+ $url_args['changed'] = $changed;
3569
+ }
3570
+
3571
+ if ( ! empty( $changed_keys ) && is_array( $changed_keys ) ) {
3572
+ $changed = empty( $url_args['changed'] ) ? array() : $url_args['changed'];
3573
+ $url_args['changed'] = array_merge( $changed, $changed_keys );
3574
+ }
3575
  }
3576
 
3577
  $url = $this->get_plugin_page_url( $url_args );
3586
  * @throws Exception
3587
  */
3588
  private function handle_change_bucket() {
3589
+ if ( $this->get_defined_setting( 'bucket' ) ) {
3590
+ return array();
3591
+ }
3592
+
3593
  // Quick check that bucket name actually given.
3594
  $bucket = empty( $_POST['bucket_name'] ) ? false : $_POST['bucket_name'];
3595
 
3612
 
3613
  // Check and set region.
3614
  $region = empty( $_POST['region_name'] ) ? '' : $_POST['region_name'];
3615
+ $region_required = 'create' === $bucket_mode ? true : $this->get_storage_provider()->region_required();
3616
  $region = $this->check_region( $region, $region_required );
3617
 
3618
  if ( false === $region ) {
3678
  return $changed_keys;
3679
  }
3680
 
3681
+ /**
3682
+ * Handle saving the block all public access preference to the bucket.
3683
+ *
3684
+ * @return array|bool
3685
+ *
3686
+ * There's no actual setting for this, the state of public access to the bucket is checked as required.
3687
+ */
3688
+ private function handle_change_bucket_access() {
3689
+ // Whatever happens, refresh the Use Bucket ACLs setting afterwards.
3690
+ $this->get_settings();
3691
+ $this->remove_setting( 'use-bucket-acls' );
3692
+ $this->save_settings();
3693
+
3694
+ if ( false === $this->get_storage_provider()->block_public_access_allowed() ) {
3695
+ $this->notices->add_notice(
3696
+ printf( _x( "Can't change Block All Public Access setting for %s buckets.", "Trying to change public access setting for given provider's bucket.", 'amazon-s3-and-cloudfront' ), $this->get_storage_provider()->get_provider_service_name() ),
3697
+ array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
3698
+ );
3699
+
3700
+ return false;
3701
+ }
3702
+
3703
+ if ( false === isset( $_POST['block-public-access'] ) ) {
3704
+ $this->notices->add_notice(
3705
+ __( 'No block public access setting provided.', 'amazon-s3-and-cloudfront' ),
3706
+ array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
3707
+ );
3708
+
3709
+ return false;
3710
+ }
3711
+
3712
+ $block_public_access = empty( $_POST['block-public-access'] ) ? false : true;
3713
+
3714
+ $bucket = $this->get_setting( 'bucket' );
3715
+
3716
+ if ( $this->get_storage_provider()->needs_access_keys() ) {
3717
+ $this->notices->add_notice(
3718
+ __( 'Storage Provider not configured with access credentials.', 'amazon-s3-and-cloudfront' ),
3719
+ array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
3720
+ );
3721
+
3722
+ return false;
3723
+ }
3724
+
3725
+ if ( empty( $bucket ) ) {
3726
+ $this->notices->add_notice(
3727
+ __( 'No bucket name provided.', 'amazon-s3-and-cloudfront' ),
3728
+ array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
3729
+ );
3730
+
3731
+ return false;
3732
+ }
3733
+
3734
+ try {
3735
+ $public_access_blocked = $this->get_provider_client()->public_access_blocked( $bucket );
3736
+ } catch ( Exception $e ) {
3737
+ $public_access_blocked = null;
3738
+ }
3739
+
3740
+ if ( empty( $block_public_access ) !== empty( $public_access_blocked ) ) {
3741
+ try {
3742
+ $this->get_provider_client()->block_public_access( $bucket, $block_public_access );
3743
+ } catch ( Exception $e ) {
3744
+ $this->notices->add_notice(
3745
+ __( 'Could not change Block All Public Access status for bucket.', 'amazon-s3-and-cloudfront' ),
3746
+ array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
3747
+ );
3748
+
3749
+ return false;
3750
+ }
3751
+
3752
+ // The bucket level request may succeed, but account level overrides may negate the change or the change simply silently failed.
3753
+ // So check that all is as expected as we can't change the account level settings.
3754
+ try {
3755
+ $public_access_blocked = $this->get_provider_client()->public_access_blocked( $bucket );
3756
+ } catch ( Exception $e ) {
3757
+ $public_access_blocked = null;
3758
+ }
3759
+
3760
+ if ( empty( $block_public_access ) !== empty( $public_access_blocked ) ) {
3761
+ if ( $block_public_access ) {
3762
+ $notice_message = __( '<strong>Failed to Enable Block All Public Access</strong> &mdash; We could not enable Block All Public Access. You will need to log in to the AWS Console and do it manually.', 'amazon-s3-and-cloudfront' );
3763
+ } else {
3764
+ $notice_message = __( '<strong>Failed to Disable Block All Public Access</strong> &mdash; We could not disable Block All Public Access. You will need to log in to the AWS Console and do it manually.', 'amazon-s3-and-cloudfront' );
3765
+ }
3766
+ $notice_message .= ' ' . $this->settings_more_info_link( 'bucket' );
3767
+
3768
+ $this->notices->add_notice(
3769
+ $notice_message,
3770
+ array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
3771
+ );
3772
+
3773
+ return false;
3774
+ }
3775
+
3776
+ // No settings keys actually changed, but flag it anyway as status of bucket has changed.
3777
+ return array( 'use-bucket-acls' );
3778
+ }
3779
+
3780
+ // No settings keys actually changed.
3781
+ return array();
3782
+ }
3783
+
3784
  /**
3785
  * Handle saving settings submitted by user.
3786
  *
3829
  continue;
3830
  }
3831
 
3832
+ if ( 'signed-urls-key-id' === $var && empty( $value ) && ! empty( $_POST['enable-signed-urls'] ) ) {
3833
+ $this->notices->add_notice(
3834
+ $this->get_delivery_provider()->signed_urls_key_id_name() . _x( ' not provided.', 'missing form field', 'amazon-s3-and-cloudfront' ),
3835
+ array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
3836
+ );
3837
+
3838
+ return false;
3839
+ }
3840
+
3841
+ if ( 'signed-urls-key-file-path' === $var && is_string( $value ) && ! empty( $value ) ) {
3842
+ // Can be a Windows path with backslashes, so need to undo what POST does to them.
3843
+ $value = stripslashes( $value );
3844
+ }
3845
+
3846
+ if ( 'signed-urls-key-file-path' === $var && empty( $value ) && ! empty( $_POST['enable-signed-urls'] ) ) {
3847
+ $this->notices->add_notice(
3848
+ $this->get_delivery_provider()->signed_urls_key_file_path_name() . _x( ' not provided.', 'missing form field', 'amazon-s3-and-cloudfront' ),
3849
+ array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
3850
+ );
3851
+
3852
+ return false;
3853
+ }
3854
+
3855
+ if ( 'signed-urls-object-prefix' === $var && empty( $value ) && ! empty( $_POST['enable-signed-urls'] ) ) {
3856
+ $this->notices->add_notice(
3857
+ $this->get_delivery_provider()->signed_urls_object_prefix_name() . _x( ' not provided.', 'missing form field', 'amazon-s3-and-cloudfront' ),
3858
+ array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
3859
+ );
3860
+
3861
+ return false;
3862
+ }
3863
+
3864
  $this->set_setting( $var, $value );
3865
 
3866
  // Some setting changes might have knock-on effects that require confirmation of secondary settings.
3867
+ if ( ( empty( $old_settings[ $var ] ) !== empty( $value ) ) || ( isset( $old_settings[ $var ] ) && $old_settings[ $var ] !== $value ) ) {
3868
  $changed_keys[] = $var;
3869
  }
3870
  }
4046
 
4047
  foreach ( $blogs as $blog ) {
4048
  $blog = (array) $blog;
4049
+ $blog_ids[] = (int) $blog['blog_id'];
4050
  }
4051
 
4052
  return $blog_ids;
4065
  return true;
4066
  }
4067
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4068
  /**
4069
  * Make admin notice for when object ACL has changed
4070
  *
4072
  */
4073
  function make_acl_admin_notice( Media_Library_Item $as3cf_item ) {
4074
  $filename = wp_basename( $as3cf_item->path() );
4075
+ $acl = $as3cf_item->is_private() ? $this->get_storage_provider()->get_private_acl() : $this->get_storage_provider()->get_default_acl();
4076
  $acl_name = $this->get_acl_display_name( $acl );
4077
  $text = sprintf( __( '<strong>WP Offload Media</strong> &mdash; The file %s has been given %s permissions in the bucket.', 'amazon-s3-and-cloudfront' ), "<strong>{$filename}</strong>", "<strong>{$acl_name}</strong>" );
4078
 
4343
  $media_counts = $this->media_counts();
4344
 
4345
  $output .= 'Media Files: ';
4346
+ $output .= number_format_i18n( $media_counts['total'] );
4347
  $output .= "\r\n";
4348
 
4349
  $output .= 'Offloaded Media Files: ';
4350
+ $output .= number_format_i18n( $media_counts['offloaded'] );
4351
  $output .= "\r\n";
4352
 
4353
  $output .= 'Not Offloaded Media Files: ';
4354
+ $output .= number_format_i18n( $media_counts['not_offloaded'] );
 
 
4355
  $output .= "\r\n\r\n";
4356
 
4357
  $output .= 'Number of Image Sizes: ';
4436
  $output .= "\r\n";
4437
  $output .= "\r\n";
4438
 
4439
+ $output .= 'OME Metadata Version: ';
4440
+ $output .= esc_html( $this->get_setting( 'post_meta_version' ) );
4441
+ $output .= "\r\n\r\n";
4442
+
4443
+ $storage_provider = $this->get_storage_provider();
4444
 
4445
+ if ( empty( $storage_provider ) ) {
4446
+ $output .= 'Storage Provider: Not configured';
4447
  $output .= "\r\n";
4448
  } else {
4449
+ $output .= 'Storage Provider: ' . $storage_provider::get_provider_service_name();
4450
  $output .= "\r\n";
4451
 
4452
+ if ( $storage_provider::use_server_roles_allowed() ) {
4453
+ $output .= 'Use Server Roles: ';
4454
+ $output .= $storage_provider->use_server_roles() ? 'On' : 'Off';
4455
  } else {
4456
  $output .= 'Use Server Roles: N/A';
4457
  }
4458
  $output .= "\r\n";
4459
 
4460
+ if ( $storage_provider::use_key_file_allowed() ) {
4461
  $output .= 'Key File Path: ';
4462
+ $output .= empty( $storage_provider->get_key_file_path() ) ? 'None' : esc_html( $storage_provider->get_key_file_path() );
4463
  $output .= "\r\n";
4464
  $output .= 'Key File Path Define: ';
4465
+ $output .= $storage_provider::key_file_path_constant() ? $storage_provider::key_file_path_constant() : 'Not defined';
4466
  } else {
4467
  $output .= 'Key File Path: N/A';
4468
  }
4469
  $output .= "\r\n";
4470
 
4471
+ if ( $storage_provider::use_access_keys_allowed() ) {
4472
  $output .= 'Access Keys Set: ';
4473
+ $output .= $storage_provider->are_access_keys_set() ? 'Yes' : 'No';
4474
  $output .= "\r\n";
4475
  $output .= 'Access Key ID Define: ';
4476
+ $output .= $storage_provider::access_key_id_constant() ? $storage_provider::access_key_id_constant() : 'Not defined';
4477
  $output .= "\r\n";
4478
  $output .= 'Secret Access Key Define: ';
4479
+ $output .= $storage_provider::secret_access_key_constant() ? $storage_provider::secret_access_key_constant() : 'Not defined';
4480
  } else {
4481
  $output .= 'Access Keys Set: N/A';
4482
  }
4484
  }
4485
  $output .= "\r\n";
4486
 
4487
+ $bucket = $this->get_setting( 'bucket' );
4488
  $output .= 'Bucket: ';
4489
+ $output .= empty( $bucket ) ? '(none)' : esc_html( $bucket );
4490
  $output .= "\r\n";
4491
+ $value = $this->get_setting( 'region' );
4492
  $output .= 'Region: ';
4493
+ if ( is_wp_error( $value ) ) {
4494
+ $output .= '(error: "' . esc_html( $value->get_error_message() ) . '")';
4495
+ } elseif ( empty( $value ) ) {
4496
+ $output .= '(empty)';
4497
+ } else {
4498
+ $output .= esc_html( $value );
4499
  }
4500
  $output .= "\r\n";
4501
+ if (
4502
+ ! empty( $storage_provider ) &&
4503
+ ! empty( $bucket ) &&
4504
+ ! $storage_provider->needs_access_keys() &&
4505
+ $storage_provider->block_public_access_allowed()
4506
+ ) {
4507
+ try {
4508
+ $public_access_blocked = $this->get_provider_client()->public_access_blocked( $bucket );
4509
+ } catch ( Exception $e ) {
4510
+ $public_access_blocked = null;
4511
+ }
4512
+ $output .= 'Block All Public Access: ';
4513
+ if ( true === $public_access_blocked ) {
4514
+ $output .= 'Enabled';
4515
+ } elseif ( false === $public_access_blocked ) {
4516
+ $output .= 'Disabled';
4517
+ } else {
4518
+ $output .= 'Unknown';
4519
+ }
4520
+ $output .= "\r\n";
4521
+ }
4522
  $output .= "\r\n";
4523
 
4524
  $output .= 'Copy Files to Bucket: ';
4527
  $output .= 'Enable Path: ';
4528
  $output .= $this->on_off( 'enable-object-prefix' );
4529
  $output .= "\r\n";
4530
+ $value = $this->get_setting( 'object-prefix' );
4531
  $output .= 'Custom Path: ';
4532
+ $output .= empty( $value ) ? '(none)' : esc_html( $value );
4533
  $output .= "\r\n";
4534
  $output .= 'Use Year/Month: ';
4535
  $output .= $this->on_off( 'use-yearmonth-folders' );
4539
  $output .= "\r\n";
4540
  $output .= "\r\n";
4541
 
4542
+ $delivery_provider = $this->get_delivery_provider();
4543
+
4544
+ if ( empty( $delivery_provider ) ) {
4545
+ $output .= 'Delivery Provider: Not configured';
4546
+ $output .= "\r\n";
4547
+ } else {
4548
+ $output .= 'Delivery Provider: ' . $delivery_provider::get_provider_service_name();
4549
+ $output .= "\r\n";
4550
+ $output .= 'Rewrite Media URLs: ';
4551
+ $output .= $this->on_off( 'serve-from-s3' );
4552
+ $output .= "\r\n";
4553
+
4554
+ if ( $delivery_provider::delivery_domain_allowed() ) {
4555
+ $output .= 'Enable Custom Domain (CNAME): ';
4556
+ $output .= $this->on_off( 'enable-delivery-domain' );
4557
+ $output .= "\r\n";
4558
+ $value = $this->get_setting( 'delivery-domain' );
4559
+ $output .= 'Custom Domain (CNAME): ';
4560
+ $output .= empty( $value ) ? '(none)' : esc_html( $value );
4561
+ $output .= "\r\n";
4562
+ }
4563
+
4564
+ if ( $delivery_provider::use_signed_urls_key_file_allowed() ) {
4565
+ $output .= 'Enable Signed URLs: ';
4566
+ $output .= $this->on_off( 'enable-signed-urls' );
4567
+ $output .= "\r\n";
4568
+ $output .= 'Signed URLs Key ID Set: ';
4569
+ $output .= $delivery_provider->get_signed_urls_key_id() ? 'Yes' : 'No';
4570
+ $output .= "\r\n";
4571
+ $value = $this->get_setting( 'signed-urls-key-file-path' );
4572
+ $output .= 'Signed URLs Key File Path: ';
4573
+ $output .= empty( $value ) ? '(none)' : esc_html( $value );
4574
+ $output .= "\r\n";
4575
+ $value = $this->get_setting( 'signed-urls-object-prefix' );
4576
+ $output .= 'Signed URLs Private Prefix: ';
4577
+ $output .= empty( $value ) ? '(none)' : esc_html( $value );
4578
+ $output .= "\r\n";
4579
+ }
4580
+ $output .= "\r\n";
4581
+ }
4582
+
4583
  $output .= 'Force HTTPS: ';
4584
  $output .= $this->on_off( 'force-https' );
4585
  $output .= "\r\n";
4744
  * @return string
4745
  */
4746
  function get_acl_display_name( $acl ) {
4747
+ $acl = empty( $acl ) ? 'default' : $acl;
4748
  $acl = ( 'public-read' === $acl ) ? 'public' : $acl;
4749
 
4750
  return ucwords( str_replace( '-', ' ', $acl ) );
4874
  * @return string
4875
  */
4876
  function get_access_denied_notice_message( $single = true ) {
4877
+ if ( $this->get_storage_provider()->needs_access_keys() ) {
4878
  return sprintf( __( '<a href="%s">Define your access keys</a> to enable write access to the bucket', 'amazon-s3-and-cloudfront' ), '#settings' );
4879
  }
4880
 
4978
  */
4979
  public function media_counts( $skip_transient = false, $force = false ) {
4980
  if ( $skip_transient || false === ( $attachment_counts = get_site_transient( 'as3cf_attachment_counts' ) ) ) {
4981
+ $table_prefixes = $this->get_all_blog_table_prefixes();
4982
+ $total = 0;
4983
+ $offloaded = 0;
4984
+ $not_offloaded = 0;
 
 
 
4985
 
4986
  foreach ( $table_prefixes as $blog_id => $table_prefix ) {
4987
  $this->switch_to_blog( $blog_id );
4988
 
4989
+ $counts = Media_Library_Item::count_attachments( $skip_transient, $force );
4990
+ $total += $counts['total'];
4991
+ $offloaded += $counts['offloaded'];
4992
+ $not_offloaded += $counts['not_offloaded'];
 
 
 
4993
 
4994
  $this->restore_current_blog();
4995
  }
4996
 
4997
  $attachment_counts = array(
4998
+ 'total' => $total,
4999
+ 'offloaded' => $offloaded,
5000
+ 'not_offloaded' => $not_offloaded,
 
 
 
5001
  );
5002
 
5003
+ set_site_transient( 'as3cf_attachment_counts', $attachment_counts, 5 * MINUTE_IN_SECONDS );
5004
  }
5005
 
5006
  return $attachment_counts;
5111
  exit( $exit_code );
5112
  }
5113
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5114
  /**
5115
  * Upgrade the 'virtual host' / 'bucket as domain' setting to the
5116
  * new CloudFront / Domain setting
5153
  }
5154
 
5155
  /**
5156
+ * Potentially update path for delivery URLs.
5157
  *
5158
+ * @param string $path Path in bucket to be used in URL.
5159
+ * @param string $domain Domain to be used in URL.
5160
+ * @param int|null $timestamp Optional time that signed URL expires.
5161
  *
5162
  * @return string
5163
+ *
5164
+ * Note: This is a wrapper for a filter, which only fires default (storage) delivery provider is not in use.
5165
  */
5166
+ public function maybe_update_delivery_path( $path, $domain, $timestamp = null ) {
5167
+ if ( static::get_default_delivery_provider() !== $this->get_delivery_provider()->get_provider_key_name() ) {
5168
+ $path_parts = apply_filters( 'as3cf_cloudfront_path_parts', explode( '/', $path ), $domain, $timestamp ); // Backwards compatibility.
5169
+ $path_parts = apply_filters( 'as3cf_delivery_domain_path_parts', $path_parts, $domain, $timestamp );
5170
 
5171
  if ( ! empty( $path_parts ) ) {
5172
  $path = implode( '/', $path_parts );
5260
  $provider_object['key'] = $provider_object['path'];
5261
  $provider_object['url'] = $this->get_attachment_provider_url( $id, $as3cf_item );
5262
 
5263
+ $acl = $as3cf_item->is_private() ? $this->get_storage_provider()->get_private_acl() : $this->get_storage_provider()->get_default_acl();
5264
  $acl_info = array(
5265
  'acl' => $acl,
5266
  'name' => $this->get_acl_display_name( $acl ),
5272
  }
5273
 
5274
  $provider_object['acl'] = $acl_info;
5275
+ $provider_object['region'] = $this->get_storage_provider()->get_region_name( $provider_object['region'] );
5276
  $provider_object['provider_name'] = $this->get_provider_service_name( $provider_object['provider'] );
5277
 
5278
  return $provider_object;
5354
  *
5355
  * @return array
5356
  */
5357
+ function add_media_row_actions( array $actions, $post ) {
5358
  return $actions;
5359
  }
5360
 
5443
  /**
5444
  * Get ACL for intermediate size.
5445
  *
5446
+ * @param int $attachment_id
5447
+ * @param string $size
5448
+ * @param string $bucket Optional bucket that ACL is potentially to be used with.
5449
+ * @param Media_Library_Item|null $as3cf_item Optional item.
5450
  *
5451
+ * @return string|null
5452
  */
5453
+ public function get_acl_for_intermediate_size( $attachment_id, $size, $bucket = null, Media_Library_Item $as3cf_item = null ) {
5454
+ if ( empty( $as3cf_item ) ) {
5455
+ $as3cf_item = Media_Library_Item::get_by_source_id( $attachment_id );
5456
+ }
5457
+
5458
+ $acl = null;
5459
+
5460
+ if ( $this->use_acl_for_intermediate_size( $attachment_id, $size, $bucket, $as3cf_item ) ) {
5461
+ $acl = $this->get_storage_provider()->get_default_acl();
5462
+
5463
+ if ( ! empty( $as3cf_item ) ) {
5464
+ $acl = $as3cf_item->is_private_size( $size ) ? $this->get_storage_provider()->get_private_acl() : $this->get_storage_provider()->get_default_acl();
5465
+ }
5466
+ }
5467
+
5468
+ return $acl;
5469
+ }
5470
+
5471
+ /**
5472
+ * Are ACLs in use for intermediate size on bucket?
5473
+ *
5474
+ * @param int $attachment_id
5475
+ * @param string $size
5476
+ * @param string $bucket Optional bucket that ACL is potentially to be used with.
5477
+ * @param Media_Library_Item|null $as3cf_item Optional item.
5478
+ *
5479
+ * @return bool
5480
+ */
5481
+ public function use_acl_for_intermediate_size( $attachment_id, $size, $bucket = null, Media_Library_Item $as3cf_item = null ) {
5482
+ if ( empty( $as3cf_item ) ) {
5483
+ $as3cf_item = Media_Library_Item::get_by_source_id( $attachment_id );
5484
+ }
5485
+
5486
+ if ( empty( $bucket ) ) {
5487
+ $bucket = empty( $as3cf_item ) ? null : $as3cf_item->bucket();
5488
+ }
5489
+
5490
+ if ( empty( $bucket ) ) {
5491
+ $bucket = $this->get_setting( 'bucket', null );
5492
+ }
5493
+
5494
+ $use_acl = apply_filters( 'as3cf_use_bucket_acls_for_intermediate_size', $this->get_setting( 'use-bucket-acls', true ), $attachment_id, $size, $bucket, $as3cf_item );
5495
+ $use_private_prefix = apply_filters( 'as3cf_enable_signed_urls_for_intermediate_size', $this->private_prefix_enabled(), $attachment_id, $size, $bucket, $as3cf_item );
5496
 
5497
+ // If signed custom URLs are in play, and we have a private object, usually you can not use ACLs.
5498
+ if ( $use_acl && $use_private_prefix && ! empty( $as3cf_item ) && $as3cf_item->is_private_size( $size ) ) {
5499
+ $use_acl = false;
5500
  }
5501
 
5502
+ // Allow complete override if signed custom URLs and ACLs do play nice together some how, or other factors in play.
5503
+ return apply_filters( 'as3cf_use_acl_for_intermediate_size', $use_acl, $attachment_id, $size, $bucket, $as3cf_item );
5504
  }
5505
 
5506
  /**
5607
  );
5608
  $this->notices->add_notice( $message, $args );
5609
 
5610
+ if ( is_a( $this->get_storage_provider(), '\DeliciousBrains\WP_Offload_Media\Providers\Storage\AWS_Provider' ) && $this->get_storage_provider()->needs_access_keys() ) {
5611
  // Have access keys been defined in still active AWS plugin's database settings?
5612
  $aws_settings = get_site_option( 'aws_settings' );
5613
 
5676
 
5677
  return $data;
5678
  }
5679
+
5680
+ /**
5681
+ * Is there an upgrade in progress?
5682
+ *
5683
+ * @return bool
5684
+ */
5685
+ public function is_upgrading() {
5686
+ return Upgrade::is_locked();
5687
+ }
5688
+
5689
+ /**
5690
+ * Do current settings allow for private prefix to be used?
5691
+ *
5692
+ * @return bool
5693
+ */
5694
+ public function private_prefix_enabled() {
5695
+ if (
5696
+ $this->get_setting( 'enable-delivery-domain', false ) &&
5697
+ $this->get_setting( 'enable-signed-urls', false ) &&
5698
+ ! empty( $this->get_setting( 'signed-urls-object-prefix' ) )
5699
+ ) {
5700
+ return true;
5701
+ }
5702
+
5703
+ return false;
5704
+ }
5705
  }
classes/as3cf-filter.php CHANGED
@@ -75,7 +75,7 @@ abstract class AS3CF_Filter {
75
  $url = $this->get_url( $attachment['attachment_id'] );
76
 
77
  if ( $url ) {
78
- $value[ $key ]['file'] = $this->get_url( $attachment['attachment_id'] );
79
  }
80
  }
81
 
@@ -501,7 +501,7 @@ abstract class AS3CF_Filter {
501
  return false;
502
  }
503
 
504
- $base_url = $this->as3cf->encode_filename_in_path( AS3CF_Utils::reduce_url( $this->get_base_url( $attachment_id ) ) );
505
  $basename = wp_basename( $base_url );
506
 
507
  // Add full size URL
@@ -509,10 +509,10 @@ abstract class AS3CF_Filter {
509
 
510
  // Add additional image size URLs
511
  foreach ( $meta['sizes'] as $size ) {
512
- $base_urls[] = str_replace( $basename, $this->as3cf->encode_filename_in_path( $size['file'] ), $base_url );
513
  }
514
 
515
- $url = $this->as3cf->encode_filename_in_path( AS3CF_Utils::reduce_url( $url ) );
516
 
517
  if ( in_array( $url, $base_urls ) ) {
518
  // Match found, return true
@@ -590,10 +590,10 @@ abstract class AS3CF_Filter {
590
  return null;
591
  }
592
 
593
- $basename = $this->as3cf->encode_filename_in_path( wp_basename( $this->as3cf->maybe_remove_query_string( $url ) ) );
594
 
595
  foreach ( $meta['sizes'] as $size => $file ) {
596
- if ( $basename === $this->as3cf->encode_filename_in_path( $file['file'] ) ) {
597
  return $size;
598
  }
599
  }
75
  $url = $this->get_url( $attachment['attachment_id'] );
76
 
77
  if ( $url ) {
78
+ $value[ $key ]['file'] = $url;
79
  }
80
  }
81
 
501
  return false;
502
  }
503
 
504
+ $base_url = AS3CF_Utils::encode_filename_in_path( AS3CF_Utils::reduce_url( $this->get_base_url( $attachment_id ) ) );
505
  $basename = wp_basename( $base_url );
506
 
507
  // Add full size URL
509
 
510
  // Add additional image size URLs
511
  foreach ( $meta['sizes'] as $size ) {
512
+ $base_urls[] = str_replace( $basename, AS3CF_Utils::encode_filename_in_path( $size['file'] ), $base_url );
513
  }
514
 
515
+ $url = AS3CF_Utils::encode_filename_in_path( AS3CF_Utils::reduce_url( $url ) );
516
 
517
  if ( in_array( $url, $base_urls ) ) {
518
  // Match found, return true
590
  return null;
591
  }
592
 
593
+ $basename = AS3CF_Utils::encode_filename_in_path( wp_basename( $this->as3cf->maybe_remove_query_string( $url ) ) );
594
 
595
  foreach ( $meta['sizes'] as $size => $file ) {
596
+ if ( $basename === AS3CF_Utils::encode_filename_in_path( $file['file'] ) ) {
597
  return $size;
598
  }
599
  }
classes/as3cf-notices.php CHANGED
@@ -350,8 +350,7 @@ class AS3CF_Notices {
350
  * @param string|bool $tab
351
  */
352
  protected function maybe_show_notice( $notice, $dismissed_notices, $tab ) {
353
- $screen = get_current_screen();
354
- if ( $notice['only_show_in_settings'] && false === strpos( strval( $screen->id ), $this->as3cf->hook_suffix ) ) {
355
  return;
356
  }
357
 
350
  * @param string|bool $tab
351
  */
352
  protected function maybe_show_notice( $notice, $dismissed_notices, $tab ) {
353
+ if ( $notice['only_show_in_settings'] && ! $this->as3cf->our_screen() ) {
 
354
  return;
355
  }
356
 
classes/as3cf-plugin-base.php CHANGED
@@ -117,6 +117,13 @@ abstract class AS3CF_Plugin_Base {
117
  $saved_settings = get_site_option( static::SETTINGS_KEY );
118
  $this->settings = $this->filter_settings( $saved_settings );
119
 
 
 
 
 
 
 
 
120
  // If defined settings keys have changed since last time settings were saved to database, re-save to remove the new keys.
121
  if ( ! empty( $saved_settings ) && ! empty( $this->defined_settings ) && ! empty( array_intersect_key( $saved_settings, $this->defined_settings ) ) ) {
122
  $this->save_settings();
@@ -319,6 +326,24 @@ abstract class AS3CF_Plugin_Base {
319
  return array();
320
  }
321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  /**
323
  * Sanitize a setting value, maybe.
324
  *
@@ -342,6 +367,19 @@ abstract class AS3CF_Plugin_Base {
342
  }
343
  } else {
344
  $value = sanitize_text_field( $value );
 
 
 
 
 
 
 
 
 
 
 
 
 
345
  }
346
 
347
  return $value;
117
  $saved_settings = get_site_option( static::SETTINGS_KEY );
118
  $this->settings = $this->filter_settings( $saved_settings );
119
 
120
+ // Now that we have merged database and defined settings, sanitize them before use.
121
+ if ( ! empty( $this->settings ) ) {
122
+ foreach ( $this->settings as $key => $val ) {
123
+ $this->settings[ $key ] = $this->sanitize_setting( $key, $val );
124
+ }
125
+ }
126
+
127
  // If defined settings keys have changed since last time settings were saved to database, re-save to remove the new keys.
128
  if ( ! empty( $saved_settings ) && ! empty( $this->defined_settings ) && ! empty( array_intersect_key( $saved_settings, $this->defined_settings ) ) ) {
129
  $this->save_settings();
326
  return array();
327
  }
328
 
329
+ /**
330
+ * List of settings that should be treated as paths.
331
+ *
332
+ * @return array
333
+ */
334
+ function get_path_format_settings() {
335
+ return array();
336
+ }
337
+
338
+ /**
339
+ * List of settings that should be treated as directory paths.
340
+ *
341
+ * @return array
342
+ */
343
+ function get_prefix_format_settings() {
344
+ return array();
345
+ }
346
+
347
  /**
348
  * Sanitize a setting value, maybe.
349
  *
367
  }
368
  } else {
369
  $value = sanitize_text_field( $value );
370
+
371
+ // Make sure path setting is absolute and not just "/".
372
+ // But not on Windows as it can have various forms of path, e.g. C:\Sites and \\shared\sites.
373
+ if ( '/' === DIRECTORY_SEPARATOR && in_array( $key, $this->get_path_format_settings() ) ) {
374
+ $value = trim( AS3CF_Utils::unleadingslashit( $value ) );
375
+ $value = empty( $value ) ? '' : AS3CF_Utils::leadingslashit( $value );
376
+ }
377
+
378
+ // Make sure prefix setting is relative with trailing slash for visibility.
379
+ if ( in_array( $key, $this->get_prefix_format_settings() ) ) {
380
+ $value = trim( untrailingslashit( $value ) );
381
+ $value = empty( $value ) ? '' : AS3CF_Utils::trailingslash_prefix( $value );
382
+ }
383
  }
384
 
385
  return $value;
classes/as3cf-plugin-compatibility.php CHANGED
@@ -10,7 +10,7 @@
10
  */
11
 
12
  use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
13
- use DeliciousBrains\WP_Offload_Media\Providers\Provider;
14
 
15
  // Exit if accessed directly
16
  if ( ! defined( 'ABSPATH' ) ) {
@@ -101,6 +101,7 @@ class AS3CF_Plugin_Compatibility {
101
  * /wp-includes/class-wp-image-editor.php
102
  */
103
  add_action( 'as3cf_pre_upload_attachment', array( $this, 'image_editor_remove_files' ), 10, 3 );
 
104
  add_filter( 'as3cf_get_attached_file', array( $this, 'image_editor_download_file' ), 10, 4 );
105
  add_filter( 'as3cf_upload_attachment_local_files_to_remove', array( $this, 'image_editor_remove_original_image' ), 10, 3 );
106
  add_filter( 'as3cf_get_attached_file', array( $this, 'customizer_crop_download_file' ), 10, 4 );
@@ -343,7 +344,7 @@ class AS3CF_Plugin_Compatibility {
343
  $as3cf_item->source_id(),
344
  $as3cf_item->source_path(),
345
  wp_basename( $as3cf_item->original_source_path() ),
346
- $as3cf_item->private_sizes(),
347
  $as3cf_item->id()
348
  );
349
 
@@ -369,7 +370,7 @@ class AS3CF_Plugin_Compatibility {
369
  }
370
 
371
  /**
372
- * Allow the WordPress Image Editor to edit files that have been copied to S3
373
  * but removed from the local server, by copying them back temporarily
374
  *
375
  * @param string $url
@@ -396,12 +397,12 @@ class AS3CF_Plugin_Compatibility {
396
  $as3cf_item->provider(),
397
  $as3cf_item->region(),
398
  $as3cf_item->bucket(),
399
- dirname( $as3cf_item->path() ) . '/' . $original_filename,
400
  $as3cf_item->is_private(),
401
  $as3cf_item->source_id(),
402
  $as3cf_item->source_path(),
403
  wp_basename( $as3cf_item->original_source_path() ),
404
- $as3cf_item->private_sizes(),
405
  $as3cf_item->id()
406
  );
407
  $orig_file = dirname( $file ) . '/' . $original_filename;
@@ -413,7 +414,7 @@ class AS3CF_Plugin_Compatibility {
413
  if ( $provider_file = $this->copy_provider_file_to_server( $as3cf_item, $file ) ) {
414
  // Return the file if successfully downloaded from bucket.
415
  return $provider_file;
416
- };
417
  }
418
 
419
  $action = filter_input( INPUT_GET, 'action' ) ?: filter_input( INPUT_POST, 'action' );
@@ -425,7 +426,7 @@ class AS3CF_Plugin_Compatibility {
425
  if ( $provider_file = $this->copy_provider_file_to_server( $as3cf_item, $file ) ) {
426
  // Return the file if successfully downloaded from bucket.
427
  return $provider_file;
428
- };
429
  }
430
  }
431
  }
@@ -586,11 +587,13 @@ class AS3CF_Plugin_Compatibility {
586
  * @return string|bool File if downloaded, false on failure
587
  */
588
  public function copy_provider_file_to_server( Media_Library_Item $as3cf_item, $file ) {
 
 
589
  // Make sure the directory exists
590
  $dir = dirname( $file );
591
  if ( ! wp_mkdir_p( $dir ) ) {
592
  $error_message = sprintf( __( 'The local directory %s does not exist and could not be created.', 'amazon-s3-and-cloudfront' ), $dir );
593
- AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from the bucket: %s', 'amazon-s3-and-cloudfront' ), $as3cf_item->path(), $error_message ) );
594
 
595
  return false;
596
  }
@@ -598,11 +601,11 @@ class AS3CF_Plugin_Compatibility {
598
  try {
599
  $this->as3cf->get_provider_client( $as3cf_item->region(), true )->get_object( array(
600
  'Bucket' => $as3cf_item->bucket(),
601
- 'Key' => $as3cf_item->path(),
602
  'SaveAs' => $file,
603
  ) );
604
  } catch ( Exception $e ) {
605
- AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from the bucket: %s', 'amazon-s3-and-cloudfront' ), $as3cf_item->path(), $e->getMessage() ) );
606
 
607
  return false;
608
  }
@@ -615,7 +618,7 @@ class AS3CF_Plugin_Compatibility {
615
  *
616
  * @param string $region
617
  *
618
- * @return Provider|null
619
  * @throws Exception
620
  */
621
  protected function register_stream_wrapper( $region ) {
@@ -658,7 +661,7 @@ class AS3CF_Plugin_Compatibility {
658
  $client = $this->register_stream_wrapper( $as3cf_item->region() );
659
 
660
  if ( ! empty( $client ) ) {
661
- return $client->prepare_stream_wrapper_file( $as3cf_item->region(), $as3cf_item->bucket(), $as3cf_item->path() );
662
  }
663
 
664
  return $url;
@@ -683,12 +686,12 @@ class AS3CF_Plugin_Compatibility {
683
  ) {
684
  // Ensure each filename is encoded the same way as URL, slightly fixed up for wp_basename() manipulation compatibility.
685
  if ( ! empty( $data['file'] ) ) {
686
- $data['file'] = $this->as3cf->encode_filename_in_path( $data['file'] );
687
  }
688
 
689
  if ( ! empty( $data['sizes'] ) ) {
690
  $data['sizes'] = array_map( function ( $size ) {
691
- $size['file'] = $this->as3cf->encode_filename_in_path( $size['file'] );
692
 
693
  return $size;
694
  }, $data['sizes'] );
@@ -813,9 +816,9 @@ class AS3CF_Plugin_Compatibility {
813
  return $image_meta;
814
  }
815
 
816
- $image_basename = $this->as3cf->encode_filename_in_path( wp_basename( $image_meta['file'] ) );
817
 
818
- if ( false === strpos( $this->as3cf->encode_filename_in_path( $as3cf_item->path() ), $image_basename ) ) {
819
  // Not the correct attachment, abort
820
  return $image_meta;
821
  }
@@ -828,7 +831,7 @@ class AS3CF_Plugin_Compatibility {
828
  // Ensure each size filename is encoded the same way as URL.
829
  if ( ! empty( $image_meta['sizes'] ) ) {
830
  $image_meta['sizes'] = array_map( function ( $size ) {
831
- $size['file'] = $this->as3cf->encode_filename_in_path( $size['file'] );
832
 
833
  return $size;
834
  }, $image_meta['sizes'] );
10
  */
11
 
12
  use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
13
+ use DeliciousBrains\WP_Offload_Media\Providers\Storage\Storage_Provider;
14
 
15
  // Exit if accessed directly
16
  if ( ! defined( 'ABSPATH' ) ) {
101
  * /wp-includes/class-wp-image-editor.php
102
  */
103
  add_action( 'as3cf_pre_upload_attachment', array( $this, 'image_editor_remove_files' ), 10, 3 );
104
+ add_filter( 'as3cf_get_attached_file_noop', array( $this, 'image_editor_download_file' ), 10, 4 );
105
  add_filter( 'as3cf_get_attached_file', array( $this, 'image_editor_download_file' ), 10, 4 );
106
  add_filter( 'as3cf_upload_attachment_local_files_to_remove', array( $this, 'image_editor_remove_original_image' ), 10, 3 );
107
  add_filter( 'as3cf_get_attached_file', array( $this, 'customizer_crop_download_file' ), 10, 4 );
344
  $as3cf_item->source_id(),
345
  $as3cf_item->source_path(),
346
  wp_basename( $as3cf_item->original_source_path() ),
347
+ $as3cf_item->extra_info(),
348
  $as3cf_item->id()
349
  );
350
 
370
  }
371
 
372
  /**
373
+ * Allow the WordPress Image Editor to edit files that have been copied to provider
374
  * but removed from the local server, by copying them back temporarily
375
  *
376
  * @param string $url
397
  $as3cf_item->provider(),
398
  $as3cf_item->region(),
399
  $as3cf_item->bucket(),
400
+ $as3cf_item->normalized_path_dir() . $original_filename,
401
  $as3cf_item->is_private(),
402
  $as3cf_item->source_id(),
403
  $as3cf_item->source_path(),
404
  wp_basename( $as3cf_item->original_source_path() ),
405
+ $as3cf_item->extra_info(),
406
  $as3cf_item->id()
407
  );
408
  $orig_file = dirname( $file ) . '/' . $original_filename;
414
  if ( $provider_file = $this->copy_provider_file_to_server( $as3cf_item, $file ) ) {
415
  // Return the file if successfully downloaded from bucket.
416
  return $provider_file;
417
+ }
418
  }
419
 
420
  $action = filter_input( INPUT_GET, 'action' ) ?: filter_input( INPUT_POST, 'action' );
426
  if ( $provider_file = $this->copy_provider_file_to_server( $as3cf_item, $file ) ) {
427
  // Return the file if successfully downloaded from bucket.
428
  return $provider_file;
429
+ }
430
  }
431
  }
432
  }
587
  * @return string|bool File if downloaded, false on failure
588
  */
589
  public function copy_provider_file_to_server( Media_Library_Item $as3cf_item, $file ) {
590
+ $filename = wp_basename( $file );
591
+
592
  // Make sure the directory exists
593
  $dir = dirname( $file );
594
  if ( ! wp_mkdir_p( $dir ) ) {
595
  $error_message = sprintf( __( 'The local directory %s does not exist and could not be created.', 'amazon-s3-and-cloudfront' ), $dir );
596
+ AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from the bucket: %s', 'amazon-s3-and-cloudfront' ), $as3cf_item->key( $filename ), $error_message ) );
597
 
598
  return false;
599
  }
601
  try {
602
  $this->as3cf->get_provider_client( $as3cf_item->region(), true )->get_object( array(
603
  'Bucket' => $as3cf_item->bucket(),
604
+ 'Key' => $as3cf_item->key( $filename ),
605
  'SaveAs' => $file,
606
  ) );
607
  } catch ( Exception $e ) {
608
+ AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from the bucket: %s', 'amazon-s3-and-cloudfront' ), $as3cf_item->key( $filename ), $e->getMessage() ) );
609
 
610
  return false;
611
  }
618
  *
619
  * @param string $region
620
  *
621
+ * @return Storage_Provider|null
622
  * @throws Exception
623
  */
624
  protected function register_stream_wrapper( $region ) {
661
  $client = $this->register_stream_wrapper( $as3cf_item->region() );
662
 
663
  if ( ! empty( $client ) ) {
664
+ return $client->prepare_stream_wrapper_file( $as3cf_item->region(), $as3cf_item->bucket(), $as3cf_item->key() );
665
  }
666
 
667
  return $url;
686
  ) {
687
  // Ensure each filename is encoded the same way as URL, slightly fixed up for wp_basename() manipulation compatibility.
688
  if ( ! empty( $data['file'] ) ) {
689
+ $data['file'] = AS3CF_Utils::encode_filename_in_path( $data['file'] );
690
  }
691
 
692
  if ( ! empty( $data['sizes'] ) ) {
693
  $data['sizes'] = array_map( function ( $size ) {
694
+ $size['file'] = AS3CF_Utils::encode_filename_in_path( $size['file'] );
695
 
696
  return $size;
697
  }, $data['sizes'] );
816
  return $image_meta;
817
  }
818
 
819
+ $image_basename = AS3CF_Utils::encode_filename_in_path( wp_basename( $image_meta['file'] ) );
820
 
821
+ if ( false === strpos( AS3CF_Utils::encode_filename_in_path( $as3cf_item->path() ), $image_basename ) ) {
822
  // Not the correct attachment, abort
823
  return $image_meta;
824
  }
831
  // Ensure each size filename is encoded the same way as URL.
832
  if ( ! empty( $image_meta['sizes'] ) ) {
833
  $image_meta['sizes'] = array_map( function ( $size ) {
834
+ $size['file'] = AS3CF_Utils::encode_filename_in_path( $size['file'] );
835
 
836
  return $size;
837
  }, $image_meta['sizes'] );
classes/as3cf-utils.php CHANGED
@@ -8,9 +8,9 @@
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  */
10
 
11
- // Exit if accessed directly
12
  use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
13
 
 
14
  if ( ! defined( 'ABSPATH' ) ) {
15
  exit;
16
  }
@@ -45,7 +45,40 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
45
  * @return string
46
  */
47
  public static function trailingslash_prefix( $string ) {
48
- return ltrim( trailingslashit( $string ), '/\\' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  }
50
 
51
  /**
@@ -267,10 +300,9 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
267
  * @return array
268
  */
269
  public static function get_attachment_edited_keys( $attachment_id, Media_Library_Item $as3cf_item ) {
270
- $prefix = trailingslashit( $as3cf_item->normalized_path_dir() );
271
- $paths = self::get_attachment_edited_file_paths( $attachment_id );
272
- $paths = array_map( function ( $path ) use ( $prefix ) {
273
- return array( 'Key' => $prefix . wp_basename( $path ) );
274
  }, $paths );
275
 
276
  return $paths;
@@ -574,5 +606,107 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
574
 
575
  return $paths;
576
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
577
  }
578
  }
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  */
10
 
 
11
  use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
12
 
13
+ // Exit if accessed directly
14
  if ( ! defined( 'ABSPATH' ) ) {
15
  exit;
16
  }
45
  * @return string
46
  */
47
  public static function trailingslash_prefix( $string ) {
48
+ return static::unleadingslashit( trailingslashit( trim( $string ) ) );
49
+ }
50
+
51
+ /**
52
+ * Ensure string has a leading slash, like in absolute paths.
53
+ *
54
+ * @param $string
55
+ *
56
+ * @return string
57
+ */
58
+ public static function leadingslashit( $string ) {
59
+ return '/' . static::unleadingslashit( $string );
60
+ }
61
+
62
+ /**
63
+ * Ensure string has no leading slash, like in relative paths.
64
+ *
65
+ * @param $string
66
+ *
67
+ * @return string
68
+ */
69
+ public static function unleadingslashit( $string ) {
70
+ return ltrim( trim( $string ), '/\\' );
71
+ }
72
+
73
+ /**
74
+ * Ensure string has a leading and trailing slash, like in absolute directory paths.
75
+ *
76
+ * @param $string
77
+ *
78
+ * @return string
79
+ */
80
+ public static function leadingtrailingslashit( $string ) {
81
+ return static::leadingslashit( trailingslashit( trim( $string ) ) );
82
  }
83
 
84
  /**
300
  * @return array
301
  */
302
  public static function get_attachment_edited_keys( $attachment_id, Media_Library_Item $as3cf_item ) {
303
+ $paths = self::get_attachment_edited_file_paths( $attachment_id );
304
+ $paths = array_map( function ( $path ) use ( $as3cf_item ) {
305
+ return array( 'Key' => $as3cf_item->key( wp_basename( $path ) ) );
 
306
  }, $paths );
307
 
308
  return $paths;
606
 
607
  return $paths;
608
  }
609
+
610
+ /**
611
+ * Convert dimensions to size
612
+ *
613
+ * @param int $attachment_id
614
+ * @param array $dimensions
615
+ *
616
+ * @return null|string
617
+ */
618
+ public static function convert_dimensions_to_size_name( $attachment_id, $dimensions ) {
619
+ $w = ( isset( $dimensions[0] ) && $dimensions[0] > 0 ) ? $dimensions[0] : 1;
620
+ $h = ( isset( $dimensions[1] ) && $dimensions[1] > 0 ) ? $dimensions[1] : 1;
621
+ $original_aspect_ratio = $w / $h;
622
+ $meta = wp_get_attachment_metadata( $attachment_id );
623
+
624
+ if ( ! isset( $meta['sizes'] ) || empty( $meta['sizes'] ) ) {
625
+ return null;
626
+ }
627
+
628
+ $sizes = $meta['sizes'];
629
+ uasort( $sizes, function ( $a, $b ) {
630
+ // Order by image area
631
+ return ( $a['width'] * $a['height'] ) - ( $b['width'] * $b['height'] );
632
+ } );
633
+
634
+ $nearest_matches = array();
635
+
636
+ foreach ( $sizes as $size => $value ) {
637
+ if ( $w > $value['width'] || $h > $value['height'] ) {
638
+ continue;
639
+ }
640
+
641
+ $aspect_ratio = $value['width'] / $value['height'];
642
+
643
+ if ( $aspect_ratio === $original_aspect_ratio ) {
644
+ return $size;
645
+ }
646
+
647
+ $nearest_matches[] = $size;
648
+ }
649
+
650
+ // Return nearest match
651
+ if ( ! empty( $nearest_matches ) ) {
652
+ return $nearest_matches[0];
653
+ }
654
+
655
+ return null;
656
+ }
657
+
658
+ /**
659
+ * Maybe convert size to string
660
+ *
661
+ * @param int $attachment_id
662
+ * @param mixed $size
663
+ *
664
+ * @return null|string
665
+ */
666
+ public static function maybe_convert_size_to_string( $attachment_id, $size ) {
667
+ if ( is_array( $size ) ) {
668
+ return static::convert_dimensions_to_size_name( $attachment_id, $size );
669
+ }
670
+
671
+ return $size;
672
+ }
673
+
674
+ /**
675
+ * Encode file names according to RFC 3986 when generating urls
676
+ * As per Amazon https://forums.aws.amazon.com/thread.jspa?threadID=55746#jive-message-244233
677
+ *
678
+ * @param string $file
679
+ *
680
+ * @return string Encoded filename
681
+ */
682
+ public static function encode_filename_in_path( $file ) {
683
+ $url = parse_url( $file );
684
+
685
+ if ( ! isset( $url['path'] ) ) {
686
+ // Can't determine path, return original
687
+ return $file;
688
+ }
689
+
690
+ if ( isset( $url['query'] ) ) {
691
+ // Manually strip query string, as passing $url['path'] to basename results in corrupt � characters
692
+ $file_name = wp_basename( str_replace( '?' . $url['query'], '', $file ) );
693
+ } else {
694
+ $file_name = wp_basename( $file );
695
+ }
696
+
697
+ if ( false !== strpos( $file_name, '%' ) ) {
698
+ // File name already encoded, return original
699
+ return $file;
700
+ }
701
+
702
+ $encoded_file_name = rawurlencode( $file_name );
703
+
704
+ if ( $file_name === $encoded_file_name ) {
705
+ // File name doesn't need encoding, return original
706
+ return $file;
707
+ }
708
+
709
+ return str_replace( $file_name, $encoded_file_name, $file );
710
+ }
711
  }
712
  }
classes/filters/as3cf-local-to-s3.php CHANGED
@@ -27,6 +27,8 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
27
  // Widgets
28
  add_filter( 'widget_form_callback', array( $this, 'filter_widget_display' ), 10, 2 );
29
  add_filter( 'widget_display_callback', array( $this, 'filter_widget_display' ), 10, 2 );
 
 
30
  }
31
 
32
  /**
@@ -200,35 +202,19 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
200
  * @return bool|int
201
  */
202
  protected function get_attachment_id_from_url( $url ) {
203
- global $wpdb;
204
-
205
- $full_url = AS3CF_Utils::remove_scheme( AS3CF_Utils::remove_size_from_filename( $url ) );
206
-
207
- if ( isset( $this->query_cache[ $full_url ] ) ) {
208
- // ID already cached, return
209
- return $this->query_cache[ $full_url ];
210
- }
211
-
212
- $path = AS3CF_Utils::decode_filename_in_path( ltrim( str_replace( $this->get_bare_upload_base_urls(), '', $full_url ), '/' ) );
213
-
214
- $sql = $wpdb->prepare( "
215
- SELECT post_id FROM {$wpdb->postmeta}
216
- WHERE meta_key = %s
217
- AND meta_value = %s
218
- ", '_wp_attached_file', $path );
219
-
220
- $result = $wpdb->get_var( $sql );
221
-
222
- if ( is_null( $result ) ) {
223
- // Attachment ID not found, return false
224
- $this->query_cache[ $full_url ] = false;
225
 
 
226
  return false;
227
  }
228
 
229
- $this->query_cache[ $full_url ] = (int) $result;
 
 
 
 
230
 
231
- return (int) $result;
232
  }
233
 
234
  /**
@@ -249,11 +235,22 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
249
  $urls = array( $urls );
250
  }
251
 
 
252
  $paths = array();
253
  $full_urls = array();
254
 
 
255
  foreach ( $urls as $url ) {
256
- $full_url = AS3CF_Utils::remove_scheme( AS3CF_Utils::remove_size_from_filename( $url ) );
 
 
 
 
 
 
 
 
 
257
 
258
  if ( isset( $this->query_cache[ $full_url ] ) ) {
259
  // ID already cached, use it.
@@ -296,9 +293,9 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
296
  }
297
 
298
  // No more attachment IDs found, set remaining results as false.
299
- if ( count( $urls ) !== count( $results ) ) {
300
- foreach ( $full_urls as $full_url => $sizes ) {
301
- foreach ( $sizes as $url ) {
302
  if ( ! array_key_exists( $url, $results ) ) {
303
  $this->query_cache[ $full_url ] = false;
304
  $results[ $url ] = false;
@@ -330,7 +327,7 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
330
  * @return string
331
  */
332
  protected function normalize_replace_value( $url ) {
333
- return $this->as3cf->encode_filename_in_path( $url );
334
  }
335
 
336
  /**
@@ -374,4 +371,42 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
374
 
375
  return $content;
376
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377
  }
27
  // Widgets
28
  add_filter( 'widget_form_callback', array( $this, 'filter_widget_display' ), 10, 2 );
29
  add_filter( 'widget_display_callback', array( $this, 'filter_widget_display' ), 10, 2 );
30
+ // Edit Media page
31
+ add_filter( 'set_url_scheme', array( $this, 'set_url_scheme' ), 10, 3 );
32
  }
33
 
34
  /**
202
  * @return bool|int
203
  */
204
  protected function get_attachment_id_from_url( $url ) {
205
+ $results = $this->get_attachment_ids_from_urls( array( $url ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
 
207
+ if ( empty( $results ) ) {
208
  return false;
209
  }
210
 
211
+ foreach ( $results as $result ) {
212
+ if ( $result ) {
213
+ return $result;
214
+ }
215
+ }
216
 
217
+ return false;
218
  }
219
 
220
  /**
235
  $urls = array( $urls );
236
  }
237
 
238
+ $query_set = array();
239
  $paths = array();
240
  $full_urls = array();
241
 
242
+ // Quickly parse given URLs to add versions without size as we should lookup with size info first as that could be the "full" size.
243
  foreach ( $urls as $url ) {
244
+ $query_set[] = $url;
245
+ $size_removed = AS3CF_Utils::remove_size_from_filename( $url );
246
+
247
+ if ( $url !== $size_removed ) {
248
+ $query_set[] = $size_removed;
249
+ }
250
+ }
251
+
252
+ foreach ( $query_set as $url ) {
253
+ $full_url = AS3CF_Utils::remove_scheme( $url );
254
 
255
  if ( isset( $this->query_cache[ $full_url ] ) ) {
256
  // ID already cached, use it.
293
  }
294
 
295
  // No more attachment IDs found, set remaining results as false.
296
+ if ( count( $query_set ) !== count( $results ) ) {
297
+ foreach ( $full_urls as $full_url => $schema_urls ) {
298
+ foreach ( $schema_urls as $url ) {
299
  if ( ! array_key_exists( $url, $results ) ) {
300
  $this->query_cache[ $full_url ] = false;
301
  $results[ $url ] = false;
327
  * @return string
328
  */
329
  protected function normalize_replace_value( $url ) {
330
+ return AS3CF_Utils::encode_filename_in_path( $url );
331
  }
332
 
333
  /**
371
 
372
  return $content;
373
  }
374
+
375
+ /**
376
+ * Might need to re-fix remote URL's schema if WordPress core has substituted in HTTP but HTTPS is required.
377
+ *
378
+ * @param string $url
379
+ * @param string $scheme
380
+ * @param string $orig_scheme
381
+ *
382
+ * @return string
383
+ */
384
+ public function set_url_scheme( $url, $scheme, $orig_scheme ) {
385
+ if (
386
+ $this->as3cf->get_setting( 'force-https' ) &&
387
+ $this->should_filter_content() &&
388
+ ! $this->url_needs_replacing( $url ) &&
389
+ 'http' === $scheme && empty( $orig_scheme )
390
+ ) {
391
+ // Check that it's one of ours and not external.
392
+ $parts = AS3CF_Utils::parse_url( $url );
393
+
394
+ if ( empty( $parts['scheme'] ) || empty( $parts['host'] ) || 'http' !== $parts['scheme'] ) {
395
+ return $url;
396
+ }
397
+
398
+ $ours = false;
399
+ if ( $this->as3cf->get_setting( 'enable-delivery-domain' ) && $this->as3cf->get_setting( 'delivery-domain', '' ) === $parts['host'] ) {
400
+ $ours = true;
401
+ } elseif ( false !== strpos( $parts['host'], $this->as3cf->get_storage_provider()->get_domain() ) ) {
402
+ $ours = true;
403
+ }
404
+
405
+ if ( $ours ) {
406
+ return substr_replace( $url, 'https', 0, 4 );
407
+ }
408
+ }
409
+
410
+ return $url;
411
+ }
412
  }
classes/filters/as3cf-s3-to-local.php CHANGED
@@ -113,8 +113,28 @@ class AS3CF_S3_To_Local extends AS3CF_Filter {
113
  * @return bool|int
114
  */
115
  public function get_attachment_id_from_url( $url ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  $full_url = AS3CF_Utils::remove_size_from_filename( $url );
117
 
 
 
 
 
 
 
 
118
  // Result for URL already cached in request whether found or not, return it.
119
  if ( isset( $this->query_cache[ $full_url ] ) ) {
120
  return $this->query_cache[ $full_url ];
@@ -160,7 +180,7 @@ class AS3CF_S3_To_Local extends AS3CF_Filter {
160
  * @return string
161
  */
162
  protected function normalize_find_value( $url ) {
163
- return $this->as3cf->encode_filename_in_path( $url );
164
  }
165
 
166
  /**
113
  * @return bool|int
114
  */
115
  public function get_attachment_id_from_url( $url ) {
116
+ // Result for sized URL already cached in request, return it.
117
+ if ( isset( $this->query_cache[ $url ] ) ) {
118
+ return $this->query_cache[ $url ];
119
+ }
120
+
121
+ $post_id = Media_Library_Item::get_source_id_by_remote_url( $url );
122
+
123
+ if ( $post_id ) {
124
+ $this->query_cache[ $url ] = $post_id;
125
+
126
+ return $post_id;
127
+ }
128
+
129
  $full_url = AS3CF_Utils::remove_size_from_filename( $url );
130
 
131
+ // If we've already tried to find this URL above because it didn't have a size suffix, cache and return.
132
+ if ( $url === $full_url ) {
133
+ $this->query_cache[ $url ] = $post_id;
134
+
135
+ return $post_id;
136
+ }
137
+
138
  // Result for URL already cached in request whether found or not, return it.
139
  if ( isset( $this->query_cache[ $full_url ] ) ) {
140
  return $this->query_cache[ $full_url ];
180
  * @return string
181
  */
182
  protected function normalize_find_value( $url ) {
183
+ return AS3CF_Utils::encode_filename_in_path( $url );
184
  }
185
 
186
  /**
classes/items/item.php CHANGED
@@ -485,7 +485,7 @@ abstract class Item {
485
  'bucket' => '%s',
486
  'path' => '%s',
487
  'original_path' => '%s',
488
- 'is_private' => '%s',
489
  'source_type' => '%s',
490
  'source_id' => '%d',
491
  'source_path' => '%s',
@@ -775,7 +775,7 @@ abstract class Item {
775
  *
776
  * @return array
777
  */
778
- protected function extra_info() {
779
  return unserialize( $this->extra_info );
780
  }
781
 
@@ -787,7 +787,7 @@ abstract class Item {
787
  public function normalized_path_dir() {
788
  $directory = dirname( $this->path );
789
 
790
- return ( '.' === $directory ) ? '' : trailingslashit( $directory );
791
  }
792
 
793
  /**
@@ -840,6 +840,11 @@ abstract class Item {
840
  public static function get_source_id_by_remote_url( $url ) {
841
  global $wpdb;
842
 
 
 
 
 
 
843
  $parts = AS3CF_Utils::parse_url( $url );
844
  $path = AS3CF_Utils::decode_filename_in_path( ltrim( $parts['path'], '/' ) );
845
 
@@ -847,6 +852,25 @@ abstract class Item {
847
  if ( false !== strpos( $path, '/' ) ) {
848
  $path = explode( '/', $path );
849
  array_shift( $path );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
850
  $path = implode( '/', $path );
851
  }
852
 
@@ -865,11 +889,7 @@ abstract class Item {
865
  return false;
866
  }
867
 
868
- // Only one attachment matched, return ID.
869
- if ( 1 === count( $results ) ) {
870
- return $results[0]->source_id;
871
- }
872
-
873
  $path = ltrim( $parts['path'], '/' );
874
 
875
  foreach ( $results as $result ) {
@@ -882,6 +902,11 @@ abstract class Item {
882
  $match_path = $path;
883
  }
884
 
 
 
 
 
 
885
  // Exact match, return ID.
886
  if ( $as3cf_item->path() === $match_path || $as3cf_item->original_path() === $match_path ) {
887
  return $as3cf_item->source_id();
485
  'bucket' => '%s',
486
  'path' => '%s',
487
  'original_path' => '%s',
488
+ 'is_private' => '%d',
489
  'source_type' => '%s',
490
  'source_id' => '%d',
491
  'source_path' => '%s',
775
  *
776
  * @return array
777
  */
778
+ public function extra_info() {
779
  return unserialize( $this->extra_info );
780
  }
781
 
787
  public function normalized_path_dir() {
788
  $directory = dirname( $this->path );
789
 
790
+ return ( '.' === $directory ) ? '' : AS3CF_Utils::trailingslash_prefix( $directory );
791
  }
792
 
793
  /**
840
  public static function get_source_id_by_remote_url( $url ) {
841
  global $wpdb;
842
 
843
+ /**
844
+ * @var Amazon_S3_And_CloudFront|\Amazon_S3_And_CloudFront_Pro $as3cf
845
+ */
846
+ global $as3cf;
847
+
848
  $parts = AS3CF_Utils::parse_url( $url );
849
  $path = AS3CF_Utils::decode_filename_in_path( ltrim( $parts['path'], '/' ) );
850
 
852
  if ( false !== strpos( $path, '/' ) ) {
853
  $path = explode( '/', $path );
854
  array_shift( $path );
855
+
856
+ // If private prefix enabled, check if first segment and remove it as path/original_path do not include it.
857
+ // We can't check every possible private prefix as each item may have a unique private prefix.
858
+ // The only way to do that is with some fancy SQL, but that's not feasible as this particular
859
+ // SQL query is already troublesome on some sites with badly behaved themes/plugins.
860
+ if ( count( $path ) && $as3cf->get_delivery_provider()->use_signed_urls_key_file() ) {
861
+ // We have to be able to handle multi-segment private prefixes such as "private/downloads/".
862
+ $private_prefixes = explode( '/', untrailingslashit( $as3cf->get_setting( 'signed-urls-object-prefix' ) ) );
863
+
864
+ foreach ( $private_prefixes as $private_prefix ) {
865
+ if ( $private_prefix === $path[0] ) {
866
+ array_shift( $path );
867
+ } else {
868
+ // As soon as we don't have a match stop looking.
869
+ break;
870
+ }
871
+ }
872
+ }
873
+
874
  $path = implode( '/', $path );
875
  }
876
 
889
  return false;
890
  }
891
 
892
+ // Regardless of whether 1 or many items found, must validate match.
 
 
 
 
893
  $path = ltrim( $parts['path'], '/' );
894
 
895
  foreach ( $results as $result ) {
902
  $match_path = $path;
903
  }
904
 
905
+ // If item's private prefix matches first segment of URL path, remove it from URL path before checking match.
906
+ if ( ! empty( $as3cf_item->private_prefix() ) && 0 === strpos( $match_path, $as3cf_item->private_prefix() ) ) {
907
+ $match_path = ltrim( substr_replace( $match_path, '', 0, strlen( $as3cf_item->private_prefix() ) ), '/' );
908
+ }
909
+
910
  // Exact match, return ID.
911
  if ( $as3cf_item->path() === $match_path || $as3cf_item->original_path() === $match_path ) {
912
  return $as3cf_item->source_id();
classes/items/media-library-item.php CHANGED
@@ -4,6 +4,7 @@ namespace DeliciousBrains\WP_Offload_Media\Items;
4
 
5
  use Amazon_S3_And_CloudFront;
6
  use WP_Error;
 
7
 
8
  class Media_Library_Item extends Item {
9
  private static $attachment_counts = array();
@@ -20,32 +21,43 @@ class Media_Library_Item extends Item {
20
  * @param int $source_id ID that source has.
21
  * @param string $source_path Path that source uses, could be relative or absolute depending on source.
22
  * @param string $original_filename An optional filename with no path that was previously used for the item.
23
- * @param array $private_sizes An optional array of thumbnail sizes that should be private objects in the bucket.
 
 
 
 
 
24
  * @param null $id Optional Item record ID.
25
  */
26
- public function __construct( $provider, $region, $bucket, $path, $is_private, $source_id, $source_path, $original_filename = null, $private_sizes = array(), $id = null ) {
27
  // For Media Library items, the source path should be relative to the Media Library's uploads directory.
28
  $uploads = wp_upload_dir();
29
 
30
  if ( false === $uploads['error'] && 0 === strpos( $source_path, $uploads['basedir'] ) ) {
31
- $source_path = ltrim( substr( $source_path, strlen( $uploads['basedir'] ) ), DIRECTORY_SEPARATOR );
32
  }
33
 
34
- /*
35
- * We only need private sizes info at the moment, but just in case we add a bit more extra info...
36
- */
37
 
38
  // Ensure re-hydration is clean.
39
- if ( ! empty( $private_sizes['private_sizes'] ) ) {
40
- $private_sizes = $private_sizes['private_sizes'];
41
- }
 
 
 
 
42
 
43
- if ( empty( $private_sizes ) || ! is_array( $private_sizes ) ) {
44
- $private_sizes = array();
 
 
45
  }
46
 
47
  $extra_info = array(
48
- 'private_sizes' => $private_sizes,
 
49
  );
50
 
51
  parent::__construct( $provider, $region, $bucket, $path, $is_private, $source_id, $source_path, $original_filename, $extra_info, $id );
@@ -82,6 +94,40 @@ class Media_Library_Item extends Item {
82
  return $as3cf_item;
83
  }
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  /**
86
  * Get absolute file paths associated with source item.
87
  *
@@ -104,6 +150,15 @@ class Media_Library_Item extends Item {
104
  $extra_info = $this->extra_info();
105
 
106
  if ( ! empty( $extra_info['private_sizes'] ) ) {
 
 
 
 
 
 
 
 
 
107
  return $extra_info['private_sizes'];
108
  }
109
 
@@ -118,13 +173,28 @@ class Media_Library_Item extends Item {
118
  * @return bool
119
  */
120
  public function is_private_size( $size ) {
121
- if ( ( 'original' === $size || empty( $size ) ) ) {
122
  return $this->is_private();
123
  }
124
 
125
  return in_array( $size, $this->private_sizes() );
126
  }
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  /**
129
  * Count attachments on current site.
130
  *
@@ -151,21 +221,20 @@ class Media_Library_Item extends Item {
151
  // We want to count distinct relative Media Library paths
152
  // and ensure type is also attachment as other post types can use the same _wp_attached_file postmeta key.
153
  $sql = "
154
- SELECT COUNT(DISTINCT p.`ID`) total, COUNT(DISTINCT i.`id`) offloaded, COUNT(DISTINCT m.`meta_value`) total_paths, COUNT(DISTINCT i.`source_path`) offloaded_paths
155
- FROM " . $wpdb->postmeta . " AS m
156
- LEFT JOIN " . $wpdb->posts . " AS p ON m.post_id = p.ID AND p.`post_type` = 'attachment'
157
  LEFT OUTER JOIN " . static::items_table() . " AS i ON p.`ID` = i.`source_id` AND i.`source_type` = 'media-library'
158
- WHERE m.`meta_key` = '_wp_attached_file'
159
  ";
160
 
161
  $result = $wpdb->get_row( $sql, ARRAY_A );
162
 
163
- $result['not_offloaded'] = $result['total'] - $result['offloaded'];
164
- $result['not_offloaded_paths'] = max( 0, $result['total_paths'] - $result['offloaded_paths'] );
165
 
166
  ksort( $result );
167
 
168
- set_site_transient( $transient_key, $result, 2 * MINUTE_IN_SECONDS );
169
 
170
  // One way or another we've skipped the transient.
171
  self::$attachment_count_skips[ $transient_key ] = true;
@@ -222,7 +291,7 @@ class Media_Library_Item extends Item {
222
  $ignored_mime_types = apply_filters( 'as3cf_ignored_mime_types', array() );
223
  if ( is_array( $ignored_mime_types ) && ! empty( $ignored_mime_types ) ) {
224
  $ignored_mime_types = array_map( 'sanitize_text_field', $ignored_mime_types );
225
- $sql .= ' AND posts.post_mime_type NOT IN ("' . implode( '", "', $ignored_mime_types ) . '")';
226
  }
227
 
228
  if ( ! $count ) {
@@ -266,7 +335,7 @@ class Media_Library_Item extends Item {
266
 
267
  $sql = '
268
  SELECT DISTINCT items.*
269
- FROM ' . static::items_table() . ' AS items
270
  WHERE items.source_type = %s
271
  ';
272
 
@@ -279,14 +348,14 @@ class Media_Library_Item extends Item {
279
  }
280
 
281
  if ( $exact_match ) {
282
- $sql .= ' AND (items.source_path IN ("' . join( '","', $paths ) . '")';
283
- $sql .= ' OR items.original_source_path IN ("' . join( '","', $paths ) . '"))';
284
  } else {
285
  $likes = array_map( function ( $path ) {
286
  $ext = '.' . pathinfo( $path, PATHINFO_EXTENSION );
287
  $path = substr_replace( $path, '%', -strlen( $ext ) );
288
 
289
- return 'items.source_path LIKE "' . $path . '" OR items.original_source_path LIKE "' . $path . '"';
290
  }, $paths );
291
 
292
  $sql .= ' AND (' . join( ' OR ', $likes ) . ')';
@@ -345,7 +414,7 @@ class Media_Library_Item extends Item {
345
  $result->post_id,
346
  $this->source_path(),
347
  wp_basename( $this->original_source_path() ),
348
- $this->private_sizes()
349
  );
350
  $as3cf_item->save();
351
  }
@@ -401,7 +470,7 @@ class Media_Library_Item extends Item {
401
 
402
  if ( ! empty( $provider_object ) && is_array( $provider_object ) && ! empty( $provider_object['bucket'] ) && ! empty( $provider_object['key'] ) ) {
403
  $provider_object = array_merge( array(
404
- 'provider' => Amazon_S3_And_CloudFront::get_default_provider(),
405
  ), $provider_object );
406
  } else {
407
  return false;
4
 
5
  use Amazon_S3_And_CloudFront;
6
  use WP_Error;
7
+ use AS3CF_Utils;
8
 
9
  class Media_Library_Item extends Item {
10
  private static $attachment_counts = array();
21
  * @param int $source_id ID that source has.
22
  * @param string $source_path Path that source uses, could be relative or absolute depending on source.
23
  * @param string $original_filename An optional filename with no path that was previously used for the item.
24
+ * @param array $extra_info An optional associative array of extra data to be associated with the item.
25
+ * Recognised keys:
26
+ * 'private_sizes' => ['thumbnail', 'medium', ...]
27
+ * 'private_prefix' => 'private/'
28
+ * For backwards compatibility, if a simple array is supplied it is treated as
29
+ * private thumbnail sizes that should be private objects in the bucket.
30
  * @param null $id Optional Item record ID.
31
  */
32
+ public function __construct( $provider, $region, $bucket, $path, $is_private, $source_id, $source_path, $original_filename = null, $extra_info = array(), $id = null ) {
33
  // For Media Library items, the source path should be relative to the Media Library's uploads directory.
34
  $uploads = wp_upload_dir();
35
 
36
  if ( false === $uploads['error'] && 0 === strpos( $source_path, $uploads['basedir'] ) ) {
37
+ $source_path = AS3CF_Utils::unleadingslashit( substr( $source_path, strlen( $uploads['basedir'] ) ) );
38
  }
39
 
40
+ $private_sizes = array();
41
+ $private_prefix = '';
 
42
 
43
  // Ensure re-hydration is clean.
44
+ if ( ! empty( $extra_info ) && is_array( $extra_info ) ) {
45
+ if ( isset( $extra_info['private_sizes'] ) ) {
46
+ $private_sizes = $extra_info['private_sizes'];
47
+ }
48
+ if ( isset( $extra_info['private_prefix'] ) ) {
49
+ $private_prefix = $extra_info['private_prefix'];
50
+ }
51
 
52
+ // Compatibility fallback for if just an array of private sizes is supplied.
53
+ if ( ! isset( $extra_info['private_sizes'] ) && ! isset( $extra_info['private_prefix'] ) ) {
54
+ $private_sizes = $extra_info;
55
+ }
56
  }
57
 
58
  $extra_info = array(
59
+ 'private_sizes' => $private_sizes,
60
+ 'private_prefix' => $private_prefix,
61
  );
62
 
63
  parent::__construct( $provider, $region, $bucket, $path, $is_private, $source_id, $source_path, $original_filename, $extra_info, $id );
94
  return $as3cf_item;
95
  }
96
 
97
+ /**
98
+ * Full key (path) for given file that belongs to offloaded attachment.
99
+ *
100
+ * If no filename given, full sized path returned.
101
+ * Path is prepended with private prefix if size associated with filename is private,
102
+ * and a private prefix has been assigned to offload.
103
+ *
104
+ * @param string|null $filename
105
+ *
106
+ * @return string
107
+ */
108
+ public function key( $filename = null ) {
109
+ // Public full path.
110
+ if ( empty( $filename ) && empty( $this->private_prefix() ) ) {
111
+ return parent::path();
112
+ }
113
+
114
+ if ( empty( $filename ) ) {
115
+ $filename = wp_basename( parent::path() );
116
+ }
117
+
118
+ if ( ! empty( $this->private_prefix() ) ) {
119
+ $size = \AS3CF_Utils::get_intermediate_size_from_filename( $this->source_id(), $filename );
120
+
121
+ // Private path.
122
+ if ( $this->is_private_size( $size ) ) {
123
+ return $this->private_prefix() . $this->normalized_path_dir() . $filename;
124
+ }
125
+ }
126
+
127
+ // Public path.
128
+ return $this->normalized_path_dir() . $filename;
129
+ }
130
+
131
  /**
132
  * Get absolute file paths associated with source item.
133
  *
150
  $extra_info = $this->extra_info();
151
 
152
  if ( ! empty( $extra_info['private_sizes'] ) ) {
153
+ // There was an issue with class re-hydration that meant empty private sizes embedded itself inside its key.
154
+ if (
155
+ isset( $extra_info['private_sizes']['private_sizes'] ) &&
156
+ is_array( $extra_info['private_sizes']['private_sizes'] ) &&
157
+ empty( $extra_info['private_sizes']['private_sizes'] )
158
+ ) {
159
+ unset( $extra_info['private_sizes']['private_sizes'] );
160
+ }
161
+
162
  return $extra_info['private_sizes'];
163
  }
164
 
173
  * @return bool
174
  */
175
  public function is_private_size( $size ) {
176
+ if ( empty( $size ) || in_array( $size, array( 'full', 'original' ) ) ) {
177
  return $this->is_private();
178
  }
179
 
180
  return in_array( $size, $this->private_sizes() );
181
  }
182
 
183
+ /**
184
+ * Get the private prefix for attachment's private objects.
185
+ *
186
+ * @return string
187
+ */
188
+ public function private_prefix() {
189
+ $extra_info = $this->extra_info();
190
+
191
+ if ( ! empty( $extra_info['private_prefix'] ) ) {
192
+ return \AS3CF_Utils::trailingslash_prefix( $extra_info['private_prefix'] );
193
+ }
194
+
195
+ return '';
196
+ }
197
+
198
  /**
199
  * Count attachments on current site.
200
  *
221
  // We want to count distinct relative Media Library paths
222
  // and ensure type is also attachment as other post types can use the same _wp_attached_file postmeta key.
223
  $sql = "
224
+ SELECT COUNT(DISTINCT p.`ID`) total, COUNT(DISTINCT i.`id`) offloaded
225
+ FROM " . $wpdb->posts . " AS p
226
+ STRAIGHT_JOIN " . $wpdb->postmeta . " AS m ON p.ID = m.post_id AND m.`meta_key` = '_wp_attached_file'
227
  LEFT OUTER JOIN " . static::items_table() . " AS i ON p.`ID` = i.`source_id` AND i.`source_type` = 'media-library'
228
+ WHERE p.`post_type` = 'attachment'
229
  ";
230
 
231
  $result = $wpdb->get_row( $sql, ARRAY_A );
232
 
233
+ $result['not_offloaded'] = max( $result['total'] - $result['offloaded'], 0 );
 
234
 
235
  ksort( $result );
236
 
237
+ set_site_transient( $transient_key, $result, 5 * MINUTE_IN_SECONDS );
238
 
239
  // One way or another we've skipped the transient.
240
  self::$attachment_count_skips[ $transient_key ] = true;
291
  $ignored_mime_types = apply_filters( 'as3cf_ignored_mime_types', array() );
292
  if ( is_array( $ignored_mime_types ) && ! empty( $ignored_mime_types ) ) {
293
  $ignored_mime_types = array_map( 'sanitize_text_field', $ignored_mime_types );
294
+ $sql .= " AND posts.post_mime_type NOT IN ('" . implode( "','", $ignored_mime_types ) . "')";
295
  }
296
 
297
  if ( ! $count ) {
335
 
336
  $sql = '
337
  SELECT DISTINCT items.*
338
+ FROM ' . static::items_table() . ' AS items USE INDEX (uidx_source_path, uidx_original_source_path)
339
  WHERE items.source_type = %s
340
  ';
341
 
348
  }
349
 
350
  if ( $exact_match ) {
351
+ $sql .= " AND (items.source_path IN ('" . join( "','", $paths ) . "')";
352
+ $sql .= " OR items.original_source_path IN ('" . join( "','", $paths ) . "'))";
353
  } else {
354
  $likes = array_map( function ( $path ) {
355
  $ext = '.' . pathinfo( $path, PATHINFO_EXTENSION );
356
  $path = substr_replace( $path, '%', -strlen( $ext ) );
357
 
358
+ return "items.source_path LIKE '" . $path . "' OR items.original_source_path LIKE '" . $path . "'";
359
  }, $paths );
360
 
361
  $sql .= ' AND (' . join( ' OR ', $likes ) . ')';
414
  $result->post_id,
415
  $this->source_path(),
416
  wp_basename( $this->original_source_path() ),
417
+ $this->extra_info()
418
  );
419
  $as3cf_item->save();
420
  }
470
 
471
  if ( ! empty( $provider_object ) && is_array( $provider_object ) && ! empty( $provider_object['bucket'] ) && ! empty( $provider_object['key'] ) ) {
472
  $provider_object = array_merge( array(
473
+ 'provider' => Amazon_S3_And_CloudFront::get_default_storage_provider(),
474
  ), $provider_object );
475
  } else {
476
  return false;
classes/providers/delivery/another-cdn.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
4
+
5
+ class Another_CDN extends Delivery_Provider {
6
+
7
+ /**
8
+ * @var string
9
+ */
10
+ protected static $provider_name = 'Another';
11
+
12
+ /**
13
+ * @var string
14
+ */
15
+ protected static $provider_short_name = 'Another';
16
+
17
+ /**
18
+ * Used in filters and settings.
19
+ *
20
+ * @var string
21
+ */
22
+ protected static $provider_key_name = 'another';
23
+
24
+ /**
25
+ * @var string
26
+ */
27
+ protected static $service_name = 'CDN';
28
+
29
+ /**
30
+ * @var string
31
+ */
32
+ protected static $service_short_name = 'CDN';
33
+
34
+ /**
35
+ * Used in filters and settings.
36
+ *
37
+ * @var string
38
+ */
39
+ protected static $service_key_name = 'cdn';
40
+
41
+ /**
42
+ * A short description of what features the delivery provider enables.
43
+ *
44
+ * @return string
45
+ */
46
+ public function features_description() {
47
+ return __( 'Fast, No Private Media', 'amazon-s3-and-cloudfront' );
48
+ }
49
+ }
classes/providers/delivery/aws-cloudfront.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
4
+
5
+ class AWS_CloudFront extends Delivery_Provider {
6
+
7
+ /**
8
+ * Which storage providers does the delivery provider support, empty means all.
9
+ *
10
+ * @var array
11
+ */
12
+ protected static $supported_storage_providers = array(
13
+ 'aws',
14
+ );
15
+
16
+ /**
17
+ * @var string
18
+ */
19
+ protected static $provider_name = 'Amazon Web Services';
20
+
21
+ /**
22
+ * @var string
23
+ */
24
+ protected static $provider_short_name = 'AWS';
25
+
26
+ /**
27
+ * Used in filters and settings.
28
+ *
29
+ * @var string
30
+ */
31
+ protected static $provider_key_name = 'aws';
32
+
33
+ /**
34
+ * @var string
35
+ */
36
+ protected static $service_name = 'CloudFront';
37
+
38
+ /**
39
+ * @var string
40
+ */
41
+ protected static $service_short_name = 'CloudFront';
42
+
43
+ /**
44
+ * Used in filters and settings.
45
+ *
46
+ * @var string
47
+ */
48
+ protected static $service_key_name = 'cloudfront';
49
+
50
+ /**
51
+ * Optional override of "Provider Name" + "Service Name" for friendly name for service.
52
+ *
53
+ * @var string
54
+ */
55
+ protected static $provider_service_name = 'Amazon CloudFront';
56
+
57
+ /**
58
+ * The slug for the service's quick start guide doc.
59
+ *
60
+ * @var string
61
+ */
62
+ protected static $provider_service_quick_start_slug = 'amazon-cloudfront-quick-start-guide';
63
+
64
+ /**
65
+ * @var string
66
+ */
67
+ protected $default_domain = 'cloudfront.net';
68
+
69
+ /**
70
+ * @var string
71
+ */
72
+ protected $console_url = 'https://console.aws.amazon.com/cloudfront/home';
73
+
74
+ /**
75
+ * AWS_CloudFront constructor.
76
+ *
77
+ * @param \AS3CF_Plugin_Base $as3cf
78
+ */
79
+ public function __construct( \AS3CF_Plugin_Base $as3cf ) {
80
+ parent::__construct( $as3cf );
81
+
82
+ $this->disable_csm();
83
+
84
+ // Autoloader.
85
+ require_once $as3cf->get_plugin_sdks_dir_path() . '/Aws3/aws-autoloader.php';
86
+ }
87
+
88
+ /**
89
+ * Disable AWS CSM which tries to check ~/.aws/config causing issues if open_basedir in effect.
90
+ *
91
+ * @see https://github.com/aws/aws-sdk-php/issues/1659
92
+ */
93
+ private function disable_csm() {
94
+ if ( apply_filters( 'as3cf_disable_aws_csm', true ) ) {
95
+ putenv( 'AWS_CSM_ENABLED=false' );
96
+ }
97
+ }
98
+
99
+ /**
100
+ * A short description of what features the delivery provider enables.
101
+ *
102
+ * @return string
103
+ */
104
+ public function features_description() {
105
+ return sprintf(
106
+ __( 'Fast, Private Media Supported with <a href="%s" target="_blank">upgrade</a>', 'amazon-s3-and-cloudfront' ),
107
+ $this->as3cf->dbrains_url( '/wp-offload-media/upgrade/', array(
108
+ 'utm_campaign' => 'WP+Offload+S3',
109
+ ) )
110
+ );
111
+ }
112
+ }
classes/providers/delivery/cloudflare.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
4
+
5
+ class Cloudflare extends Another_CDN {
6
+
7
+ /**
8
+ * Which storage providers does the delivery provider support, empty means all.
9
+ *
10
+ * @var array
11
+ */
12
+ protected static $supported_storage_providers = array(
13
+ // TODO: Add 'do' after testing and documenting.
14
+ 'aws',
15
+ );
16
+
17
+ /**
18
+ * @var string
19
+ */
20
+ protected static $provider_name = 'Cloudflare';
21
+
22
+ /**
23
+ * @var string
24
+ */
25
+ protected static $provider_short_name = 'Cloudflare';
26
+
27
+ /**
28
+ * Used in filters and settings.
29
+ *
30
+ * @var string
31
+ */
32
+ protected static $provider_key_name = 'cloudflare';
33
+
34
+ /**
35
+ * @var string
36
+ */
37
+ protected static $service_name = 'CDN';
38
+
39
+ /**
40
+ * @var string
41
+ */
42
+ protected static $service_short_name = 'CDN';
43
+
44
+ /**
45
+ * Used in filters and settings.
46
+ *
47
+ * @var string
48
+ */
49
+ protected static $service_key_name = 'cdn';
50
+
51
+ /**
52
+ * Optional override of "Provider Name" + "Service Name" for friendly name for service.
53
+ *
54
+ * @var string
55
+ */
56
+ protected static $provider_service_name = 'Cloudflare';
57
+
58
+ /**
59
+ * @var string
60
+ */
61
+ protected static $provider_service_quick_start_slug = 'cloudflare-setup';
62
+ }
classes/providers/delivery/delivery-provider.php ADDED
@@ -0,0 +1,428 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
4
+
5
+ use AS3CF_Utils;
6
+ use DeliciousBrains\WP_Offload_Media\Items\Item;
7
+ use DeliciousBrains\WP_Offload_Media\Providers\Provider;
8
+
9
+ abstract class Delivery_Provider extends Provider {
10
+
11
+ /**
12
+ * @var string
13
+ */
14
+ protected static $provider_service_name_setting_name = 'delivery-provider-service-name';
15
+
16
+ /**
17
+ * @var bool
18
+ */
19
+ protected static $delivery_domain_allowed = true;
20
+
21
+ /**
22
+ * Which storage providers does the delivery provider support, empty means all.
23
+ *
24
+ * @var array
25
+ */
26
+ protected static $supported_storage_providers = array();
27
+
28
+ /**
29
+ * @var string
30
+ */
31
+ protected static $signed_urls_key_id_setting_name = 'signed-urls-key-id';
32
+
33
+ /**
34
+ * @var string
35
+ */
36
+ protected static $signed_urls_key_file_path_setting_name = 'signed-urls-key-file-path';
37
+
38
+ /**
39
+ * @var string
40
+ */
41
+ protected static $signed_urls_object_prefix_setting_name = 'signed-urls-object-prefix';
42
+
43
+ /**
44
+ * If left empty, private signing key file not allowed.
45
+ *
46
+ * @var array
47
+ */
48
+ protected static $signed_urls_key_id_constants = array();
49
+
50
+ /**
51
+ * If left empty, private signing key file not allowed.
52
+ *
53
+ * @var array
54
+ */
55
+ protected static $signed_urls_key_file_path_constants = array();
56
+
57
+ /**
58
+ * If left empty, private signing key file not allowed.
59
+ *
60
+ * @var array
61
+ */
62
+ protected static $signed_urls_object_prefix_constants = array();
63
+
64
+ /**
65
+ * Does the delivery provider allow for setting a custom delivery domain?
66
+ *
67
+ * @return bool
68
+ */
69
+ public static function delivery_domain_allowed() {
70
+ return static::$delivery_domain_allowed;
71
+ }
72
+
73
+ /**
74
+ * Does provider support given storage provider?
75
+ *
76
+ * @param string $storage_provider_key
77
+ *
78
+ * @return bool
79
+ */
80
+ public function supports_storage( $storage_provider_key ) {
81
+ if ( empty( static::$supported_storage_providers ) || in_array( $storage_provider_key, static::$supported_storage_providers ) ) {
82
+ return true;
83
+ }
84
+
85
+ return false;
86
+ }
87
+
88
+ /**
89
+ * Title used in various places for the Signed URLs Key ID.
90
+ *
91
+ * @return string
92
+ */
93
+ public static function signed_urls_key_id_name() {
94
+ return __( 'Signing Key ID', 'amazon-s3-and-cloudfront' );
95
+ }
96
+
97
+ /**
98
+ * Description used in various places for the Signed URLs Key ID.
99
+ *
100
+ * @return string
101
+ */
102
+ public static function signed_urls_key_id_description() {
103
+ return '';
104
+ }
105
+
106
+ /**
107
+ * Title used in various places for the Signed URLs Key File Path.
108
+ *
109
+ * @return string
110
+ */
111
+ public static function signed_urls_key_file_path_name() {
112
+ return __( 'Signing Key File Path', 'amazon-s3-and-cloudfront' );
113
+ }
114
+
115
+ /**
116
+ * Description used in various places for the Signed URLs Key File Path.
117
+ *
118
+ * @return string
119
+ */
120
+ public static function signed_urls_key_file_path_description() {
121
+ return '';
122
+ }
123
+
124
+ /**
125
+ * Title used in various places for the Signed URLs Private Object Prefix.
126
+ *
127
+ * @return string
128
+ */
129
+ public static function signed_urls_object_prefix_name() {
130
+ return __( 'Private Path', 'amazon-s3-and-cloudfront' );
131
+ }
132
+
133
+ /**
134
+ * Description used in various places for the Signed URLs Private Object Prefix.
135
+ *
136
+ * @return string
137
+ */
138
+ public static function signed_urls_object_prefix_description() {
139
+ return '';
140
+ }
141
+
142
+ /**
143
+ * Is the provider able to use a private signing key file?
144
+ *
145
+ * @return bool
146
+ */
147
+ public static function use_signed_urls_key_file_allowed() {
148
+ return ! empty( static::$signed_urls_key_id_constants ) && ! empty( static::$signed_urls_key_file_path_constants ) && ! empty( static::$signed_urls_object_prefix_constants );
149
+ }
150
+
151
+ /**
152
+ * If private signing key file allowed, returns first (preferred) key id constant that should be defined, otherwise blank.
153
+ *
154
+ * @return string
155
+ */
156
+ public static function preferred_signed_urls_key_id_constant() {
157
+ if ( static::use_signed_urls_key_file_allowed() ) {
158
+ return static::$signed_urls_key_id_constants[0];
159
+ } else {
160
+ return '';
161
+ }
162
+ }
163
+
164
+ /**
165
+ * If private signing key file allowed, returns first (preferred) key file path constant that should be defined, otherwise blank.
166
+ *
167
+ * @return string
168
+ */
169
+ public static function preferred_signed_urls_key_file_path_constant() {
170
+ if ( static::use_signed_urls_key_file_allowed() ) {
171
+ return static::$signed_urls_key_file_path_constants[0];
172
+ } else {
173
+ return '';
174
+ }
175
+ }
176
+
177
+ /**
178
+ * If private signing key file allowed, returns first (preferred) object prefix constant that should be defined, otherwise blank.
179
+ *
180
+ * @return string
181
+ */
182
+ public static function preferred_signed_urls_object_prefix_constant() {
183
+ if ( static::use_signed_urls_key_file_allowed() ) {
184
+ return static::$signed_urls_object_prefix_constants[0];
185
+ } else {
186
+ return '';
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Check if private signing key id and file path set.
192
+ *
193
+ * @return bool
194
+ */
195
+ public function use_signed_urls_key_file() {
196
+ if ( ! static::use_signed_urls_key_file_allowed() ) {
197
+ return false;
198
+ }
199
+
200
+ return $this->get_signed_urls_key_id() && $this->get_signed_urls_key_file_path() && $this->get_signed_urls_object_prefix();
201
+ }
202
+
203
+ /**
204
+ * Get the private signing key id from a constant or the settings.
205
+ *
206
+ * Falls back to settings if constant is not defined.
207
+ *
208
+ * @return string
209
+ */
210
+ public function get_signed_urls_key_id() {
211
+ if ( static::is_signed_urls_key_id_constant_defined() ) {
212
+ $constant = static::signed_urls_key_id_constant();
213
+
214
+ return $constant ? constant( $constant ) : '';
215
+ }
216
+
217
+ return $this->as3cf->get_core_setting( static::$signed_urls_key_id_setting_name );
218
+ }
219
+
220
+ /**
221
+ * Get the private signing key file path from a constant or the settings.
222
+ *
223
+ * Falls back to settings if constant is not defined.
224
+ *
225
+ * @return string|bool
226
+ */
227
+ public function get_signed_urls_key_file_path() {
228
+ if ( static::is_signed_urls_key_file_path_constant_defined() ) {
229
+ $constant = static::signed_urls_key_file_path_constant();
230
+
231
+ if ( $constant ) {
232
+ return $this->validate_signed_urls_key_file_path( constant( $constant ) );
233
+ } else {
234
+ // Constant defined but value is not a non-empty string.
235
+ return false;
236
+ }
237
+ }
238
+
239
+ return $this->validate_signed_urls_key_file_path( $this->as3cf->get_core_setting( static::$signed_urls_key_file_path_setting_name, false ) );
240
+ }
241
+
242
+ /**
243
+ * Get the private signing object prefix from a constant or the settings.
244
+ *
245
+ * Falls back to settings if constant is not defined.
246
+ *
247
+ * @return string
248
+ */
249
+ public function get_signed_urls_object_prefix() {
250
+ if ( static::is_signed_urls_object_prefix_constant_defined() ) {
251
+ $constant = static::signed_urls_object_prefix_constant();
252
+
253
+ return $constant ? constant( $constant ) : '';
254
+ }
255
+
256
+ return $this->as3cf->get_core_setting( static::$signed_urls_object_prefix_setting_name );
257
+ }
258
+
259
+ /**
260
+ * Validate a private signing key file path to ensure it exists, is readable, and contains something.
261
+ *
262
+ * @param string $signed_urls_key_file_path
263
+ *
264
+ * @return bool|string
265
+ */
266
+ public function validate_signed_urls_key_file_path( $signed_urls_key_file_path ) {
267
+ $notice_id = 'validate-signed-urls-key-file-path';
268
+ $this->as3cf->notices->remove_notice_by_id( $notice_id );
269
+
270
+ if ( empty( $signed_urls_key_file_path ) ) {
271
+ return false;
272
+ }
273
+
274
+ if ( ! file_exists( $signed_urls_key_file_path ) ) {
275
+ $this->as3cf->notices->add_notice( __( 'Given Signing Key File Path is invalid or could not be accessed.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
276
+
277
+ return false;
278
+ }
279
+
280
+ try {
281
+ $value = file_get_contents( $signed_urls_key_file_path );
282
+
283
+ // An exception isn't always thrown, so check value instead.
284
+ if ( empty( $value ) ) {
285
+ $this->as3cf->notices->add_notice( __( 'Could not read Signing Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
286
+
287
+ return false;
288
+ }
289
+ } catch ( \Exception $e ) {
290
+ $this->as3cf->notices->add_notice( __( 'Could not read Signing Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
291
+
292
+ return false;
293
+ }
294
+
295
+ // File exists and has contents.
296
+ return $signed_urls_key_file_path;
297
+ }
298
+
299
+ /**
300
+ * Check if private signing key id constant is defined.
301
+ *
302
+ * @return bool
303
+ */
304
+ public static function is_signed_urls_key_id_constant_defined() {
305
+ $constant = static::signed_urls_key_id_constant();
306
+
307
+ return $constant && constant( $constant );
308
+ }
309
+
310
+ /**
311
+ * Check if private signing key file path constant is defined, for speed, does not check validity of file path.
312
+ *
313
+ * @return bool
314
+ */
315
+ public static function is_signed_urls_key_file_path_constant_defined() {
316
+ $constant = static::signed_urls_key_file_path_constant();
317
+
318
+ return $constant && constant( $constant );
319
+ }
320
+
321
+ /**
322
+ * Check if private signing object prefix constant is defined.
323
+ *
324
+ * @return bool
325
+ */
326
+ public static function is_signed_urls_object_prefix_constant_defined() {
327
+ $constant = static::signed_urls_object_prefix_constant();
328
+
329
+ return $constant && constant( $constant );
330
+ }
331
+
332
+ /**
333
+ * Get the constant used to define the private signing key id.
334
+ *
335
+ * @return string|false Constant name if defined, otherwise false
336
+ */
337
+ public static function signed_urls_key_id_constant() {
338
+ return AS3CF_Utils::get_first_defined_constant( static::$signed_urls_key_id_constants );
339
+ }
340
+
341
+ /**
342
+ * Get the constant used to define the private signing key file path.
343
+ *
344
+ * @return string|false Constant name if defined, otherwise false
345
+ */
346
+ public static function signed_urls_key_file_path_constant() {
347
+ return AS3CF_Utils::get_first_defined_constant( static::$signed_urls_key_file_path_constants );
348
+ }
349
+
350
+ /**
351
+ * Get the constant used to define the private signing object prefix.
352
+ *
353
+ * @return string|false Constant name if defined, otherwise false
354
+ */
355
+ public static function signed_urls_object_prefix_constant() {
356
+ return AS3CF_Utils::get_first_defined_constant( static::$signed_urls_object_prefix_constants );
357
+ }
358
+
359
+ /**
360
+ * Get a site specific file path example for a signed URL key file.
361
+ *
362
+ * @return string
363
+ */
364
+ public static function signed_urls_key_file_path_placeholder() {
365
+ $filename = 'pk-12345678ABCDE.pem';
366
+
367
+ return dirname( ABSPATH ) . DIRECTORY_SEPARATOR . $filename;
368
+ }
369
+
370
+ /**
371
+ * Return a fully formed and potentially expiring signed URL for the given Item.
372
+ *
373
+ * @param Item $as3cf_item
374
+ * @param string $path The required bucket path, may differ from Item's path if image subsize etc.
375
+ * @param string $domain The domain to use for the URL if at all possible.
376
+ * @param string $scheme The scheme to be used if possible.
377
+ * @param array|null $headers Optional array of headers to be passed along to underlying requests.
378
+ *
379
+ * @return string
380
+ */
381
+ public function get_url( Item $as3cf_item, $path, $domain, $scheme, $headers = array() ) {
382
+ $item_path = $this->as3cf->maybe_update_delivery_path( $path, $domain );
383
+ $item_path = AS3CF_Utils::encode_filename_in_path( $item_path );
384
+
385
+ return $scheme . '://' . $domain . '/' . $item_path;
386
+ }
387
+
388
+ /**
389
+ * Return a fully formed and expiring signed URL for the given Item.
390
+ *
391
+ * @param Item $as3cf_item
392
+ * @param string $path The required bucket path, may differ from Item's path if image subsize etc.
393
+ * @param string $domain The domain to use for the URL if at all possible.
394
+ * @param string $scheme The scheme to be used if possible.
395
+ * @param int $timestamp URL expires at the given time.
396
+ * @param array|null $headers Optional array of headers to be passed along to underlying requests.
397
+ *
398
+ * @return string
399
+ * @throws \Exception
400
+ */
401
+ public function get_signed_url( Item $as3cf_item, $path, $domain, $scheme, $timestamp, $headers = array() ) {
402
+ /**
403
+ * This default implementation defers to the storage provider's signed URLs.
404
+ * Therefore we need to use a storage provider client instance for the item's region.
405
+ */
406
+ if ( ! empty( $as3cf_item->region() ) && ( $this->as3cf->get_storage_provider()->region_required() || $this->as3cf->get_storage_provider()->get_default_region() !== $as3cf_item->region() ) ) {
407
+ $region = $this->as3cf->get_storage_provider()->sanitize_region( $as3cf_item->region() );
408
+ } else {
409
+ $region = '';
410
+ }
411
+
412
+ // Storage Provider may support signing custom domain, e.g. GCP.
413
+ if ( $this->as3cf->get_storage_provider()->get_domain() !== $domain ) {
414
+ $headers['BaseURL'] = $scheme . '://' . $domain;
415
+ }
416
+
417
+ return $this->as3cf->get_provider_client( $region )->get_object_url( $as3cf_item->bucket(), $path, $timestamp, $headers );
418
+ }
419
+
420
+ /**
421
+ * A short description of what features the delivery provider enables.
422
+ *
423
+ * TODO: Use properties to specify features list, allowing some to be derived from storage provider (e.g. GCP can be fast by default).
424
+ *
425
+ * @return string
426
+ */
427
+ abstract public function features_description();
428
+ }
classes/providers/delivery/digitalocean-spaces-cdn.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
4
+
5
+ class DigitalOcean_Spaces_CDN extends Delivery_Provider {
6
+
7
+ /**
8
+ * Which storage providers does the delivery provider support, empty means all.
9
+ *
10
+ * @var array
11
+ */
12
+ protected static $supported_storage_providers = array(
13
+ 'do',
14
+ );
15
+
16
+ /**
17
+ * @var string
18
+ */
19
+ protected static $provider_name = 'DigitalOcean';
20
+
21
+ /**
22
+ * @var string
23
+ */
24
+ protected static $provider_short_name = 'DigitalOcean';
25
+
26
+ /**
27
+ * Used in filters and settings.
28
+ *
29
+ * @var string
30
+ */
31
+ protected static $provider_key_name = 'do';
32
+
33
+ /**
34
+ * @var string
35
+ */
36
+ protected static $service_name = 'Spaces CDN';
37
+
38
+ /**
39
+ * @var string
40
+ */
41
+ protected static $service_short_name = 'Spaces CDN';
42
+
43
+ /**
44
+ * Used in filters and settings.
45
+ *
46
+ * @var string
47
+ */
48
+ protected static $service_key_name = 'spaces-cdn';
49
+
50
+ /**
51
+ * Optional override of "Provider Name" + "Service Name" for friendly name for service.
52
+ *
53
+ * @var string
54
+ */
55
+ protected static $provider_service_name = 'DigitalOcean Spaces CDN';
56
+
57
+ /**
58
+ * The slug for the service's quick start guide doc.
59
+ *
60
+ * @var string
61
+ */
62
+ protected static $provider_service_quick_start_slug = 'digitalocean-spaces-cdn-setup';
63
+
64
+ /**
65
+ * @var string
66
+ */
67
+ protected $default_domain = 'cdn.digitaloceanspaces.com';
68
+
69
+ /**
70
+ * @var string
71
+ */
72
+ protected $console_url = 'https://cloud.digitalocean.com/spaces/';
73
+
74
+ /**
75
+ * @var string
76
+ */
77
+ protected $console_url_prefix_param = '?path=';
78
+
79
+ /**
80
+ * @inheritDoc
81
+ */
82
+ public function features_description() {
83
+ return __( 'Fast, No Private Media', 'amazon-s3-and-cloudfront' );
84
+ }
85
+ }
classes/providers/delivery/gcp-cdn.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
4
+
5
+ class GCP_CDN extends Delivery_Provider {
6
+
7
+ /**
8
+ * Which storage providers does the delivery provider support, empty means all.
9
+ *
10
+ * @var array
11
+ */
12
+ protected static $supported_storage_providers = array(
13
+ 'gcp',
14
+ );
15
+
16
+ /**
17
+ * @var string
18
+ */
19
+ protected static $provider_name = 'Google Cloud Platform';
20
+
21
+ /**
22
+ * @var string
23
+ */
24
+ protected static $provider_short_name = 'GCP';
25
+
26
+ /**
27
+ * Used in filters and settings.
28
+ *
29
+ * @var string
30
+ */
31
+ protected static $provider_key_name = 'gcp';
32
+
33
+ /**
34
+ * @var string
35
+ */
36
+ protected static $service_name = 'Cloud CDN';
37
+
38
+ /**
39
+ * @var string
40
+ */
41
+ protected static $service_short_name = 'Cloud CDN';
42
+
43
+ /**
44
+ * Used in filters and settings.
45
+ *
46
+ * @var string
47
+ */
48
+ protected static $service_key_name = 'cdn';
49
+
50
+ /**
51
+ * Optional override of "Provider Name" + "Service Name" for friendly name for service.
52
+ *
53
+ * @var string
54
+ */
55
+ protected static $provider_service_name = 'GCP Cloud CDN';
56
+
57
+ /**
58
+ * The slug for the service's quick start guide doc.
59
+ *
60
+ * @var string
61
+ */
62
+ protected static $provider_service_quick_start_slug = 'how-to-set-up-a-custom-domain-cdn-for-google-cloud-storage';
63
+
64
+ /**
65
+ * @var string
66
+ */
67
+ protected $console_url = 'https://console.cloud.google.com/net-services/cdn/list';
68
+
69
+ /**
70
+ * @inheritDoc
71
+ */
72
+ public function features_description() {
73
+ return __( 'Fast, Private Media Supported', 'amazon-s3-and-cloudfront' );
74
+ }
75
+ }
classes/providers/delivery/keycdn.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
4
+
5
+ class KeyCDN extends Another_CDN {
6
+
7
+ /**
8
+ * Which storage providers does the delivery provider support, empty means all.
9
+ *
10
+ * @var array
11
+ */
12
+ protected static $supported_storage_providers = array(
13
+ // TODO: Add 'aws' after testing and documenting.
14
+ 'do',
15
+ );
16
+
17
+ /**
18
+ * @var string
19
+ */
20
+ protected static $provider_name = 'KeyCDN';
21
+
22
+ /**
23
+ * @var string
24
+ */
25
+ protected static $provider_short_name = 'KeyCDN';
26
+
27
+ /**
28
+ * Used in filters and settings.
29
+ *
30
+ * @var string
31
+ */
32
+ protected static $provider_key_name = 'keycdn';
33
+
34
+ /**
35
+ * @var string
36
+ */
37
+ protected static $service_name = 'CDN';
38
+
39
+ /**
40
+ * @var string
41
+ */
42
+ protected static $service_short_name = 'CDN';
43
+
44
+ /**
45
+ * Used in filters and settings.
46
+ *
47
+ * @var string
48
+ */
49
+ protected static $service_key_name = 'cdn';
50
+
51
+ /**
52
+ * Optional override of "Provider Name" + "Service Name" for friendly name for service.
53
+ *
54
+ * @var string
55
+ */
56
+ protected static $provider_service_name = 'KeyCDN';
57
+
58
+ /**
59
+ * @var string
60
+ */
61
+ protected static $provider_service_quick_start_slug = 'how-to-set-up-a-custom-domain-for-digitalocean-spaces-with-keycdn';
62
+ }
classes/providers/delivery/other.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
4
+
5
+ /**
6
+ * Class Other
7
+ *
8
+ * This is effectively dummy class that fulfils the requirements of a selectable "Other" default sub-option for Another CDN.
9
+ *
10
+ * @package DeliciousBrains\WP_Offload_Media\Providers\Delivery
11
+ */
12
+ class Other extends Another_CDN {
13
+
14
+ /**
15
+ * Can the displayed provider service name be overridden by the user?
16
+ *
17
+ * @var bool
18
+ */
19
+ protected static $provider_service_name_override_allowed = true;
20
+
21
+ /**
22
+ * @var string
23
+ */
24
+ protected static $provider_name = 'Other';
25
+
26
+ /**
27
+ * @var string
28
+ */
29
+ protected static $provider_short_name = 'Other';
30
+
31
+ /**
32
+ * Used in filters and settings.
33
+ *
34
+ * @var string
35
+ */
36
+ protected static $provider_key_name = 'other';
37
+
38
+ /**
39
+ * @var string
40
+ */
41
+ protected static $service_name = 'Unknown';
42
+
43
+ /**
44
+ * @var string
45
+ */
46
+ protected static $service_short_name = 'Unknown';
47
+
48
+ /**
49
+ * Used in filters and settings.
50
+ *
51
+ * @var string
52
+ */
53
+ protected static $service_key_name = 'unknown';
54
+
55
+ /**
56
+ * Optional override of "Provider Name" + "Service Name" for friendly name for service.
57
+ *
58
+ * @var string
59
+ */
60
+ protected static $provider_service_name = 'Other';
61
+ }
classes/providers/delivery/stackpath.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
4
+
5
+ class StackPath extends Another_CDN {
6
+
7
+ /**
8
+ * Which storage providers does the delivery provider support, empty means all.
9
+ *
10
+ * @var array
11
+ */
12
+ protected static $supported_storage_providers = array(
13
+ // TODO: Add 'do' after testing and documenting.
14
+ 'aws',
15
+ );
16
+
17
+ /**
18
+ * @var string
19
+ */
20
+ protected static $provider_name = 'StackPath';
21
+
22
+ /**
23
+ * @var string
24
+ */
25
+ protected static $provider_short_name = 'StackPath';
26
+
27
+ /**
28
+ * Used in filters and settings.
29
+ *
30
+ * @var string
31
+ */
32
+ protected static $provider_key_name = 'stackpath';
33
+
34
+ /**
35
+ * @var string
36
+ */
37
+ protected static $service_name = 'CDN';
38
+
39
+ /**
40
+ * @var string
41
+ */
42
+ protected static $service_short_name = 'CDN';
43
+
44
+ /**
45
+ * Used in filters and settings.
46
+ *
47
+ * @var string
48
+ */
49
+ protected static $service_key_name = 'cdn';
50
+
51
+ /**
52
+ * Optional override of "Provider Name" + "Service Name" for friendly name for service.
53
+ *
54
+ * @var string
55
+ */
56
+ protected static $provider_service_name = 'StackPath';
57
+
58
+ /**
59
+ * @var string
60
+ */
61
+ protected static $provider_service_quick_start_slug = 'stackpath-setup';
62
+ }
classes/providers/delivery/storage.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Items\Item;
6
+
7
+ class Storage extends Delivery_Provider {
8
+
9
+ /**
10
+ * @var bool
11
+ */
12
+ protected static $delivery_domain_allowed = false;
13
+
14
+ /**
15
+ * @var string
16
+ */
17
+ protected static $provider_name = 'Storage Provider';
18
+
19
+ /**
20
+ * @var string
21
+ */
22
+ protected static $provider_short_name = 'Storage';
23
+
24
+ /**
25
+ * Used in filters and settings.
26
+ *
27
+ * @var string
28
+ */
29
+ protected static $provider_key_name = 'storage';
30
+
31
+ /**
32
+ * @var string
33
+ */
34
+ protected static $service_name = 'Bucket';
35
+
36
+ /**
37
+ * @var string
38
+ */
39
+ protected static $service_short_name = 'Bucket';
40
+
41
+ /**
42
+ * Used in filters and settings.
43
+ *
44
+ * @var string
45
+ */
46
+ protected static $service_key_name = 'bucket';
47
+
48
+ /**
49
+ * Returns the full name for the provider.
50
+ *
51
+ * @return string
52
+ */
53
+ public static function get_provider_name() {
54
+ /** @var \Amazon_S3_And_CloudFront $as3cf */
55
+ global $as3cf;
56
+
57
+ return $as3cf->get_storage_provider()->get_provider_name();
58
+ }
59
+
60
+ /**
61
+ * Returns the full name for the service.
62
+ *
63
+ * @return string
64
+ */
65
+ public static function get_service_name() {
66
+ /** @var \Amazon_S3_And_CloudFront $as3cf */
67
+ global $as3cf;
68
+
69
+ return $as3cf->get_storage_provider()->get_service_name();
70
+ }
71
+
72
+ /**
73
+ * Returns the full name for the provider and service for display.
74
+ *
75
+ * @param bool $override_allowed Not used.
76
+ *
77
+ * @return string
78
+ */
79
+ public static function get_provider_service_name( $override_allowed = true ) {
80
+ /** @var \Amazon_S3_And_CloudFront $as3cf */
81
+ global $as3cf;
82
+
83
+ return $as3cf->get_storage_provider()->get_provider_service_name();
84
+ }
85
+
86
+ /**
87
+ * A short description of what features the delivery provider enables.
88
+ *
89
+ * @return string
90
+ */
91
+ public function features_description() {
92
+ return __( 'Slow, Private Media Supported', 'amazon-s3-and-cloudfront' );
93
+ }
94
+
95
+ /**
96
+ * @inheritDoc
97
+ */
98
+ public function get_url( Item $as3cf_item, $path, $domain, $scheme, $headers = array() ) {
99
+ $domain = $this->as3cf->get_storage_provider()->get_url_domain( $as3cf_item->bucket(), $as3cf_item->region() );
100
+
101
+ return parent::get_url( $as3cf_item, $path, $domain, $scheme, $headers );
102
+ }
103
+ }
classes/providers/provider.php CHANGED
@@ -3,21 +3,26 @@
3
  namespace DeliciousBrains\WP_Offload_Media\Providers;
4
 
5
  use AS3CF_Plugin_Base;
6
- use AS3CF_Error;
7
- use AS3CF_Utils;
8
- use Exception;
9
 
10
  abstract class Provider {
11
 
12
  /**
13
  * @var \Amazon_S3_And_CloudFront|\Amazon_S3_And_CloudFront_Pro
14
  */
15
- private $as3cf;
16
 
17
  /**
18
- * @var
 
 
 
 
 
 
 
19
  */
20
- private $client;
21
 
22
  /**
23
  * @var string
@@ -67,72 +72,6 @@ abstract class Provider {
67
  */
68
  protected static $provider_service_quick_start_slug = 'quick-start-guide';
69
 
70
- /**
71
- * @var string
72
- */
73
- protected static $access_key_id_setting_name = 'access-key-id';
74
-
75
- /**
76
- * @var string
77
- */
78
- protected static $secret_access_key_setting_name = 'secret-access-key';
79
-
80
- /**
81
- * @var string
82
- */
83
- protected static $use_server_roles_setting_name = 'use-server-roles';
84
-
85
- /**
86
- * @var string
87
- */
88
- protected static $key_file_setting_name = 'key-file';
89
-
90
- /**
91
- * @var string
92
- */
93
- protected static $key_file_path_setting_name = 'key-file-path';
94
-
95
- /**
96
- * If left empty, access keys not allowed.
97
- *
98
- * @var array
99
- */
100
- protected static $access_key_id_constants = array();
101
-
102
- /**
103
- * @var array
104
- */
105
- protected static $secret_access_key_constants = array();
106
-
107
- /**
108
- * If left empty, server roles not allowed.
109
- *
110
- * @var array
111
- */
112
- protected static $use_server_roles_constants = array();
113
-
114
- /**
115
- * If left empty, key file not allowed.
116
- *
117
- * @var array
118
- */
119
- protected static $key_file_path_constants = array();
120
-
121
- /**
122
- * @var array
123
- */
124
- protected $regions = array();
125
-
126
- /**
127
- * @var bool
128
- */
129
- protected $region_required = false;
130
-
131
- /**
132
- * @var string
133
- */
134
- protected $default_region = '';
135
-
136
  /**
137
  * @var string
138
  */
@@ -153,7 +92,7 @@ abstract class Provider {
153
  *
154
  * @param AS3CF_Plugin_Base $as3cf
155
  */
156
- public function __construct( \AS3CF_Plugin_Base $as3cf ) {
157
  $this->as3cf = $as3cf;
158
  }
159
 
@@ -176,338 +115,69 @@ abstract class Provider {
176
  }
177
 
178
  /**
179
- * Returns the key friendly name for the service.
180
- *
181
- * @return string
182
- */
183
- public static function get_service_key_name() {
184
- return static::$provider_key_name;
185
- }
186
-
187
- /**
188
- * Returns the full name for the provider and service for display.
189
  *
190
  * @return string
191
  */
192
- public static function get_provider_service_name() {
193
- if ( ! empty( static::$provider_service_name ) ) {
194
- return static::$provider_service_name;
195
- }
196
-
197
- return static::$provider_name . ' ' . static::$service_name;
198
- }
199
-
200
- /**
201
- * Returns the slug for the service's quick start guide doc.
202
- *
203
- * @return string
204
- */
205
- public static function get_provider_service_quick_start_slug() {
206
- return static::$provider_service_quick_start_slug;
207
- }
208
-
209
- /**
210
- * Is the provider able to use access keys?
211
- *
212
- * @return bool
213
- */
214
- public static function use_access_keys_allowed() {
215
- return ! empty( static::$access_key_id_constants );
216
  }
217
 
218
  /**
219
- * Whether or not access keys are needed.
220
- *
221
- * Keys are needed if we are not using server roles or not defined/set yet.
222
- *
223
- * @return bool
224
- */
225
- public function needs_access_keys() {
226
- if ( $this->use_server_roles() ) {
227
- return false;
228
- }
229
-
230
- if ( static::use_key_file() ) {
231
- return false;
232
- }
233
-
234
- return ! $this->are_access_keys_set();
235
- }
236
-
237
- /**
238
- * Check if both access key id & secret are present.
239
- *
240
- * @return bool
241
- */
242
- public function are_access_keys_set() {
243
- return $this->get_access_key_id() && $this->get_secret_access_key();
244
- }
245
-
246
- /**
247
- * Get the access key from a constant or the settings.
248
- *
249
- * Falls back to settings only if neither constant is defined.
250
- *
251
- * @return string
252
- */
253
- public function get_access_key_id() {
254
- if ( static::is_any_access_key_constant_defined() ) {
255
- $constant = static::access_key_id_constant();
256
-
257
- return $constant ? constant( $constant ) : '';
258
- }
259
-
260
- return $this->as3cf->get_core_setting( static::$access_key_id_setting_name );
261
- }
262
-
263
- /**
264
- * Get the secret access key from a constant or the settings.
265
- *
266
- * Falls back to settings only if neither constant is defined.
267
  *
268
  * @return string
269
  */
270
- public function get_secret_access_key() {
271
- if ( static::is_any_access_key_constant_defined() ) {
272
- $constant = static::secret_access_key_constant();
273
-
274
- return $constant ? constant( $constant ) : '';
275
- }
276
-
277
- return $this->as3cf->get_core_setting( static::$secret_access_key_setting_name );
278
- }
279
-
280
- /**
281
- * Check if any access key (id or secret, prefixed or not) is defined.
282
- *
283
- * @return bool
284
- */
285
- public static function is_any_access_key_constant_defined() {
286
- return static::access_key_id_constant() || static::secret_access_key_constant();
287
- }
288
-
289
- /**
290
- * Get the constant used to define the access key id.
291
- *
292
- * @return string|false Constant name if defined, otherwise false
293
- */
294
- public static function access_key_id_constant() {
295
- return AS3CF_Utils::get_first_defined_constant( static::$access_key_id_constants );
296
- }
297
-
298
- /**
299
- * Get the constant used to define the secret access key.
300
- *
301
- * @return string|false Constant name if defined, otherwise false
302
- */
303
- public static function secret_access_key_constant() {
304
- return AS3CF_Utils::get_first_defined_constant( static::$secret_access_key_constants );
305
  }
306
 
307
  /**
308
- * Is the provider able to use server roles?
309
  *
310
- * @return bool
311
- */
312
- public static function use_server_roles_allowed() {
313
- return ! empty( static::$use_server_roles_constants );
314
- }
315
-
316
- /**
317
- * If server roles allowed, returns first (preferred) constant that should be defined, otherwise blank.
318
  *
319
  * @return string
320
  */
321
- public static function preferred_use_server_roles_constant() {
322
- if ( static::use_server_roles_allowed() ) {
323
- return static::$use_server_roles_constants[0];
324
  } else {
325
- return '';
326
  }
327
- }
328
 
329
- /**
330
- * Allows the provider's client factory to use server roles instead of key/secret for credentials.
331
- *
332
- * @see http://docs.aws.amazon.com/aws-sdk-php/guide/latest/credentials.html#instance-profile-credentials
333
- *
334
- * @return bool
335
- */
336
- public function use_server_roles() {
337
- if ( ! static::use_server_roles_allowed() ) {
338
- return false;
339
- }
340
-
341
- if ( static::use_server_roles_constant() ) {
342
- $constant = static::use_server_roles_constant();
343
-
344
- return $constant ? constant( $constant ) : false;
345
- }
346
-
347
- return $this->as3cf->get_core_setting( static::$use_server_roles_setting_name, false );
348
- }
349
-
350
- /**
351
- * Get the constant used to enable the use of IAM roles.
352
- *
353
- * @return string|false Constant name if defined, otherwise false
354
- */
355
- public static function use_server_roles_constant() {
356
- return AS3CF_Utils::get_first_defined_constant( static::$use_server_roles_constants );
357
- }
358
-
359
- /**
360
- * Is the provider able to use a key file?
361
- *
362
- * @return bool
363
- */
364
- public static function use_key_file_allowed() {
365
- return ! empty( static::$key_file_path_constants );
366
- }
367
-
368
- /**
369
- * If key file allowed, returns first (preferred) constant that should be defined, otherwise blank.
370
- *
371
- * @return string
372
- */
373
- public static function preferred_key_file_path_constant() {
374
- if ( static::use_key_file_allowed() ) {
375
- return static::$key_file_path_constants[0];
376
  } else {
377
- return '';
378
- }
379
- }
380
-
381
- /**
382
- * Check if either key file path or key file set.
383
- *
384
- * @return bool
385
- */
386
- public function use_key_file() {
387
- if ( ! static::use_key_file_allowed() ) {
388
- return false;
389
- }
390
-
391
- return $this->get_key_file_path() || $this->get_key_file();
392
- }
393
-
394
- /**
395
- * Get the key file contents from settings.
396
- *
397
- * @return array|bool
398
- */
399
- public function get_key_file() {
400
- $key_file = $this->as3cf->get_core_setting( static::$key_file_setting_name, false );
401
-
402
- return $key_file;
403
- }
404
 
405
- /**
406
- * Get the key file path from a constant or the settings.
407
- *
408
- * Falls back to settings if constant is not defined.
409
- *
410
- * @return string|bool
411
- */
412
- public function get_key_file_path() {
413
- if ( static::is_key_file_path_constant_defined() ) {
414
- $constant = static::key_file_path_constant();
415
 
416
- if ( $constant ) {
417
- return $this->validate_key_file_path( constant( $constant ) );
418
  } else {
419
- // Constant defined but value is not a non-empty string.
420
- return false;
421
- }
422
- }
423
-
424
- return $this->validate_key_file_path( $this->as3cf->get_core_setting( static::$key_file_path_setting_name, false ) );
425
- }
426
-
427
- /**
428
- * Validate a key file path to ensure it exists, is readable, and contains JSON.
429
- *
430
- * @param string $key_file_path
431
- *
432
- * @return bool|string
433
- */
434
- public function validate_key_file_path( $key_file_path ) {
435
- $notice_id = 'validate-key-file-path';
436
- $this->as3cf->notices->remove_notice_by_id( $notice_id );
437
-
438
- if ( empty( $key_file_path ) ) {
439
- return false;
440
- }
441
-
442
- if ( ! file_exists( $key_file_path ) ) {
443
- $this->as3cf->notices->add_notice( __( 'Given Key File Path is invalid or could not be accessed.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
444
-
445
- return false;
446
- }
447
-
448
- try {
449
- $value = file_get_contents( $key_file_path );
450
-
451
- // An exception isn't always thrown, so check value instead.
452
- if ( empty( $value ) ) {
453
- $this->as3cf->notices->add_notice( __( 'Could not read Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
454
-
455
- return false;
456
  }
457
- } catch ( \Exception $e ) {
458
- $this->as3cf->notices->add_notice( __( 'Could not read Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
459
-
460
- return false;
461
  }
462
-
463
- $value = json_decode( $value, true );
464
-
465
- if ( empty( $value ) ) {
466
- $this->as3cf->notices->add_notice( __( 'Given Key File Path does not contain valid JSON.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
467
-
468
- return false;
469
- }
470
-
471
- // File exists and looks like JSON.
472
- return $key_file_path;
473
  }
474
 
475
  /**
476
- * Check if key file path constant is defined, for speed, does not check validity of file path.
477
  *
478
  * @return bool
479
  */
480
- public static function is_key_file_path_constant_defined() {
481
- $constant = static::key_file_path_constant();
482
-
483
- return $constant && constant( $constant );
484
- }
485
-
486
- /**
487
- * Get the constant used to define the key file path.
488
- *
489
- * @return string|false Constant name if defined, otherwise false
490
- */
491
- public static function key_file_path_constant() {
492
- return AS3CF_Utils::get_first_defined_constant( static::$key_file_path_constants );
493
  }
494
 
495
  /**
496
- * Returns the Provider's default region slug.
497
- *
498
- * @return string
499
- */
500
- public function region_required() {
501
- return $this->region_required;
502
- }
503
-
504
- /**
505
- * Returns the Provider's default region slug.
506
  *
507
  * @return string
508
  */
509
- public function get_default_region() {
510
- return $this->default_region;
511
  }
512
 
513
  /**
@@ -520,501 +190,4 @@ abstract class Provider {
520
  public function get_domain() {
521
  return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_domain', $this->default_domain );
522
  }
523
-
524
- /**
525
- * Returns an array of valid region slugs and names.
526
- *
527
- * @return array Keys are region slug, values their name
528
- */
529
- public function get_regions() {
530
- $regions = apply_filters( static::$provider_key_name . '_get_regions', $this->regions ); // Backwards compatibility, e.g. 'aws_get_regions'.
531
-
532
- return apply_filters( 'as3cf_' . static::$provider_key_name . '_get_regions', $regions );
533
- }
534
-
535
- /**
536
- * Returns readable region name.
537
- *
538
- * @param string $region
539
- * @param bool $with_key
540
- *
541
- * @return string
542
- */
543
- public function get_region_name( $region = '', $with_key = false ) {
544
- if ( empty( $region ) && ! $this->region_required() ) {
545
- $region = $this->get_default_region();
546
- }
547
-
548
- $regions = $this->get_regions();
549
-
550
- $region_name = empty( $regions[ $region ] ) ? '' : $regions[ $region ];
551
-
552
- if ( $with_key ) {
553
- $region_name .= empty( $region_name ) ? $region : ' (' . $region . ')';
554
- }
555
-
556
- return $region_name;
557
- }
558
-
559
- /**
560
- * Is given region key valid for provider?
561
- *
562
- * @param string $region
563
- *
564
- * @return bool
565
- */
566
- public function is_region_valid( $region ) {
567
- return in_array( trim( $region ), array_keys( $this->get_regions() ) );
568
- }
569
-
570
- /**
571
- * Instantiate a new service client for the provider.
572
- *
573
- * @param array $args Options for required region/endpoint
574
- *
575
- * @throws Exception
576
- */
577
- private function _init_client( Array $args ) {
578
- if ( $this->needs_access_keys() ) {
579
- throw new Exception( sprintf( __( 'You must first <a href="%s">set your access keys</a>.', 'amazon-s3-and-cloudfront' ), $this->as3cf->get_plugin_page_url() . '#settings' ) );
580
- }
581
-
582
- if ( is_null( $this->client ) ) {
583
- // There's no extra client authentication config required when using server roles.
584
- if ( ! $this->use_server_roles() ) {
585
- // Some providers can supply Key File contents or Key File Path.
586
- if ( static::use_key_file() ) {
587
- // Key File contents take precedence over Key File Path.
588
- if ( static::get_key_file() ) {
589
- $args = array_merge( array(
590
- 'keyFile' => static::get_key_file(),
591
- ), $args );
592
- } else {
593
- $args = array_merge( array(
594
- 'keyFilePath' => static::get_key_file_path(),
595
- ), $args );
596
- }
597
- } else {
598
- // Fall back is Access Keys.
599
- $args = array_merge( array(
600
- 'credentials' => array(
601
- 'key' => $this->get_access_key_id(),
602
- 'secret' => $this->get_secret_access_key(),
603
- ),
604
- ), $args );
605
- }
606
- }
607
-
608
- // Add credentials and given args to default client args and then let user override.
609
- $args = array_merge( $this->default_client_args(), $args );
610
- $args = apply_filters( 'as3cf_' . static::$provider_key_name . '_init_client_args', $this->init_client_args( $args ) );
611
- $args = apply_filters( static::$provider_key_name . '_get_client_args', $args ); // Backwards compatibility, e.g. 'aws_get_client_args'.
612
-
613
- $this->client = $this->init_client( $args );
614
- }
615
- }
616
-
617
- /**
618
- * Get the service client instance.
619
- *
620
- * @param array $args Options for required region/endpoint
621
- * @param bool $force
622
- *
623
- * @return Provider
624
- * @throws Exception
625
- */
626
- public function get_client( Array $args, $force = false ) {
627
- if ( true === $force ) {
628
- $this->client = null;
629
- }
630
-
631
- $this->_init_client( $args );
632
-
633
- $args = apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_client_args', $this->init_service_client_args( $args ) );
634
-
635
- $this->client = $this->init_service_client( $args );
636
-
637
- return $this;
638
- }
639
-
640
- /**
641
- * Get object keys from multiple clients.
642
- *
643
- * @param array $regions
644
- *
645
- * @return array
646
- */
647
- public static function get_keys_from_regions( Array $regions ) {
648
- $keys = array();
649
-
650
- foreach ( $regions as $region ) {
651
- try {
652
- /* @var $client Provider */
653
- $client = $region['provider_client'];
654
- $region_keys = $client->list_keys( $region['locations'] );
655
- } catch ( \Exception $e ) {
656
- AS3CF_Error::log( get_class( $e ) . ' exception caught when executing list_keys: ' . $e->getMessage() );
657
- continue;
658
- }
659
-
660
- if ( ! empty( $region_keys ) ) {
661
- foreach ( $region_keys as $attachment_id => $found_keys ) {
662
- $keys[ $attachment_id ] = AS3CF_Utils::validate_attachment_keys( $attachment_id, $found_keys );
663
- }
664
- }
665
- }
666
-
667
- return $keys;
668
- }
669
-
670
- /**
671
- * Generate a stream wrapper compatible URL
672
- *
673
- * @param string $region
674
- * @param string $bucket
675
- * @param string $key
676
- *
677
- * @return string
678
- */
679
- public function prepare_stream_wrapper_file( $region, $bucket, $key ) {
680
- $protocol = $this->get_stream_wrapper_protocol( $region );
681
-
682
- return $protocol . '://' . $bucket . '/' . $key;
683
- }
684
-
685
- /**
686
- * Get the region specific prefix for URL
687
- *
688
- * @param string $region
689
- * @param null|int $expires
690
- *
691
- * @return string
692
- */
693
- public function get_url_prefix( $region = '', $expires = null ) {
694
- /**
695
- * Region specific prefix for raw URL
696
- *
697
- * @param string $prefix
698
- * @param string $region
699
- * @param null|int $expires
700
- *
701
- * @return string
702
- */
703
- return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_url_prefix', $this->url_prefix( $region, $expires ), $region, $expires );
704
- }
705
-
706
- /**
707
- * Get the url domain for the files
708
- *
709
- * @param string $bucket
710
- * @param string $region
711
- * @param int $expires
712
- * @param array $args Allows you to specify custom URL settings
713
- * @param bool $preview When generating the URL preview sanitize certain output
714
- *
715
- * @return string
716
- */
717
- public function get_url_domain( $bucket, $region = '', $expires = null, $args = array(), $preview = false ) {
718
- if ( ! isset( $args['cloudfront'] ) ) {
719
- $args['cloudfront'] = $this->as3cf->get_setting( 'cloudfront' );
720
- }
721
-
722
- if ( ! isset( $args['domain'] ) ) {
723
- $args['domain'] = $this->as3cf->get_setting( 'domain' );
724
- }
725
-
726
- if ( ! isset( $args['force-https'] ) ) {
727
- $args['force-https'] = $this->as3cf->use_ssl( $this->as3cf->get_setting( 'force-https' ) );
728
- }
729
-
730
- $prefix = $this->url_prefix( $region, $expires );
731
- $domain = $this->get_domain();
732
- $domain = empty( $prefix ) ? $domain : $prefix . '.' . $domain;
733
-
734
- return apply_filters(
735
- 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_url_domain',
736
- $this->url_domain( $domain, $bucket, $region, $expires, $args, $preview ),
737
- $bucket,
738
- $region,
739
- $expires,
740
- $args,
741
- $preview
742
- );
743
- }
744
-
745
- /**
746
- * Get the link to the bucket on the provider's console.
747
- *
748
- * @param string $bucket
749
- * @param string $prefix
750
- *
751
- * @return string
752
- */
753
- public function get_console_url( $bucket = '', $prefix = '' ) {
754
- if ( '' !== $prefix ) {
755
- $prefix = $this->get_console_url_prefix_param() . apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_prefix_value', $prefix );
756
- }
757
-
758
- $suffix = apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_suffix_param', $this->get_console_url_suffix_param( $bucket, $prefix ) );
759
-
760
- return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url', $this->console_url ) . $bucket . $prefix . $suffix;
761
- }
762
-
763
- /**
764
- * Get the prefix param to append to the link to the bucket on the provider's console.
765
- *
766
- * @return string
767
- */
768
- public function get_console_url_prefix_param() {
769
- return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_prefix_param', $this->console_url_prefix_param );
770
- }
771
-
772
- /**
773
- * Returns default args array for the client.
774
- *
775
- * @return array
776
- */
777
- abstract protected function default_client_args();
778
-
779
- /**
780
- * Process the args before instantiating a new client for the provider's SDK.
781
- *
782
- * @param array $args
783
- *
784
- * @return array
785
- */
786
- abstract protected function init_client_args( Array $args );
787
-
788
- /**
789
- * Instantiate a new client for the provider's SDK.
790
- *
791
- * @param array $args
792
- */
793
- abstract protected function init_client( Array $args );
794
-
795
- /**
796
- * Process the args before instantiating a new service specific client.
797
- *
798
- * @param array $args
799
- *
800
- * @return array
801
- */
802
- abstract protected function init_service_client_args( Array $args );
803
-
804
- /**
805
- * Instantiate a new service specific client.
806
- * Depending on SDK, may simply return client instantiated with `init_client`.
807
- *
808
- * @param array $args
809
- *
810
- * @return mixed
811
- */
812
- abstract protected function init_service_client( Array $args );
813
-
814
- /**
815
- * Make sure region "slug" fits expected format.
816
- *
817
- * @param string $region
818
- *
819
- * @return string
820
- */
821
- abstract public function sanitize_region( $region );
822
-
823
- /**
824
- * Create bucket.
825
- *
826
- * @param array $args
827
- */
828
- abstract public function create_bucket( Array $args );
829
-
830
- /**
831
- * Check whether bucket exists.
832
- *
833
- * @param string $bucket
834
- *
835
- * @return bool
836
- */
837
- abstract public function does_bucket_exist( $bucket );
838
-
839
- /**
840
- * Returns region for bucket.
841
- *
842
- * @param array $args
843
- *
844
- * @return string
845
- */
846
- abstract public function get_bucket_location( Array $args );
847
-
848
- /**
849
- * List buckets.
850
- *
851
- * @param array $args
852
- *
853
- * @return array
854
- */
855
- abstract public function list_buckets( Array $args = array() );
856
-
857
- /**
858
- * Check whether key exists in bucket.
859
- *
860
- * @param string $bucket
861
- * @param string $key
862
- * @param array $options
863
- *
864
- * @return bool
865
- */
866
- abstract public function does_object_exist( $bucket, $key, Array $options = array() );
867
-
868
- /**
869
- * Get default "canned" ACL string.
870
- *
871
- * @return string
872
- */
873
- abstract public function get_default_acl();
874
-
875
- /**
876
- * Get private "canned" ACL string.
877
- *
878
- * @return string
879
- */
880
- abstract public function get_private_acl();
881
-
882
- /**
883
- * Download object, destination specified in args.
884
- *
885
- * @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#getobject
886
- *
887
- * @param array $args
888
- */
889
- abstract public function get_object( Array $args );
890
-
891
- /**
892
- * Get object's URL.
893
- *
894
- * @param string $bucket
895
- * @param string $key
896
- * @param int $expires
897
- * @param array $args
898
- *
899
- * @return string
900
- */
901
- abstract public function get_object_url( $bucket, $key, $expires, Array $args = array() );
902
-
903
- /**
904
- * List objects.
905
- *
906
- * @param array $args
907
- *
908
- * @return array
909
- */
910
- abstract public function list_objects( Array $args = array() );
911
-
912
- /**
913
- * Update the ACL for an object.
914
- *
915
- * @param array $args
916
- */
917
- abstract public function update_object_acl( Array $args );
918
-
919
- /**
920
- * Upload file to bucket.
921
- *
922
- * @param array $args
923
- */
924
- abstract public function upload_object( Array $args );
925
-
926
- /**
927
- * Delete object from bucket.
928
- *
929
- * @param array $args
930
- */
931
- abstract public function delete_object( Array $args );
932
-
933
- /**
934
- * Delete multiple objects from bucket.
935
- *
936
- * @param array $args
937
- */
938
- abstract public function delete_objects( Array $args );
939
-
940
- /**
941
- * Returns arrays of found keys for given bucket and prefix locations, retaining given array's integer based index.
942
- *
943
- * @param array $locations Array with attachment ID as key and Bucket and Prefix in an associative array as values.
944
- *
945
- * @return array
946
- */
947
- abstract public function list_keys( Array $locations );
948
-
949
- /**
950
- * Copies objects into current bucket from another bucket hosted with provider.
951
- *
952
- * @param array $items
953
- *
954
- * @return array Failures with elements Key and Message
955
- */
956
- abstract public function copy_objects( Array $items );
957
-
958
- /**
959
- * Generate the stream wrapper protocol
960
- *
961
- * @param string $region
962
- *
963
- * @return string
964
- */
965
- abstract protected function get_stream_wrapper_protocol( $region );
966
-
967
- /**
968
- * Register a stream wrapper for specific region.
969
- *
970
- * @param string $region
971
- *
972
- * @return bool
973
- */
974
- abstract public function register_stream_wrapper( $region );
975
-
976
- /**
977
- * Check that a bucket and key can be written to.
978
- *
979
- * @param string $bucket
980
- * @param string $key
981
- * @param string $file_contents
982
- *
983
- * @return bool|string Error message on unexpected exception
984
- */
985
- abstract public function can_write( $bucket, $key, $file_contents );
986
-
987
- /**
988
- * Get the region specific prefix for raw URL
989
- *
990
- * @param string $region
991
- * @param null|int $expires
992
- *
993
- * @return string
994
- */
995
- abstract protected function url_prefix( $region = '', $expires = null );
996
-
997
- /**
998
- * Get the url domain for the files
999
- *
1000
- * @param string $domain Likely prefixed with region
1001
- * @param string $bucket
1002
- * @param string $region
1003
- * @param int $expires
1004
- * @param array $args Allows you to specify custom URL settings
1005
- * @param bool $preview When generating the URL preview sanitize certain output
1006
- *
1007
- * @return string
1008
- */
1009
- abstract protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array(), $preview = false );
1010
-
1011
- /**
1012
- * Get the suffix param to append to the link to the bucket on the provider's console.
1013
- *
1014
- * @param string $bucket
1015
- * @param string $prefix
1016
- *
1017
- * @return string
1018
- */
1019
- abstract protected function get_console_url_suffix_param( $bucket = '', $prefix = '' );
1020
  }
3
  namespace DeliciousBrains\WP_Offload_Media\Providers;
4
 
5
  use AS3CF_Plugin_Base;
6
+ use DeliciousBrains\WP_Offload_Media\Items\Item;
 
 
7
 
8
  abstract class Provider {
9
 
10
  /**
11
  * @var \Amazon_S3_And_CloudFront|\Amazon_S3_And_CloudFront_Pro
12
  */
13
+ protected $as3cf;
14
 
15
  /**
16
+ * Can the displayed provider service name be overridden by the user?
17
+ *
18
+ * @var bool
19
+ */
20
+ protected static $provider_service_name_override_allowed = false;
21
+
22
+ /**
23
+ * @var string
24
  */
25
+ protected static $provider_service_name_setting_name = 'provider-service-name';
26
 
27
  /**
28
  * @var string
72
  */
73
  protected static $provider_service_quick_start_slug = 'quick-start-guide';
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  /**
76
  * @var string
77
  */
92
  *
93
  * @param AS3CF_Plugin_Base $as3cf
94
  */
95
+ public function __construct( AS3CF_Plugin_Base $as3cf ) {
96
  $this->as3cf = $as3cf;
97
  }
98
 
115
  }
116
 
117
  /**
118
+ * Returns the full name for the service.
 
 
 
 
 
 
 
 
 
119
  *
120
  * @return string
121
  */
122
+ public static function get_service_name() {
123
+ return static::$service_name;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  }
125
 
126
  /**
127
+ * Returns the key friendly name for the service.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  *
129
  * @return string
130
  */
131
+ public static function get_service_key_name() {
132
+ return static::$service_key_name;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  }
134
 
135
  /**
136
+ * Returns the full name for the provider and service for display.
137
  *
138
+ * @param bool $override_allowed Use override if available? Defaults to true.
 
 
 
 
 
 
 
139
  *
140
  * @return string
141
  */
142
+ public static function get_provider_service_name( $override_allowed = true ) {
143
+ if ( ! empty( static::$provider_service_name ) ) {
144
+ $result = static::$provider_service_name;
145
  } else {
146
+ $result = static::$provider_name . ' ' . static::$service_name;
147
  }
 
148
 
149
+ if ( false === $override_allowed || false === static::provider_service_name_override_allowed() ) {
150
+ return $result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  } else {
152
+ /** @var \Amazon_S3_And_CloudFront $as3cf */
153
+ global $as3cf;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
+ $override = stripslashes( $as3cf->get_setting( static::$provider_service_name_setting_name ) );
 
 
 
 
 
 
 
 
 
156
 
157
+ if ( empty( $override ) ) {
158
+ return $result;
159
  } else {
160
+ return $override;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
 
 
 
 
162
  }
 
 
 
 
 
 
 
 
 
 
 
163
  }
164
 
165
  /**
166
+ * Can the displayed provider service name be overridden by the user?
167
  *
168
  * @return bool
169
  */
170
+ public static function provider_service_name_override_allowed() {
171
+ return static::$provider_service_name_override_allowed;
 
 
 
 
 
 
 
 
 
 
 
172
  }
173
 
174
  /**
175
+ * Returns the slug for the service's quick start guide doc.
 
 
 
 
 
 
 
 
 
176
  *
177
  * @return string
178
  */
179
+ public static function get_provider_service_quick_start_slug() {
180
+ return static::$provider_service_quick_start_slug;
181
  }
182
 
183
  /**
190
  public function get_domain() {
191
  return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_domain', $this->default_domain );
192
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  }
classes/providers/{aws-provider.php → storage/aws-provider.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_Media\Providers;
4
 
5
  use AS3CF_Utils;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandPool;
@@ -8,9 +8,9 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3Client;
10
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sdk;
11
- use DeliciousBrains\WP_Offload_Media\Providers\Streams\AWS_S3_Stream_Wrapper;
12
 
13
- class AWS_Provider extends Provider {
14
 
15
  /**
16
  * @var Sdk
@@ -97,6 +97,11 @@ class AWS_Provider extends Provider {
97
  'AWS_USE_EC2_IAM_ROLE',
98
  );
99
 
 
 
 
 
 
100
  /**
101
  * @var array
102
  */
@@ -106,18 +111,23 @@ class AWS_Provider extends Provider {
106
  'us-west-1' => 'US West (N. California)',
107
  'us-west-2' => 'US West (Oregon)',
108
  'ca-central-1' => 'Canada (Central)',
 
 
109
  'ap-south-1' => 'Asia Pacific (Mumbai)',
110
  'ap-northeast-2' => 'Asia Pacific (Seoul)',
111
- //'ap-northeast-3' => 'Asia Pacific (Osaka-Local)', // Restricted access, left in for reference only.
112
  'ap-southeast-1' => 'Asia Pacific (Singapore)',
113
  'ap-southeast-2' => 'Asia Pacific (Sydney)',
114
  'ap-northeast-1' => 'Asia Pacific (Tokyo)',
115
- //'cn-north-1' => 'China (Beijing)', // Restricted access, left in for reference only.
116
- //'cn-northwest-1' => 'China (Ningxia)', // Restricted access, left in for reference only.
117
  'eu-central-1' => 'EU (Frankfurt)',
118
  'eu-west-1' => 'EU (Ireland)',
119
  'eu-west-2' => 'EU (London)',
 
120
  'eu-west-3' => 'EU (Paris)',
 
 
121
  'sa-east-1' => 'South America (Sao Paulo)',
122
  );
123
 
@@ -134,19 +144,26 @@ class AWS_Provider extends Provider {
134
  /**
135
  * @var string
136
  */
137
- protected $console_url = 'https://console.aws.amazon.com/s3/home?bucket=';
138
 
139
  /**
140
  * @var string
141
  */
142
- protected $console_url_prefix_param = '&prefix=';
143
 
144
  const API_VERSION = '2006-03-01';
145
  const SIGNATURE_VERSION = 'v4';
146
 
147
- const DEFAULT_ACL = 'public-read';
148
  const PRIVATE_ACL = 'private';
149
 
 
 
 
 
 
 
 
150
  /**
151
  * AWS_Provider constructor.
152
  *
@@ -161,6 +178,41 @@ class AWS_Provider extends Provider {
161
  require_once $as3cf->get_plugin_sdks_dir_path() . '/Aws3/aws-autoloader.php';
162
  }
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  /**
165
  * Disable AWS CSM which tries to check ~/.aws/config causing issues if open_basedir in effect.
166
  *
@@ -192,7 +244,7 @@ class AWS_Provider extends Provider {
192
  *
193
  * @return array
194
  */
195
- protected function init_client_args( Array $args ) {
196
  return $args;
197
  }
198
 
@@ -201,7 +253,7 @@ class AWS_Provider extends Provider {
201
  *
202
  * @param array $args
203
  */
204
- protected function init_client( Array $args ) {
205
  $this->aws_client = new Sdk( $args );
206
  }
207
 
@@ -212,7 +264,7 @@ class AWS_Provider extends Provider {
212
  *
213
  * @return array
214
  */
215
- protected function init_service_client_args( Array $args ) {
216
  return $args;
217
  }
218
 
@@ -223,7 +275,7 @@ class AWS_Provider extends Provider {
223
  *
224
  * @return S3Client
225
  */
226
- protected function init_service_client( Array $args ) {
227
  if ( empty( $args['region'] ) || $args['region'] === $this->default_region ) {
228
  $this->s3_client = $this->aws_client->createMultiRegionS3( $args );
229
  } else {
@@ -266,7 +318,7 @@ class AWS_Provider extends Provider {
266
  *
267
  * @param array $args
268
  */
269
- public function create_bucket( Array $args ) {
270
  if ( ! empty( $args['LocationConstraint'] ) ) {
271
  $args['CreateBucketConfiguration']['LocationConstraint'] = $args['LocationConstraint'];
272
  unset( $args['LocationConstraint'] );
@@ -293,7 +345,7 @@ class AWS_Provider extends Provider {
293
  *
294
  * @return string
295
  */
296
- public function get_bucket_location( Array $args ) {
297
  $location = $this->s3_client->getBucketLocation( $args );
298
  $region = empty( $location['LocationConstraint'] ) ? '' : $location['LocationConstraint'];
299
 
@@ -307,7 +359,7 @@ class AWS_Provider extends Provider {
307
  *
308
  * @return array
309
  */
310
- public function list_buckets( Array $args = array() ) {
311
  return $this->s3_client->listBuckets( $args )->toArray();
312
  }
313
 
@@ -320,17 +372,17 @@ class AWS_Provider extends Provider {
320
  *
321
  * @return bool
322
  */
323
- public function does_object_exist( $bucket, $key, Array $options = array() ) {
324
  return $this->s3_client->doesObjectExist( $bucket, $key, $options );
325
  }
326
 
327
  /**
328
- * Get default "canned" ACL string.
329
  *
330
  * @return string
331
  */
332
- public function get_default_acl() {
333
- return static::DEFAULT_ACL;
334
  }
335
 
336
  /**
@@ -342,6 +394,77 @@ class AWS_Provider extends Provider {
342
  return static::PRIVATE_ACL;
343
  }
344
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
  /**
346
  * Download object, destination specified in args.
347
  *
@@ -349,7 +472,7 @@ class AWS_Provider extends Provider {
349
  *
350
  * @param array $args
351
  */
352
- public function get_object( Array $args ) {
353
  $this->s3_client->getObject( $args );
354
  }
355
 
@@ -358,12 +481,12 @@ class AWS_Provider extends Provider {
358
  *
359
  * @param string $bucket
360
  * @param string $key
361
- * @param int $expires
362
  * @param array $args
363
  *
364
  * @return string
365
  */
366
- public function get_object_url( $bucket, $key, $expires, Array $args = array() ) {
367
  $commandArgs = [ 'Bucket' => $bucket, 'Key' => $key ];
368
 
369
  if ( ! empty( $args ) ) {
@@ -372,10 +495,10 @@ class AWS_Provider extends Provider {
372
 
373
  $command = $this->s3_client->getCommand( 'GetObject', $commandArgs );
374
 
375
- if ( empty( $expires ) || ! is_int( $expires ) || $expires < 0 ) {
376
  return (string) \DeliciousBrains\WP_Offload_Media\Aws3\Aws\serialize( $command )->getUri();
377
  } else {
378
- return (string) $this->s3_client->createPresignedRequest( $command, $expires )->getUri();
379
  }
380
  }
381
 
@@ -386,7 +509,7 @@ class AWS_Provider extends Provider {
386
  *
387
  * @return array
388
  */
389
- public function list_objects( Array $args = array() ) {
390
  return $this->s3_client->listObjects( $args )->toArray();
391
  }
392
 
@@ -395,16 +518,27 @@ class AWS_Provider extends Provider {
395
  *
396
  * @param array $args
397
  */
398
- public function update_object_acl( Array $args ) {
399
  $this->s3_client->putObjectAcl( $args );
400
  }
401
 
 
 
 
 
 
 
 
 
 
 
 
402
  /**
403
  * Upload file to bucket.
404
  *
405
  * @param array $args
406
  */
407
- public function upload_object( Array $args ) {
408
  $this->s3_client->putObject( $args );
409
  }
410
 
@@ -413,7 +547,7 @@ class AWS_Provider extends Provider {
413
  *
414
  * @param array $args
415
  */
416
- public function delete_object( Array $args ) {
417
  $this->s3_client->deleteObject( $args );
418
  }
419
 
@@ -422,7 +556,7 @@ class AWS_Provider extends Provider {
422
  *
423
  * @param array $args
424
  */
425
- public function delete_objects( Array $args ) {
426
  if ( ! isset( $args['Delete'] ) && isset( $args['Objects'] ) ) {
427
  $args['Delete']['Objects'] = $args['Objects'];
428
  unset( $args['Objects'] );
@@ -438,7 +572,7 @@ class AWS_Provider extends Provider {
438
  *
439
  * @return array
440
  */
441
- public function list_keys( Array $locations ) {
442
  $keys = array();
443
 
444
  $commands = array_map( function ( $location ) {
@@ -473,29 +607,8 @@ class AWS_Provider extends Provider {
473
  *
474
  * @return array Failures with elements Key and Message
475
  */
476
- public function copy_objects( Array $items ) {
477
- $failures = array();
478
-
479
- $commands = array_map( function ( $item ) {
480
- return $this->s3_client->getCommand( 'CopyObject', $item );
481
- }, $items );
482
-
483
- $results = CommandPool::batch( $this->s3_client, $commands );
484
-
485
- if ( ! empty( $results ) ) {
486
- foreach ( $results as $result ) {
487
- /* @var S3Exception $result */
488
- if ( is_a( $result, 'DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception' ) ) {
489
- $command = $result->getCommand()->toArray();
490
- $failures[] = array(
491
- 'Key' => $command['Key'],
492
- 'Message' => $result->getAwsErrorMessage(),
493
- );
494
- }
495
- }
496
- }
497
-
498
- return $failures;
499
  }
500
 
501
  /**
@@ -544,7 +657,6 @@ class AWS_Provider extends Provider {
544
  'Bucket' => $bucket,
545
  'Key' => $key,
546
  'Body' => $file_contents,
547
- 'ACL' => self::DEFAULT_ACL,
548
  ) );
549
 
550
  // delete it straight away if created
@@ -576,14 +688,7 @@ class AWS_Provider extends Provider {
576
  $prefix = 's3';
577
 
578
  if ( '' !== $region ) {
579
- $delimiter = '-';
580
- if ( 'eu-central-1' == $region && ! is_null( $expires ) ) {
581
- // if we are creating a secure URL for a Frankfurt base file use the alternative delimiter
582
- // http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
583
- $delimiter = '.';
584
- }
585
-
586
- $prefix .= $delimiter . $region;
587
  }
588
 
589
  return $prefix;
@@ -592,26 +697,19 @@ class AWS_Provider extends Provider {
592
  /**
593
  * Get the url domain for the files
594
  *
595
- * @param string $domain Likely prefixed with region
596
  * @param string $bucket
597
  * @param string $region
598
  * @param int $expires
599
- * @param array $args Allows you to specify custom URL settings
600
- * @param bool $preview When generating the URL preview sanitize certain output
601
  *
602
  * @return string
603
  */
604
- protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array(), $preview = false ) {
605
- if ( 'cloudfront' === $args['domain'] && is_null( $expires ) && $args['cloudfront'] ) {
606
- $cloudfront = $args['cloudfront'];
607
- if ( $preview ) {
608
- $cloudfront = AS3CF_Utils::sanitize_custom_domain( $cloudfront );
609
- }
610
-
611
- $domain = $cloudfront;
612
- } elseif ( 'virtual-host' === $args['domain'] ) {
613
- $domain = $bucket;
614
- } elseif ( 'path' === $args['domain'] || $args['force-https'] ) {
615
  $domain = $domain . '/' . $bucket;
616
  } else {
617
  $domain = $bucket . '.' . $domain;
@@ -625,10 +723,11 @@ class AWS_Provider extends Provider {
625
  *
626
  * @param string $bucket
627
  * @param string $prefix
 
628
  *
629
  * @return string
630
  */
631
- protected function get_console_url_suffix_param( $bucket = '', $prefix = '' ) {
632
- return '';
633
  }
634
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Storage;
4
 
5
  use AS3CF_Utils;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandPool;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3Client;
10
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sdk;
11
+ use DeliciousBrains\WP_Offload_Media\Providers\Storage\Streams\AWS_S3_Stream_Wrapper;
12
 
13
+ class AWS_Provider extends Storage_Provider {
14
 
15
  /**
16
  * @var Sdk
97
  'AWS_USE_EC2_IAM_ROLE',
98
  );
99
 
100
+ /**
101
+ * @var bool
102
+ */
103
+ protected static $block_public_access_allowed = true;
104
+
105
  /**
106
  * @var array
107
  */
111
  'us-west-1' => 'US West (N. California)',
112
  'us-west-2' => 'US West (Oregon)',
113
  'ca-central-1' => 'Canada (Central)',
114
+ 'af-south-1' => 'Africa (Cape Town)',
115
+ 'ap-east-1' => 'Asia Pacific (Hong Kong)',
116
  'ap-south-1' => 'Asia Pacific (Mumbai)',
117
  'ap-northeast-2' => 'Asia Pacific (Seoul)',
118
+ 'ap-northeast-3' => 'Asia Pacific (Osaka-Local)',
119
  'ap-southeast-1' => 'Asia Pacific (Singapore)',
120
  'ap-southeast-2' => 'Asia Pacific (Sydney)',
121
  'ap-northeast-1' => 'Asia Pacific (Tokyo)',
122
+ 'cn-north-1' => 'China (Beijing)',
123
+ 'cn-northwest-1' => 'China (Ningxia)',
124
  'eu-central-1' => 'EU (Frankfurt)',
125
  'eu-west-1' => 'EU (Ireland)',
126
  'eu-west-2' => 'EU (London)',
127
+ 'eu-south-1' => 'EU (Milan)',
128
  'eu-west-3' => 'EU (Paris)',
129
+ 'eu-north-1' => 'EU (Stockholm)',
130
+ 'me-south-1' => 'Middle East (Bahrain)',
131
  'sa-east-1' => 'South America (Sao Paulo)',
132
  );
133
 
144
  /**
145
  * @var string
146
  */
147
+ protected $console_url = 'https://console.aws.amazon.com/s3/buckets/';
148
 
149
  /**
150
  * @var string
151
  */
152
+ protected $console_url_prefix_param = '/';
153
 
154
  const API_VERSION = '2006-03-01';
155
  const SIGNATURE_VERSION = 'v4';
156
 
157
+ const PUBLIC_ACL = 'public-read';
158
  const PRIVATE_ACL = 'private';
159
 
160
+ /**
161
+ * Keeps track of Block Public Access state for buckets to save hitting API.
162
+ *
163
+ * @var array
164
+ */
165
+ private $blocked_buckets = array();
166
+
167
  /**
168
  * AWS_Provider constructor.
169
  *
178
  require_once $as3cf->get_plugin_sdks_dir_path() . '/Aws3/aws-autoloader.php';
179
  }
180
 
181
+ /**
182
+ * Run a command over a batch of items, returning any failures.
183
+ *
184
+ * @param string $command
185
+ * @param array $items
186
+ *
187
+ * @return array Failures with elements Key and Message
188
+ *
189
+ * NOTE: Only really useful for commands that take 'Key' as one of their args.
190
+ */
191
+ private function batch_command( $command, array $items ) {
192
+ $failures = array();
193
+
194
+ $commands = array_map( function ( $item ) use ( $command ) {
195
+ return $this->s3_client->getCommand( $command, $item );
196
+ }, $items );
197
+
198
+ $results = CommandPool::batch( $this->s3_client, $commands );
199
+
200
+ if ( ! empty( $results ) ) {
201
+ foreach ( $results as $result ) {
202
+ /* @var S3Exception $result */
203
+ if ( is_a( $result, 'DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception' ) ) {
204
+ $failed_command = $result->getCommand()->toArray();
205
+ $failures[] = array(
206
+ 'Key' => $failed_command['Key'],
207
+ 'Message' => $result->getAwsErrorMessage(),
208
+ );
209
+ }
210
+ }
211
+ }
212
+
213
+ return $failures;
214
+ }
215
+
216
  /**
217
  * Disable AWS CSM which tries to check ~/.aws/config causing issues if open_basedir in effect.
218
  *
244
  *
245
  * @return array
246
  */
247
+ protected function init_client_args( array $args ) {
248
  return $args;
249
  }
250
 
253
  *
254
  * @param array $args
255
  */
256
+ protected function init_client( array $args ) {
257
  $this->aws_client = new Sdk( $args );
258
  }
259
 
264
  *
265
  * @return array
266
  */
267
+ protected function init_service_client_args( array $args ) {
268
  return $args;
269
  }
270
 
275
  *
276
  * @return S3Client
277
  */
278
+ protected function init_service_client( array $args ) {
279
  if ( empty( $args['region'] ) || $args['region'] === $this->default_region ) {
280
  $this->s3_client = $this->aws_client->createMultiRegionS3( $args );
281
  } else {
318
  *
319
  * @param array $args
320
  */
321
+ public function create_bucket( array $args ) {
322
  if ( ! empty( $args['LocationConstraint'] ) ) {
323
  $args['CreateBucketConfiguration']['LocationConstraint'] = $args['LocationConstraint'];
324
  unset( $args['LocationConstraint'] );
345
  *
346
  * @return string
347
  */
348
+ public function get_bucket_location( array $args ) {
349
  $location = $this->s3_client->getBucketLocation( $args );
350
  $region = empty( $location['LocationConstraint'] ) ? '' : $location['LocationConstraint'];
351
 
359
  *
360
  * @return array
361
  */
362
+ public function list_buckets( array $args = array() ) {
363
  return $this->s3_client->listBuckets( $args )->toArray();
364
  }
365
 
372
  *
373
  * @return bool
374
  */
375
+ public function does_object_exist( $bucket, $key, array $options = array() ) {
376
  return $this->s3_client->doesObjectExist( $bucket, $key, $options );
377
  }
378
 
379
  /**
380
+ * Get public "canned" ACL string.
381
  *
382
  * @return string
383
  */
384
+ public function get_public_acl() {
385
+ return static::PUBLIC_ACL;
386
  }
387
 
388
  /**
394
  return static::PRIVATE_ACL;
395
  }
396
 
397
+ /**
398
+ * Is public access to the given bucket prohibited?
399
+ *
400
+ * @param string $bucket
401
+ *
402
+ * @return bool|null
403
+ *
404
+ * Note: It's very possible that permissions don't allow the check, in which case default value is returned.
405
+ */
406
+ public function public_access_blocked( $bucket ) {
407
+ if ( isset( $this->blocked_buckets[ $bucket ] ) ) {
408
+ return $this->blocked_buckets[ $bucket ];
409
+ }
410
+
411
+ $blocked = parent::public_access_blocked( $bucket );
412
+
413
+ try {
414
+ $result = $this->s3_client->getPublicAccessBlock( [ 'Bucket' => $bucket ] );
415
+ } catch ( \Exception $e ) {
416
+ // No policy defined at either bucket or account level, so no blocking happening.
417
+ if ( false !== strpos( $e->getMessage(), 'NoSuchPublicAccessBlockConfiguration' ) ) {
418
+ $blocked = false;
419
+ }
420
+ }
421
+
422
+ if ( ! empty( $result ) && ! empty( $result['PublicAccessBlockConfiguration'] ) ) {
423
+ $settings = $result['PublicAccessBlockConfiguration'];
424
+ if (
425
+ empty( $settings['BlockPublicAcls'] ) &&
426
+ empty( $settings['BlockPublicPolicy'] ) &&
427
+ empty( $settings['IgnorePublicAcls'] ) &&
428
+ empty( $settings['RestrictPublicBuckets'] ) ) {
429
+ $blocked = false;
430
+ } else {
431
+ $blocked = true;
432
+ }
433
+ }
434
+
435
+ $this->blocked_buckets[ $bucket ] = $blocked;
436
+
437
+ return $blocked;
438
+ }
439
+
440
+ /**
441
+ * Update the block public access setting for the given bucket.
442
+ *
443
+ * @param string $bucket
444
+ * @param bool $block
445
+ */
446
+ public function block_public_access( $bucket, $block ) {
447
+ if ( empty( $bucket ) || ! is_bool( $block ) ) {
448
+ return;
449
+ }
450
+
451
+ $setting = array(
452
+ 'Bucket' => $bucket,
453
+ 'PublicAccessBlockConfiguration' => array(
454
+ 'BlockPublicAcls' => $block,
455
+ 'BlockPublicPolicy' => $block,
456
+ 'IgnorePublicAcls' => $block,
457
+ 'RestrictPublicBuckets' => $block,
458
+ ),
459
+ );
460
+
461
+ $this->s3_client->putPublicAccessBlock( $setting );
462
+
463
+ unset( $this->blocked_buckets[ $bucket ] );
464
+
465
+ return;
466
+ }
467
+
468
  /**
469
  * Download object, destination specified in args.
470
  *
472
  *
473
  * @param array $args
474
  */
475
+ public function get_object( array $args ) {
476
  $this->s3_client->getObject( $args );
477
  }
478
 
481
  *
482
  * @param string $bucket
483
  * @param string $key
484
+ * @param int $timestamp
485
  * @param array $args
486
  *
487
  * @return string
488
  */
489
+ public function get_object_url( $bucket, $key, $timestamp, array $args = array() ) {
490
  $commandArgs = [ 'Bucket' => $bucket, 'Key' => $key ];
491
 
492
  if ( ! empty( $args ) ) {
495
 
496
  $command = $this->s3_client->getCommand( 'GetObject', $commandArgs );
497
 
498
+ if ( empty( $timestamp ) || ! is_int( $timestamp ) || $timestamp < 0 ) {
499
  return (string) \DeliciousBrains\WP_Offload_Media\Aws3\Aws\serialize( $command )->getUri();
500
  } else {
501
+ return (string) $this->s3_client->createPresignedRequest( $command, $timestamp )->getUri();
502
  }
503
  }
504
 
509
  *
510
  * @return array
511
  */
512
+ public function list_objects( array $args = array() ) {
513
  return $this->s3_client->listObjects( $args )->toArray();
514
  }
515
 
518
  *
519
  * @param array $args
520
  */
521
+ public function update_object_acl( array $args ) {
522
  $this->s3_client->putObjectAcl( $args );
523
  }
524
 
525
+ /**
526
+ * Update the ACL for multiple objects.
527
+ *
528
+ * @param array $items
529
+ *
530
+ * @return array Failures with elements Key and Message
531
+ */
532
+ public function update_object_acls( array $items ) {
533
+ return $this->batch_command( 'PutObjectAcl', $items );
534
+ }
535
+
536
  /**
537
  * Upload file to bucket.
538
  *
539
  * @param array $args
540
  */
541
+ public function upload_object( array $args ) {
542
  $this->s3_client->putObject( $args );
543
  }
544
 
547
  *
548
  * @param array $args
549
  */
550
+ public function delete_object( array $args ) {
551
  $this->s3_client->deleteObject( $args );
552
  }
553
 
556
  *
557
  * @param array $args
558
  */
559
+ public function delete_objects( array $args ) {
560
  if ( ! isset( $args['Delete'] ) && isset( $args['Objects'] ) ) {
561
  $args['Delete']['Objects'] = $args['Objects'];
562
  unset( $args['Objects'] );
572
  *
573
  * @return array
574
  */
575
+ public function list_keys( array $locations ) {
576
  $keys = array();
577
 
578
  $commands = array_map( function ( $location ) {
607
  *
608
  * @return array Failures with elements Key and Message
609
  */
610
+ public function copy_objects( array $items ) {
611
+ return $this->batch_command( 'CopyObject', $items );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
612
  }
613
 
614
  /**
657
  'Bucket' => $bucket,
658
  'Key' => $key,
659
  'Body' => $file_contents,
 
660
  ) );
661
 
662
  // delete it straight away if created
688
  $prefix = 's3';
689
 
690
  if ( '' !== $region ) {
691
+ $prefix .= '.' . $region;
 
 
 
 
 
 
 
692
  }
693
 
694
  return $prefix;
697
  /**
698
  * Get the url domain for the files
699
  *
700
+ * @param string $domain Likely prefixed with region
701
  * @param string $bucket
702
  * @param string $region
703
  * @param int $expires
704
+ * @param array $args Allows you to specify custom URL settings
 
705
  *
706
  * @return string
707
  */
708
+ protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array() ) {
709
+ if ( apply_filters( 'as3cf_' . static::get_provider_key_name() . '_' . static::get_service_key_name() . '_bucket_in_path', false !== strpos( $bucket, '.' ) ) ) {
710
+ // TODO: This mode is going away, kinda, sorta, one day.
711
+ // TODO: When AWS sort out HTTPS for bucket in domain with dots we can remove this format.
712
+ // @see https://aws.amazon.com/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story/
 
 
 
 
 
 
713
  $domain = $domain . '/' . $bucket;
714
  } else {
715
  $domain = $bucket . '.' . $domain;
723
  *
724
  * @param string $bucket
725
  * @param string $prefix
726
+ * @param string $region
727
  *
728
  * @return string
729
  */
730
+ protected function get_console_url_suffix_param( $bucket = '', $prefix = '', $region = '' ) {
731
+ return empty( $region ) ? '' : '?region=' . $region;
732
  }
733
  }
classes/providers/{digitalocean-provider.php → storage/digitalocean-provider.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_Media\Providers;
4
 
5
  class DigitalOcean_Provider extends AWS_Provider {
6
 
@@ -71,6 +71,11 @@ class DigitalOcean_Provider extends AWS_Provider {
71
  */
72
  protected static $use_server_roles_constants = array();
73
 
 
 
 
 
 
74
  /**
75
  * @var array
76
  */
@@ -143,6 +148,17 @@ class DigitalOcean_Provider extends AWS_Provider {
143
  return $args;
144
  }
145
 
 
 
 
 
 
 
 
 
 
 
 
146
  /**
147
  * Create bucket.
148
  *
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Storage;
4
 
5
  class DigitalOcean_Provider extends AWS_Provider {
6
 
71
  */
72
  protected static $use_server_roles_constants = array();
73
 
74
+ /**
75
+ * @var bool
76
+ */
77
+ protected static $block_public_access_allowed = false;
78
+
79
  /**
80
  * @var array
81
  */
148
  return $args;
149
  }
150
 
151
+ /**
152
+ * Update the block public access setting for the given bucket.
153
+ *
154
+ * @param string $bucket
155
+ * @param bool $block
156
+ */
157
+ public function block_public_access( $bucket, $block ) {
158
+ // DigitalOcean doesn't support this, so do nothing.
159
+ return;
160
+ }
161
+
162
  /**
163
  * Create bucket.
164
  *
classes/providers/{gcp-provider.php → storage/gcp-provider.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_Media\Providers;
4
 
5
  use AS3CF_Utils;
6
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Core\Exception\GoogleException;
@@ -8,9 +8,9 @@ use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Core\ServiceBuilder;
8
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\Bucket;
9
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageClient;
10
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageObject;
11
- use DeliciousBrains\WP_Offload_Media\Providers\Streams\GCP_GCS_Stream_Wrapper;
12
 
13
- class GCP_Provider extends Provider {
14
 
15
  /**
16
  * @var ServiceBuilder
@@ -97,18 +97,25 @@ class GCP_Provider extends Provider {
97
  'us-east4' => 'Northern Virginia',
98
  'us-west1' => 'Oregon',
99
  'us-west2' => 'Los Angeles',
 
 
100
  'southamerica-east1' => 'São Paulo',
101
  'europe-north1' => 'Finland',
102
  'europe-west1' => 'Belgium',
103
  'europe-west2' => 'London',
104
  'europe-west3' => 'Frankfurt',
105
  'europe-west4' => 'Netherlands',
 
106
  'asia-east1' => 'Taiwan',
107
  'asia-east2' => 'Hong Kong',
108
  'asia-northeast1' => 'Tokyo',
 
 
109
  'asia-south1' => 'Mumbai',
110
  'asia-southeast1' => 'Singapore',
111
  'australia-southeast1' => 'Sydney',
 
 
112
  );
113
 
114
  /**
@@ -131,7 +138,7 @@ class GCP_Provider extends Provider {
131
  */
132
  protected $console_url_prefix_param = '/';
133
 
134
- const DEFAULT_ACL = 'publicRead';
135
  const PRIVATE_ACL = 'projectPrivate';
136
 
137
  /**
@@ -162,7 +169,7 @@ class GCP_Provider extends Provider {
162
  *
163
  * @return array
164
  */
165
- protected function init_client_args( Array $args ) {
166
  return $args;
167
  }
168
 
@@ -171,7 +178,7 @@ class GCP_Provider extends Provider {
171
  *
172
  * @param array $args
173
  */
174
- protected function init_client( Array $args ) {
175
  $this->cloud = new ServiceBuilder( $args );
176
  }
177
 
@@ -182,7 +189,7 @@ class GCP_Provider extends Provider {
182
  *
183
  * @return array
184
  */
185
- protected function init_service_client_args( Array $args ) {
186
  return $args;
187
  }
188
 
@@ -193,7 +200,7 @@ class GCP_Provider extends Provider {
193
  *
194
  * @return StorageClient
195
  */
196
- protected function init_service_client( Array $args ) {
197
  $this->storage = $this->cloud->storage( $args );
198
 
199
  return $this->storage;
@@ -222,7 +229,7 @@ class GCP_Provider extends Provider {
222
  *
223
  * @throws GoogleException
224
  */
225
- public function create_bucket( Array $args ) {
226
  $name = '';
227
  if ( ! empty( $args['Bucket'] ) ) {
228
  $name = $args['Bucket'];
@@ -255,7 +262,7 @@ class GCP_Provider extends Provider {
255
  *
256
  * @return string
257
  */
258
- public function get_bucket_location( Array $args ) {
259
  $info = $this->storage->bucket( $args['Bucket'] )->info();
260
  $region = empty( $info['location'] ) ? '' : $info['location'];
261
 
@@ -270,7 +277,7 @@ class GCP_Provider extends Provider {
270
  * @return array
271
  * @throws GoogleException
272
  */
273
- public function list_buckets( Array $args = array() ) {
274
  $result = array();
275
 
276
  $buckets = $this->storage->buckets( $args );
@@ -296,17 +303,17 @@ class GCP_Provider extends Provider {
296
  *
297
  * @return bool
298
  */
299
- public function does_object_exist( $bucket, $key, Array $options = array() ) {
300
  return $this->storage->bucket( $bucket )->object( $key )->exists( $options );
301
  }
302
 
303
  /**
304
- * Get default "canned" ACL string.
305
  *
306
  * @return string
307
  */
308
- public function get_default_acl() {
309
- return static::DEFAULT_ACL;
310
  }
311
 
312
  /**
@@ -326,7 +333,7 @@ class GCP_Provider extends Provider {
326
  *
327
  * @param array $args
328
  */
329
- public function get_object( Array $args ) {
330
  $this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->downloadToFile( $args['SaveAs'] );
331
  }
332
 
@@ -335,13 +342,13 @@ class GCP_Provider extends Provider {
335
  *
336
  * @param string $bucket
337
  * @param string $key
338
- * @param int $expires
339
  * @param array $args
340
  *
341
  * @return string
342
  */
343
- public function get_object_url( $bucket, $key, $expires, Array $args = array() ) {
344
- if ( empty( $expires ) || ! is_int( $expires ) || $expires < 0 ) {
345
  $info = $this->storage->bucket( $bucket )->object( $key )->info();
346
  $link = empty( $info['selfLink'] ) ? '' : $info['selfLink'];
347
 
@@ -353,7 +360,7 @@ class GCP_Provider extends Provider {
353
  $options['cname'] = $args['BaseURL'];
354
  }
355
 
356
- return $this->storage->bucket( $bucket )->object( $key )->signedUrl( time() + $expires, $options );
357
  }
358
  }
359
 
@@ -364,7 +371,7 @@ class GCP_Provider extends Provider {
364
  *
365
  * @return array
366
  */
367
- public function list_objects( Array $args = array() ) {
368
  $result = array();
369
 
370
  $objects = $this->storage->bucket( $args['Bucket'] )->objects( $args['Prefix'] );
@@ -387,11 +394,42 @@ class GCP_Provider extends Provider {
387
  * Update the ACL for an object.
388
  *
389
  * @param array $args
 
 
390
  */
391
- public function update_object_acl( Array $args ) {
 
 
 
 
392
  $this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->update( array( 'predefinedAcl' => $args['ACL'] ) );
393
  }
394
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  /**
396
  * Upload file to bucket.
397
  *
@@ -399,7 +437,7 @@ class GCP_Provider extends Provider {
399
  *
400
  * @throws \Exception
401
  */
402
- public function upload_object( Array $args ) {
403
  if ( ! empty( $args['SourceFile'] ) ) {
404
  $file = fopen( $args['SourceFile'], 'r' );
405
  } elseif ( ! empty( $args['Body'] ) ) {
@@ -409,10 +447,13 @@ class GCP_Provider extends Provider {
409
  }
410
 
411
  $options = array(
412
- 'name' => $args['Key'],
413
- 'predefinedAcl' => $args['ACL'],
414
  );
415
 
 
 
 
 
416
  if ( ! empty( $args['ContentType'] ) ) {
417
  $options['metadata']['contentType'] = $args['ContentType'];
418
  }
@@ -431,7 +472,7 @@ class GCP_Provider extends Provider {
431
  *
432
  * @param array $args
433
  */
434
- public function delete_object( Array $args ) {
435
  $this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->delete();
436
  }
437
 
@@ -440,7 +481,7 @@ class GCP_Provider extends Provider {
440
  *
441
  * @param array $args
442
  */
443
- public function delete_objects( Array $args ) {
444
  if ( isset( $args['Delete']['Objects'] ) ) {
445
  $keys = $args['Delete']['Objects'];
446
  } elseif ( isset( $args['Objects'] ) ) {
@@ -464,7 +505,7 @@ class GCP_Provider extends Provider {
464
  *
465
  * @return array
466
  */
467
- public function list_keys( Array $locations ) {
468
  $keys = array();
469
 
470
  $results = array_map( function ( $location ) {
@@ -488,20 +529,23 @@ class GCP_Provider extends Provider {
488
  *
489
  * @return array Failures with elements Key and Message
490
  */
491
- public function copy_objects( Array $items ) {
492
  $failures = array();
493
 
494
  // Unfortunately the GCP PHP SDK does not have batch operations.
495
  foreach ( $items as $item ) {
496
  list( $bucket, $key ) = explode( '/', urldecode( $item['CopySource'] ), 2 );
 
 
 
 
 
 
 
 
 
497
  try {
498
- $this->storage->bucket( $bucket )->object( $key )->copy(
499
- $item['Bucket'],
500
- array(
501
- 'name' => $item['Key'],
502
- 'predefinedAcl' => $item['ACL'],
503
- )
504
- );
505
  } catch ( \Exception $e ) {
506
  $failures[] = array(
507
  'Key' => $item['Key'],
@@ -562,7 +606,6 @@ class GCP_Provider extends Provider {
562
  'Bucket' => $bucket,
563
  'Key' => $key,
564
  'Body' => $file_contents,
565
- 'ACL' => self::DEFAULT_ACL,
566
  ) );
567
 
568
  // delete it straight away if created
@@ -578,6 +621,8 @@ class GCP_Provider extends Provider {
578
  return $e->getMessage();
579
  }
580
  }
 
 
581
  }
582
 
583
  /**
@@ -595,25 +640,20 @@ class GCP_Provider extends Provider {
595
  /**
596
  * Get the url domain for the files
597
  *
598
- * @param string $domain Likely prefixed with region
599
  * @param string $bucket
600
  * @param string $region
601
  * @param int $expires
602
- * @param array $args Allows you to specify custom URL settings
603
- * @param bool $preview When generating the URL preview sanitize certain output
604
  *
605
  * @return string
606
  */
607
- protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array(), $preview = false ) {
608
- if ( 'cloudfront' === $args['domain'] && $args['cloudfront'] ) {
609
- $cloudfront = $args['cloudfront'];
610
- if ( $preview ) {
611
- $cloudfront = AS3CF_Utils::sanitize_custom_domain( $cloudfront );
612
- }
613
-
614
- $domain = $cloudfront;
615
- } else {
616
  $domain = $domain . '/' . $bucket;
 
 
 
617
  }
618
 
619
  return $domain;
@@ -624,10 +664,11 @@ class GCP_Provider extends Provider {
624
  *
625
  * @param string $bucket
626
  * @param string $prefix
 
627
  *
628
  * @return string
629
  */
630
- protected function get_console_url_suffix_param( $bucket = '', $prefix = '' ) {
631
  if ( ! empty( $this->get_project_id() ) ) {
632
  return '?project=' . $this->get_project_id();
633
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Storage;
4
 
5
  use AS3CF_Utils;
6
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Core\Exception\GoogleException;
8
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\Bucket;
9
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageClient;
10
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageObject;
11
+ use DeliciousBrains\WP_Offload_Media\Providers\Storage\Streams\GCP_GCS_Stream_Wrapper;
12
 
13
+ class GCP_Provider extends Storage_Provider {
14
 
15
  /**
16
  * @var ServiceBuilder
97
  'us-east4' => 'Northern Virginia',
98
  'us-west1' => 'Oregon',
99
  'us-west2' => 'Los Angeles',
100
+ 'us-west3' => 'Salt Lake City',
101
+ 'us-west4' => 'Las Vegas',
102
  'southamerica-east1' => 'São Paulo',
103
  'europe-north1' => 'Finland',
104
  'europe-west1' => 'Belgium',
105
  'europe-west2' => 'London',
106
  'europe-west3' => 'Frankfurt',
107
  'europe-west4' => 'Netherlands',
108
+ 'europe-west6' => 'Zürich',
109
  'asia-east1' => 'Taiwan',
110
  'asia-east2' => 'Hong Kong',
111
  'asia-northeast1' => 'Tokyo',
112
+ 'asia-northeast2' => 'Osaka',
113
+ 'asia-northeast3' => 'Seoul',
114
  'asia-south1' => 'Mumbai',
115
  'asia-southeast1' => 'Singapore',
116
  'australia-southeast1' => 'Sydney',
117
+ 'eur4' => 'EUR4 (Finland/Netherlands Dual-Region)',
118
+ 'nam4' => 'NAM4 (Iowa/South Carolina Dual-Region)',
119
  );
120
 
121
  /**
138
  */
139
  protected $console_url_prefix_param = '/';
140
 
141
+ const PUBLIC_ACL = 'publicRead';
142
  const PRIVATE_ACL = 'projectPrivate';
143
 
144
  /**
169
  *
170
  * @return array
171
  */
172
+ protected function init_client_args( array $args ) {
173
  return $args;
174
  }
175
 
178
  *
179
  * @param array $args
180
  */
181
+ protected function init_client( array $args ) {
182
  $this->cloud = new ServiceBuilder( $args );
183
  }
184
 
189
  *
190
  * @return array
191
  */
192
+ protected function init_service_client_args( array $args ) {
193
  return $args;
194
  }
195
 
200
  *
201
  * @return StorageClient
202
  */
203
+ protected function init_service_client( array $args ) {
204
  $this->storage = $this->cloud->storage( $args );
205
 
206
  return $this->storage;
229
  *
230
  * @throws GoogleException
231
  */
232
+ public function create_bucket( array $args ) {
233
  $name = '';
234
  if ( ! empty( $args['Bucket'] ) ) {
235
  $name = $args['Bucket'];
262
  *
263
  * @return string
264
  */
265
+ public function get_bucket_location( array $args ) {
266
  $info = $this->storage->bucket( $args['Bucket'] )->info();
267
  $region = empty( $info['location'] ) ? '' : $info['location'];
268
 
277
  * @return array
278
  * @throws GoogleException
279
  */
280
+ public function list_buckets( array $args = array() ) {
281
  $result = array();
282
 
283
  $buckets = $this->storage->buckets( $args );
303
  *
304
  * @return bool
305
  */
306
+ public function does_object_exist( $bucket, $key, array $options = array() ) {
307
  return $this->storage->bucket( $bucket )->object( $key )->exists( $options );
308
  }
309
 
310
  /**
311
+ * Get public "canned" ACL string.
312
  *
313
  * @return string
314
  */
315
+ public function get_public_acl() {
316
+ return static::PUBLIC_ACL;
317
  }
318
 
319
  /**
333
  *
334
  * @param array $args
335
  */
336
+ public function get_object( array $args ) {
337
  $this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->downloadToFile( $args['SaveAs'] );
338
  }
339
 
342
  *
343
  * @param string $bucket
344
  * @param string $key
345
+ * @param int $timestamp
346
  * @param array $args
347
  *
348
  * @return string
349
  */
350
+ public function get_object_url( $bucket, $key, $timestamp, array $args = array() ) {
351
+ if ( empty( $timestamp ) || ! is_int( $timestamp ) || $timestamp < 0 ) {
352
  $info = $this->storage->bucket( $bucket )->object( $key )->info();
353
  $link = empty( $info['selfLink'] ) ? '' : $info['selfLink'];
354
 
360
  $options['cname'] = $args['BaseURL'];
361
  }
362
 
363
+ return $this->storage->bucket( $bucket )->object( $key )->signedUrl( $timestamp, $options );
364
  }
365
  }
366
 
371
  *
372
  * @return array
373
  */
374
+ public function list_objects( array $args = array() ) {
375
  $result = array();
376
 
377
  $objects = $this->storage->bucket( $args['Bucket'] )->objects( $args['Prefix'] );
394
  * Update the ACL for an object.
395
  *
396
  * @param array $args
397
+ *
398
+ * @throws \Exception
399
  */
400
+ public function update_object_acl( array $args ) {
401
+ if ( empty( $args['ACL'] ) ) {
402
+ throw new \Exception( __METHOD__ . ' called without "ACL" arg.' );
403
+ }
404
+
405
  $this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->update( array( 'predefinedAcl' => $args['ACL'] ) );
406
  }
407
 
408
+ /**
409
+ * Update the ACL for multiple objects.
410
+ *
411
+ * @param array $items
412
+ *
413
+ * @return array Failures with elements Key and Message
414
+ */
415
+ public function update_object_acls( array $items ) {
416
+ $failures = array();
417
+
418
+ // Unfortunately the GCP PHP SDK does not have batch operations.
419
+ foreach ( $items as $item ) {
420
+ try {
421
+ $this->update_object_acl( $item );
422
+ } catch ( \Exception $e ) {
423
+ $failures[] = array(
424
+ 'Key' => $item['Key'],
425
+ 'Message' => $e->getMessage(),
426
+ );
427
+ }
428
+ }
429
+
430
+ return $failures;
431
+ }
432
+
433
  /**
434
  * Upload file to bucket.
435
  *
437
  *
438
  * @throws \Exception
439
  */
440
+ public function upload_object( array $args ) {
441
  if ( ! empty( $args['SourceFile'] ) ) {
442
  $file = fopen( $args['SourceFile'], 'r' );
443
  } elseif ( ! empty( $args['Body'] ) ) {
447
  }
448
 
449
  $options = array(
450
+ 'name' => $args['Key'],
 
451
  );
452
 
453
+ if ( ! empty( $args['ACL'] ) ) {
454
+ $options['predefinedAcl'] = $args['ACL'];
455
+ }
456
+
457
  if ( ! empty( $args['ContentType'] ) ) {
458
  $options['metadata']['contentType'] = $args['ContentType'];
459
  }
472
  *
473
  * @param array $args
474
  */
475
+ public function delete_object( array $args ) {
476
  $this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->delete();
477
  }
478
 
481
  *
482
  * @param array $args
483
  */
484
+ public function delete_objects( array $args ) {
485
  if ( isset( $args['Delete']['Objects'] ) ) {
486
  $keys = $args['Delete']['Objects'];
487
  } elseif ( isset( $args['Objects'] ) ) {
505
  *
506
  * @return array
507
  */
508
+ public function list_keys( array $locations ) {
509
  $keys = array();
510
 
511
  $results = array_map( function ( $location ) {
529
  *
530
  * @return array Failures with elements Key and Message
531
  */
532
+ public function copy_objects( array $items ) {
533
  $failures = array();
534
 
535
  // Unfortunately the GCP PHP SDK does not have batch operations.
536
  foreach ( $items as $item ) {
537
  list( $bucket, $key ) = explode( '/', urldecode( $item['CopySource'] ), 2 );
538
+
539
+ $options = array(
540
+ 'name' => $item['Key'],
541
+ );
542
+
543
+ if ( ! empty( $item['ACL'] ) ) {
544
+ $options['predefinedAcl'] = $item['ACL'];
545
+ }
546
+
547
  try {
548
+ $this->storage->bucket( $bucket )->object( $key )->copy( $item['Bucket'], $options );
 
 
 
 
 
 
549
  } catch ( \Exception $e ) {
550
  $failures[] = array(
551
  'Key' => $item['Key'],
606
  'Bucket' => $bucket,
607
  'Key' => $key,
608
  'Body' => $file_contents,
 
609
  ) );
610
 
611
  // delete it straight away if created
621
  return $e->getMessage();
622
  }
623
  }
624
+
625
+ return false;
626
  }
627
 
628
  /**
640
  /**
641
  * Get the url domain for the files
642
  *
643
+ * @param string $domain Likely prefixed with region
644
  * @param string $bucket
645
  * @param string $region
646
  * @param int $expires
647
+ * @param array $args Allows you to specify custom URL settings
 
648
  *
649
  * @return string
650
  */
651
+ protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array() ) {
652
+ if ( apply_filters( 'as3cf_' . static::get_provider_key_name() . '_' . static::get_service_key_name() . '_bucket_in_path', false !== strpos( $bucket, '.' ) ) ) {
 
 
 
 
 
 
 
653
  $domain = $domain . '/' . $bucket;
654
+ } else {
655
+ // TODO: Is this mode allowed for GCS native URLs?
656
+ $domain = $bucket . '.' . $domain;
657
  }
658
 
659
  return $domain;
664
  *
665
  * @param string $bucket
666
  * @param string $prefix
667
+ * @param string $region
668
  *
669
  * @return string
670
  */
671
+ protected function get_console_url_suffix_param( $bucket = '', $prefix = '', $region = '' ) {
672
  if ( ! empty( $this->get_project_id() ) ) {
673
  return '?project=' . $this->get_project_id();
674
  }
classes/providers/{null-provider.php → storage/null-provider.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_Media\Providers;
4
 
5
  use AS3CF_Error;
6
 
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Storage;
4
 
5
  use AS3CF_Error;
6
 
classes/providers/storage/storage-provider.php ADDED
@@ -0,0 +1,958 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Storage;
4
+
5
+ use Amazon_S3_And_CloudFront;
6
+ use AS3CF_Error;
7
+ use AS3CF_Utils;
8
+ use DeliciousBrains\WP_Offload_Media\Providers\Provider;
9
+ use Exception;
10
+
11
+ abstract class Storage_Provider extends Provider {
12
+
13
+ /**
14
+ * @var
15
+ */
16
+ private $client;
17
+
18
+ /**
19
+ * @var string
20
+ */
21
+ protected static $access_key_id_setting_name = 'access-key-id';
22
+
23
+ /**
24
+ * @var string
25
+ */
26
+ protected static $secret_access_key_setting_name = 'secret-access-key';
27
+
28
+ /**
29
+ * @var string
30
+ */
31
+ protected static $use_server_roles_setting_name = 'use-server-roles';
32
+
33
+ /**
34
+ * @var string
35
+ */
36
+ protected static $key_file_setting_name = 'key-file';
37
+
38
+ /**
39
+ * @var string
40
+ */
41
+ protected static $key_file_path_setting_name = 'key-file-path';
42
+
43
+ /**
44
+ * If left empty, access keys not allowed.
45
+ *
46
+ * @var array
47
+ */
48
+ protected static $access_key_id_constants = array();
49
+
50
+ /**
51
+ * @var array
52
+ */
53
+ protected static $secret_access_key_constants = array();
54
+
55
+ /**
56
+ * If left empty, server roles not allowed.
57
+ *
58
+ * @var array
59
+ */
60
+ protected static $use_server_roles_constants = array();
61
+
62
+ /**
63
+ * If left empty, key file not allowed.
64
+ *
65
+ * @var array
66
+ */
67
+ protected static $key_file_path_constants = array();
68
+
69
+ /**
70
+ * @var bool
71
+ */
72
+ protected static $block_public_access_allowed = false;
73
+
74
+ /**
75
+ * @var array
76
+ */
77
+ protected $regions = array();
78
+
79
+ /**
80
+ * @var bool
81
+ */
82
+ protected $region_required = false;
83
+
84
+ /**
85
+ * @var string
86
+ */
87
+ protected $default_region = '';
88
+
89
+ /**
90
+ * @var string
91
+ */
92
+ protected $default_domain = '';
93
+
94
+ /**
95
+ * @var string
96
+ */
97
+ protected $console_url = '';
98
+
99
+ /**
100
+ * @var string
101
+ */
102
+ protected $console_url_prefix_param = '';
103
+
104
+ /**
105
+ * Is the provider able to use access keys?
106
+ *
107
+ * @return bool
108
+ */
109
+ public static function use_access_keys_allowed() {
110
+ return ! empty( static::$access_key_id_constants );
111
+ }
112
+
113
+ /**
114
+ * Whether or not access keys are needed.
115
+ *
116
+ * Keys are needed if we are not using server roles or not defined/set yet.
117
+ *
118
+ * @return bool
119
+ */
120
+ public function needs_access_keys() {
121
+ if ( $this->use_server_roles() ) {
122
+ return false;
123
+ }
124
+
125
+ if ( static::use_key_file() ) {
126
+ return false;
127
+ }
128
+
129
+ return ! $this->are_access_keys_set();
130
+ }
131
+
132
+ /**
133
+ * Check if both access key id & secret are present.
134
+ *
135
+ * @return bool
136
+ */
137
+ public function are_access_keys_set() {
138
+ return $this->get_access_key_id() && $this->get_secret_access_key();
139
+ }
140
+
141
+ /**
142
+ * Get the access key from a constant or the settings.
143
+ *
144
+ * Falls back to settings only if neither constant is defined.
145
+ *
146
+ * @return string
147
+ */
148
+ public function get_access_key_id() {
149
+ if ( static::is_any_access_key_constant_defined() ) {
150
+ $constant = static::access_key_id_constant();
151
+
152
+ return $constant ? constant( $constant ) : '';
153
+ }
154
+
155
+ return $this->as3cf->get_core_setting( static::$access_key_id_setting_name );
156
+ }
157
+
158
+ /**
159
+ * Get the secret access key from a constant or the settings.
160
+ *
161
+ * Falls back to settings only if neither constant is defined.
162
+ *
163
+ * @return string
164
+ */
165
+ public function get_secret_access_key() {
166
+ if ( static::is_any_access_key_constant_defined() ) {
167
+ $constant = static::secret_access_key_constant();
168
+
169
+ return $constant ? constant( $constant ) : '';
170
+ }
171
+
172
+ return $this->as3cf->get_core_setting( static::$secret_access_key_setting_name );
173
+ }
174
+
175
+ /**
176
+ * Check if any access key (id or secret, prefixed or not) is defined.
177
+ *
178
+ * @return bool
179
+ */
180
+ public static function is_any_access_key_constant_defined() {
181
+ return static::access_key_id_constant() || static::secret_access_key_constant();
182
+ }
183
+
184
+ /**
185
+ * Get the constant used to define the access key id.
186
+ *
187
+ * @return string|false Constant name if defined, otherwise false
188
+ */
189
+ public static function access_key_id_constant() {
190
+ return AS3CF_Utils::get_first_defined_constant( static::$access_key_id_constants );
191
+ }
192
+
193
+ /**
194
+ * Get the constant used to define the secret access key.
195
+ *
196
+ * @return string|false Constant name if defined, otherwise false
197
+ */
198
+ public static function secret_access_key_constant() {
199
+ return AS3CF_Utils::get_first_defined_constant( static::$secret_access_key_constants );
200
+ }
201
+
202
+ /**
203
+ * Is the provider able to use server roles?
204
+ *
205
+ * @return bool
206
+ */
207
+ public static function use_server_roles_allowed() {
208
+ return ! empty( static::$use_server_roles_constants );
209
+ }
210
+
211
+ /**
212
+ * If server roles allowed, returns first (preferred) constant that should be defined, otherwise blank.
213
+ *
214
+ * @return string
215
+ */
216
+ public static function preferred_use_server_roles_constant() {
217
+ if ( static::use_server_roles_allowed() ) {
218
+ return static::$use_server_roles_constants[0];
219
+ } else {
220
+ return '';
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Allows the provider's client factory to use server roles instead of key/secret for credentials.
226
+ *
227
+ * @see http://docs.aws.amazon.com/aws-sdk-php/guide/latest/credentials.html#instance-profile-credentials
228
+ *
229
+ * @return bool
230
+ */
231
+ public function use_server_roles() {
232
+ if ( ! static::use_server_roles_allowed() ) {
233
+ return false;
234
+ }
235
+
236
+ if ( static::use_server_roles_constant() ) {
237
+ $constant = static::use_server_roles_constant();
238
+
239
+ return $constant ? constant( $constant ) : false;
240
+ }
241
+
242
+ return $this->as3cf->get_core_setting( static::$use_server_roles_setting_name, false );
243
+ }
244
+
245
+ /**
246
+ * Get the constant used to enable the use of IAM roles.
247
+ *
248
+ * @return string|false Constant name if defined, otherwise false
249
+ */
250
+ public static function use_server_roles_constant() {
251
+ return AS3CF_Utils::get_first_defined_constant( static::$use_server_roles_constants );
252
+ }
253
+
254
+ /**
255
+ * Is the provider able to use a key file?
256
+ *
257
+ * @return bool
258
+ */
259
+ public static function use_key_file_allowed() {
260
+ return ! empty( static::$key_file_path_constants );
261
+ }
262
+
263
+ /**
264
+ * If key file allowed, returns first (preferred) constant that should be defined, otherwise blank.
265
+ *
266
+ * @return string
267
+ */
268
+ public static function preferred_key_file_path_constant() {
269
+ if ( static::use_key_file_allowed() ) {
270
+ return static::$key_file_path_constants[0];
271
+ } else {
272
+ return '';
273
+ }
274
+ }
275
+
276
+ /**
277
+ * Check if either key file path or key file set.
278
+ *
279
+ * @return bool
280
+ */
281
+ public function use_key_file() {
282
+ if ( ! static::use_key_file_allowed() ) {
283
+ return false;
284
+ }
285
+
286
+ return $this->get_key_file_path() || $this->get_key_file();
287
+ }
288
+
289
+ /**
290
+ * Get the key file contents from settings.
291
+ *
292
+ * @return array|bool
293
+ */
294
+ public function get_key_file() {
295
+ $key_file = $this->as3cf->get_core_setting( static::$key_file_setting_name, false );
296
+
297
+ return $key_file;
298
+ }
299
+
300
+ /**
301
+ * Get the key file path from a constant or the settings.
302
+ *
303
+ * Falls back to settings if constant is not defined.
304
+ *
305
+ * @return string|bool
306
+ */
307
+ public function get_key_file_path() {
308
+ if ( static::is_key_file_path_constant_defined() ) {
309
+ $constant = static::key_file_path_constant();
310
+
311
+ if ( $constant ) {
312
+ return $this->validate_key_file_path( constant( $constant ) );
313
+ } else {
314
+ // Constant defined but value is not a non-empty string.
315
+ return false;
316
+ }
317
+ }
318
+
319
+ return $this->validate_key_file_path( $this->as3cf->get_core_setting( static::$key_file_path_setting_name, false ) );
320
+ }
321
+
322
+ /**
323
+ * Validate a key file path to ensure it exists, is readable, and contains JSON.
324
+ *
325
+ * @param string $key_file_path
326
+ *
327
+ * @return bool|string
328
+ */
329
+ public function validate_key_file_path( $key_file_path ) {
330
+ $notice_id = 'validate-key-file-path';
331
+ $this->as3cf->notices->remove_notice_by_id( $notice_id );
332
+
333
+ if ( empty( $key_file_path ) ) {
334
+ return false;
335
+ }
336
+
337
+ if ( ! file_exists( $key_file_path ) ) {
338
+ $this->as3cf->notices->add_notice( __( 'Given Key File Path is invalid or could not be accessed.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
339
+
340
+ return false;
341
+ }
342
+
343
+ try {
344
+ $value = file_get_contents( $key_file_path );
345
+
346
+ // An exception isn't always thrown, so check value instead.
347
+ if ( empty( $value ) ) {
348
+ $this->as3cf->notices->add_notice( __( 'Could not read Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
349
+
350
+ return false;
351
+ }
352
+ } catch ( Exception $e ) {
353
+ $this->as3cf->notices->add_notice( __( 'Could not read Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
354
+
355
+ return false;
356
+ }
357
+
358
+ $value = json_decode( $value, true );
359
+
360
+ if ( empty( $value ) ) {
361
+ $this->as3cf->notices->add_notice( __( 'Given Key File Path does not contain valid JSON.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
362
+
363
+ return false;
364
+ }
365
+
366
+ // File exists and looks like JSON.
367
+ return $key_file_path;
368
+ }
369
+
370
+ /**
371
+ * Check if key file path constant is defined, for speed, does not check validity of file path.
372
+ *
373
+ * @return bool
374
+ */
375
+ public static function is_key_file_path_constant_defined() {
376
+ $constant = static::key_file_path_constant();
377
+
378
+ return $constant && constant( $constant );
379
+ }
380
+
381
+ /**
382
+ * Get the constant used to define the key file path.
383
+ *
384
+ * @return string|false Constant name if defined, otherwise false
385
+ */
386
+ public static function key_file_path_constant() {
387
+ return AS3CF_Utils::get_first_defined_constant( static::$key_file_path_constants );
388
+ }
389
+
390
+ /**
391
+ * Get default "canned" ACL string.
392
+ *
393
+ * @return string|null
394
+ */
395
+ public function get_default_acl() {
396
+ return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_default_acl', $this->get_public_acl() );
397
+ }
398
+
399
+ /**
400
+ * Does provider have functionality to block direct public access to bucket?
401
+ *
402
+ * @return bool
403
+ */
404
+ public static function block_public_access_allowed() {
405
+ return static::$block_public_access_allowed;
406
+ }
407
+
408
+ /**
409
+ * Is public access to the given bucket prohibited?
410
+ *
411
+ * @param string $bucket
412
+ *
413
+ * @return bool|null
414
+ */
415
+ public function public_access_blocked( $bucket ) {
416
+ if ( static::block_public_access_allowed() ) {
417
+ return null; // Unknown until sub class overrides this function.
418
+ } else {
419
+ return false;
420
+ }
421
+ }
422
+
423
+ /**
424
+ * Update the block public access setting for the given bucket.
425
+ *
426
+ * @param string $bucket
427
+ * @param bool $block
428
+ *
429
+ * Note: Should be overridden and implemented as required.
430
+ */
431
+ public function block_public_access( $bucket, $block ) {
432
+ return;
433
+ }
434
+
435
+ /**
436
+ * Returns the Provider's default region slug.
437
+ *
438
+ * @return string
439
+ */
440
+ public function region_required() {
441
+ return $this->region_required;
442
+ }
443
+
444
+ /**
445
+ * Returns the Provider's default region slug.
446
+ *
447
+ * @return string
448
+ */
449
+ public function get_default_region() {
450
+ return $this->default_region;
451
+ }
452
+
453
+ /**
454
+ * Returns an array of valid region slugs and names.
455
+ *
456
+ * @return array Keys are region slug, values their name
457
+ */
458
+ public function get_regions() {
459
+ $regions = apply_filters( static::$provider_key_name . '_get_regions', $this->regions ); // Backwards compatibility, e.g. 'aws_get_regions'.
460
+
461
+ return apply_filters( 'as3cf_' . static::$provider_key_name . '_get_regions', $regions );
462
+ }
463
+
464
+ /**
465
+ * Returns readable region name.
466
+ *
467
+ * @param string $region
468
+ * @param bool $with_key
469
+ *
470
+ * @return string
471
+ */
472
+ public function get_region_name( $region = '', $with_key = false ) {
473
+ if ( is_wp_error( $region ) ) {
474
+ return '';
475
+ }
476
+ if ( empty( $region ) && ! $this->region_required() ) {
477
+ $region = $this->get_default_region();
478
+ }
479
+
480
+ $regions = $this->get_regions();
481
+
482
+ $region_name = empty( $regions[ $region ] ) ? '' : $regions[ $region ];
483
+
484
+ if ( $with_key ) {
485
+ $region_name .= empty( $region_name ) ? $region : ' (' . $region . ')';
486
+ }
487
+
488
+ return $region_name;
489
+ }
490
+
491
+ /**
492
+ * Is given region key valid for provider?
493
+ *
494
+ * @param string $region
495
+ *
496
+ * @return bool
497
+ */
498
+ public function is_region_valid( $region ) {
499
+ return in_array( trim( $region ), array_keys( $this->get_regions() ) );
500
+ }
501
+
502
+ /**
503
+ * Instantiate a new service client for the provider.
504
+ *
505
+ * @param array $args Options for required region/endpoint
506
+ *
507
+ * @throws Exception
508
+ */
509
+ private function _init_client( array $args ) {
510
+ if ( $this->needs_access_keys() ) {
511
+ throw new Exception( sprintf( __( 'You must first <a href="%s">set your access keys</a>.', 'amazon-s3-and-cloudfront' ), $this->as3cf->get_plugin_page_url() . '#settings' ) );
512
+ }
513
+
514
+ if ( is_null( $this->client ) ) {
515
+ // There's no extra client authentication config required when using server roles.
516
+ if ( ! $this->use_server_roles() ) {
517
+ // Some providers can supply Key File contents or Key File Path.
518
+ if ( static::use_key_file() ) {
519
+ // Key File contents take precedence over Key File Path.
520
+ if ( static::get_key_file() ) {
521
+ $args = array_merge( array(
522
+ 'keyFile' => static::get_key_file(),
523
+ ), $args );
524
+ } else {
525
+ $args = array_merge( array(
526
+ 'keyFilePath' => static::get_key_file_path(),
527
+ ), $args );
528
+ }
529
+ } else {
530
+ // Fall back is Access Keys.
531
+ $args = array_merge( array(
532
+ 'credentials' => array(
533
+ 'key' => $this->get_access_key_id(),
534
+ 'secret' => $this->get_secret_access_key(),
535
+ ),
536
+ ), $args );
537
+ }
538
+ }
539
+
540
+ // Add credentials and given args to default client args and then let user override.
541
+ $args = array_merge( $this->default_client_args(), $args );
542
+ $args = apply_filters( 'as3cf_' . static::$provider_key_name . '_init_client_args', $this->init_client_args( $args ) );
543
+ $args = apply_filters( static::$provider_key_name . '_get_client_args', $args ); // Backwards compatibility, e.g. 'aws_get_client_args'.
544
+
545
+ $this->client = $this->init_client( $args );
546
+ }
547
+ }
548
+
549
+ /**
550
+ * Get the service client instance.
551
+ *
552
+ * @param array $args Options for required region/endpoint
553
+ * @param bool $force
554
+ *
555
+ * @return Storage_Provider
556
+ * @throws Exception
557
+ */
558
+ public function get_client( array $args, $force = false ) {
559
+ if ( true === $force ) {
560
+ $this->client = null;
561
+ }
562
+
563
+ $this->_init_client( $args );
564
+
565
+ $args = apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_client_args', $this->init_service_client_args( $args ) );
566
+
567
+ $this->client = $this->init_service_client( $args );
568
+
569
+ return $this;
570
+ }
571
+
572
+ /**
573
+ * Get object keys from multiple clients.
574
+ *
575
+ * @param array $regions
576
+ *
577
+ * @return array
578
+ */
579
+ public static function get_keys_from_regions( array $regions ) {
580
+ $keys = array();
581
+
582
+ foreach ( $regions as $region ) {
583
+ try {
584
+ /* @var $client Storage_Provider */
585
+ $client = $region['provider_client'];
586
+ $region_keys = $client->list_keys( $region['locations'] );
587
+ } catch ( Exception $e ) {
588
+ AS3CF_Error::log( get_class( $e ) . ' exception caught when executing list_keys: ' . $e->getMessage() );
589
+ continue;
590
+ }
591
+
592
+ if ( ! empty( $region_keys ) ) {
593
+ foreach ( $region_keys as $attachment_id => $found_keys ) {
594
+ $keys[ $attachment_id ] = AS3CF_Utils::validate_attachment_keys( $attachment_id, $found_keys );
595
+ }
596
+ }
597
+ }
598
+
599
+ return $keys;
600
+ }
601
+
602
+ /**
603
+ * Generate a stream wrapper compatible URL
604
+ *
605
+ * @param string $region
606
+ * @param string $bucket
607
+ * @param string $key
608
+ *
609
+ * @return string
610
+ */
611
+ public function prepare_stream_wrapper_file( $region, $bucket, $key ) {
612
+ $protocol = $this->get_stream_wrapper_protocol( $region );
613
+
614
+ return $protocol . '://' . $bucket . '/' . $key;
615
+ }
616
+
617
+ /**
618
+ * Get the region specific prefix for URL
619
+ *
620
+ * @param string $region
621
+ * @param null|int $expires
622
+ *
623
+ * @return string
624
+ */
625
+ public function get_url_prefix( $region = '', $expires = null ) {
626
+ /**
627
+ * Region specific prefix for raw URL
628
+ *
629
+ * @param string $prefix
630
+ * @param string $region
631
+ * @param null|int $expires
632
+ *
633
+ * @return string
634
+ */
635
+ return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_url_prefix', $this->url_prefix( $region, $expires ), $region, $expires );
636
+ }
637
+
638
+ /**
639
+ * Get the url domain for the files
640
+ *
641
+ * @param string $bucket
642
+ * @param string $region
643
+ * @param int $expires
644
+ *
645
+ * @return string
646
+ */
647
+ public function get_url_domain( $bucket, $region = '', $expires = null ) {
648
+ $args = array(
649
+ 'delivery-provider' => $this->as3cf->get_setting( 'delivery-provider' ),
650
+ 'enable-delivery-domain' => $this->as3cf->get_setting( 'enable-delivery-domain' ),
651
+ 'delivery-domain' => $this->as3cf->get_setting( 'delivery-domain' ),
652
+ 'force-https' => $this->as3cf->use_ssl( $this->as3cf->get_setting( 'force-https' ) ),
653
+ );
654
+
655
+ // Backwards Compat.
656
+ $args['domain'] = $args['enable-delivery-domain'] && Amazon_S3_And_CloudFront::get_default_delivery_provider() !== $args['delivery-provider'] ? 'cloudfront' : 'path';
657
+ $args['cloudfront'] = $args['delivery-domain'];
658
+
659
+ $prefix = $this->url_prefix( $region, $expires );
660
+ $domain = $this->get_domain();
661
+ $domain = empty( $prefix ) ? $domain : $prefix . '.' . $domain;
662
+
663
+ return apply_filters(
664
+ 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_url_domain',
665
+ $this->url_domain( $domain, $bucket, $region, $expires, $args ),
666
+ $bucket,
667
+ $region,
668
+ $expires,
669
+ $args
670
+ );
671
+ }
672
+
673
+ /**
674
+ * Get the link to the bucket on the provider's console.
675
+ *
676
+ * @param string $bucket
677
+ * @param string $prefix
678
+ * @param string $region
679
+ *
680
+ * @return string
681
+ */
682
+ public function get_console_url( $bucket = '', $prefix = '', $region = '' ) {
683
+ if ( '' !== $prefix ) {
684
+ $prefix = $this->get_console_url_prefix_param() . apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_prefix_value', $prefix );
685
+ }
686
+
687
+ $suffix = apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_suffix_param', $this->get_console_url_suffix_param( $bucket, $prefix, $region ) );
688
+
689
+ return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url', $this->console_url ) . $bucket . $prefix . $suffix;
690
+ }
691
+
692
+ /**
693
+ * Get the prefix param to append to the link to the bucket on the provider's console.
694
+ *
695
+ * @return string
696
+ */
697
+ public function get_console_url_prefix_param() {
698
+ return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_prefix_param', $this->console_url_prefix_param );
699
+ }
700
+
701
+ /**
702
+ * Returns default args array for the client.
703
+ *
704
+ * @return array
705
+ */
706
+ abstract protected function default_client_args();
707
+
708
+ /**
709
+ * Process the args before instantiating a new client for the provider's SDK.
710
+ *
711
+ * @param array $args
712
+ *
713
+ * @return array
714
+ */
715
+ abstract protected function init_client_args( array $args );
716
+
717
+ /**
718
+ * Instantiate a new client for the provider's SDK.
719
+ *
720
+ * @param array $args
721
+ */
722
+ abstract protected function init_client( array $args );
723
+
724
+ /**
725
+ * Process the args before instantiating a new service specific client.
726
+ *
727
+ * @param array $args
728
+ *
729
+ * @return array
730
+ */
731
+ abstract protected function init_service_client_args( array $args );
732
+
733
+ /**
734
+ * Instantiate a new service specific client.
735
+ * Depending on SDK, may simply return client instantiated with `init_client`.
736
+ *
737
+ * @param array $args
738
+ *
739
+ * @return mixed
740
+ */
741
+ abstract protected function init_service_client( array $args );
742
+
743
+ /**
744
+ * Make sure region "slug" fits expected format.
745
+ *
746
+ * @param string $region
747
+ *
748
+ * @return string
749
+ */
750
+ abstract public function sanitize_region( $region );
751
+
752
+ /**
753
+ * Create bucket.
754
+ *
755
+ * @param array $args
756
+ */
757
+ abstract public function create_bucket( array $args );
758
+
759
+ /**
760
+ * Check whether bucket exists.
761
+ *
762
+ * @param string $bucket
763
+ *
764
+ * @return bool
765
+ */
766
+ abstract public function does_bucket_exist( $bucket );
767
+
768
+ /**
769
+ * Returns region for bucket.
770
+ *
771
+ * @param array $args
772
+ *
773
+ * @return string
774
+ */
775
+ abstract public function get_bucket_location( array $args );
776
+
777
+ /**
778
+ * List buckets.
779
+ *
780
+ * @param array $args
781
+ *
782
+ * @return array
783
+ */
784
+ abstract public function list_buckets( array $args = array() );
785
+
786
+ /**
787
+ * Check whether key exists in bucket.
788
+ *
789
+ * @param string $bucket
790
+ * @param string $key
791
+ * @param array $options
792
+ *
793
+ * @return bool
794
+ */
795
+ abstract public function does_object_exist( $bucket, $key, array $options = array() );
796
+
797
+ /**
798
+ * Get public "canned" ACL string.
799
+ *
800
+ * @return string
801
+ */
802
+ abstract public function get_public_acl();
803
+
804
+ /**
805
+ * Get private "canned" ACL string.
806
+ *
807
+ * @return string
808
+ */
809
+ abstract public function get_private_acl();
810
+
811
+ /**
812
+ * Download object, destination specified in args.
813
+ *
814
+ * @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#getobject
815
+ *
816
+ * @param array $args
817
+ */
818
+ abstract public function get_object( array $args );
819
+
820
+ /**
821
+ * Get object's URL.
822
+ *
823
+ * @param string $bucket
824
+ * @param string $key
825
+ * @param int $timestamp
826
+ * @param array $args
827
+ *
828
+ * @return string
829
+ */
830
+ abstract public function get_object_url( $bucket, $key, $timestamp, array $args = array() );
831
+
832
+ /**
833
+ * List objects.
834
+ *
835
+ * @param array $args
836
+ *
837
+ * @return array
838
+ */
839
+ abstract public function list_objects( array $args = array() );
840
+
841
+ /**
842
+ * Update the ACL for an object.
843
+ *
844
+ * @param array $args
845
+ */
846
+ abstract public function update_object_acl( array $args );
847
+
848
+ /**
849
+ * Update the ACL for multiple objects.
850
+ *
851
+ * @param array $items
852
+ *
853
+ * @return array Failures with elements Key and Message
854
+ */
855
+ abstract public function update_object_acls( array $items );
856
+
857
+ /**
858
+ * Upload file to bucket.
859
+ *
860
+ * @param array $args
861
+ */
862
+ abstract public function upload_object( array $args );
863
+
864
+ /**
865
+ * Delete object from bucket.
866
+ *
867
+ * @param array $args
868
+ */
869
+ abstract public function delete_object( array $args );
870
+
871
+ /**
872
+ * Delete multiple objects from bucket.
873
+ *
874
+ * @param array $args
875
+ */
876
+ abstract public function delete_objects( array $args );
877
+
878
+ /**
879
+ * Returns arrays of found keys for given bucket and prefix locations, retaining given array's integer based index.
880
+ *
881
+ * @param array $locations Array with attachment ID as key and Bucket and Prefix in an associative array as values.
882
+ *
883
+ * @return array
884
+ */
885
+ abstract public function list_keys( array $locations );
886
+
887
+ /**
888
+ * Copies objects into current bucket from another bucket hosted with provider.
889
+ *
890
+ * @param array $items
891
+ *
892
+ * @return array Failures with elements Key and Message
893
+ */
894
+ abstract public function copy_objects( array $items );
895
+
896
+ /**
897
+ * Generate the stream wrapper protocol
898
+ *
899
+ * @param string $region
900
+ *
901
+ * @return string
902
+ */
903
+ abstract protected function get_stream_wrapper_protocol( $region );
904
+
905
+ /**
906
+ * Register a stream wrapper for specific region.
907
+ *
908
+ * @param string $region
909
+ *
910
+ * @return bool
911
+ */
912
+ abstract public function register_stream_wrapper( $region );
913
+
914
+ /**
915
+ * Check that a bucket and key can be written to.
916
+ *
917
+ * @param string $bucket
918
+ * @param string $key
919
+ * @param string $file_contents
920
+ *
921
+ * @return bool|string Error message on unexpected exception
922
+ */
923
+ abstract public function can_write( $bucket, $key, $file_contents );
924
+
925
+ /**
926
+ * Get the region specific prefix for raw URL
927
+ *
928
+ * @param string $region
929
+ * @param null|int $expires
930
+ *
931
+ * @return string
932
+ */
933
+ abstract protected function url_prefix( $region = '', $expires = null );
934
+
935
+ /**
936
+ * Get the url domain for the files
937
+ *
938
+ * @param string $domain Likely prefixed with region
939
+ * @param string $bucket
940
+ * @param string $region
941
+ * @param int $expires
942
+ * @param array $args Allows you to specify custom URL settings
943
+ *
944
+ * @return string
945
+ */
946
+ abstract protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array() );
947
+
948
+ /**
949
+ * Get the suffix param to append to the link to the bucket on the provider's console.
950
+ *
951
+ * @param string $bucket
952
+ * @param string $prefix
953
+ * @param string $region
954
+ *
955
+ * @return string
956
+ */
957
+ abstract protected function get_console_url_suffix_param( $bucket = '', $prefix = '', $region = '' );
958
+ }
classes/providers/{streams → storage/streams}/aws-s3-stream-wrapper.php RENAMED
@@ -1,11 +1,10 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_Media\Providers\Streams;
4
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3ClientInterface;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\StreamWrapper;
8
- use DeliciousBrains\WP_Offload_Media\Providers\AWS_Provider;
9
 
10
  class AWS_S3_Stream_Wrapper extends StreamWrapper {
11
 
@@ -76,22 +75,41 @@ class AWS_S3_Stream_Wrapper extends StreamWrapper {
76
  * @return bool
77
  */
78
  public function stream_flush() {
79
- $context = stream_context_get_default();
 
80
 
81
- if ( null !== $this->context ) {
82
- $context = $this->context;
83
- }
 
 
 
84
 
85
- $options = stream_context_get_options( $context );
86
 
87
- // Set the ACL as public by default
88
- $options[ static::$wrapper ]['ACL'] = AWS_Provider::DEFAULT_ACL;
 
89
 
90
- $options = apply_filters( 'wpos3_stream_flush_params', $options ); // Backwards compatibility
91
- $options = apply_filters( 'as3cf_stream_flush_params', $options );
92
 
93
- stream_context_set_option( $context, $options );
 
94
 
95
  return parent::stream_flush();
96
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Storage\Streams;
4
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3ClientInterface;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\StreamWrapper;
 
8
 
9
  class AWS_S3_Stream_Wrapper extends StreamWrapper {
10
 
75
  * @return bool
76
  */
77
  public function stream_flush() {
78
+ /** @var \Amazon_S3_And_CloudFront|\Amazon_S3_And_CloudFront_Pro $as3cf */
79
+ global $as3cf;
80
 
81
+ if ( $as3cf->get_setting( 'use-bucket-acls' ) ) {
82
+ $context = stream_context_get_default();
83
+
84
+ if ( null !== $this->context ) {
85
+ $context = $this->context;
86
+ }
87
 
88
+ $options = stream_context_get_options( $context );
89
 
90
+ // Set the ACL, usually defaults to public.
91
+ $provider = $as3cf->get_storage_provider();
92
+ $options[ static::$wrapper ]['ACL'] = $provider->get_default_acl();
93
 
94
+ $options = apply_filters( 'wpos3_stream_flush_params', $options ); // Backwards compatibility
95
+ $options = apply_filters( 'as3cf_stream_flush_params', $options );
96
 
97
+ stream_context_set_option( $context, $options );
98
+ }
99
 
100
  return parent::stream_flush();
101
  }
102
+
103
+ /**
104
+ * Dummy function to stop PHP from throwing a wobbly.
105
+ *
106
+ * @param string $path
107
+ * @param int $option
108
+ * @param mixed $value
109
+ *
110
+ * @return bool
111
+ */
112
+ public function stream_metadata( $path, $option, $value ) {
113
+ return true;
114
+ }
115
  }
classes/providers/{streams → storage/streams}/gcp-gcs-stream-wrapper.php RENAMED
@@ -1,10 +1,9 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_Media\Providers\Streams;
4
 
5
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageClient;
6
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StreamWrapper;
7
- use DeliciousBrains\WP_Offload_Media\Providers\GCP_Provider;
8
 
9
  class GCP_GCS_Stream_Wrapper extends StreamWrapper {
10
 
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers\Storage\Streams;
4
 
5
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageClient;
6
  use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StreamWrapper;
 
7
 
8
  class GCP_GCS_Stream_Wrapper extends StreamWrapper {
9
 
classes/upgrades/upgrade-filter-post.php CHANGED
@@ -112,12 +112,12 @@ abstract class Upgrade_Filter_Post extends Upgrade {
112
  /**
113
  * Upgrade attachment.
114
  *
115
- * @throws Batch_Limits_Exceeded_Exception
116
- * @throws Too_Many_Errors_Exception
117
- *
118
  * @param mixed $attachment
119
  *
120
  * @return bool
 
 
 
121
  */
122
  protected function upgrade_item( $attachment ) {
123
  $limit = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_sql_limit', 100000 );
@@ -275,7 +275,7 @@ abstract class Upgrade_Filter_Post extends Upgrade {
275
  protected function maybe_add_encoded_url_pairs( $url_pairs ) {
276
  foreach ( $url_pairs as $url_pair ) {
277
  $file_name = wp_basename( $url_pair['old_url'] );
278
- $encoded_file_name = $this->as3cf->encode_filename_in_path( $file_name );
279
 
280
  if ( $file_name !== $encoded_file_name ) {
281
  $url_pair['old_url'] = str_replace( $file_name, $encoded_file_name, $url_pair['old_url'] );
112
  /**
113
  * Upgrade attachment.
114
  *
 
 
 
115
  * @param mixed $attachment
116
  *
117
  * @return bool
118
+ * @throws Batch_Limits_Exceeded_Exception
119
+ * @throws Too_Many_Errors_Exception
120
+ *
121
  */
122
  protected function upgrade_item( $attachment ) {
123
  $limit = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_sql_limit', 100000 );
275
  protected function maybe_add_encoded_url_pairs( $url_pairs ) {
276
  foreach ( $url_pairs as $url_pair ) {
277
  $file_name = wp_basename( $url_pair['old_url'] );
278
+ $encoded_file_name = AS3CF_Utils::encode_filename_in_path( $file_name );
279
 
280
  if ( $file_name !== $encoded_file_name ) {
281
  $url_pair['old_url'] = str_replace( $file_name, $encoded_file_name, $url_pair['old_url'] );
classes/upgrades/upgrade-items-table.php CHANGED
@@ -162,8 +162,8 @@ class Upgrade_Items_Table extends Upgrade {
162
  return $wpdb->get_var( $sql );
163
  }
164
 
165
- $sql = 'SELECT DISTINCT a.post_id AS ID, a.meta_value AS source_path, p.meta_value AS provider_object' . $sql;
166
- $sql .= ' ORDER BY p.post_id, p.meta_id';
167
 
168
  if ( $limit && $limit > 0 ) {
169
  $sql .= sprintf( ' LIMIT %d', (int) $limit );
162
  return $wpdb->get_var( $sql );
163
  }
164
 
165
+ $sql = 'SELECT a.post_id AS ID, p.meta_id AS po_id, a.meta_value AS source_path, p.meta_value AS provider_object' . $sql;
166
+ $sql .= ' ORDER BY ID, po_id';
167
 
168
  if ( $limit && $limit > 0 ) {
169
  $sql .= sprintf( ' LIMIT %d', (int) $limit );
classes/upgrades/upgrade.php CHANGED
@@ -168,6 +168,9 @@ abstract class Upgrade {
168
  add_action( 'as3cf_pre_settings_render', array( $this, 'maybe_display_notices' ) );
169
  add_action( 'admin_init', array( $this, 'maybe_handle_action' ) );
170
 
 
 
 
171
  // Do default checks if the upgrade can be started
172
  if ( $this->maybe_init() ) {
173
  $this->init();
@@ -937,4 +940,26 @@ abstract class Upgrade {
937
 
938
  return is_admin();
939
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
940
  }
168
  add_action( 'as3cf_pre_settings_render', array( $this, 'maybe_display_notices' ) );
169
  add_action( 'admin_init', array( $this, 'maybe_handle_action' ) );
170
 
171
+ // Settings Tab
172
+ add_action( 'as3cf_pre_tab_render', array( $this, 'pre_tab_render' ) );
173
+
174
  // Do default checks if the upgrade can be started
175
  if ( $this->maybe_init() ) {
176
  $this->init();
940
 
941
  return is_admin();
942
  }
943
+
944
+ /**
945
+ * Maybe add notices etc. at top of settings tab.
946
+ *
947
+ * @param string $tab
948
+ *
949
+ * @handles as3cf_pre_tab_render filter
950
+ */
951
+ public function pre_tab_render( $tab ) {
952
+ if ( 'media' === $tab ) {
953
+ $title = ucwords( $this->upgrade_type ) . ' Update';
954
+
955
+ $lock_settings_args = array(
956
+ 'message' => sprintf( __( '<strong>Settings Locked Temporarily</strong> &mdash; You can\'t change any of your settings until the "%s" has completed.', 'amazon-s3-and-cloudfront' ), $title ),
957
+ 'id' => 'as3cf-media-settings-locked-upgrade',
958
+ 'inline' => true,
959
+ 'type' => 'notice-warning',
960
+ 'style' => 'display: none',
961
+ );
962
+ $this->as3cf->render_view( 'notice', $lock_settings_args );
963
+ }
964
+ }
965
  }
include/functions.php CHANGED
@@ -1,16 +1,40 @@
1
  <?php
2
- /**
3
- * API function to generate a link to download a file from Amazon S3 using
4
- * query string authentication, expiring after a set amount of time.
5
- *
6
- * @param mixed $post_id Post ID of the attachment or null to use the loop
7
- * @param int $expires Seconds for the link to live
8
- * @param mixed $size Size of the image to get
9
- */
 
 
 
 
 
 
 
 
 
 
 
10
  if ( ! function_exists( 'as3cf_get_secure_attachment_url' ) ) {
11
- function as3cf_get_secure_attachment_url( $post_id, $expires = 900, $size = null ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  global $as3cf;
13
 
14
- return $as3cf->get_secure_attachment_url( $post_id, $expires, $size );
15
  }
16
  }
1
  <?php
2
+ if ( ! function_exists( 'as3cf_get_attachment_url' ) ) {
3
+ /**
4
+ * Get the url of the file from provider, may be a signed expiring URL if associated file is set as private.
5
+ *
6
+ * NOTE: Returns false if attachment is not offloaded.
7
+ *
8
+ * @param int $post_id Post ID of the attachment, required.
9
+ * @param string|null $size Size of the image to get, optional.
10
+ * @param bool $skip_rewrite_check Always return the URL regardless of the 'Rewrite File URLs' setting, optional, default: false.
11
+ *
12
+ * @return string|bool|WP_Error
13
+ */
14
+ function as3cf_get_attachment_url( $post_id, $size = null, $skip_rewrite_check = false ) {
15
+ /** @var Amazon_S3_And_CloudFront $as3cf */
16
+ global $as3cf;
17
+
18
+ return $as3cf->get_attachment_url( $post_id, null, $size, null, array(), $skip_rewrite_check );
19
+ }
20
+ }
21
  if ( ! function_exists( 'as3cf_get_secure_attachment_url' ) ) {
22
+ /**
23
+ * Get the signed expiring url of the file from provider.
24
+ *
25
+ * NOTE: Returns false if attachment is not offloaded.
26
+ *
27
+ * @param int $post_id Post ID of the attachment, required.
28
+ * @param int|null $expires Seconds for the link to live, optional, default: 900 (15 minutes).
29
+ * @param string|null $size Size of the image to get, optional.
30
+ * @param bool $skip_rewrite_check Always return the URL regardless of the 'Rewrite File URLs' setting, optional, default: false.
31
+ *
32
+ * @return string|bool|WP_Error
33
+ */
34
+ function as3cf_get_secure_attachment_url( $post_id, $expires = 900, $size = null, $skip_rewrite_check = false ) {
35
+ /** @var Amazon_S3_And_CloudFront $as3cf */
36
  global $as3cf;
37
 
38
+ return $as3cf->get_secure_attachment_url( $post_id, $expires, $size, array(), $skip_rewrite_check );
39
  }
40
  }
languages/amazon-s3-and-cloudfront-en.pot CHANGED
@@ -8,7 +8,7 @@ msgid ""
8
  msgstr ""
9
  "Project-Id-Version: amazon-s3-and-cloudfront\n"
10
  "Report-Msgid-Bugs-To: nom@deliciousbrains.com\n"
11
- "POT-Creation-Date: 2019-12-09 11:47+0000\n"
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,182 +17,232 @@ msgstr ""
17
  "Content-Type: text/plain; charset=UTF-8\n"
18
  "Content-Transfer-Encoding: 8bit\n"
19
 
20
- #: classes/amazon-s3-and-cloudfront.php:138
21
- #: classes/amazon-s3-and-cloudfront.php:139
22
  msgid "Offload Media Lite"
23
  msgstr ""
24
 
25
- #: classes/amazon-s3-and-cloudfront.php:279
26
- #: classes/amazon-s3-and-cloudfront.php:293
27
  msgid "Unknown"
28
  msgstr ""
29
 
30
- #: classes/amazon-s3-and-cloudfront.php:365
31
- #: view/bucket-setting.php:17
 
 
32
  #: view/provider-select.php:122
 
 
 
33
  msgid "defined in wp-config.php"
34
  msgstr ""
35
 
36
- #: classes/amazon-s3-and-cloudfront.php:1153
37
  #, php-format
38
  msgid "Media Library item with ID %d does not have a valid file path"
39
  msgstr ""
40
 
41
- #: classes/amazon-s3-and-cloudfront.php:1203
42
- #: classes/amazon-s3-and-cloudfront.php:1365
43
  #, php-format
44
  msgid "File %s does not exist"
45
  msgstr ""
46
 
47
- #: classes/amazon-s3-and-cloudfront.php:1233
48
  #, php-format
49
  msgid "Mime type %s is not allowed"
50
  msgstr ""
51
 
52
- #: classes/amazon-s3-and-cloudfront.php:1244
53
  msgid "Already offloaded to a different provider"
54
  msgstr ""
55
 
56
- #: classes/amazon-s3-and-cloudfront.php:1327
57
- #: classes/amazon-s3-and-cloudfront.php:1378
58
  #, php-format
59
  msgid "Error offloading %s to provider: %s"
60
  msgstr ""
61
 
62
- #: classes/amazon-s3-and-cloudfront.php:2533
63
  msgid "This action can only be performed through an admin screen."
64
  msgstr ""
65
 
66
- #: classes/amazon-s3-and-cloudfront.php:2535
67
  msgid "Cheatin&#8217; eh?"
68
  msgstr ""
69
 
70
- #: classes/amazon-s3-and-cloudfront.php:2537
71
  msgid "You do not have sufficient permissions to access this page."
72
  msgstr ""
73
 
74
- #: classes/amazon-s3-and-cloudfront.php:2826
75
  msgid "Error Getting Bucket Region"
76
  msgstr ""
77
 
78
- #: classes/amazon-s3-and-cloudfront.php:2827
79
  #, php-format
80
  msgid "There was an error attempting to get the region of the bucket %s: %s"
81
  msgstr ""
82
 
83
- #: classes/amazon-s3-and-cloudfront.php:2930
84
  msgid ""
85
  "This is a test file to check if the user has write permission to the bucket. "
86
  "Delete me if found."
87
  msgstr ""
88
 
89
- #: classes/amazon-s3-and-cloudfront.php:2936
90
  #, php-format
91
  msgid ""
92
  "There was an error attempting to check the permissions of the bucket %s: %s"
93
  msgstr ""
94
 
95
- #: classes/amazon-s3-and-cloudfront.php:3018
96
  msgid "Error creating bucket"
97
  msgstr ""
98
 
99
- #: classes/amazon-s3-and-cloudfront.php:3019
100
  msgid "Bucket name too short."
101
  msgstr ""
102
 
103
- #: classes/amazon-s3-and-cloudfront.php:3020
104
  msgid "Bucket name too long."
105
  msgstr ""
106
 
107
- #: classes/amazon-s3-and-cloudfront.php:3021
108
  msgid ""
109
  "Invalid character. Bucket names can contain lowercase letters, numbers, "
110
  "periods and hyphens."
111
  msgstr ""
112
 
113
- #: classes/amazon-s3-and-cloudfront.php:3022
114
  msgid "Error saving bucket"
115
  msgstr ""
116
 
117
- #: classes/amazon-s3-and-cloudfront.php:3023
118
  msgid "Error fetching buckets"
119
  msgstr ""
120
 
121
- #: classes/amazon-s3-and-cloudfront.php:3024
122
  msgid "Error getting URL preview: "
123
  msgstr ""
124
 
125
- #: classes/amazon-s3-and-cloudfront.php:3025
126
  msgid "The changes you made will be lost if you navigate away from this page"
127
  msgstr ""
128
 
129
- #: classes/amazon-s3-and-cloudfront.php:3026
130
  msgid "Getting diagnostic info..."
131
  msgstr ""
132
 
133
- #: classes/amazon-s3-and-cloudfront.php:3027
134
  msgid "Error getting diagnostic info: "
135
  msgstr ""
136
 
137
- #: classes/amazon-s3-and-cloudfront.php:3028
138
  msgctxt "placeholder for hidden access key, 39 char max"
139
  msgid "-- not shown --"
140
  msgstr ""
141
 
142
- #: classes/amazon-s3-and-cloudfront.php:3030
143
- #: classes/amazon-s3-and-cloudfront.php:5024
144
  msgid "Settings saved."
145
  msgstr ""
146
 
147
- #: classes/amazon-s3-and-cloudfront.php:3120
148
  msgid "Cheatin' eh?"
149
  msgstr ""
150
 
151
- #: classes/amazon-s3-and-cloudfront.php:3204
 
 
 
 
 
 
152
  msgid "No bucket name provided."
153
  msgstr ""
154
 
155
- #: classes/amazon-s3-and-cloudfront.php:3213
156
  msgid "Bucket name not valid."
157
  msgstr ""
158
 
159
- #: classes/amazon-s3-and-cloudfront.php:3226
160
  msgid "No region provided."
161
  msgstr ""
162
 
163
- #: classes/amazon-s3-and-cloudfront.php:3303
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  #: view/provider-select.php:329
165
  msgctxt "placeholder for hidden secret access key, 39 char max"
166
  msgid "-- not shown --"
167
  msgstr ""
168
 
169
- #: classes/amazon-s3-and-cloudfront.php:3326
170
  msgid "Key File not valid JSON."
171
  msgstr ""
172
 
173
- #: classes/amazon-s3-and-cloudfront.php:3372
 
 
 
 
 
 
 
174
  msgctxt "Show the media library tab"
175
  msgid "Media Library"
176
  msgstr ""
177
 
178
- #: classes/amazon-s3-and-cloudfront.php:3373
179
  msgctxt "Show the addons tab"
180
  msgid "Addons"
181
  msgstr ""
182
 
183
- #: classes/amazon-s3-and-cloudfront.php:3374
184
  msgctxt "Show the support tab"
185
  msgid "Support"
186
  msgstr ""
187
 
188
- #: classes/amazon-s3-and-cloudfront.php:3601
189
  #, php-format
190
  msgid ""
191
  "<strong>WP Offload Media</strong> &mdash; The file %s has been given %s "
192
  "permissions in the bucket."
193
  msgstr ""
194
 
195
- #: classes/amazon-s3-and-cloudfront.php:3620
196
  msgid ""
197
  "<strong>WP Offload Media Requirement Missing</strong> &mdash; Looks like you "
198
  "don't have an image manipulation library installed on this server and "
@@ -200,18 +250,18 @@ msgid ""
200
  "Please setup GD or ImageMagick."
201
  msgstr ""
202
 
203
- #: classes/amazon-s3-and-cloudfront.php:4339
204
  #, php-format
205
  msgid ""
206
  "<a href=\"%s\">Define your access keys</a> to enable write access to the "
207
  "bucket"
208
  msgstr ""
209
 
210
- #: classes/amazon-s3-and-cloudfront.php:4346
211
  msgid "Quick Start Guide"
212
  msgstr ""
213
 
214
- #: classes/amazon-s3-and-cloudfront.php:4348
215
  #, php-format
216
  msgid ""
217
  "Looks like we don't have write access to this bucket. It's likely that the "
@@ -220,7 +270,7 @@ msgid ""
220
  "correctly."
221
  msgstr ""
222
 
223
- #: classes/amazon-s3-and-cloudfront.php:4350
224
  #, php-format
225
  msgid ""
226
  "Looks like we don't have access to the buckets. It's likely that the user "
@@ -228,39 +278,39 @@ msgid ""
228
  "Please see our %s for instructions on setting up permissions correctly."
229
  msgstr ""
230
 
231
- #: classes/amazon-s3-and-cloudfront.php:4485
232
  msgid "WP Offload Media Activation"
233
  msgstr ""
234
 
235
- #: classes/amazon-s3-and-cloudfront.php:4486
236
  msgid ""
237
  "WP Offload Media Lite and WP Offload Media cannot both be active. We've "
238
  "automatically deactivated WP Offload Media Lite."
239
  msgstr ""
240
 
241
- #: classes/amazon-s3-and-cloudfront.php:4488
242
  msgid "WP Offload Media Lite Activation"
243
  msgstr ""
244
 
245
- #: classes/amazon-s3-and-cloudfront.php:4489
246
  msgid ""
247
  "WP Offload Media Lite and WP Offload Media cannot both be active. We've "
248
  "automatically deactivated WP Offload Media."
249
  msgstr ""
250
 
251
- #: classes/amazon-s3-and-cloudfront.php:4541
252
  msgid "More&nbsp;info&nbsp;&raquo;"
253
  msgstr ""
254
 
255
- #: classes/amazon-s3-and-cloudfront.php:4636
256
  msgid "this doc"
257
  msgstr ""
258
 
259
- #: classes/amazon-s3-and-cloudfront.php:4638
260
  msgid "WP Offload Media Feature Removed"
261
  msgstr ""
262
 
263
- #: classes/amazon-s3-and-cloudfront.php:4639
264
  #, php-format
265
  msgid ""
266
  "You had the \"Always non-SSL\" option selected in your settings, but we've "
@@ -271,59 +321,59 @@ msgid ""
271
  "to the old behavior."
272
  msgstr ""
273
 
274
- #: classes/amazon-s3-and-cloudfront.php:4669
275
  msgid "Offload"
276
  msgstr ""
277
 
278
- #: classes/amazon-s3-and-cloudfront.php:4774
279
  msgctxt "Storage provider key name"
280
  msgid "Storage Provider"
281
  msgstr ""
282
 
283
- #: classes/amazon-s3-and-cloudfront.php:4775
284
  msgctxt "Storage provider name"
285
  msgid "Storage Provider"
286
  msgstr ""
287
 
288
- #: classes/amazon-s3-and-cloudfront.php:4776
289
  msgctxt "Bucket name"
290
  msgid "Bucket"
291
  msgstr ""
292
 
293
- #: classes/amazon-s3-and-cloudfront.php:4777
294
  msgctxt "Path to file in bucket"
295
  msgid "Path"
296
  msgstr ""
297
 
298
- #: classes/amazon-s3-and-cloudfront.php:4778
299
  msgctxt "Location of bucket"
300
  msgid "Region"
301
  msgstr ""
302
 
303
- #: classes/amazon-s3-and-cloudfront.php:4779
304
  msgctxt "Access control list of the file in bucket"
305
  msgid "Access"
306
  msgstr ""
307
 
308
- #: classes/amazon-s3-and-cloudfront.php:4780
309
  msgid "URL"
310
  msgstr ""
311
 
312
- #: classes/amazon-s3-and-cloudfront.php:4987
313
  msgid "Assets Pull"
314
  msgstr ""
315
 
316
- #: classes/amazon-s3-and-cloudfront.php:4988
317
  msgid ""
318
  "An addon for WP Offload Media to serve your site's JS, CSS, and other "
319
  "enqueued assets from Amazon CloudFront or another CDN."
320
  msgstr ""
321
 
322
- #: classes/amazon-s3-and-cloudfront.php:4992
323
  msgid "Feature"
324
  msgstr ""
325
 
326
- #: classes/amazon-s3-and-cloudfront.php:5038
327
  #, php-format
328
  msgid ""
329
  "<strong>Amazon Web Services Plugin No Longer Required</strong> &mdash; As of "
@@ -334,7 +384,7 @@ msgid ""
334
  "plugin, it should be safe to deactivate and delete it. %2$s"
335
  msgstr ""
336
 
337
- #: classes/amazon-s3-and-cloudfront.php:5070
338
  #, php-format
339
  msgid ""
340
  "<strong>WP Offload Media Settings Moved</strong> &mdash; You now define your "
@@ -455,52 +505,93 @@ msgid ""
455
  "zlib. Your server currently has"
456
  msgstr ""
457
 
458
- #: classes/as3cf-notices.php:431
459
  msgid "Error dismissing notice."
460
  msgstr ""
461
 
462
- #: classes/as3cf-notices.php:446
463
  msgid "Invalid notice ID."
464
  msgstr ""
465
 
466
- #: classes/as3cf-plugin-base.php:537
467
  msgid "Settings"
468
  msgstr ""
469
 
470
- #: classes/as3cf-plugin-compatibility.php:592
471
  #, php-format
472
  msgid "The local directory %s does not exist and could not be created."
473
  msgstr ""
474
 
475
- #: classes/as3cf-plugin-compatibility.php:593
476
- #: classes/as3cf-plugin-compatibility.php:605
477
  #: classes/upgrades/upgrade-meta-wp-error.php:81
478
  #, php-format
479
  msgid ""
480
  "There was an error attempting to download the file %s from the bucket: %s"
481
  msgstr ""
482
 
483
- #: classes/as3cf-plugin-compatibility.php:930
484
  #, php-format
485
  msgid ""
486
  "<strong>Warning:</strong> This site is using PHP %1$s, in a future update WP "
487
  "Offload Media will require PHP %2$s or later. %3$s"
488
  msgstr ""
489
 
490
- #: classes/providers/provider.php:443
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491
  msgid "Given Key File Path is invalid or could not be accessed."
492
  msgstr ""
493
 
494
- #: classes/providers/provider.php:453
495
- #: classes/providers/provider.php:458
496
  msgid "Could not read Key File Path's contents."
497
  msgstr ""
498
 
499
- #: classes/providers/provider.php:466
500
  msgid "Given Key File Path does not contain valid JSON."
501
  msgstr ""
502
 
503
- #: classes/providers/provider.php:579
504
  #, php-format
505
  msgid "You must first <a href=\"%s\">set your access keys</a>."
506
  msgstr ""
@@ -581,19 +672,19 @@ msgid ""
581
  "version."
582
  msgstr ""
583
 
584
- #: classes/upgrades/upgrade.php:407
585
  msgid "Pause Update"
586
  msgstr ""
587
 
588
- #: classes/upgrades/upgrade.php:415
589
  msgid "Restart Update"
590
  msgstr ""
591
 
592
- #: classes/upgrades/upgrade.php:419
593
  msgid "Try To Run It Again"
594
  msgstr ""
595
 
596
- #: classes/upgrades/upgrade.php:442
597
  #, php-format
598
  msgid ""
599
  "<strong>Running %1$s Update%2$s</strong> &mdash; We&#8217;re going through "
@@ -603,14 +694,14 @@ msgid ""
603
  "performance."
604
  msgstr ""
605
 
606
- #: classes/upgrades/upgrade.php:456
607
  #, php-format
608
  msgid ""
609
  "<strong>%1$s Update Paused%2$s</strong> &mdash; Updating Media Library %3$s "
610
  "has been paused."
611
  msgstr ""
612
 
613
- #: classes/upgrades/upgrade.php:469
614
  #, php-format
615
  msgid ""
616
  "<strong>Error Updating %1$s</strong> &mdash; We ran into some errors "
@@ -618,16 +709,23 @@ msgid ""
618
  "been offloaded. Please check your error log for details. (#%3$d)"
619
  msgstr ""
620
 
621
- #: classes/upgrades/upgrade.php:493
622
  #, php-format
623
  msgid " (%s%% Complete)"
624
  msgstr ""
625
 
626
- #: classes/upgrades/upgrade.php:626
627
  #, php-format
628
  msgid "Every %d Minutes"
629
  msgstr ""
630
 
 
 
 
 
 
 
 
631
  #: view/addon.php:11
632
  msgid "More Details &raquo;"
633
  msgstr ""
@@ -664,118 +762,252 @@ msgstr ""
664
  msgid "File exists on server"
665
  msgstr ""
666
 
667
- #: view/bucket-select.php:38
 
 
668
  #: view/provider-select.php:21
669
  msgid "&laquo;&nbsp;Back"
670
  msgstr ""
671
 
672
- #: view/bucket-select.php:44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
  msgid "What bucket would you like to use?"
674
  msgstr ""
675
 
676
- #: view/bucket-select.php:57
677
- #: view/bucket-select.php:110
678
- #: view/bucket-select.php:163
679
  msgid "Region:"
680
  msgstr ""
681
 
682
- #: view/bucket-select.php:72
683
- #: view/bucket-select.php:125
684
- #: view/bucket-select.php:180
685
  #, php-format
686
  msgid "%s (defined in wp-config.php)"
687
  msgstr ""
688
 
689
- #: view/bucket-select.php:79
690
- #: view/bucket-select.php:131
691
- #: view/bucket-select.php:186
692
- #: view/bucket-setting.php:8
693
  msgid "Bucket:"
694
  msgstr ""
695
 
696
- #: view/bucket-select.php:82
697
  msgid "Existing bucket name"
698
  msgstr ""
699
 
700
- #: view/bucket-select.php:88
 
 
 
 
 
 
701
  msgid "Save Bucket Setting"
702
  msgstr ""
703
 
704
- #: view/bucket-select.php:89
705
- #: view/bucket-select.php:196
706
  msgid "Browse existing buckets"
707
  msgstr ""
708
 
709
- #: view/bucket-select.php:90
710
- #: view/bucket-select.php:145
711
- #: view/bucket-select.php:151
712
  msgid "Create new bucket"
713
  msgstr ""
714
 
715
- #: view/bucket-select.php:95
716
  msgid "Select bucket"
717
  msgstr ""
718
 
719
- #: view/bucket-select.php:134
720
- #: view/bucket-select.php:139
721
  msgid "Loading..."
722
  msgstr ""
723
 
724
- #: view/bucket-select.php:134
725
- #: view/bucket-select.php:139
726
  msgid "Nothing found"
727
  msgstr ""
728
 
729
- #: view/bucket-select.php:143
730
  msgid "Save Selected Bucket"
731
  msgstr ""
732
 
733
- #: view/bucket-select.php:144
734
- #: view/bucket-select.php:197
735
  msgid "Enter bucket name"
736
  msgstr ""
737
 
738
- #: view/bucket-select.php:146
739
  msgid "Refresh"
740
  msgstr ""
741
 
742
- #: view/bucket-select.php:189
743
  msgid "New bucket name"
744
  msgstr ""
745
 
746
- #: view/bucket-select.php:195
747
  msgid "Create New Bucket"
748
  msgstr ""
749
 
750
- #: view/bucket-setting.php:13
751
  msgid "View in provider's console"
752
  msgstr ""
753
 
754
- #: view/bucket-setting.php:19
 
755
  #: view/provider-setting.php:17
756
  msgid "Change"
757
  msgstr ""
758
 
759
- #: view/bucket-setting.php:22
760
  msgid "The region that the bucket is in."
761
  msgstr ""
762
 
763
- #: view/bucket-setting.php:43
764
- #, php-format
 
 
 
 
 
 
 
765
  msgid ""
766
- "<strong>Bucket Select Disabled</strong> &mdash; <a href=\"%s\">Define your "
767
- "access keys</a> to configure the bucket"
 
 
 
768
  msgstr ""
769
 
770
- #: view/bucket-setting.php:52
771
  msgid ""
772
- "<strong>Provider &amp; Bucket Select Disabled</strong> &mdash; Provider and "
773
- "bucket selection has been disabled while files are copied between buckets."
774
  msgstr ""
775
 
776
- #: view/cloudfront-setting.php:7
777
- #: view/deprecated-domain-setting.php:49
778
- msgid "Invalid character. Letters, numbers, periods and hyphens are allowed."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
779
  msgstr ""
780
 
781
  #: view/debug-info.php:2
@@ -787,37 +1019,47 @@ msgctxt "Download to your computer"
787
  msgid "Download"
788
  msgstr ""
789
 
790
- #: view/deprecated-domain-setting.php:5
791
- msgid "Domain:"
792
  msgstr ""
793
 
794
- #: view/deprecated-domain-setting.php:30
795
- msgid "Bucket name as subdomain"
796
  msgstr ""
797
 
798
- #: view/deprecated-domain-setting.php:35
799
- msgid "Bucket name in path"
800
  msgstr ""
801
 
802
- #: view/deprecated-domain-setting.php:40
803
- msgid "Bucket name as domain"
804
  msgstr ""
805
 
806
- #: view/deprecated-domain-setting.php:45
807
- msgid "CloudFront or custom domain"
 
808
  msgstr ""
809
 
810
- #: view/domain-setting.php:19
811
  msgid "Custom Domain (CNAME)"
812
  msgstr ""
813
 
814
- #: view/domain-setting.php:21
815
  #, php-format
816
  msgid ""
817
- "We strongly recommend you configure a CDN to point at your bucket and "
818
- "configure a subdomain of %1$s to point at your CDN. If you don't enter a "
819
- "subdomain of your site's domain in the field below it will negatively impact "
820
- "your site's SEO."
 
 
 
 
 
 
 
 
 
821
  msgstr ""
822
 
823
  #: view/error-access.php:4
@@ -959,18 +1201,10 @@ msgid ""
959
  msgstr ""
960
 
961
  #: view/provider-select.php:373
962
- msgid "Next"
963
- msgstr ""
964
-
965
- #: view/provider-select.php:373
966
- #: view/settings/media.php:264
967
  msgid "Save Changes"
968
  msgstr ""
969
 
970
- #: view/provider-setting.php:12
971
- msgid "Provider:"
972
- msgstr ""
973
-
974
  #: view/settings/addons.php:10
975
  #, php-format
976
  msgid ""
@@ -979,7 +1213,7 @@ msgid ""
979
  "\">deliciousbrains.com</a> to purchase in just a few clicks."
980
  msgstr ""
981
 
982
- #: view/settings/media.php:76
983
  #, php-format
984
  msgid ""
985
  "Yikes! That's not a very SEO-friendly URL. We strongly recommend you "
@@ -987,106 +1221,109 @@ msgid ""
987
  "point at your CDN. %2$s"
988
  msgstr ""
989
 
990
- #: view/settings/media.php:92
991
  msgid "Storage"
992
  msgstr ""
993
 
994
- #: view/settings/media.php:120
995
  msgid "Copy Files to Bucket"
996
  msgstr ""
997
 
998
- #: view/settings/media.php:122
999
  msgid "When a file is uploaded to the Media Library, copy it to the bucket."
1000
  msgstr ""
1001
 
1002
- #: view/settings/media.php:137
1003
  msgid "Path"
1004
  msgstr ""
1005
 
1006
- #: view/settings/media.php:139
1007
  msgid "By default the path is the same as your local WordPress files."
1008
  msgstr ""
1009
 
1010
- #: view/settings/media.php:157
 
1011
  msgid "Year/Month"
1012
  msgstr ""
1013
 
1014
- #: view/settings/media.php:159
1015
  msgid ""
1016
  "Add the Year/Month to the end of the path above just like WordPress does by "
1017
  "default."
1018
  msgstr ""
1019
 
1020
- #: view/settings/media.php:172
 
1021
  msgid "Object Versioning"
1022
  msgstr ""
1023
 
1024
- #: view/settings/media.php:174
1025
  msgid ""
1026
  "Append a timestamp to the file's bucket path. Recommended when using a CDN "
1027
  "so you don't have to worry about cache invalidation."
1028
  msgstr ""
1029
 
1030
- #: view/settings/media.php:182
1031
- msgid "URL Rewriting"
1032
  msgstr ""
1033
 
1034
- #: view/settings/media.php:192
1035
  msgid "Rewrite Media URLs"
1036
  msgstr ""
1037
 
1038
- #: view/settings/media.php:194
 
1039
  msgid ""
1040
  "For Media Library files that have been copied to your bucket, rewrite the "
1041
- "URLs so that they are served from the bucket or CDN instead of your server."
1042
  msgstr ""
1043
 
1044
- #: view/settings/media.php:210
1045
  msgid "Force HTTPS"
1046
  msgstr ""
1047
 
1048
- #: view/settings/media.php:212
1049
  msgid ""
1050
  "By default we use HTTPS when the request is HTTPS and regular HTTP when the "
1051
  "request is HTTP, but you may want to force the use of HTTPS always, "
1052
  "regardless of the request."
1053
  msgstr ""
1054
 
1055
- #: view/settings/media.php:220
1056
  msgid "Advanced Options"
1057
  msgstr ""
1058
 
1059
- #: view/settings/media.php:230
1060
  msgid "Remove Files From Server"
1061
  msgstr ""
1062
 
1063
- #: view/settings/media.php:231
1064
  msgid ""
1065
  "Once a file has been copied to the bucket, remove it from the local server."
1066
  msgstr ""
1067
 
1068
- #: view/settings/media.php:235
1069
  msgid ""
1070
  "<strong>Broken URLs</strong> &mdash; There will be broken URLs for files "
1071
  "that don't exist locally. You can fix this by enabling <strong>Rewrite Media "
1072
  "URLs</strong> to use the offloaded media."
1073
  msgstr ""
1074
 
1075
- #: view/settings/media.php:246
1076
  #, php-format
1077
  msgid ""
1078
  "<strong>Warning</strong> &mdash; Some plugins depend on the file being "
1079
  "present on the local server and may not work when the file is removed. %s"
1080
  msgstr ""
1081
 
1082
- #: view/settings/media.php:248
1083
  msgid ""
1084
  "If you have a backup system in place (as you should) that backs up your site "
1085
  "files, media, and database, your media will no longer be backed up as it "
1086
  "will no longer be present on the filesystem."
1087
  msgstr ""
1088
 
1089
- #: view/settings/media.php:276
1090
  #, php-format
1091
  msgid ""
1092
  "Need help getting your Access Keys? <a href=\"%s\">Check out the Quick Start "
@@ -1114,7 +1351,7 @@ msgid "Easy Digital Downloads integration"
1114
  msgstr ""
1115
 
1116
  #: view/sidebar.php:18
1117
- msgid "PriorityExpert™ email support"
1118
  msgstr ""
1119
 
1120
  #: view/sidebar.php:25
@@ -1154,6 +1391,22 @@ msgid ""
1154
  "unsubscribe with 1-click anytime."
1155
  msgstr ""
1156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1157
  #: view/wordpress-org-support.php:2
1158
  msgid "As this is a free plugin, we do not provide support."
1159
  msgstr ""
8
  msgstr ""
9
  "Project-Id-Version: amazon-s3-and-cloudfront\n"
10
  "Report-Msgid-Bugs-To: nom@deliciousbrains.com\n"
11
+ "POT-Creation-Date: 2020-07-14 09:51+0100\n"
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
17
  "Content-Type: text/plain; charset=UTF-8\n"
18
  "Content-Transfer-Encoding: 8bit\n"
19
 
20
+ #: classes/amazon-s3-and-cloudfront.php:165
21
+ #: classes/amazon-s3-and-cloudfront.php:166
22
  msgid "Offload Media Lite"
23
  msgstr ""
24
 
25
+ #: classes/amazon-s3-and-cloudfront.php:389
26
+ #: classes/amazon-s3-and-cloudfront.php:406
27
  msgid "Unknown"
28
  msgstr ""
29
 
30
+ #: classes/amazon-s3-and-cloudfront.php:478
31
+ #: view/bucket-select.php:87
32
+ #: view/delivery-provider-select.php:129
33
+ #: view/delivery-provider-select.php:149
34
  #: view/provider-select.php:122
35
+ #: view/signed-urls-setting.php:18
36
+ #: view/signed-urls-setting.php:48
37
+ #: view/signed-urls-setting.php:79
38
  msgid "defined in wp-config.php"
39
  msgstr ""
40
 
41
+ #: classes/amazon-s3-and-cloudfront.php:1404
42
  #, php-format
43
  msgid "Media Library item with ID %d does not have a valid file path"
44
  msgstr ""
45
 
46
+ #: classes/amazon-s3-and-cloudfront.php:1454
47
+ #: classes/amazon-s3-and-cloudfront.php:1653
48
  #, php-format
49
  msgid "File %s does not exist"
50
  msgstr ""
51
 
52
+ #: classes/amazon-s3-and-cloudfront.php:1484
53
  #, php-format
54
  msgid "Mime type %s is not allowed"
55
  msgstr ""
56
 
57
+ #: classes/amazon-s3-and-cloudfront.php:1495
58
  msgid "Already offloaded to a different provider"
59
  msgstr ""
60
 
61
+ #: classes/amazon-s3-and-cloudfront.php:1601
62
+ #: classes/amazon-s3-and-cloudfront.php:1666
63
  #, php-format
64
  msgid "Error offloading %s to provider: %s"
65
  msgstr ""
66
 
67
+ #: classes/amazon-s3-and-cloudfront.php:2782
68
  msgid "This action can only be performed through an admin screen."
69
  msgstr ""
70
 
71
+ #: classes/amazon-s3-and-cloudfront.php:2784
72
  msgid "Cheatin&#8217; eh?"
73
  msgstr ""
74
 
75
+ #: classes/amazon-s3-and-cloudfront.php:2786
76
  msgid "You do not have sufficient permissions to access this page."
77
  msgstr ""
78
 
79
+ #: classes/amazon-s3-and-cloudfront.php:3110
80
  msgid "Error Getting Bucket Region"
81
  msgstr ""
82
 
83
+ #: classes/amazon-s3-and-cloudfront.php:3111
84
  #, php-format
85
  msgid "There was an error attempting to get the region of the bucket %s: %s"
86
  msgstr ""
87
 
88
+ #: classes/amazon-s3-and-cloudfront.php:3214
89
  msgid ""
90
  "This is a test file to check if the user has write permission to the bucket. "
91
  "Delete me if found."
92
  msgstr ""
93
 
94
+ #: classes/amazon-s3-and-cloudfront.php:3220
95
  #, php-format
96
  msgid ""
97
  "There was an error attempting to check the permissions of the bucket %s: %s"
98
  msgstr ""
99
 
100
+ #: classes/amazon-s3-and-cloudfront.php:3316
101
  msgid "Error creating bucket"
102
  msgstr ""
103
 
104
+ #: classes/amazon-s3-and-cloudfront.php:3317
105
  msgid "Bucket name too short."
106
  msgstr ""
107
 
108
+ #: classes/amazon-s3-and-cloudfront.php:3318
109
  msgid "Bucket name too long."
110
  msgstr ""
111
 
112
+ #: classes/amazon-s3-and-cloudfront.php:3319
113
  msgid ""
114
  "Invalid character. Bucket names can contain lowercase letters, numbers, "
115
  "periods and hyphens."
116
  msgstr ""
117
 
118
+ #: classes/amazon-s3-and-cloudfront.php:3320
119
  msgid "Error saving bucket"
120
  msgstr ""
121
 
122
+ #: classes/amazon-s3-and-cloudfront.php:3321
123
  msgid "Error fetching buckets"
124
  msgstr ""
125
 
126
+ #: classes/amazon-s3-and-cloudfront.php:3322
127
  msgid "Error getting URL preview: "
128
  msgstr ""
129
 
130
+ #: classes/amazon-s3-and-cloudfront.php:3323
131
  msgid "The changes you made will be lost if you navigate away from this page"
132
  msgstr ""
133
 
134
+ #: classes/amazon-s3-and-cloudfront.php:3324
135
  msgid "Getting diagnostic info..."
136
  msgstr ""
137
 
138
+ #: classes/amazon-s3-and-cloudfront.php:3325
139
  msgid "Error getting diagnostic info: "
140
  msgstr ""
141
 
142
+ #: classes/amazon-s3-and-cloudfront.php:3326
143
  msgctxt "placeholder for hidden access key, 39 char max"
144
  msgid "-- not shown --"
145
  msgstr ""
146
 
147
+ #: classes/amazon-s3-and-cloudfront.php:3328
148
+ #: classes/amazon-s3-and-cloudfront.php:5585
149
  msgid "Settings saved."
150
  msgstr ""
151
 
152
+ #: classes/amazon-s3-and-cloudfront.php:3449
153
  msgid "Cheatin' eh?"
154
  msgstr ""
155
 
156
+ #: classes/amazon-s3-and-cloudfront.php:3522
157
+ #, php-format
158
+ msgid "Could not set new Delivery Provider: %s"
159
+ msgstr ""
160
+
161
+ #: classes/amazon-s3-and-cloudfront.php:3597
162
+ #: classes/amazon-s3-and-cloudfront.php:3727
163
  msgid "No bucket name provided."
164
  msgstr ""
165
 
166
+ #: classes/amazon-s3-and-cloudfront.php:3606
167
  msgid "Bucket name not valid."
168
  msgstr ""
169
 
170
+ #: classes/amazon-s3-and-cloudfront.php:3619
171
  msgid "No region provided."
172
  msgstr ""
173
 
174
+ #: classes/amazon-s3-and-cloudfront.php:3696
175
+ #, php-format
176
+ msgctxt "Trying to change public access setting for given provider's bucket."
177
+ msgid "Can't change Block All Public Access setting for %s buckets."
178
+ msgstr ""
179
+
180
+ #: classes/amazon-s3-and-cloudfront.php:3705
181
+ msgid "No block public access setting provided."
182
+ msgstr ""
183
+
184
+ #: classes/amazon-s3-and-cloudfront.php:3718
185
+ msgid "Storage Provider not configured with access credentials."
186
+ msgstr ""
187
+
188
+ #: classes/amazon-s3-and-cloudfront.php:3745
189
+ msgid "Could not change Block All Public Access status for bucket."
190
+ msgstr ""
191
+
192
+ #: classes/amazon-s3-and-cloudfront.php:3762
193
+ msgid ""
194
+ "<strong>Failed to Enable Block All Public Access</strong> &mdash; We could "
195
+ "not enable Block All Public Access. You will need to log in to the AWS "
196
+ "Console and do it manually."
197
+ msgstr ""
198
+
199
+ #: classes/amazon-s3-and-cloudfront.php:3764
200
+ msgid ""
201
+ "<strong>Failed to Disable Block All Public Access</strong> &mdash; We could "
202
+ "not disable Block All Public Access. You will need to log in to the AWS "
203
+ "Console and do it manually."
204
+ msgstr ""
205
+
206
+ #: classes/amazon-s3-and-cloudfront.php:3799
207
  #: view/provider-select.php:329
208
  msgctxt "placeholder for hidden secret access key, 39 char max"
209
  msgid "-- not shown --"
210
  msgstr ""
211
 
212
+ #: classes/amazon-s3-and-cloudfront.php:3822
213
  msgid "Key File not valid JSON."
214
  msgstr ""
215
 
216
+ #: classes/amazon-s3-and-cloudfront.php:3834
217
+ #: classes/amazon-s3-and-cloudfront.php:3848
218
+ #: classes/amazon-s3-and-cloudfront.php:3857
219
+ msgctxt "missing form field"
220
+ msgid " not provided."
221
+ msgstr ""
222
+
223
+ #: classes/amazon-s3-and-cloudfront.php:3900
224
  msgctxt "Show the media library tab"
225
  msgid "Media Library"
226
  msgstr ""
227
 
228
+ #: classes/amazon-s3-and-cloudfront.php:3901
229
  msgctxt "Show the addons tab"
230
  msgid "Addons"
231
  msgstr ""
232
 
233
+ #: classes/amazon-s3-and-cloudfront.php:3902
234
  msgctxt "Show the support tab"
235
  msgid "Support"
236
  msgstr ""
237
 
238
+ #: classes/amazon-s3-and-cloudfront.php:4077
239
  #, php-format
240
  msgid ""
241
  "<strong>WP Offload Media</strong> &mdash; The file %s has been given %s "
242
  "permissions in the bucket."
243
  msgstr ""
244
 
245
+ #: classes/amazon-s3-and-cloudfront.php:4096
246
  msgid ""
247
  "<strong>WP Offload Media Requirement Missing</strong> &mdash; Looks like you "
248
  "don't have an image manipulation library installed on this server and "
250
  "Please setup GD or ImageMagick."
251
  msgstr ""
252
 
253
+ #: classes/amazon-s3-and-cloudfront.php:4878
254
  #, php-format
255
  msgid ""
256
  "<a href=\"%s\">Define your access keys</a> to enable write access to the "
257
  "bucket"
258
  msgstr ""
259
 
260
+ #: classes/amazon-s3-and-cloudfront.php:4885
261
  msgid "Quick Start Guide"
262
  msgstr ""
263
 
264
+ #: classes/amazon-s3-and-cloudfront.php:4887
265
  #, php-format
266
  msgid ""
267
  "Looks like we don't have write access to this bucket. It's likely that the "
270
  "correctly."
271
  msgstr ""
272
 
273
+ #: classes/amazon-s3-and-cloudfront.php:4889
274
  #, php-format
275
  msgid ""
276
  "Looks like we don't have access to the buckets. It's likely that the user "
278
  "Please see our %s for instructions on setting up permissions correctly."
279
  msgstr ""
280
 
281
+ #: classes/amazon-s3-and-cloudfront.php:5015
282
  msgid "WP Offload Media Activation"
283
  msgstr ""
284
 
285
+ #: classes/amazon-s3-and-cloudfront.php:5016
286
  msgid ""
287
  "WP Offload Media Lite and WP Offload Media cannot both be active. We've "
288
  "automatically deactivated WP Offload Media Lite."
289
  msgstr ""
290
 
291
+ #: classes/amazon-s3-and-cloudfront.php:5018
292
  msgid "WP Offload Media Lite Activation"
293
  msgstr ""
294
 
295
+ #: classes/amazon-s3-and-cloudfront.php:5019
296
  msgid ""
297
  "WP Offload Media Lite and WP Offload Media cannot both be active. We've "
298
  "automatically deactivated WP Offload Media."
299
  msgstr ""
300
 
301
+ #: classes/amazon-s3-and-cloudfront.php:5071
302
  msgid "More&nbsp;info&nbsp;&raquo;"
303
  msgstr ""
304
 
305
+ #: classes/amazon-s3-and-cloudfront.php:5147
306
  msgid "this doc"
307
  msgstr ""
308
 
309
+ #: classes/amazon-s3-and-cloudfront.php:5149
310
  msgid "WP Offload Media Feature Removed"
311
  msgstr ""
312
 
313
+ #: classes/amazon-s3-and-cloudfront.php:5150
314
  #, php-format
315
  msgid ""
316
  "You had the \"Always non-SSL\" option selected in your settings, but we've "
321
  "to the old behavior."
322
  msgstr ""
323
 
324
+ #: classes/amazon-s3-and-cloudfront.php:5185
325
  msgid "Offload"
326
  msgstr ""
327
 
328
+ #: classes/amazon-s3-and-cloudfront.php:5290
329
  msgctxt "Storage provider key name"
330
  msgid "Storage Provider"
331
  msgstr ""
332
 
333
+ #: classes/amazon-s3-and-cloudfront.php:5291
334
  msgctxt "Storage provider name"
335
  msgid "Storage Provider"
336
  msgstr ""
337
 
338
+ #: classes/amazon-s3-and-cloudfront.php:5292
339
  msgctxt "Bucket name"
340
  msgid "Bucket"
341
  msgstr ""
342
 
343
+ #: classes/amazon-s3-and-cloudfront.php:5293
344
  msgctxt "Path to file in bucket"
345
  msgid "Path"
346
  msgstr ""
347
 
348
+ #: classes/amazon-s3-and-cloudfront.php:5294
349
  msgctxt "Location of bucket"
350
  msgid "Region"
351
  msgstr ""
352
 
353
+ #: classes/amazon-s3-and-cloudfront.php:5295
354
  msgctxt "Access control list of the file in bucket"
355
  msgid "Access"
356
  msgstr ""
357
 
358
+ #: classes/amazon-s3-and-cloudfront.php:5296
359
  msgid "URL"
360
  msgstr ""
361
 
362
+ #: classes/amazon-s3-and-cloudfront.php:5548
363
  msgid "Assets Pull"
364
  msgstr ""
365
 
366
+ #: classes/amazon-s3-and-cloudfront.php:5549
367
  msgid ""
368
  "An addon for WP Offload Media to serve your site's JS, CSS, and other "
369
  "enqueued assets from Amazon CloudFront or another CDN."
370
  msgstr ""
371
 
372
+ #: classes/amazon-s3-and-cloudfront.php:5553
373
  msgid "Feature"
374
  msgstr ""
375
 
376
+ #: classes/amazon-s3-and-cloudfront.php:5599
377
  #, php-format
378
  msgid ""
379
  "<strong>Amazon Web Services Plugin No Longer Required</strong> &mdash; As of "
384
  "plugin, it should be safe to deactivate and delete it. %2$s"
385
  msgstr ""
386
 
387
+ #: classes/amazon-s3-and-cloudfront.php:5631
388
  #, php-format
389
  msgid ""
390
  "<strong>WP Offload Media Settings Moved</strong> &mdash; You now define your "
505
  "zlib. Your server currently has"
506
  msgstr ""
507
 
508
+ #: classes/as3cf-notices.php:430
509
  msgid "Error dismissing notice."
510
  msgstr ""
511
 
512
+ #: classes/as3cf-notices.php:445
513
  msgid "Invalid notice ID."
514
  msgstr ""
515
 
516
+ #: classes/as3cf-plugin-base.php:575
517
  msgid "Settings"
518
  msgstr ""
519
 
520
+ #: classes/as3cf-plugin-compatibility.php:595
521
  #, php-format
522
  msgid "The local directory %s does not exist and could not be created."
523
  msgstr ""
524
 
525
+ #: classes/as3cf-plugin-compatibility.php:596
526
+ #: classes/as3cf-plugin-compatibility.php:608
527
  #: classes/upgrades/upgrade-meta-wp-error.php:81
528
  #, php-format
529
  msgid ""
530
  "There was an error attempting to download the file %s from the bucket: %s"
531
  msgstr ""
532
 
533
+ #: classes/as3cf-plugin-compatibility.php:933
534
  #, php-format
535
  msgid ""
536
  "<strong>Warning:</strong> This site is using PHP %1$s, in a future update WP "
537
  "Offload Media will require PHP %2$s or later. %3$s"
538
  msgstr ""
539
 
540
+ #: classes/providers/delivery/another-cdn.php:47
541
+ #: classes/providers/delivery/digitalocean-spaces-cdn.php:83
542
+ msgid "Fast, No Private Media"
543
+ msgstr ""
544
+
545
+ #: classes/providers/delivery/aws-cloudfront.php:106
546
+ #, php-format
547
+ msgid ""
548
+ "Fast, Private Media Supported with <a href=\"%s\" target=\"_blank\">upgrade</"
549
+ "a>"
550
+ msgstr ""
551
+
552
+ #: classes/providers/delivery/delivery-provider.php:94
553
+ msgid "Signing Key ID"
554
+ msgstr ""
555
+
556
+ #: classes/providers/delivery/delivery-provider.php:112
557
+ msgid "Signing Key File Path"
558
+ msgstr ""
559
+
560
+ #: classes/providers/delivery/delivery-provider.php:130
561
+ msgid "Private Path"
562
+ msgstr ""
563
+
564
+ #: classes/providers/delivery/delivery-provider.php:275
565
+ msgid "Given Signing Key File Path is invalid or could not be accessed."
566
+ msgstr ""
567
+
568
+ #: classes/providers/delivery/delivery-provider.php:285
569
+ #: classes/providers/delivery/delivery-provider.php:290
570
+ msgid "Could not read Signing Key File Path's contents."
571
+ msgstr ""
572
+
573
+ #: classes/providers/delivery/gcp-cdn.php:73
574
+ msgid "Fast, Private Media Supported"
575
+ msgstr ""
576
+
577
+ #: classes/providers/delivery/storage.php:92
578
+ msgid "Slow, Private Media Supported"
579
+ msgstr ""
580
+
581
+ #: classes/providers/storage/storage-provider.php:338
582
  msgid "Given Key File Path is invalid or could not be accessed."
583
  msgstr ""
584
 
585
+ #: classes/providers/storage/storage-provider.php:348
586
+ #: classes/providers/storage/storage-provider.php:353
587
  msgid "Could not read Key File Path's contents."
588
  msgstr ""
589
 
590
+ #: classes/providers/storage/storage-provider.php:361
591
  msgid "Given Key File Path does not contain valid JSON."
592
  msgstr ""
593
 
594
+ #: classes/providers/storage/storage-provider.php:511
595
  #, php-format
596
  msgid "You must first <a href=\"%s\">set your access keys</a>."
597
  msgstr ""
672
  "version."
673
  msgstr ""
674
 
675
+ #: classes/upgrades/upgrade.php:410
676
  msgid "Pause Update"
677
  msgstr ""
678
 
679
+ #: classes/upgrades/upgrade.php:418
680
  msgid "Restart Update"
681
  msgstr ""
682
 
683
+ #: classes/upgrades/upgrade.php:422
684
  msgid "Try To Run It Again"
685
  msgstr ""
686
 
687
+ #: classes/upgrades/upgrade.php:445
688
  #, php-format
689
  msgid ""
690
  "<strong>Running %1$s Update%2$s</strong> &mdash; We&#8217;re going through "
694
  "performance."
695
  msgstr ""
696
 
697
+ #: classes/upgrades/upgrade.php:459
698
  #, php-format
699
  msgid ""
700
  "<strong>%1$s Update Paused%2$s</strong> &mdash; Updating Media Library %3$s "
701
  "has been paused."
702
  msgstr ""
703
 
704
+ #: classes/upgrades/upgrade.php:472
705
  #, php-format
706
  msgid ""
707
  "<strong>Error Updating %1$s</strong> &mdash; We ran into some errors "
709
  "been offloaded. Please check your error log for details. (#%3$d)"
710
  msgstr ""
711
 
712
+ #: classes/upgrades/upgrade.php:496
713
  #, php-format
714
  msgid " (%s%% Complete)"
715
  msgstr ""
716
 
717
+ #: classes/upgrades/upgrade.php:629
718
  #, php-format
719
  msgid "Every %d Minutes"
720
  msgstr ""
721
 
722
+ #: classes/upgrades/upgrade.php:956
723
+ #, php-format
724
+ msgid ""
725
+ "<strong>Settings Locked Temporarily</strong> &mdash; You can't change any of "
726
+ "your settings until the \"%s\" has completed."
727
+ msgstr ""
728
+
729
  #: view/addon.php:11
730
  msgid "More Details &raquo;"
731
  msgstr ""
762
  msgid "File exists on server"
763
  msgstr ""
764
 
765
+ #: view/bucket-access-select.php:11
766
+ #: view/bucket-select.php:39
767
+ #: view/delivery-provider-select.php:17
768
  #: view/provider-select.php:21
769
  msgid "&laquo;&nbsp;Back"
770
  msgstr ""
771
 
772
+ #: view/bucket-access-select.php:42
773
+ #: view/bucket-access-select.php:65
774
+ msgid "Block All Public Access is currently disabled"
775
+ msgstr ""
776
+
777
+ #: view/bucket-access-select.php:45
778
+ msgid ""
779
+ "Since you're using Amazon CloudFront for delivery we recommend you enable "
780
+ "Block All Public Access once you have set up the required Origin Access "
781
+ "Identity and bucket policy."
782
+ msgstr ""
783
+
784
+ #: view/bucket-access-select.php:54
785
+ #, php-format
786
+ msgid ""
787
+ "I have set up the required <a href=\"%1$s\">Origin Access Identity and "
788
+ "bucket policy</a>"
789
+ msgstr ""
790
+
791
+ #: view/bucket-access-select.php:61
792
+ #: view/bucket-access-select.php:74
793
+ msgid "Enable \"Block All Public Access\""
794
+ msgstr ""
795
+
796
+ #: view/bucket-access-select.php:62
797
+ msgid "Leave \"Block All Public Access\" disabled"
798
+ msgstr ""
799
+
800
+ #: view/bucket-access-select.php:68
801
+ msgid ""
802
+ "Since you're not using Amazon CloudFront for delivery, we recommend you keep "
803
+ "Block All Public Access disabled unless you have a very good reason to "
804
+ "enable it."
805
+ msgstr ""
806
+
807
+ #: view/bucket-access-select.php:73
808
+ msgid "Leave \"Block All Public Access\" Disabled"
809
+ msgstr ""
810
+
811
+ #: view/bucket-access-select.php:81
812
+ #: view/bucket-access-select.php:108
813
+ msgid "Block All Public Access is currently enabled"
814
+ msgstr ""
815
+
816
+ #: view/bucket-access-select.php:84
817
+ msgid ""
818
+ "Since you're using Amazon CloudFront for delivery we recommend you keep "
819
+ "Block All Public Access enabled."
820
+ msgstr ""
821
+
822
+ #: view/bucket-access-select.php:89
823
+ #: view/bucket-access-select.php:124
824
+ msgid "Leave \"Block All Public Access\" enabled"
825
+ msgstr ""
826
+
827
+ #: view/bucket-access-select.php:90
828
+ #: view/bucket-access-select.php:105
829
+ #: view/bucket-access-select.php:123
830
+ msgid "Disable \"Block All Public Access\""
831
+ msgstr ""
832
+
833
+ #: view/bucket-access-select.php:93
834
+ msgid "Warning: Block All Public Access is currently enabled"
835
+ msgstr ""
836
+
837
+ #: view/bucket-access-select.php:97
838
+ #, php-format
839
+ msgid ""
840
+ "If you're following <a href=\"%1$s\">our documentation on setting up Amazon "
841
+ "CloudFront for delivery</a>, you can ignore this warning and continue. If "
842
+ "you're not planning on using Amazon CloudFront for delivery, you need to <a "
843
+ "href=\"%2$s\">disable Block All Public Access</a>."
844
+ msgstr ""
845
+
846
+ #: view/bucket-access-select.php:104
847
+ msgid "Continue"
848
+ msgstr ""
849
+
850
+ #: view/bucket-access-select.php:112
851
+ msgid ""
852
+ "You need to disable Block All Public Access so that your bucket is "
853
+ "accessible for delivery. Block All Public Access should only been enabled "
854
+ "when Amazon CloudFront is configured for delivery."
855
+ msgstr ""
856
+
857
+ #: view/bucket-access-select.php:115
858
+ #, php-format
859
+ msgid ""
860
+ "You need to disable Block All Public Access so that %1$s can access your "
861
+ "bucket for delivery. Block All Public Access should only been enabled when "
862
+ "Amazon CloudFront is configured for delivery."
863
+ msgstr ""
864
+
865
+ #: view/bucket-select.php:45
866
  msgid "What bucket would you like to use?"
867
  msgstr ""
868
 
869
+ #: view/bucket-select.php:58
870
+ #: view/bucket-select.php:128
871
+ #: view/bucket-select.php:181
872
  msgid "Region:"
873
  msgstr ""
874
 
875
+ #: view/bucket-select.php:73
876
+ #: view/bucket-select.php:143
877
+ #: view/bucket-select.php:198
878
  #, php-format
879
  msgid "%s (defined in wp-config.php)"
880
  msgstr ""
881
 
882
+ #: view/bucket-select.php:80
883
+ #: view/bucket-select.php:149
884
+ #: view/bucket-select.php:204
885
+ #: view/bucket-setting.php:16
886
  msgid "Bucket:"
887
  msgstr ""
888
 
889
+ #: view/bucket-select.php:95
890
  msgid "Existing bucket name"
891
  msgstr ""
892
 
893
+ #: view/bucket-select.php:104
894
+ #: view/delivery-provider-select.php:189
895
+ #: view/provider-select.php:373
896
+ msgid "Next"
897
+ msgstr ""
898
+
899
+ #: view/bucket-select.php:104
900
  msgid "Save Bucket Setting"
901
  msgstr ""
902
 
903
+ #: view/bucket-select.php:106
904
+ #: view/bucket-select.php:214
905
  msgid "Browse existing buckets"
906
  msgstr ""
907
 
908
+ #: view/bucket-select.php:107
909
+ #: view/bucket-select.php:163
910
+ #: view/bucket-select.php:169
911
  msgid "Create new bucket"
912
  msgstr ""
913
 
914
+ #: view/bucket-select.php:113
915
  msgid "Select bucket"
916
  msgstr ""
917
 
918
+ #: view/bucket-select.php:152
919
+ #: view/bucket-select.php:157
920
  msgid "Loading..."
921
  msgstr ""
922
 
923
+ #: view/bucket-select.php:152
924
+ #: view/bucket-select.php:157
925
  msgid "Nothing found"
926
  msgstr ""
927
 
928
+ #: view/bucket-select.php:161
929
  msgid "Save Selected Bucket"
930
  msgstr ""
931
 
932
+ #: view/bucket-select.php:162
933
+ #: view/bucket-select.php:215
934
  msgid "Enter bucket name"
935
  msgstr ""
936
 
937
+ #: view/bucket-select.php:164
938
  msgid "Refresh"
939
  msgstr ""
940
 
941
+ #: view/bucket-select.php:207
942
  msgid "New bucket name"
943
  msgstr ""
944
 
945
+ #: view/bucket-select.php:213
946
  msgid "Create New Bucket"
947
  msgstr ""
948
 
949
+ #: view/bucket-setting.php:21
950
  msgid "View in provider's console"
951
  msgstr ""
952
 
953
+ #: view/bucket-setting.php:25
954
+ #: view/delivery-provider-setting.php:17
955
  #: view/provider-setting.php:17
956
  msgid "Change"
957
  msgstr ""
958
 
959
+ #: view/bucket-setting.php:28
960
  msgid "The region that the bucket is in."
961
  msgstr ""
962
 
963
+ #: view/bucket-setting.php:33
964
+ msgid "Unknown Region"
965
+ msgstr ""
966
+
967
+ #: view/bucket-setting.php:54
968
+ msgid "Block All Public Access Enabled"
969
+ msgstr ""
970
+
971
+ #: view/bucket-setting.php:55
972
  msgid ""
973
+ "Public access to bucket has been blocked at either account or bucket level."
974
+ msgstr ""
975
+
976
+ #: view/bucket-setting.php:57
977
+ msgid "Block All Public Access Disabled"
978
  msgstr ""
979
 
980
+ #: view/bucket-setting.php:58
981
  msgid ""
982
+ "Public access to bucket has not been blocked at either account or bucket "
983
+ "level."
984
  msgstr ""
985
 
986
+ #: view/bucket-setting.php:60
987
+ msgid "Block All Public Access Status Unknown"
988
+ msgstr ""
989
+
990
+ #: view/bucket-setting.php:61
991
+ msgid ""
992
+ "Public access to bucket status unknown, please grant IAM User the s3:"
993
+ "GetBucketPublicAccessBlock permission."
994
+ msgstr ""
995
+
996
+ #: view/bucket-setting.php:82
997
+ #, php-format
998
+ msgid ""
999
+ "<strong>Block All Public Access is Enabled</strong> &mdash; If you're "
1000
+ "following <a href=\"%1$s\">our documentation on setting up Amazon CloudFront "
1001
+ "for delivery</a>, you can ignore this warning and continue. If you're not "
1002
+ "planning on using Amazon CloudFront for delivery, you need to <a href=\"%2$s"
1003
+ "\">disable Block All Public Access</a>."
1004
+ msgstr ""
1005
+
1006
+ #: view/bucket-setting.php:114
1007
+ #, php-format
1008
+ msgid ""
1009
+ "<strong>Bucket Select Disabled</strong> &mdash; <a href=\"%s\">Define your "
1010
+ "access keys</a> to configure the bucket"
1011
  msgstr ""
1012
 
1013
  #: view/debug-info.php:2
1019
  msgid "Download"
1020
  msgstr ""
1021
 
1022
+ #: view/delivery-domain-setting.php:10
1023
+ msgid "Invalid character. Letters, numbers, periods and hyphens are allowed."
1024
  msgstr ""
1025
 
1026
+ #: view/delivery-provider-select.php:19
1027
+ msgid "How would you like to deliver your media?"
1028
  msgstr ""
1029
 
1030
+ #: view/delivery-provider-select.php:154
1031
+ msgid "CDN Name"
1032
  msgstr ""
1033
 
1034
+ #: view/delivery-provider-select.php:189
1035
+ msgid "Save Delivery Provider"
1036
  msgstr ""
1037
 
1038
+ #: view/delivery-provider-setting.php:12
1039
+ #: view/provider-setting.php:12
1040
+ msgid "Provider:"
1041
  msgstr ""
1042
 
1043
+ #: view/enable-delivery-domain-setting.php:15
1044
  msgid "Custom Domain (CNAME)"
1045
  msgstr ""
1046
 
1047
+ #: view/enable-delivery-domain-setting.php:17
1048
  #, php-format
1049
  msgid ""
1050
+ "We strongly recommend you configure a subdomain of %1$s to point at your "
1051
+ "%2$s distribution. If you don't enter a subdomain of your site's domain in "
1052
+ "the field below it will negatively impact your site's SEO."
1053
+ msgstr ""
1054
+
1055
+ #: view/enable-signed-urls-setting.php:18
1056
+ msgid "Private Media"
1057
+ msgstr ""
1058
+
1059
+ #: view/enable-signed-urls-setting.php:20
1060
+ msgid ""
1061
+ "You can prevent public access to certain media files by enabling this option "
1062
+ "and the files will only be accessibly via signed URLs."
1063
  msgstr ""
1064
 
1065
  #: view/error-access.php:4
1201
  msgstr ""
1202
 
1203
  #: view/provider-select.php:373
1204
+ #: view/settings/media.php:315
 
 
 
 
1205
  msgid "Save Changes"
1206
  msgstr ""
1207
 
 
 
 
 
1208
  #: view/settings/addons.php:10
1209
  #, php-format
1210
  msgid ""
1213
  "\">deliciousbrains.com</a> to purchase in just a few clicks."
1214
  msgstr ""
1215
 
1216
+ #: view/settings/media.php:108
1217
  #, php-format
1218
  msgid ""
1219
  "Yikes! That's not a very SEO-friendly URL. We strongly recommend you "
1221
  "point at your CDN. %2$s"
1222
  msgstr ""
1223
 
1224
+ #: view/settings/media.php:124
1225
  msgid "Storage"
1226
  msgstr ""
1227
 
1228
+ #: view/settings/media.php:152
1229
  msgid "Copy Files to Bucket"
1230
  msgstr ""
1231
 
1232
+ #: view/settings/media.php:154
1233
  msgid "When a file is uploaded to the Media Library, copy it to the bucket."
1234
  msgstr ""
1235
 
1236
+ #: view/settings/media.php:169
1237
  msgid "Path"
1238
  msgstr ""
1239
 
1240
+ #: view/settings/media.php:171
1241
  msgid "By default the path is the same as your local WordPress files."
1242
  msgstr ""
1243
 
1244
+ #: view/settings/media.php:189
1245
+ #: view/settings/media.php:194
1246
  msgid "Year/Month"
1247
  msgstr ""
1248
 
1249
+ #: view/settings/media.php:191
1250
  msgid ""
1251
  "Add the Year/Month to the end of the path above just like WordPress does by "
1252
  "default."
1253
  msgstr ""
1254
 
1255
+ #: view/settings/media.php:205
1256
+ #: view/settings/media.php:210
1257
  msgid "Object Versioning"
1258
  msgstr ""
1259
 
1260
+ #: view/settings/media.php:207
1261
  msgid ""
1262
  "Append a timestamp to the file's bucket path. Recommended when using a CDN "
1263
  "so you don't have to worry about cache invalidation."
1264
  msgstr ""
1265
 
1266
+ #: view/settings/media.php:216
1267
+ msgid "Delivery"
1268
  msgstr ""
1269
 
1270
+ #: view/settings/media.php:234
1271
  msgid "Rewrite Media URLs"
1272
  msgstr ""
1273
 
1274
+ #: view/settings/media.php:236
1275
+ #, php-format
1276
  msgid ""
1277
  "For Media Library files that have been copied to your bucket, rewrite the "
1278
+ "URLs so that they are served from %s instead of your server."
1279
  msgstr ""
1280
 
1281
+ #: view/settings/media.php:261
1282
  msgid "Force HTTPS"
1283
  msgstr ""
1284
 
1285
+ #: view/settings/media.php:263
1286
  msgid ""
1287
  "By default we use HTTPS when the request is HTTPS and regular HTTP when the "
1288
  "request is HTTP, but you may want to force the use of HTTPS always, "
1289
  "regardless of the request."
1290
  msgstr ""
1291
 
1292
+ #: view/settings/media.php:271
1293
  msgid "Advanced Options"
1294
  msgstr ""
1295
 
1296
+ #: view/settings/media.php:281
1297
  msgid "Remove Files From Server"
1298
  msgstr ""
1299
 
1300
+ #: view/settings/media.php:282
1301
  msgid ""
1302
  "Once a file has been copied to the bucket, remove it from the local server."
1303
  msgstr ""
1304
 
1305
+ #: view/settings/media.php:286
1306
  msgid ""
1307
  "<strong>Broken URLs</strong> &mdash; There will be broken URLs for files "
1308
  "that don't exist locally. You can fix this by enabling <strong>Rewrite Media "
1309
  "URLs</strong> to use the offloaded media."
1310
  msgstr ""
1311
 
1312
+ #: view/settings/media.php:297
1313
  #, php-format
1314
  msgid ""
1315
  "<strong>Warning</strong> &mdash; Some plugins depend on the file being "
1316
  "present on the local server and may not work when the file is removed. %s"
1317
  msgstr ""
1318
 
1319
+ #: view/settings/media.php:299
1320
  msgid ""
1321
  "If you have a backup system in place (as you should) that backs up your site "
1322
  "files, media, and database, your media will no longer be backed up as it "
1323
  "will no longer be present on the filesystem."
1324
  msgstr ""
1325
 
1326
+ #: view/settings/media.php:327
1327
  #, php-format
1328
  msgid ""
1329
  "Need help getting your Access Keys? <a href=\"%s\">Check out the Quick Start "
1351
  msgstr ""
1352
 
1353
  #: view/sidebar.php:18
1354
+ msgid "Priority email support"
1355
  msgstr ""
1356
 
1357
  #: view/sidebar.php:25
1391
  "unsubscribe with 1-click anytime."
1392
  msgstr ""
1393
 
1394
+ #: view/signed-urls-setting.php:41
1395
+ msgid "Invalid character. Letters and numbers are allowed."
1396
+ msgstr ""
1397
+
1398
+ #: view/signed-urls-setting.php:72
1399
+ msgid ""
1400
+ "Invalid character. Letters, numbers, periods, hyphens, colons, spaces and "
1401
+ "slashes are allowed."
1402
+ msgstr ""
1403
+
1404
+ #: view/signed-urls-setting.php:103
1405
+ msgid ""
1406
+ "Invalid character. Letters, numbers, hyphens, spaces and forward slashes are "
1407
+ "allowed."
1408
+ msgstr ""
1409
+
1410
  #: view/wordpress-org-support.php:2
1411
  msgid "As this is a free plugin, we do not provide support."
1412
  msgstr ""
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: bradt, deliciousbrains, ianmjones
3
  Tags: uploads, amazon, s3, amazon s3, digitalocean, digitalocean spaces, google cloud storage, gcs, mirror, admin, media, cdn, cloudfront
4
  Requires at least: 4.9
5
- Tested up to: 5.4
6
  Requires PHP: 5.5
7
- Stable tag: 2.3.2
8
  License: GPLv3
9
 
10
  Copies files to Amazon S3, DigitalOcean Spaces or Google Cloud Storage as they are uploaded to the Media Library. Optionally configure Amazon CloudFront or another CDN for faster delivery.
@@ -32,7 +32,7 @@ Although WP Offload Media doesn't include image optimization features, we work c
32
  * [Assets Pull addon](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=assets%2Baddon#addons) - Serve your CSS, JS and fonts via CloudFront or another CDN
33
  * [WooCommerce integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=woocommerce%2Baddon#integrations)
34
  * [Easy Digital Downloads integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=edd%2Baddon#integrations)
35
- * PriorityExpert&trade; email support
36
 
37
  [Compare pro vs free &rarr;](https://deliciousbrains.com/wp-offload-media/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
38
 
@@ -81,6 +81,34 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
81
 
82
  == Changelog ==
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  = WP Offload Media Lite 2.3.2 - 2019-12-09 =
85
  * Improvement: Reduced database queries when external object cache available
86
  * Bug fix: Uncaught Error: Call to undefined function DeliciousBrains\WP_Offload_Media\Gcp\GuzzleHttp\choose_handler()
2
  Contributors: bradt, deliciousbrains, ianmjones
3
  Tags: uploads, amazon, s3, amazon s3, digitalocean, digitalocean spaces, google cloud storage, gcs, mirror, admin, media, cdn, cloudfront
4
  Requires at least: 4.9
5
+ Tested up to: 5.5
6
  Requires PHP: 5.5
7
+ Stable tag: 2.4
8
  License: GPLv3
9
 
10
  Copies files to Amazon S3, DigitalOcean Spaces or Google Cloud Storage as they are uploaded to the Media Library. Optionally configure Amazon CloudFront or another CDN for faster delivery.
32
  * [Assets Pull addon](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=assets%2Baddon#addons) - Serve your CSS, JS and fonts via CloudFront or another CDN
33
  * [WooCommerce integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=woocommerce%2Baddon#integrations)
34
  * [Easy Digital Downloads integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=edd%2Baddon#integrations)
35
+ * Priority email support
36
 
37
  [Compare pro vs free &rarr;](https://deliciousbrains.com/wp-offload-media/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
38
 
81
 
82
  == Changelog ==
83
 
84
+ = WP Offload Media Lite 2.4 - 2020-07-14 =
85
+ * [Release Summary Blog Post](https://deliciousbrains.com/wp-offload-media-2-4-released/?utm_campaign=changelogs&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
86
+ * New: Setting to choose a Delivery Provider (i.e. S3, CloudFront, another CDN)
87
+ * New: Support for Block All Public Access setting on S3 buckets
88
+ * New: Raw S3 URLs use bucket in domain rather than path where possible as per changes required by AWS
89
+ * New: Raw S3 URLs use dot rather than dash between s3 and region name as per changes required by AWS
90
+ * New: Added S3 regions for Africa (Cape Town), Asia Pacific (Hong Kong), EU (Milan), EU (Stockholm), and Middle East (Bahrain)
91
+ * New: Added GCS regions for Salt Lake City, Las Vegas, Zürich, Osaka, Seoul, EUR4 (dual-region), and NAM4 (dual-region)
92
+ * Improvement: Updated AWS PHP SDK to v3.133.40
93
+ * Improvement: Updated Google Cloud Storage SDK to v1.18.0
94
+ * Improvement: S3 regions for China no longer hidden (configuration via AWS Console still required)
95
+ * Bug fix: Private images not showing in grid mode Media page overlay
96
+ * Bug fix: Public image thumbnails not showing in grid mode Media page when original is private
97
+ * Bug fix: URL rewriting sometimes fails for sites hosted on Windows
98
+ * Bug fix: URL rewrite fails for image when original upload has size in file name
99
+ * Bug fix: External URLs rewritten to local URLs when they shouldn't
100
+ * Bug fix: StreamWrappers don't work with private buckets
101
+ * Bug fix: Database error when inserting media library item and using HyperDB
102
+ * Bug fix: S3 bucket link in settings no longer goes direct to bucket contents
103
+ * Bug fix: New uploads slow with very large Media Library
104
+ * Bug fix: Migration to custom table very slow with large postmeta tables
105
+ * Bug fix: Signed GCS URLs have incorrect expires value
106
+ * Bug fix: The use-server-roles AS3CF_SETTINGS value is not properly reflected in Diagnostic Info
107
+ * Bug fix: Unknown column '2019/12/some-file-name.pdf' in 'where clause' when using managed MySQL on DigitalOcean
108
+ * Bug fix: WordPress database error Expression #1 of ORDER BY clause is not in SELECT list when using MySQL8
109
+ * Bug fix: WordPress forces HTTP in Edit Media page if site is not HTTPS, breaking remote URLs that require HTTPS
110
+ * Tested: WordPress 5.5
111
+
112
  = WP Offload Media Lite 2.3.2 - 2019-12-09 =
113
  * Improvement: Reduced database queries when external object cache available
114
  * Bug fix: Uncaught Error: Call to undefined function DeliciousBrains\WP_Offload_Media\Gcp\GuzzleHttp\choose_handler()
vendor/Aws3/Aws/AbstractConfigurationProvider.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
6
+ /**
7
+ * A configuration provider is a function that returns a promise that is
8
+ * fulfilled with a configuration object. This class provides base functionality
9
+ * usable by specific configuration provider implementations
10
+ */
11
+ abstract class AbstractConfigurationProvider
12
+ {
13
+ const ENV_PROFILE = 'AWS_PROFILE';
14
+ const ENV_CONFIG_FILE = 'AWS_CONFIG_FILE';
15
+ public static $cacheKey;
16
+ protected static $interfaceClass;
17
+ protected static $exceptionClass;
18
+ /**
19
+ * Wraps a config provider and saves provided configuration in an
20
+ * instance of Aws\CacheInterface. Forwards calls when no config found
21
+ * in cache and updates cache with the results.
22
+ *
23
+ * @param callable $provider Configuration provider function to wrap
24
+ * @param CacheInterface $cache Cache to store configuration
25
+ * @param string|null $cacheKey (optional) Cache key to use
26
+ *
27
+ * @return callable
28
+ */
29
+ public static function cache(callable $provider, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface $cache, $cacheKey = null)
30
+ {
31
+ $cacheKey = $cacheKey ?: static::$cacheKey;
32
+ return function () use($provider, $cache, $cacheKey) {
33
+ $found = $cache->get($cacheKey);
34
+ if ($found instanceof static::$interfaceClass) {
35
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for($found);
36
+ }
37
+ return $provider()->then(function ($config) use($cache, $cacheKey) {
38
+ $cache->set($cacheKey, $config);
39
+ return $config;
40
+ });
41
+ };
42
+ }
43
+ /**
44
+ * Creates an aggregate configuration provider that invokes the provided
45
+ * variadic providers one after the other until a provider returns
46
+ * configuration.
47
+ *
48
+ * @return callable
49
+ */
50
+ public static function chain()
51
+ {
52
+ $links = func_get_args();
53
+ if (empty($links)) {
54
+ throw new \InvalidArgumentException('No providers in chain');
55
+ }
56
+ return function () use($links) {
57
+ /** @var callable $parent */
58
+ $parent = array_shift($links);
59
+ $promise = $parent();
60
+ while ($next = array_shift($links)) {
61
+ $promise = $promise->otherwise($next);
62
+ }
63
+ return $promise;
64
+ };
65
+ }
66
+ /**
67
+ * Gets the environment's HOME directory if available.
68
+ *
69
+ * @return null|string
70
+ */
71
+ protected static function getHomeDir()
72
+ {
73
+ // On Linux/Unix-like systems, use the HOME environment variable
74
+ if ($homeDir = getenv('HOME')) {
75
+ return $homeDir;
76
+ }
77
+ // Get the HOMEDRIVE and HOMEPATH values for Windows hosts
78
+ $homeDrive = getenv('HOMEDRIVE');
79
+ $homePath = getenv('HOMEPATH');
80
+ return $homeDrive && $homePath ? $homeDrive . $homePath : null;
81
+ }
82
+ /**
83
+ * Gets default config file location from environment, falling back to aws
84
+ * default location
85
+ *
86
+ * @return string
87
+ */
88
+ protected static function getDefaultConfigFilename()
89
+ {
90
+ if ($filename = getenv(self::ENV_CONFIG_FILE)) {
91
+ return $filename;
92
+ }
93
+ return self::getHomeDir() . '/.aws/config';
94
+ }
95
+ /**
96
+ * Wraps a config provider and caches previously provided configuration.
97
+ *
98
+ * @param callable $provider Config provider function to wrap.
99
+ *
100
+ * @return callable
101
+ */
102
+ public static function memoize(callable $provider)
103
+ {
104
+ return function () use($provider) {
105
+ static $result;
106
+ static $isConstant;
107
+ // Constant config will be returned constantly.
108
+ if ($isConstant) {
109
+ return $result;
110
+ }
111
+ // Create the initial promise that will be used as the cached value
112
+ if (null === $result) {
113
+ $result = $provider();
114
+ }
115
+ // Return config and set flag that provider is already set
116
+ return $result->then(function ($config) use(&$isConstant) {
117
+ $isConstant = true;
118
+ return $config;
119
+ });
120
+ };
121
+ }
122
+ /**
123
+ * Reject promise with standardized exception.
124
+ *
125
+ * @param $msg
126
+ * @return Promise\RejectedPromise
127
+ */
128
+ protected static function reject($msg)
129
+ {
130
+ $exceptionClass = static::$exceptionClass;
131
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\RejectedPromise(new $exceptionClass($msg));
132
+ }
133
+ }
vendor/Aws3/Aws/Api/ApiProvider.php CHANGED
@@ -148,7 +148,7 @@ class ApiProvider
148
  return array_values(array_unique($this->manifest[$service]['versions']));
149
  }
150
  /**
151
- * Execute the the provider.
152
  *
153
  * @param string $type Type of data ('api', 'waiter', 'paginator').
154
  * @param string $service Service name.
148
  return array_values(array_unique($this->manifest[$service]['versions']));
149
  }
150
  /**
151
+ * Execute the provider.
152
  *
153
  * @param string $type Type of data ('api', 'waiter', 'paginator').
154
  * @param string $service Service name.
vendor/Aws3/Aws/Api/DocModel.php CHANGED
@@ -94,7 +94,7 @@ class DocModel
94
  if (!$content) {
95
  return '';
96
  }
97
- $tidy = new \Tidy();
98
  $tidy->parseString($content, ['indent' => true, 'doctype' => 'omit', 'output-html' => true, 'show-body-only' => true, 'drop-empty-paras' => true, 'drop-font-tags' => true, 'drop-proprietary-attributes' => true, 'hide-comments' => true, 'logical-emphasis' => true]);
99
  $tidy->cleanRepair();
100
  return (string) $content;
94
  if (!$content) {
95
  return '';
96
  }
97
+ $tidy = new \tidy();
98
  $tidy->parseString($content, ['indent' => true, 'doctype' => 'omit', 'output-html' => true, 'show-body-only' => true, 'drop-empty-paras' => true, 'drop-font-tags' => true, 'drop-proprietary-attributes' => true, 'hide-comments' => true, 'logical-emphasis' => true]);
99
  $tidy->cleanRepair();
100
  return (string) $content;
vendor/Aws3/Aws/Api/ErrorParser/AbstractErrorParser.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\MetadataParserTrait;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\PayloadParserTrait;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
10
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
11
+ abstract class AbstractErrorParser
12
+ {
13
+ use MetadataParserTrait;
14
+ use PayloadParserTrait;
15
+ /**
16
+ * @var Service
17
+ */
18
+ protected $api;
19
+ /**
20
+ * @param Service $api
21
+ */
22
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api = null)
23
+ {
24
+ $this->api = $api;
25
+ }
26
+ protected abstract function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member);
27
+ protected function extractPayload(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
28
+ {
29
+ if ($member instanceof StructureShape) {
30
+ // Structure members parse top-level data into a specific key.
31
+ return $this->payload($response, $member);
32
+ } else {
33
+ // Streaming data is just the stream from the response body.
34
+ return $response->getBody();
35
+ }
36
+ }
37
+ protected function populateShape(array &$data, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command = null)
38
+ {
39
+ $data['body'] = [];
40
+ if (!empty($command) && !empty($this->api)) {
41
+ // If modeled error code is indicated, check for known error shape
42
+ if (!empty($data['code'])) {
43
+ $errors = $this->api->getOperation($command->getName())->getErrors();
44
+ foreach ($errors as $key => $error) {
45
+ // If error code matches a known error shape, populate the body
46
+ if ($data['code'] == $error['name'] && $error instanceof StructureShape) {
47
+ $modeledError = $error;
48
+ $data['body'] = $this->extractPayload($modeledError, $response);
49
+ foreach ($error->getMembers() as $name => $member) {
50
+ switch ($member['location']) {
51
+ case 'header':
52
+ $this->extractHeader($name, $member, $response, $data['body']);
53
+ break;
54
+ case 'headers':
55
+ $this->extractHeaders($name, $member, $response, $data['body']);
56
+ break;
57
+ case 'statusCode':
58
+ $this->extractStatus($name, $response, $data['body']);
59
+ break;
60
+ }
61
+ }
62
+ break;
63
+ }
64
+ }
65
+ }
66
+ }
67
+ return $data;
68
+ }
69
+ }
vendor/Aws3/Aws/Api/ErrorParser/JsonParserTrait.php CHANGED
@@ -3,6 +3,7 @@
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
4
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\PayloadParserTrait;
 
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
7
  /**
8
  * Provides basic JSON error parsing functionality.
@@ -15,4 +16,11 @@ trait JsonParserTrait
15
  $code = (string) $response->getStatusCode();
16
  return ['request_id' => (string) $response->getHeaderLine('x-amzn-requestid'), 'code' => null, 'message' => null, 'type' => $code[0] == '4' ? 'client' : 'server', 'parsed' => $this->parseJson($response->getBody(), $response)];
17
  }
 
 
 
 
 
 
 
18
  }
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
4
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\PayloadParserTrait;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
8
  /**
9
  * Provides basic JSON error parsing functionality.
16
  $code = (string) $response->getStatusCode();
17
  return ['request_id' => (string) $response->getHeaderLine('x-amzn-requestid'), 'code' => null, 'message' => null, 'type' => $code[0] == '4' ? 'client' : 'server', 'parsed' => $this->parseJson($response->getBody(), $response)];
18
  }
19
+ protected function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member)
20
+ {
21
+ $jsonBody = $this->parseJson($response->getBody(), $response);
22
+ if ($jsonBody) {
23
+ return $this->parser->parse($member, $jsonBody);
24
+ }
25
+ }
26
  }
vendor/Aws3/Aws/Api/ErrorParser/JsonRpcErrorParser.php CHANGED
@@ -2,14 +2,23 @@
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
4
 
 
 
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
6
  /**
7
  * Parsers JSON-RPC errors.
8
  */
9
- class JsonRpcErrorParser
10
  {
11
  use JsonParserTrait;
12
- public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
 
 
 
 
 
 
13
  {
14
  $data = $this->genericHandler($response);
15
  // Make the casing consistent across services.
@@ -21,6 +30,7 @@ class JsonRpcErrorParser
21
  $data['code'] = isset($parts[1]) ? $parts[1] : $parts[0];
22
  $data['message'] = isset($data['parsed']['message']) ? $data['parsed']['message'] : null;
23
  }
 
24
  return $data;
25
  }
26
  }
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
9
  /**
10
  * Parsers JSON-RPC errors.
11
  */
12
+ class JsonRpcErrorParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser\AbstractErrorParser
13
  {
14
  use JsonParserTrait;
15
+ private $parser;
16
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api = null, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser $parser = null)
17
+ {
18
+ parent::__construct($api);
19
+ $this->parser = $parser ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser();
20
+ }
21
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command = null)
22
  {
23
  $data = $this->genericHandler($response);
24
  // Make the casing consistent across services.
30
  $data['code'] = isset($parts[1]) ? $parts[1] : $parts[0];
31
  $data['message'] = isset($data['parsed']['message']) ? $data['parsed']['message'] : null;
32
  }
33
+ $this->populateShape($data, $response, $command);
34
  return $data;
35
  }
36
  }
vendor/Aws3/Aws/Api/ErrorParser/RestJsonErrorParser.php CHANGED
@@ -2,14 +2,24 @@
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
4
 
 
 
 
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
6
  /**
7
  * Parses JSON-REST errors.
8
  */
9
- class RestJsonErrorParser
10
  {
11
  use JsonParserTrait;
12
- public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
 
 
 
 
 
 
13
  {
14
  $data = $this->genericHandler($response);
15
  // Merge in error data from the JSON body
@@ -25,6 +35,9 @@ class RestJsonErrorParser
25
  $colon = strpos($code, ':');
26
  $data['code'] = $colon ? substr($code, 0, $colon) : $code;
27
  }
 
 
 
28
  return $data;
29
  }
30
  }
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
10
  /**
11
  * Parses JSON-REST errors.
12
  */
13
+ class RestJsonErrorParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser\AbstractErrorParser
14
  {
15
  use JsonParserTrait;
16
+ private $parser;
17
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api = null, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser $parser = null)
18
+ {
19
+ parent::__construct($api);
20
+ $this->parser = $parser ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser();
21
+ }
22
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command = null)
23
  {
24
  $data = $this->genericHandler($response);
25
  // Merge in error data from the JSON body
35
  $colon = strpos($code, ':');
36
  $data['code'] = $colon ? substr($code, 0, $colon) : $code;
37
  }
38
+ // Retrieve error message directly
39
+ $data['message'] = isset($data['parsed']['message']) ? $data['parsed']['message'] : (isset($data['parsed']['Message']) ? $data['parsed']['Message'] : null);
40
+ $this->populateShape($data, $response, $command);
41
  return $data;
42
  }
43
  }
vendor/Aws3/Aws/Api/ErrorParser/XmlErrorParser.php CHANGED
@@ -3,14 +3,24 @@
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
4
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\PayloadParserTrait;
 
 
 
 
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
7
  /**
8
  * Parses XML errors.
9
  */
10
- class XmlErrorParser
11
  {
12
  use PayloadParserTrait;
13
- public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
 
 
 
 
 
 
14
  {
15
  $code = (string) $response->getStatusCode();
16
  $data = ['type' => $code[0] == '4' ? 'client' : 'server', 'request_id' => null, 'code' => null, 'message' => null, 'parsed' => null];
@@ -20,6 +30,7 @@ class XmlErrorParser
20
  } else {
21
  $this->parseHeaders($response, $data);
22
  }
 
23
  return $data;
24
  }
25
  private function parseHeaders(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, array &$data)
@@ -36,15 +47,7 @@ class XmlErrorParser
36
  private function parseBody(\SimpleXMLElement $body, array &$data)
37
  {
38
  $data['parsed'] = $body;
39
- $namespaces = $body->getDocNamespaces();
40
- if (!isset($namespaces[''])) {
41
- $prefix = '';
42
- } else {
43
- // Account for the default namespace being defined and PHP not
44
- // being able to handle it :(.
45
- $body->registerXPathNamespace('ns', $namespaces['']);
46
- $prefix = 'ns:';
47
- }
48
  if ($tempXml = $body->xpath("//{$prefix}Code[1]")) {
49
  $data['code'] = (string) $tempXml[0];
50
  }
@@ -52,11 +55,28 @@ class XmlErrorParser
52
  $data['message'] = (string) $tempXml[0];
53
  }
54
  $tempXml = $body->xpath("//{$prefix}RequestId[1]");
55
- if (empty($tempXml)) {
56
- $tempXml = $body->xpath("//{$prefix}RequestID[1]");
57
- }
58
  if (isset($tempXml[0])) {
59
  $data['request_id'] = (string) $tempXml[0];
60
  }
61
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  }
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
4
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\PayloadParserTrait;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\XmlParser;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
10
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
11
  /**
12
  * Parses XML errors.
13
  */
14
+ class XmlErrorParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser\AbstractErrorParser
15
  {
16
  use PayloadParserTrait;
17
+ protected $parser;
18
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api = null, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\XmlParser $parser = null)
19
+ {
20
+ parent::__construct($api);
21
+ $this->parser = $parser ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\XmlParser();
22
+ }
23
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command = null)
24
  {
25
  $code = (string) $response->getStatusCode();
26
  $data = ['type' => $code[0] == '4' ? 'client' : 'server', 'request_id' => null, 'code' => null, 'message' => null, 'parsed' => null];
30
  } else {
31
  $this->parseHeaders($response, $data);
32
  }
33
+ $this->populateShape($data, $response, $command);
34
  return $data;
35
  }
36
  private function parseHeaders(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, array &$data)
47
  private function parseBody(\SimpleXMLElement $body, array &$data)
48
  {
49
  $data['parsed'] = $body;
50
+ $prefix = $this->registerNamespacePrefix($body);
 
 
 
 
 
 
 
 
51
  if ($tempXml = $body->xpath("//{$prefix}Code[1]")) {
52
  $data['code'] = (string) $tempXml[0];
53
  }
55
  $data['message'] = (string) $tempXml[0];
56
  }
57
  $tempXml = $body->xpath("//{$prefix}RequestId[1]");
 
 
 
58
  if (isset($tempXml[0])) {
59
  $data['request_id'] = (string) $tempXml[0];
60
  }
61
  }
62
+ protected function registerNamespacePrefix(\SimpleXMLElement $element)
63
+ {
64
+ $namespaces = $element->getDocNamespaces();
65
+ if (!isset($namespaces[''])) {
66
+ return '';
67
+ }
68
+ // Account for the default namespace being defined and PHP not
69
+ // being able to handle it :(.
70
+ $element->registerXPathNamespace('ns', $namespaces['']);
71
+ return 'ns:';
72
+ }
73
+ protected function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member)
74
+ {
75
+ $xmlBody = $this->parseXml($response->getBody(), $response);
76
+ $prefix = $this->registerNamespacePrefix($xmlBody);
77
+ $errorBody = $xmlBody->xpath("//{$prefix}Error");
78
+ if (is_array($errorBody) && !empty($errorBody[0])) {
79
+ return $this->parser->parse($member, $errorBody[0]);
80
+ }
81
+ }
82
  }
vendor/Aws3/Aws/Api/Parser/AbstractRestParser.php CHANGED
@@ -99,10 +99,20 @@ abstract class AbstractRestParser extends \DeliciousBrains\WP_Offload_Media\Aws3
99
  return;
100
  }
101
  case 'string':
102
- if ($shape['jsonvalue']) {
103
- $value = $this->parseJson(base64_decode($value), $response);
 
 
 
 
 
 
 
 
 
 
 
104
  }
105
- break;
106
  }
107
  $result[$name] = $value;
108
  }
99
  return;
100
  }
101
  case 'string':
102
+ try {
103
+ if ($shape['jsonvalue']) {
104
+ $value = $this->parseJson(base64_decode($value), $response);
105
+ }
106
+ // If value is not set, do not add to output structure.
107
+ if (!isset($value)) {
108
+ return;
109
+ }
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
  $result[$name] = $value;
118
  }
vendor/Aws3/Aws/Api/Parser/DecodingEventStreamIterator.php CHANGED
@@ -29,7 +29,7 @@ class DecodingEventStreamIterator implements \Iterator
29
  private $currentEvent;
30
  /** @var int Current in-order event key. */
31
  private $key;
32
- /** @var resource|HashContext CRC32 hash context for event validation */
33
  private $hashContext;
34
  /** @var int $currentPosition */
35
  private $currentPosition;
29
  private $currentEvent;
30
  /** @var int Current in-order event key. */
31
  private $key;
32
+ /** @var resource|\HashContext CRC32 hash context for event validation */
33
  private $hashContext;
34
  /** @var int $currentPosition */
35
  private $currentPosition;
vendor/Aws3/Aws/Api/Parser/Exception/ParserException.php CHANGED
@@ -5,15 +5,38 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\Exception;
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface;
 
8
  class ParserException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface
9
  {
10
  use HasMonitoringEventsTrait;
 
 
11
  private $response;
12
  public function __construct($message = '', $code = 0, $previous = null, array $context = [])
13
  {
 
 
14
  $this->response = isset($context['response']) ? $context['response'] : null;
15
  parent::__construct($message, $code, $previous);
16
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  /**
18
  * Get the received HTTP response if any.
19
  *
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
9
  class ParserException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface
10
  {
11
  use HasMonitoringEventsTrait;
12
+ private $errorCode;
13
+ private $requestId;
14
  private $response;
15
  public function __construct($message = '', $code = 0, $previous = null, array $context = [])
16
  {
17
+ $this->errorCode = isset($context['error_code']) ? $context['error_code'] : null;
18
+ $this->requestId = isset($context['request_id']) ? $context['request_id'] : null;
19
  $this->response = isset($context['response']) ? $context['response'] : null;
20
  parent::__construct($message, $code, $previous);
21
  }
22
+ /**
23
+ * Get the error code, if any.
24
+ *
25
+ * @return string|null
26
+ */
27
+ public function getErrorCode()
28
+ {
29
+ return $this->errorCode;
30
+ }
31
+ /**
32
+ * Get the request ID, if any.
33
+ *
34
+ * @return string|null
35
+ */
36
+ public function getRequestId()
37
+ {
38
+ return $this->requestId;
39
+ }
40
  /**
41
  * Get the received HTTP response if any.
42
  *
vendor/Aws3/Aws/Api/Parser/MetadataParserTrait.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
8
+ trait MetadataParserTrait
9
+ {
10
+ /**
11
+ * Extract a single header from the response into the result.
12
+ */
13
+ protected function extractHeader($name, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, &$result)
14
+ {
15
+ $value = $response->getHeaderLine($shape['locationName'] ?: $name);
16
+ switch ($shape->getType()) {
17
+ case 'float':
18
+ case 'double':
19
+ $value = (double) $value;
20
+ break;
21
+ case 'long':
22
+ $value = (int) $value;
23
+ break;
24
+ case 'boolean':
25
+ $value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
26
+ break;
27
+ case 'blob':
28
+ $value = base64_decode($value);
29
+ break;
30
+ case 'timestamp':
31
+ try {
32
+ if (!empty($shape['timestampFormat']) && $shape['timestampFormat'] === 'unixTimestamp') {
33
+ $value = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult::fromEpoch($value);
34
+ }
35
+ $value = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult($value);
36
+ break;
37
+ } catch (\Exception $e) {
38
+ // If the value cannot be parsed, then do not add it to the
39
+ // output structure.
40
+ return;
41
+ }
42
+ case 'string':
43
+ if ($shape['jsonvalue']) {
44
+ $value = $this->parseJson(base64_decode($value), $response);
45
+ }
46
+ break;
47
+ }
48
+ $result[$name] = $value;
49
+ }
50
+ /**
51
+ * Extract a map of headers with an optional prefix from the response.
52
+ */
53
+ protected function extractHeaders($name, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, &$result)
54
+ {
55
+ // Check if the headers are prefixed by a location name
56
+ $result[$name] = [];
57
+ $prefix = $shape['locationName'];
58
+ $prefixLen = strlen($prefix);
59
+ foreach ($response->getHeaders() as $k => $values) {
60
+ if (!$prefixLen) {
61
+ $result[$name][$k] = implode(', ', $values);
62
+ } elseif (stripos($k, $prefix) === 0) {
63
+ $result[$name][substr($k, $prefixLen)] = implode(', ', $values);
64
+ }
65
+ }
66
+ }
67
+ /**
68
+ * Places the status code of the response into the result array.
69
+ */
70
+ protected function extractStatus($name, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, array &$result)
71
+ {
72
+ $result[$name] = (int) $response->getStatusCode();
73
+ }
74
+ }
vendor/Aws3/Aws/Api/Parser/PayloadParserTrait.php CHANGED
@@ -28,7 +28,7 @@ trait PayloadParserTrait
28
  *
29
  * @return \SimpleXMLElement
30
  */
31
- private function parseXml($xml, $response)
32
  {
33
  $priorSetting = libxml_use_internal_errors(true);
34
  try {
28
  *
29
  * @return \SimpleXMLElement
30
  */
31
+ protected function parseXml($xml, $response)
32
  {
33
  $priorSetting = libxml_use_internal_errors(true);
34
  try {
vendor/Aws3/Aws/Api/Parser/XmlParser.php CHANGED
@@ -33,6 +33,11 @@ class XmlParser
33
  $node = $this->memberKey($member, $name);
34
  if (isset($value->{$node})) {
35
  $target[$name] = $this->dispatch($member, $value->{$node});
 
 
 
 
 
36
  }
37
  }
38
  return $target;
@@ -99,4 +104,15 @@ class XmlParser
99
  }
100
  return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult($value);
101
  }
 
 
 
 
 
 
 
 
 
 
 
102
  }
33
  $node = $this->memberKey($member, $name);
34
  if (isset($value->{$node})) {
35
  $target[$name] = $this->dispatch($member, $value->{$node});
36
+ } else {
37
+ $memberShape = $shape->getMember($name);
38
+ if (!empty($memberShape['xmlAttribute'])) {
39
+ $target[$name] = $this->parse_xml_attribute($shape, $memberShape, $value);
40
+ }
41
  }
42
  }
43
  return $target;
104
  }
105
  return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult($value);
106
  }
107
+ private function parse_xml_attribute(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $memberShape, $value)
108
+ {
109
+ $namespace = $shape['xmlNamespace']['uri'] ? $shape['xmlNamespace']['uri'] : '';
110
+ $prefix = $shape['xmlNamespace']['prefix'] ? $shape['xmlNamespace']['prefix'] : '';
111
+ if (!empty($prefix)) {
112
+ $prefix .= ':';
113
+ }
114
+ $key = str_replace($prefix, '', $memberShape['locationName']);
115
+ $attributes = $value->attributes($namespace);
116
+ return isset($attributes[$key]) ? (string) $attributes[$key] : null;
117
+ }
118
  }
vendor/Aws3/Aws/Api/Serializer/RestJsonSerializer.php CHANGED
@@ -22,7 +22,7 @@ class RestJsonSerializer extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\
22
  public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, $endpoint, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody $jsonFormatter = null)
23
  {
24
  parent::__construct($api, $endpoint);
25
- $this->contentType = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody::getContentType($api);
26
  $this->jsonFormatter = $jsonFormatter ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody($api);
27
  }
28
  protected function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member, array $value, array &$opts)
22
  public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, $endpoint, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody $jsonFormatter = null)
23
  {
24
  parent::__construct($api, $endpoint);
25
+ $this->contentType = 'application/json';
26
  $this->jsonFormatter = $jsonFormatter ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody($api);
27
  }
28
  protected function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member, array $value, array &$opts)
vendor/Aws3/Aws/Api/Serializer/RestSerializer.php CHANGED
@@ -160,6 +160,11 @@ abstract class RestSerializer
160
  $append = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\build_query($opts['query']);
161
  $relative .= strpos($relative, '?') ? "&{$append}" : "?{$append}";
162
  }
 
 
 
 
 
163
  // Expand path place holders using Amazon's slightly different URI
164
  // template syntax.
165
  return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\UriResolver::resolve($this->endpoint, new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri($relative));
160
  $append = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\build_query($opts['query']);
161
  $relative .= strpos($relative, '?') ? "&{$append}" : "?{$append}";
162
  }
163
+ // If endpoint has path, remove leading '/' to preserve URI resolution.
164
+ $path = $this->endpoint->getPath();
165
+ if ($path && $relative[0] === '/') {
166
+ $relative = substr($relative, 1);
167
+ }
168
  // Expand path place holders using Amazon's slightly different URI
169
  // template syntax.
170
  return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\UriResolver::resolve($this->endpoint, new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri($relative));
vendor/Aws3/Aws/Api/Serializer/XmlBody.php CHANGED
@@ -61,7 +61,7 @@ class XmlBody
61
  private function defaultShape(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
62
  {
63
  $this->startElement($shape, $name, $xml);
64
- $xml->writeRaw($value);
65
  $xml->endElement();
66
  }
67
  private function add_structure(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $shape, $name, array $value, \XMLWriter $xml)
61
  private function defaultShape(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
62
  {
63
  $this->startElement($shape, $name, $xml);
64
+ $xml->text($value);
65
  $xml->endElement();
66
  }
67
  private function add_structure(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $shape, $name, array $value, \XMLWriter $xml)
vendor/Aws3/Aws/Api/Service.php CHANGED
@@ -67,16 +67,18 @@ class Service extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\AbstractMod
67
  /**
68
  * Creates an error parser for the given protocol.
69
  *
 
 
70
  * @param string $protocol Protocol to parse (e.g., query, json, etc.)
71
  *
72
  * @return callable
73
  * @throws \UnexpectedValueException
74
  */
75
- public static function createErrorParser($protocol)
76
  {
77
  static $mapping = ['json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\JsonRpcErrorParser', 'query' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser', 'rest-json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\RestJsonErrorParser', 'rest-xml' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser', 'ec2' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser'];
78
  if (isset($mapping[$protocol])) {
79
- return new $mapping[$protocol]();
80
  }
81
  throw new \UnexpectedValueException("Unknown protocol: {$protocol}");
82
  }
@@ -224,6 +226,22 @@ class Service extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\AbstractMod
224
  }
225
  return $result;
226
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  /**
228
  * Get all of the service metadata or a specific metadata key value.
229
  *
67
  /**
68
  * Creates an error parser for the given protocol.
69
  *
70
+ * Redundant method signature to preserve backwards compatibility.
71
+ *
72
  * @param string $protocol Protocol to parse (e.g., query, json, etc.)
73
  *
74
  * @return callable
75
  * @throws \UnexpectedValueException
76
  */
77
+ public static function createErrorParser($protocol, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api = null)
78
  {
79
  static $mapping = ['json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\JsonRpcErrorParser', 'query' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser', 'rest-json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\RestJsonErrorParser', 'rest-xml' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser', 'ec2' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser'];
80
  if (isset($mapping[$protocol])) {
81
+ return new $mapping[$protocol]($api);
82
  }
83
  throw new \UnexpectedValueException("Unknown protocol: {$protocol}");
84
  }
226
  }
227
  return $result;
228
  }
229
+ /**
230
+ * Get all of the error shapes of the service
231
+ *
232
+ * @return array
233
+ */
234
+ public function getErrorShapes()
235
+ {
236
+ $result = [];
237
+ foreach ($this->definition['shapes'] as $name => $definition) {
238
+ if (!empty($definition['exception'])) {
239
+ $definition['name'] = $name;
240
+ $result[] = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape($definition, $this->getShapeMap());
241
+ }
242
+ }
243
+ return $result;
244
+ }
245
  /**
246
  * Get all of the service metadata or a specific metadata key value.
247
  *
vendor/Aws3/Aws/Api/ShapeMap.php CHANGED
@@ -47,7 +47,9 @@ class ShapeMap
47
  }
48
  $definition = $shapeRef + $this->definitions[$shape];
49
  $definition['name'] = $definition['shape'];
50
- unset($definition['shape']);
 
 
51
  $result = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape::create($definition, $this);
52
  if ($isSimple) {
53
  $this->simple[$shape] = $result;
47
  }
48
  $definition = $shapeRef + $this->definitions[$shape];
49
  $definition['name'] = $definition['shape'];
50
+ if (isset($definition['shape'])) {
51
+ unset($definition['shape']);
52
+ }
53
  $result = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape::create($definition, $this);
54
  if ($isSimple) {
55
  $this->simple[$shape] = $result;
vendor/Aws3/Aws/Api/Validator.php CHANGED
@@ -164,7 +164,17 @@ class Validator
164
  }
165
  private function checkAssociativeArray($value)
166
  {
167
- if (!is_array($value) || isset($value[0])) {
 
 
 
 
 
 
 
 
 
 
168
  $this->addError('must be an associative array. Found ' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\describe_type($value));
169
  return false;
170
  }
164
  }
165
  private function checkAssociativeArray($value)
166
  {
167
+ $isAssociative = false;
168
+ if (is_array($value)) {
169
+ $expectedIndex = 0;
170
+ $key = key($value);
171
+ do {
172
+ $isAssociative = $key !== $expectedIndex++;
173
+ next($value);
174
+ $key = key($value);
175
+ } while (!$isAssociative && null !== $key);
176
+ }
177
+ if (!$isAssociative) {
178
  $this->addError('must be an associative array. Found ' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\describe_type($value));
179
  return false;
180
  }
vendor/Aws3/Aws/Arn/AccessPointArn.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException;
6
+ /**
7
+ * @internal
8
+ */
9
+ class AccessPointArn extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Arn implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface
10
+ {
11
+ use ResourceTypeAndIdTrait;
12
+ /**
13
+ * AccessPointArn constructor
14
+ *
15
+ * @param $data
16
+ */
17
+ public function __construct($data)
18
+ {
19
+ parent::__construct($data);
20
+ static::validate($this->data);
21
+ }
22
+ public static function parse($string)
23
+ {
24
+ $data = parent::parse($string);
25
+ return self::parseResourceTypeAndId($data);
26
+ }
27
+ /**
28
+ * Validation specific to AccessPointArn
29
+ *
30
+ * @param array $data
31
+ */
32
+ protected static function validate(array $data)
33
+ {
34
+ if (empty($data['region'])) {
35
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 4th component of an access point ARN" . " represents the region and must not be empty.");
36
+ }
37
+ if (empty($data['account_id'])) {
38
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 5th component of an access point ARN" . " represents the account ID and must not be empty.");
39
+ }
40
+ if (!self::isValidHostLabel($data['account_id'])) {
41
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The account ID in an access point ARN" . " must be a valid host label value.");
42
+ }
43
+ if ($data['resource_type'] !== 'accesspoint') {
44
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 6th component of an access point ARN" . " represents the resource type and must be 'accesspoint'.");
45
+ }
46
+ if (empty($data['resource_id'])) {
47
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 7th component of an access point ARN" . " represents the resource ID and must not be empty.");
48
+ }
49
+ if (strpos($data['resource_id'], ':') !== false) {
50
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The resource ID component of an access" . " point ARN must not contain additional components" . " (delimited by ':').");
51
+ }
52
+ if (!self::isValidHostLabel($data['resource_id'])) {
53
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The resource ID in an access point ARN" . " must be a valid host label value.");
54
+ }
55
+ }
56
+ protected static function isValidHostLabel($string)
57
+ {
58
+ $length = strlen($string);
59
+ if ($length < 1 || $length > 63) {
60
+ return false;
61
+ }
62
+ if ($value = preg_match("/^[a-zA-Z0-9-]+\$/", $string)) {
63
+ return true;
64
+ }
65
+ return false;
66
+ }
67
+ }
vendor/Aws3/Aws/Arn/Arn.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException;
6
+ /**
7
+ * Amazon Resource Names (ARNs) uniquely identify AWS resources. The Arn class
8
+ * parses and stores a generic ARN object representation that can apply to any
9
+ * service resource.
10
+ *
11
+ * @internal
12
+ */
13
+ class Arn implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface
14
+ {
15
+ protected $data;
16
+ protected $string;
17
+ public static function parse($string)
18
+ {
19
+ $data = ['arn' => null, 'partition' => null, 'service' => null, 'region' => null, 'account_id' => null, 'resource' => null];
20
+ $length = strlen($string);
21
+ $lastDelim = 0;
22
+ $numComponents = 0;
23
+ for ($i = 0; $i < $length; $i++) {
24
+ if ($numComponents < 5 && $string[$i] === ':') {
25
+ // Split components between delimiters
26
+ $data[key($data)] = substr($string, $lastDelim, $i - $lastDelim);
27
+ // Do not include delimiter character itself
28
+ $lastDelim = $i + 1;
29
+ next($data);
30
+ $numComponents++;
31
+ }
32
+ if ($i === $length - 1) {
33
+ // Put the remainder in the last component.
34
+ if (in_array($numComponents, [5])) {
35
+ $data['resource'] = substr($string, $lastDelim);
36
+ } else {
37
+ // If there are < 5 components, put remainder in current
38
+ // component.
39
+ $data[key($data)] = substr($string, $lastDelim);
40
+ }
41
+ }
42
+ }
43
+ return $data;
44
+ }
45
+ public function __construct($data)
46
+ {
47
+ if (is_array($data)) {
48
+ $this->data = $data;
49
+ } elseif (is_string($data)) {
50
+ $this->data = static::parse($data);
51
+ } else {
52
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException('Constructor accepts a string or an' . ' array as an argument.');
53
+ }
54
+ self::validate($this->data);
55
+ }
56
+ public function __toString()
57
+ {
58
+ if (!isset($this->string)) {
59
+ $components = [$this->getPrefix(), $this->getPartition(), $this->getService(), $this->getRegion(), $this->getAccountId(), $this->getResource()];
60
+ $this->string = implode(':', $components);
61
+ }
62
+ return $this->string;
63
+ }
64
+ public function getPrefix()
65
+ {
66
+ return $this->data['arn'];
67
+ }
68
+ public function getPartition()
69
+ {
70
+ return $this->data['partition'];
71
+ }
72
+ public function getService()
73
+ {
74
+ return $this->data['service'];
75
+ }
76
+ public function getRegion()
77
+ {
78
+ return $this->data['region'];
79
+ }
80
+ public function getAccountId()
81
+ {
82
+ return $this->data['account_id'];
83
+ }
84
+ public function getResource()
85
+ {
86
+ return $this->data['resource'];
87
+ }
88
+ public function toArray()
89
+ {
90
+ return $this->data;
91
+ }
92
+ /**
93
+ * Minimally restrictive generic ARN validation
94
+ *
95
+ * @param array $data
96
+ */
97
+ protected static function validate(array $data)
98
+ {
99
+ if ($data['arn'] !== 'arn') {
100
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 1st component of an ARN must be" . " 'arn'.");
101
+ }
102
+ if (empty($data['partition'])) {
103
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 2nd component of an ARN" . " represents the partition and must not be empty.");
104
+ }
105
+ if (empty($data['service'])) {
106
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 3rd component of an ARN" . " represents the service and must not be empty.");
107
+ }
108
+ if (empty($data['resource'])) {
109
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 6th component of an ARN" . " represents the resource information and must not be empty." . " Individual service ARNs may include additional delimiters" . " to further qualify resources.");
110
+ }
111
+ }
112
+ }
vendor/Aws3/Aws/Arn/ArnInterface.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn;
4
+
5
+ /**
6
+ * Amazon Resource Names (ARNs) uniquely identify AWS resources. Classes
7
+ * implementing ArnInterface parse and store an ARN object representation.
8
+ *
9
+ * Valid ARN formats include:
10
+ *
11
+ * arn:partition:service:region:account-id:resource-id
12
+ * arn:partition:service:region:account-id:resource-type/resource-id
13
+ * arn:partition:service:region:account-id:resource-type:resource-id
14
+ *
15
+ * Some components may be omitted, depending on the service and resource type.
16
+ *
17
+ * @internal
18
+ */
19
+ interface ArnInterface
20
+ {
21
+ public static function parse($string);
22
+ public function __toString();
23
+ public function getPrefix();
24
+ public function getPartition();
25
+ public function getService();
26
+ public function getRegion();
27
+ public function getAccountId();
28
+ public function getResource();
29
+ public function toArray();
30
+ }
vendor/Aws3/Aws/Arn/ArnParser.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn as S3AccessPointArn;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\BucketArn;
7
+ /**
8
+ * @internal
9
+ */
10
+ class ArnParser
11
+ {
12
+ /**
13
+ * @param $string
14
+ * @return bool
15
+ */
16
+ public static function isArn($string)
17
+ {
18
+ return strpos($string, 'arn:') === 0;
19
+ }
20
+ /**
21
+ * Parses a string and returns an instance of ArnInterface. Returns a
22
+ * specific type of Arn object if it has a specific class representation
23
+ * or a generic Arn object if not.
24
+ *
25
+ * @param $string
26
+ * @return ArnInterface
27
+ */
28
+ public static function parse($string)
29
+ {
30
+ $data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Arn::parse($string);
31
+ if (substr($data['resource'], 0, 11) === 'accesspoint') {
32
+ if ($data['service'] === 's3') {
33
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn($string);
34
+ }
35
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\AccessPointArn($string);
36
+ }
37
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Arn($data);
38
+ }
39
+ }
vendor/Aws3/Aws/Arn/Exception/InvalidArnException.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception;
4
+
5
+ /**
6
+ * Represents a failed attempt to construct an Arn
7
+ */
8
+ class InvalidArnException extends \RuntimeException
9
+ {
10
+ }
vendor/Aws3/Aws/Arn/ResourceTypeAndIdTrait.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn;
4
+
5
+ /**
6
+ * @internal
7
+ */
8
+ trait ResourceTypeAndIdTrait
9
+ {
10
+ public function getResourceType()
11
+ {
12
+ return $this->data['resource_type'];
13
+ }
14
+ public function getResourceId()
15
+ {
16
+ return $this->data['resource_id'];
17
+ }
18
+ private static function parseResourceTypeAndId(array $data)
19
+ {
20
+ $data['resource_type'] = null;
21
+ $data['resource_id'] = null;
22
+ $length = strlen($data['resource']);
23
+ for ($i = 0; $i < $length; $i++) {
24
+ if (in_array($data['resource'][$i], ['/', ':'])) {
25
+ $data['resource_type'] = substr($data['resource'], 0, $i);
26
+ $data['resource_id'] = substr($data['resource'], $i + 1);
27
+ break;
28
+ }
29
+ }
30
+ return $data;
31
+ }
32
+ }
vendor/Aws3/Aws/Arn/S3/AccessPointArn.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\AccessPointArn as BaseAccessPointArn;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException;
8
+ /**
9
+ * @internal
10
+ */
11
+ class AccessPointArn extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\AccessPointArn implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface
12
+ {
13
+ /**
14
+ * Validation specific to AccessPointArn
15
+ *
16
+ * @param array $data
17
+ */
18
+ protected static function validate(array $data)
19
+ {
20
+ parent::validate($data);
21
+ if ($data['service'] !== 's3') {
22
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 3rd component of an S3 access" . " point ARN represents the region and must be 's3'.");
23
+ }
24
+ }
25
+ }
vendor/Aws3/Aws/AwsClient.php CHANGED
@@ -8,6 +8,7 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallAttemptMonitoringMiddleware;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallMonitoringMiddleware;
10
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider;
 
11
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Signature\SignatureProvider;
12
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri;
13
  /**
@@ -17,6 +18,8 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
17
  {
18
  use AwsClientTrait;
19
  /** @var array */
 
 
20
  private $config;
21
  /** @var string */
22
  private $region;
@@ -57,6 +60,16 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
57
  * credentials or return null. See Aws\Credentials\CredentialProvider for
58
  * a list of built-in credentials providers. If no credentials are
59
  * provided, the SDK will attempt to load them from the environment.
 
 
 
 
 
 
 
 
 
 
60
  * - debug: (bool|array) Set to true to display debug information when
61
  * sending requests. Alternatively, you can provide an associative array
62
  * with the following keys: logfn: (callable) Function that is invoked
@@ -83,6 +96,14 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
83
  * - endpoint: (string) The full URI of the webservice. This is only
84
  * required when connecting to a custom endpoint (e.g., a local version
85
  * of S3).
 
 
 
 
 
 
 
 
86
  * - endpoint_provider: (callable) An optional PHP callable that
87
  * accepts a hash of options including a "service" and "region" key and
88
  * returns NULL or a hash of endpoint data, of which the "endpoint" key
@@ -162,8 +183,10 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
162
  $this->defaultRequestOptions = $config['http'];
163
  $this->addSignatureMiddleware();
164
  $this->addInvocationId();
165
- $this->addClientSideMonitoring($args);
166
  $this->addEndpointParameterMiddleware($args);
 
 
 
167
  if (isset($args['with_resolved'])) {
168
  $args['with_resolved']($config);
169
  }
@@ -244,6 +267,13 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
244
  $list->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointParameterMiddleware::wrap($this->api), 'endpoint_parameter');
245
  }
246
  }
 
 
 
 
 
 
 
247
  private function addSignatureMiddleware()
248
  {
249
  $api = $this->getApi();
@@ -252,6 +282,9 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
252
  $name = $this->config['signing_name'];
253
  $region = $this->config['signing_region'];
254
  $resolver = static function (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $c) use($api, $provider, $name, $region, $version) {
 
 
 
255
  $authType = $api->getOperation($c->getName())['authtype'];
256
  switch ($authType) {
257
  case 'none':
@@ -270,12 +303,24 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
270
  // Add invocation id to each request
271
  $this->handlerList->prependSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::invocationId(), 'invocation-id');
272
  }
273
- private function addClientSideMonitoring($args)
274
  {
275
- $options = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::defaultProvider($args);
276
- $this->handlerList->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallMonitoringMiddleware::wrap($this->credentialProvider, $options, $this->region, $this->getApi()->getServiceId()), 'ApiCallMonitoringMiddleware');
277
- $callAttemptMiddleware = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallAttemptMonitoringMiddleware::wrap($this->credentialProvider, $options, $this->region, $this->getApi()->getServiceId());
278
- $this->handlerList->appendAttempt($callAttemptMiddleware, 'ApiCallAttemptMonitoringMiddleware');
 
 
 
 
 
 
 
 
 
 
 
 
279
  }
280
  /**
281
  * Returns a service model and doc model with any necessary changes
@@ -291,6 +336,18 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
291
  */
292
  public static function applyDocFilters(array $api, array $docs)
293
  {
 
 
 
 
 
 
 
 
 
 
 
 
294
  return [new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service($api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::defaultProvider()), new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel($docs)];
295
  }
296
  /**
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallAttemptMonitoringMiddleware;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallMonitoringMiddleware;
10
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider;
11
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\EndpointDiscoveryMiddleware;
12
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Signature\SignatureProvider;
13
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri;
14
  /**
18
  {
19
  use AwsClientTrait;
20
  /** @var array */
21
+ private $aliases;
22
+ /** @var array */
23
  private $config;
24
  /** @var string */
25
  private $region;
60
  * credentials or return null. See Aws\Credentials\CredentialProvider for
61
  * a list of built-in credentials providers. If no credentials are
62
  * provided, the SDK will attempt to load them from the environment.
63
+ * - csm:
64
+ * (Aws\ClientSideMonitoring\ConfigurationInterface|array|callable) Specifies
65
+ * the credentials used to sign requests. Provide an
66
+ * Aws\ClientSideMonitoring\ConfigurationInterface object, a callable
67
+ * configuration provider used to create client-side monitoring configuration,
68
+ * `false` to disable csm, or an associative array with the following keys:
69
+ * enabled: (bool) Set to true to enable client-side monitoring, defaults
70
+ * to false; host: (string) the host location to send monitoring events to,
71
+ * defaults to 127.0.0.1; port: (int) The port used for the host connection,
72
+ * defaults to 31000; client_id: (string) An identifier for this project
73
  * - debug: (bool|array) Set to true to display debug information when
74
  * sending requests. Alternatively, you can provide an associative array
75
  * with the following keys: logfn: (callable) Function that is invoked
96
  * - endpoint: (string) The full URI of the webservice. This is only
97
  * required when connecting to a custom endpoint (e.g., a local version
98
  * of S3).
99
+ * - endpoint_discovery: (Aws\EndpointDiscovery\ConfigurationInterface,
100
+ * Aws\CacheInterface, array, callable) Settings for endpoint discovery.
101
+ * Provide an instance of Aws\EndpointDiscovery\ConfigurationInterface,
102
+ * an instance Aws\CacheInterface, a callable that provides a promise for
103
+ * a Configuration object, or an associative array with the following
104
+ * keys: enabled: (bool) Set to true to enable endpoint discovery,
105
+ * defaults to false; cache_limit: (int) The maximum number of keys in the
106
+ * endpoints cache, defaults to 1000.
107
  * - endpoint_provider: (callable) An optional PHP callable that
108
  * accepts a hash of options including a "service" and "region" key and
109
  * returns NULL or a hash of endpoint data, of which the "endpoint" key
183
  $this->defaultRequestOptions = $config['http'];
184
  $this->addSignatureMiddleware();
185
  $this->addInvocationId();
 
186
  $this->addEndpointParameterMiddleware($args);
187
+ $this->addEndpointDiscoveryMiddleware($config, $args);
188
+ $this->loadAliases();
189
+ $this->addStreamRequestPayload();
190
  if (isset($args['with_resolved'])) {
191
  $args['with_resolved']($config);
192
  }
267
  $list->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointParameterMiddleware::wrap($this->api), 'endpoint_parameter');
268
  }
269
  }
270
+ private function addEndpointDiscoveryMiddleware($config, $args)
271
+ {
272
+ $list = $this->getHandlerList();
273
+ if (!isset($args['endpoint'])) {
274
+ $list->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\EndpointDiscoveryMiddleware::wrap($this, $args, $config['endpoint_discovery']), 'EndpointDiscoveryMiddleware');
275
+ }
276
+ }
277
  private function addSignatureMiddleware()
278
  {
279
  $api = $this->getApi();
282
  $name = $this->config['signing_name'];
283
  $region = $this->config['signing_region'];
284
  $resolver = static function (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $c) use($api, $provider, $name, $region, $version) {
285
+ if (!empty($c['@context']['signing_region'])) {
286
+ $region = $c['@context']['signing_region'];
287
+ }
288
  $authType = $api->getOperation($c->getName())['authtype'];
289
  switch ($authType) {
290
  case 'none':
303
  // Add invocation id to each request
304
  $this->handlerList->prependSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::invocationId(), 'invocation-id');
305
  }
306
+ private function loadAliases($file = null)
307
  {
308
+ if (!isset($this->aliases)) {
309
+ if (is_null($file)) {
310
+ $file = __DIR__ . '/data/aliases.json';
311
+ }
312
+ $aliases = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json($file);
313
+ $serviceId = $this->api->getServiceId();
314
+ $version = $this->getApi()->getApiVersion();
315
+ if (!empty($aliases['operations'][$serviceId][$version])) {
316
+ $this->aliases = array_flip($aliases['operations'][$serviceId][$version]);
317
+ }
318
+ }
319
+ }
320
+ private function addStreamRequestPayload()
321
+ {
322
+ $streamRequestPayloadMiddleware = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\StreamRequestPayloadMiddleware::wrap($this->api);
323
+ $this->handlerList->prependSign($streamRequestPayloadMiddleware, 'StreamRequestPayloadMiddleware');
324
  }
325
  /**
326
  * Returns a service model and doc model with any necessary changes
336
  */
337
  public static function applyDocFilters(array $api, array $docs)
338
  {
339
+ $aliases = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json(__DIR__ . '/data/aliases.json');
340
+ $serviceId = $api['metadata']['serviceId'];
341
+ $version = $api['metadata']['apiVersion'];
342
+ // Replace names for any operations with SDK aliases
343
+ if (!empty($aliases['operations'][$serviceId][$version])) {
344
+ foreach ($aliases['operations'][$serviceId][$version] as $op => $alias) {
345
+ $api['operations'][$alias] = $api['operations'][$op];
346
+ $docs['operations'][$alias] = $docs['operations'][$op];
347
+ unset($api['operations'][$op], $docs['operations'][$op]);
348
+ }
349
+ }
350
+ ksort($api['operations']);
351
  return [new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service($api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::defaultProvider()), new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel($docs)];
352
  }
353
  /**
vendor/Aws3/Aws/AwsClientTrait.php CHANGED
@@ -49,9 +49,16 @@ trait AwsClientTrait
49
  }
50
  public function __call($name, array $args)
51
  {
52
- $params = isset($args[0]) ? $args[0] : [];
53
  if (substr($name, -5) === 'Async') {
54
- return $this->executeAsync($this->getCommand(substr($name, 0, -5), $params));
 
 
 
 
 
 
 
 
55
  }
56
  return $this->execute($this->getCommand($name, $params));
57
  }
49
  }
50
  public function __call($name, array $args)
51
  {
 
52
  if (substr($name, -5) === 'Async') {
53
+ $name = substr($name, 0, -5);
54
+ $isAsync = true;
55
+ }
56
+ if (!empty($this->aliases[ucfirst($name)])) {
57
+ $name = $this->aliases[ucfirst($name)];
58
+ }
59
+ $params = isset($args[0]) ? $args[0] : [];
60
+ if (!empty($isAsync)) {
61
+ return $this->executeAsync($this->getCommand($name, $params));
62
  }
63
  return $this->execute($this->getCommand($name, $params));
64
  }
vendor/Aws3/Aws/ClientResolver.php CHANGED
@@ -5,9 +5,15 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Validator;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
 
 
 
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\Credentials;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface;
10
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider;
 
 
 
11
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Signature\SignatureProvider;
12
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\EndpointProvider;
13
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialProvider;
@@ -22,7 +28,7 @@ class ClientResolver
22
  private $argDefinitions;
23
  /** @var array Map of types to a corresponding function */
24
  private static $typeMap = ['resource' => 'is_resource', 'callable' => 'is_callable', 'int' => 'is_int', 'bool' => 'is_bool', 'string' => 'is_string', 'object' => 'is_object', 'array' => 'is_array'];
25
- private static $defaultArgs = ['service' => ['type' => 'value', 'valid' => ['string'], '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).', 'required' => true, 'internal' => true], 'exception_class' => ['type' => 'value', 'valid' => ['string'], 'doc' => 'Exception class to create when an error occurs.', 'default' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Exception\\AwsException', 'internal' => true], 'scheme' => ['type' => 'value', 'valid' => ['string'], 'default' => 'https', '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".'], 'disable_host_prefix_injection' => ['type' => 'value', 'valid' => ['bool'], 'doc' => 'Set to true to disable host prefix injection logic for services that use it. This disables the entire prefix injection, including the portions supplied by user-defined parameters. Setting this flag will have no effect on services that do not use host prefix injection.', 'default' => false], 'endpoint' => ['type' => 'value', 'valid' => ['string'], 'doc' => 'The full URI of the webservice. This is only required when connecting to a custom endpoint (e.g., a local version of S3).', 'fn' => [__CLASS__, '_apply_endpoint']], 'region' => ['type' => 'value', 'valid' => ['string'], 'required' => [__CLASS__, '_missing_region'], 'doc' => 'Region to connect to. See http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of available regions.'], 'version' => ['type' => 'value', 'valid' => ['string'], 'required' => [__CLASS__, '_missing_version'], 'doc' => 'The version of the webservice to utilize (e.g., 2006-03-01).'], 'signature_provider' => ['type' => 'value', 'valid' => ['callable'], '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', 'default' => [__CLASS__, '_default_signature_provider']], 'api_provider' => ['type' => 'value', 'valid' => ['callable'], '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.', 'fn' => [__CLASS__, '_apply_api_provider'], 'default' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::class, 'defaultProvider']], 'endpoint_provider' => ['type' => 'value', 'valid' => ['callable'], 'fn' => [__CLASS__, '_apply_endpoint_provider'], '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.', 'default' => [__CLASS__, '_default_endpoint_provider']], 'serializer' => ['default' => [__CLASS__, '_default_serializer'], 'fn' => [__CLASS__, '_apply_serializer'], 'internal' => true, 'type' => 'value', 'valid' => ['callable']], 'signature_version' => ['type' => 'config', 'valid' => ['string'], '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.', 'default' => [__CLASS__, '_default_signature_version']], 'signing_name' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'A string representing a custom service name to be used when calculating a request signature.', 'default' => [__CLASS__, '_default_signing_name']], 'signing_region' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'A string representing a custom region name to be used when calculating a request signature.', 'default' => [__CLASS__, '_default_signing_region']], 'profile' => ['type' => 'config', 'valid' => ['string'], '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.', 'fn' => [__CLASS__, '_apply_profile']], 'credentials' => ['type' => 'value', 'valid' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface::class, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface::class, 'array', 'bool', 'callable'], '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.', 'fn' => [__CLASS__, '_apply_credentials'], 'default' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialProvider::class, 'defaultProvider']], 'stats' => ['type' => 'value', 'valid' => ['bool', 'array'], 'default' => false, 'doc' => 'Set to true to gather transfer statistics on requests sent. Alternatively, you can provide an associative array with the following keys: retries: (bool) Set to false to disable reporting on retries attempted; http: (bool) Set to true to enable collecting statistics from lower level HTTP adapters (e.g., values returned in GuzzleHttp\\TransferStats). HTTP handlers must support an http_stats_receiver option for this to have an effect; timer: (bool) Set to true to enable a command timer that reports the total wall clock time spent on an operation in seconds.', 'fn' => [__CLASS__, '_apply_stats']], 'retries' => ['type' => 'value', 'valid' => ['int'], 'doc' => 'Configures the maximum number of allowed retries for a client (pass 0 to disable retries). ', 'fn' => [__CLASS__, '_apply_retries'], 'default' => 3], 'validate' => ['type' => 'value', 'valid' => ['bool', 'array'], 'default' => true, 'doc' => 'Set to false to disable client-side parameter validation. Set to true to utilize default validation constraints. Set to an associative array of validation options to enable specific validation constraints.', 'fn' => [__CLASS__, '_apply_validate']], 'debug' => ['type' => 'value', 'valid' => ['bool', 'array'], '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).', 'fn' => [__CLASS__, '_apply_debug']], 'http' => ['type' => 'value', 'valid' => ['array'], 'default' => [], 'doc' => 'Set to an array of SDK request options to apply to each request (e.g., proxy, verify, etc.).'], 'http_handler' => ['type' => 'value', 'valid' => ['callable'], '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.', 'fn' => [__CLASS__, '_apply_http_handler']], 'handler' => ['type' => 'value', 'valid' => ['callable'], '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.', 'fn' => [__CLASS__, '_apply_handler'], 'default' => [__CLASS__, '_default_handler']], 'ua_append' => ['type' => 'value', 'valid' => ['string', 'array'], 'doc' => 'Provide a string or array of strings to send in the User-Agent header.', 'fn' => [__CLASS__, '_apply_user_agent'], 'default' => []], 'idempotency_auto_fill' => ['type' => 'value', 'valid' => ['bool', 'callable'], 'doc' => 'Set to false to disable SDK to populate parameters that enabled \'idempotencyToken\' trait with a random UUID v4 value on your behalf. Using default value \'true\' still allows parameter value to be overwritten when provided. Note: auto-fill only works when cryptographically secure random bytes generator functions(random_bytes, openssl_random_pseudo_bytes or mcrypt_create_iv) can be found. You may also provide a callable source of random bytes.', 'default' => true, 'fn' => [__CLASS__, '_apply_idempotency_auto_fill']]];
26
  /**
27
  * Gets an array of default client arguments, each argument containing a
28
  * hash of the following:
@@ -204,6 +210,19 @@ class ClientResolver
204
  throw new \InvalidArgumentException('Credentials must be an instance of ' . 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Credentials\\CredentialsInterface, an associative ' . 'array that contains "key", "secret", and an optional "token" ' . 'key-value pairs, a credentials provider function, or false.');
205
  }
206
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
207
  public static function _apply_api_provider(callable $value, array &$args)
208
  {
209
  $api = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::resolve($value, 'api', $args['service'], $args['version']), $value);
@@ -212,14 +231,14 @@ class ClientResolver
212
  }
213
  $args['api'] = $api;
214
  $args['parser'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service::createParser($api);
215
- $args['error_parser'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service::createErrorParser($api->getProtocol());
216
  }
217
  public static function _apply_endpoint_provider(callable $value, array &$args)
218
  {
219
  if (!isset($args['endpoint'])) {
220
  $endpointPrefix = isset($args['api']['metadata']['endpointPrefix']) ? $args['api']['metadata']['endpointPrefix'] : $args['service'];
221
  // Invoke the endpoint provider and throw if it does not resolve.
222
- $result = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\EndpointProvider::resolve($value, ['service' => $endpointPrefix, 'region' => $args['region'], 'scheme' => $args['scheme']]);
223
  $args['endpoint'] = $result['endpoint'];
224
  if (empty($args['config']['signature_version']) && isset($result['signatureVersion'])) {
225
  $args['config']['signature_version'] = $result['signatureVersion'];
@@ -232,6 +251,14 @@ class ClientResolver
232
  }
233
  }
234
  }
 
 
 
 
 
 
 
 
235
  public static function _apply_serializer($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
236
  {
237
  $list->prependBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::requestBuilder($value), 'builder');
@@ -318,7 +345,8 @@ class ClientResolver
318
  }
319
  public static function _default_endpoint_provider(array $args)
320
  {
321
- return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider::defaultProvider()->getPartition($args['region'], $args['service']);
 
322
  }
323
  public static function _default_serializer(array $args)
324
  {
@@ -392,4 +420,21 @@ A "region" configuration value is required for the "{$service}" service
392
  found at http://docs.aws.amazon.com/general/latest/gr/rande.html.
393
  EOT;
394
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  }
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Validator;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallAttemptMonitoringMiddleware;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallMonitoringMiddleware;
10
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration;
11
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\Credentials;
12
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface;
13
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider;
14
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationInterface;
15
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationProvider;
16
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\EndpointDiscoveryMiddleware;
17
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Signature\SignatureProvider;
18
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\EndpointProvider;
19
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialProvider;
28
  private $argDefinitions;
29
  /** @var array Map of types to a corresponding function */
30
  private static $typeMap = ['resource' => 'is_resource', 'callable' => 'is_callable', 'int' => 'is_int', 'bool' => 'is_bool', 'string' => 'is_string', 'object' => 'is_object', 'array' => 'is_array'];
31
+ private static $defaultArgs = ['service' => ['type' => 'value', 'valid' => ['string'], '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).', 'required' => true, 'internal' => true], 'exception_class' => ['type' => 'value', 'valid' => ['string'], 'doc' => 'Exception class to create when an error occurs.', 'default' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Exception\\AwsException', 'internal' => true], 'scheme' => ['type' => 'value', 'valid' => ['string'], 'default' => 'https', '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".'], 'disable_host_prefix_injection' => ['type' => 'value', 'valid' => ['bool'], 'doc' => 'Set to true to disable host prefix injection logic for services that use it. This disables the entire prefix injection, including the portions supplied by user-defined parameters. Setting this flag will have no effect on services that do not use host prefix injection.', 'default' => false], 'endpoint' => ['type' => 'value', 'valid' => ['string'], 'doc' => 'The full URI of the webservice. This is only required when connecting to a custom endpoint (e.g., a local version of S3).', 'fn' => [__CLASS__, '_apply_endpoint']], 'region' => ['type' => 'value', 'valid' => ['string'], 'required' => [__CLASS__, '_missing_region'], 'doc' => 'Region to connect to. See http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of available regions.'], 'version' => ['type' => 'value', 'valid' => ['string'], 'required' => [__CLASS__, '_missing_version'], 'doc' => 'The version of the webservice to utilize (e.g., 2006-03-01).'], 'signature_provider' => ['type' => 'value', 'valid' => ['callable'], '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', 'default' => [__CLASS__, '_default_signature_provider']], 'api_provider' => ['type' => 'value', 'valid' => ['callable'], '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.', 'fn' => [__CLASS__, '_apply_api_provider'], 'default' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::class, 'defaultProvider']], 'endpoint_provider' => ['type' => 'value', 'valid' => ['callable'], 'fn' => [__CLASS__, '_apply_endpoint_provider'], '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.', 'default' => [__CLASS__, '_default_endpoint_provider']], 'serializer' => ['default' => [__CLASS__, '_default_serializer'], 'fn' => [__CLASS__, '_apply_serializer'], 'internal' => true, 'type' => 'value', 'valid' => ['callable']], 'signature_version' => ['type' => 'config', 'valid' => ['string'], '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.', 'default' => [__CLASS__, '_default_signature_version']], 'signing_name' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'A string representing a custom service name to be used when calculating a request signature.', 'default' => [__CLASS__, '_default_signing_name']], 'signing_region' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'A string representing a custom region name to be used when calculating a request signature.', 'default' => [__CLASS__, '_default_signing_region']], 'profile' => ['type' => 'config', 'valid' => ['string'], '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.', 'fn' => [__CLASS__, '_apply_profile']], 'credentials' => ['type' => 'value', 'valid' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface::class, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface::class, 'array', 'bool', 'callable'], '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.', 'fn' => [__CLASS__, '_apply_credentials'], 'default' => [__CLASS__, '_default_credential_provider']], 'endpoint_discovery' => ['type' => 'value', 'valid' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationInterface::class, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface::class, 'array', 'callable'], 'doc' => 'Specifies settings for endpoint discovery. Provide an instance of Aws\\EndpointDiscovery\\ConfigurationInterface, an instance Aws\\CacheInterface, a callable that provides a promise for a Configuration object, or an associative array with the following keys: enabled: (bool) Set to true to enable endpoint discovery. Defaults to false; cache_limit: (int) The maximum number of keys in the endpoints cache. Defaults to 1000.', 'fn' => [__CLASS__, '_apply_endpoint_discovery'], 'default' => [__CLASS__, '_default_endpoint_discovery_provider']], 'stats' => ['type' => 'value', 'valid' => ['bool', 'array'], 'default' => false, 'doc' => 'Set to true to gather transfer statistics on requests sent. Alternatively, you can provide an associative array with the following keys: retries: (bool) Set to false to disable reporting on retries attempted; http: (bool) Set to true to enable collecting statistics from lower level HTTP adapters (e.g., values returned in GuzzleHttp\\TransferStats). HTTP handlers must support an http_stats_receiver option for this to have an effect; timer: (bool) Set to true to enable a command timer that reports the total wall clock time spent on an operation in seconds.', 'fn' => [__CLASS__, '_apply_stats']], 'retries' => ['type' => 'value', 'valid' => ['int'], 'doc' => 'Configures the maximum number of allowed retries for a client (pass 0 to disable retries). ', 'fn' => [__CLASS__, '_apply_retries'], 'default' => 3], 'validate' => ['type' => 'value', 'valid' => ['bool', 'array'], 'default' => true, 'doc' => 'Set to false to disable client-side parameter validation. Set to true to utilize default validation constraints. Set to an associative array of validation options to enable specific validation constraints.', 'fn' => [__CLASS__, '_apply_validate']], 'debug' => ['type' => 'value', 'valid' => ['bool', 'array'], '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).', 'fn' => [__CLASS__, '_apply_debug']], 'csm' => ['type' => 'value', 'valid' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationInterface::class, 'callable', 'array', 'bool'], 'doc' => 'CSM options for the client. Provides a callable wrapping a promise, a boolean "false", an instance of ConfigurationInterface, or an associative array of "enabled", "host", "port", and "client_id".', 'fn' => [__CLASS__, '_apply_csm'], 'default' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::class, 'defaultProvider']], 'http' => ['type' => 'value', 'valid' => ['array'], 'default' => [], 'doc' => 'Set to an array of SDK request options to apply to each request (e.g., proxy, verify, etc.).'], 'http_handler' => ['type' => 'value', 'valid' => ['callable'], '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.', 'fn' => [__CLASS__, '_apply_http_handler']], 'handler' => ['type' => 'value', 'valid' => ['callable'], '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.', 'fn' => [__CLASS__, '_apply_handler'], 'default' => [__CLASS__, '_default_handler']], 'ua_append' => ['type' => 'value', 'valid' => ['string', 'array'], 'doc' => 'Provide a string or array of strings to send in the User-Agent header.', 'fn' => [__CLASS__, '_apply_user_agent'], 'default' => []], 'idempotency_auto_fill' => ['type' => 'value', 'valid' => ['bool', 'callable'], 'doc' => 'Set to false to disable SDK to populate parameters that enabled \'idempotencyToken\' trait with a random UUID v4 value on your behalf. Using default value \'true\' still allows parameter value to be overwritten when provided. Note: auto-fill only works when cryptographically secure random bytes generator functions(random_bytes, openssl_random_pseudo_bytes or mcrypt_create_iv) can be found. You may also provide a callable source of random bytes.', 'default' => true, 'fn' => [__CLASS__, '_apply_idempotency_auto_fill']]];
32
  /**
33
  * Gets an array of default client arguments, each argument containing a
34
  * hash of the following:
210
  throw new \InvalidArgumentException('Credentials must be an instance of ' . 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Credentials\\CredentialsInterface, an associative ' . 'array that contains "key", "secret", and an optional "token" ' . 'key-value pairs, a credentials provider function, or false.');
211
  }
212
  }
213
+ public static function _default_credential_provider(array $args)
214
+ {
215
+ return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialProvider::defaultProvider($args);
216
+ }
217
+ public static function _apply_csm($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
218
+ {
219
+ if ($value === false) {
220
+ $value = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration(false, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_HOST, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_PORT, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_CLIENT_ID);
221
+ $args['csm'] = $value;
222
+ }
223
+ $list->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallMonitoringMiddleware::wrap($args['credentials'], $value, $args['region'], $args['api']->getServiceId()), 'ApiCallMonitoringMiddleware');
224
+ $list->appendAttempt(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallAttemptMonitoringMiddleware::wrap($args['credentials'], $value, $args['region'], $args['api']->getServiceId()), 'ApiCallAttemptMonitoringMiddleware');
225
+ }
226
  public static function _apply_api_provider(callable $value, array &$args)
227
  {
228
  $api = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::resolve($value, 'api', $args['service'], $args['version']), $value);
231
  }
232
  $args['api'] = $api;
233
  $args['parser'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service::createParser($api);
234
+ $args['error_parser'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service::createErrorParser($api->getProtocol(), $api);
235
  }
236
  public static function _apply_endpoint_provider(callable $value, array &$args)
237
  {
238
  if (!isset($args['endpoint'])) {
239
  $endpointPrefix = isset($args['api']['metadata']['endpointPrefix']) ? $args['api']['metadata']['endpointPrefix'] : $args['service'];
240
  // Invoke the endpoint provider and throw if it does not resolve.
241
+ $result = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\EndpointProvider::resolve($value, ['service' => $endpointPrefix, 'region' => $args['region'], 'scheme' => $args['scheme'], 'options' => self::getEndpointProviderOptions($args)]);
242
  $args['endpoint'] = $result['endpoint'];
243
  if (empty($args['config']['signature_version']) && isset($result['signatureVersion'])) {
244
  $args['config']['signature_version'] = $result['signatureVersion'];
251
  }
252
  }
253
  }
254
+ public static function _apply_endpoint_discovery($value, array &$args)
255
+ {
256
+ $args['endpoint_discovery'] = $value;
257
+ }
258
+ public static function _default_endpoint_discovery_provider(array $args)
259
+ {
260
+ return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationProvider::defaultProvider($args);
261
+ }
262
  public static function _apply_serializer($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
263
  {
264
  $list->prependBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::requestBuilder($value), 'builder');
345
  }
346
  public static function _default_endpoint_provider(array $args)
347
  {
348
+ $options = self::getEndpointProviderOptions($args);
349
+ return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider::defaultProvider($options)->getPartition($args['region'], $args['service']);
350
  }
351
  public static function _default_serializer(array $args)
352
  {
420
  found at http://docs.aws.amazon.com/general/latest/gr/rande.html.
421
  EOT;
422
  }
423
+ /**
424
+ * Extracts client options for the endpoint provider to its own array
425
+ *
426
+ * @param array $args
427
+ * @return array
428
+ */
429
+ private static function getEndpointProviderOptions(array $args)
430
+ {
431
+ $options = [];
432
+ $optionKeys = ['sts_regional_endpoints', 's3_us_east_1_regional_endpoint'];
433
+ foreach ($optionKeys as $key) {
434
+ if (isset($args[$key])) {
435
+ $options[$key] = $args[$key];
436
+ }
437
+ }
438
+ return $options;
439
+ }
440
  }
vendor/Aws3/Aws/ClientSideMonitoring/AbstractMonitoringMiddleware.php CHANGED
@@ -57,7 +57,7 @@ abstract class AbstractMonitoringMiddleware implements \DeliciousBrains\WP_Offlo
57
  *
58
  * @param callable $handler
59
  * @param callable $credentialProvider
60
- * @param array $options
61
  * @param $region
62
  * @param $service
63
  */
@@ -110,6 +110,10 @@ abstract class AbstractMonitoringMiddleware implements \DeliciousBrains\WP_Offlo
110
  $event = ['Api' => $cmd->getName(), 'ClientId' => $this->getClientId(), 'Region' => $this->getRegion(), 'Service' => $this->getService(), 'Timestamp' => (int) floor(microtime(true) * 1000), 'UserAgent' => substr($request->getHeaderLine('User-Agent') . ' ' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_user_agent(), 0, 256), 'Version' => 1];
111
  return $event;
112
  }
 
 
 
 
113
  private function getPort()
114
  {
115
  return $this->unwrappedOptions()->getPort();
@@ -181,7 +185,7 @@ abstract class AbstractMonitoringMiddleware implements \DeliciousBrains\WP_Offlo
181
  if (!is_resource(self::$socket) || $forceNewConnection || socket_last_error(self::$socket)) {
182
  self::$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
183
  socket_clear_error(self::$socket);
184
- socket_connect(self::$socket, '127.0.0.1', $this->getPort());
185
  }
186
  return self::$socket;
187
  }
@@ -210,7 +214,12 @@ abstract class AbstractMonitoringMiddleware implements \DeliciousBrains\WP_Offlo
210
  private function unwrappedOptions()
211
  {
212
  if (!$this->options instanceof ConfigurationInterface) {
213
- $this->options = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::unwrap($this->options);
 
 
 
 
 
214
  }
215
  return $this->options;
216
  }
57
  *
58
  * @param callable $handler
59
  * @param callable $credentialProvider
60
+ * @param $options
61
  * @param $region
62
  * @param $service
63
  */
110
  $event = ['Api' => $cmd->getName(), 'ClientId' => $this->getClientId(), 'Region' => $this->getRegion(), 'Service' => $this->getService(), 'Timestamp' => (int) floor(microtime(true) * 1000), 'UserAgent' => substr($request->getHeaderLine('User-Agent') . ' ' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_user_agent(), 0, 256), 'Version' => 1];
111
  return $event;
112
  }
113
+ private function getHost()
114
+ {
115
+ return $this->unwrappedOptions()->getHost();
116
+ }
117
  private function getPort()
118
  {
119
  return $this->unwrappedOptions()->getPort();
185
  if (!is_resource(self::$socket) || $forceNewConnection || socket_last_error(self::$socket)) {
186
  self::$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
187
  socket_clear_error(self::$socket);
188
+ socket_connect(self::$socket, $this->getHost(), $this->getPort());
189
  }
190
  return self::$socket;
191
  }
214
  private function unwrappedOptions()
215
  {
216
  if (!$this->options instanceof ConfigurationInterface) {
217
+ try {
218
+ $this->options = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::unwrap($this->options);
219
+ } catch (\Exception $e) {
220
+ // Errors unwrapping CSM config defaults to disabling it
221
+ $this->options = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration(false, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_HOST, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_PORT);
222
+ }
223
  }
224
  return $this->options;
225
  }
vendor/Aws3/Aws/ClientSideMonitoring/Configuration.php CHANGED
@@ -6,16 +6,19 @@ class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Client
6
  {
7
  private $clientId;
8
  private $enabled;
 
9
  private $port;
10
  /**
11
  * Constructs a new Configuration object with the specified CSM options set.
12
  *
13
  * @param mixed $enabled
 
14
  * @param string|int $port
15
  * @param string $clientId
16
  */
17
- public function __construct($enabled, $port, $clientId = '')
18
  {
 
19
  $this->port = filter_var($port, FILTER_VALIDATE_INT);
20
  if ($this->port === false) {
21
  throw new \InvalidArgumentException("CSM 'port' value must be an integer!");
@@ -38,6 +41,13 @@ class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Client
38
  {
39
  return $this->clientId;
40
  }
 
 
 
 
 
 
 
41
  /**
42
  * {@inheritdoc}
43
  */
@@ -50,6 +60,6 @@ class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Client
50
  */
51
  public function toArray()
52
  {
53
- return ['client_id' => $this->getClientId(), 'enabled' => $this->isEnabled(), 'port' => $this->getPort()];
54
  }
55
  }
6
  {
7
  private $clientId;
8
  private $enabled;
9
+ private $host;
10
  private $port;
11
  /**
12
  * Constructs a new Configuration object with the specified CSM options set.
13
  *
14
  * @param mixed $enabled
15
+ * @param string $host
16
  * @param string|int $port
17
  * @param string $clientId
18
  */
19
+ public function __construct($enabled, $host, $port, $clientId = '')
20
  {
21
+ $this->host = $host;
22
  $this->port = filter_var($port, FILTER_VALIDATE_INT);
23
  if ($this->port === false) {
24
  throw new \InvalidArgumentException("CSM 'port' value must be an integer!");
41
  {
42
  return $this->clientId;
43
  }
44
+ /**
45
+ * /{@inheritdoc}
46
+ */
47
+ public function getHost()
48
+ {
49
+ return $this->host;
50
+ }
51
  /**
52
  * {@inheritdoc}
53
  */
60
  */
61
  public function toArray()
62
  {
63
+ return ['client_id' => $this->getClientId(), 'enabled' => $this->isEnabled(), 'host' => $this->getHost(), 'port' => $this->getPort()];
64
  }
65
  }
vendor/Aws3/Aws/ClientSideMonitoring/ConfigurationInterface.php CHANGED
@@ -4,7 +4,7 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring;
4
 
5
  /**
6
  * Provides access to client-side monitoring configuration options:
7
- * 'client_id', 'enabled', 'port'
8
  */
9
  interface ConfigurationInterface
10
  {
@@ -20,6 +20,12 @@ interface ConfigurationInterface
20
  * @return string|null
21
  */
22
  public function getClientId();
 
 
 
 
 
 
23
  /**
24
  * Returns the configured port.
25
  *
4
 
5
  /**
6
  * Provides access to client-side monitoring configuration options:
7
+ * 'client_id', 'enabled', 'host', 'port'
8
  */
9
  interface ConfigurationInterface
10
  {
20
  * @return string|null
21
  */
22
  public function getClientId();
23
+ /**
24
+ * Returns the configured host.
25
+ *
26
+ * @return string|null
27
+ */
28
+ public function getHost();
29
  /**
30
  * Returns the configured port.
31
  *
vendor/Aws3/Aws/ClientSideMonitoring/ConfigurationProvider.php CHANGED
@@ -2,8 +2,10 @@
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring;
4
 
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Exception\ConfigurationException;
 
7
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
9
  /**
@@ -40,75 +42,32 @@ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
40
  * $config = $promise->wait();
41
  * </code>
42
  */
43
- class ConfigurationProvider
44
  {
45
- const CACHE_KEY = 'aws_cached_csm_config';
46
  const DEFAULT_CLIENT_ID = '';
47
  const DEFAULT_ENABLED = false;
 
48
  const DEFAULT_PORT = 31000;
49
  const ENV_CLIENT_ID = 'AWS_CSM_CLIENT_ID';
50
  const ENV_ENABLED = 'AWS_CSM_ENABLED';
 
51
  const ENV_PORT = 'AWS_CSM_PORT';
52
  const ENV_PROFILE = 'AWS_PROFILE';
 
 
 
53
  /**
54
- * Wraps a credential provider and saves provided credentials in an
55
- * instance of Aws\CacheInterface. Forwards calls when no credentials found
56
- * in cache and updates cache with the results.
57
- *
58
- * @param callable $provider Credentials provider function to wrap
59
- * @param CacheInterface $cache Cache to store credentials
60
- * @param string|null $cacheKey (optional) Cache key to use
61
- *
62
- * @return callable
63
- */
64
- public static function cache(callable $provider, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface $cache, $cacheKey = null)
65
- {
66
- $cacheKey = $cacheKey ?: self::CACHE_KEY;
67
- return function () use($provider, $cache, $cacheKey) {
68
- $found = $cache->get($cacheKey);
69
- if ($found instanceof ConfigurationInterface) {
70
- return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for($found);
71
- }
72
- return $provider()->then(function (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationInterface $config) use($cache, $cacheKey) {
73
- $cache->set($cacheKey, $config);
74
- return $config;
75
- });
76
- };
77
- }
78
- /**
79
- * Creates an aggregate credentials provider that invokes the provided
80
- * variadic providers one after the other until a provider returns
81
- * credentials.
82
- *
83
- * @return callable
84
- */
85
- public static function chain()
86
- {
87
- $links = func_get_args();
88
- if (empty($links)) {
89
- throw new \InvalidArgumentException('No providers in chain');
90
- }
91
- return function () use($links) {
92
- /** @var callable $parent */
93
- $parent = array_shift($links);
94
- $promise = $parent();
95
- while ($next = array_shift($links)) {
96
- $promise = $promise->otherwise($next);
97
- }
98
- return $promise;
99
- };
100
- }
101
- /**
102
- * Create a default CSM config provider that first checks for environment
103
- * variables, then checks for a specified profile in ~/.aws/config, then
104
- * checks for the "aws_csm" profile in ~/.aws/config, and failing those uses
105
- * a default fallback set of configuration options.
106
  *
107
  * This provider is automatically wrapped in a memoize function that caches
108
  * previously provided config options.
109
  *
110
- * @param array $config Optional array of ecs/instance profile credentials
111
- * provider options.
112
  *
113
  * @return callable
114
  */
@@ -117,7 +76,7 @@ class ConfigurationProvider
117
  $configProviders = [self::env(), self::ini(), self::fallback()];
118
  $memo = self::memoize(call_user_func_array('self::chain', $configProviders));
119
  if (isset($config['csm']) && $config['csm'] instanceof CacheInterface) {
120
- return self::cache($memo, $config['csm'], self::CACHE_KEY);
121
  }
122
  return $memo;
123
  }
@@ -132,9 +91,9 @@ class ConfigurationProvider
132
  // Use credentials from environment variables, if available
133
  $enabled = getenv(self::ENV_ENABLED);
134
  if ($enabled !== false) {
135
- return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($enabled, getenv(self::ENV_PORT) ?: self::DEFAULT_PORT, getenv(self::ENV_CLIENT_ID) ?: self::DEFAULT_CLIENT_ID));
136
  }
137
- return self::reject('Could not find environment variable CSM config' . ' in ' . self::ENV_ENABLED . '/' . self::ENV_PORT . '/' . self::ENV_CLIENT_ID);
138
  };
139
  }
140
  /**
@@ -145,45 +104,30 @@ class ConfigurationProvider
145
  public static function fallback()
146
  {
147
  return function () {
148
- return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration(self::DEFAULT_ENABLED, self::DEFAULT_PORT, self::DEFAULT_CLIENT_ID));
149
  };
150
  }
151
  /**
152
- * Gets the environment's HOME directory if available.
153
- *
154
- * @return null|string
155
- */
156
- private static function getHomeDir()
157
- {
158
- // On Linux/Unix-like systems, use the HOME environment variable
159
- if ($homeDir = getenv('HOME')) {
160
- return $homeDir;
161
- }
162
- // Get the HOMEDRIVE and HOMEPATH values for Windows hosts
163
- $homeDrive = getenv('HOMEDRIVE');
164
- $homePath = getenv('HOMEPATH');
165
- return $homeDrive && $homePath ? $homeDrive . $homePath : null;
166
- }
167
- /**
168
- * CSM config provider that creates CSM config using an ini file stored
169
- * in the current user's home directory.
170
  *
171
  * @param string|null $profile Profile to use. If not specified will use
172
- * the "aws_csm" profile in "~/.aws/config".
173
  * @param string|null $filename If provided, uses a custom filename rather
174
- * than looking in the home directory.
175
  *
176
  * @return callable
177
  */
178
  public static function ini($profile = null, $filename = null)
179
  {
180
- $filename = $filename ?: self::getHomeDir() . '/.aws/config';
181
  $profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'aws_csm');
182
  return function () use($profile, $filename) {
183
  if (!is_readable($filename)) {
184
  return self::reject("Cannot read CSM config from {$filename}");
185
  }
186
- $data = parse_ini_file($filename, true);
187
  if ($data === false) {
188
  return self::reject("Invalid config file: {$filename}");
189
  }
@@ -193,6 +137,10 @@ class ConfigurationProvider
193
  if (!isset($data[$profile]['csm_enabled'])) {
194
  return self::reject("Required CSM config values not present in \n INI profile '{$profile}' ({$filename})");
195
  }
 
 
 
 
196
  // port is optional
197
  if (empty($data[$profile]['csm_port'])) {
198
  $data[$profile]['csm_port'] = self::DEFAULT_PORT;
@@ -201,49 +149,9 @@ class ConfigurationProvider
201
  if (empty($data[$profile]['csm_client_id'])) {
202
  $data[$profile]['csm_client_id'] = self::DEFAULT_CLIENT_ID;
203
  }
204
- return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($data[$profile]['csm_enabled'], $data[$profile]['csm_port'], $data[$profile]['csm_client_id']));
205
- };
206
- }
207
- /**
208
- * Wraps a CSM config provider and caches previously provided configuration.
209
- *
210
- * Ensures that cached configuration is refreshed when it expires.
211
- *
212
- * @param callable $provider CSM config provider function to wrap.
213
- *
214
- * @return callable
215
- */
216
- public static function memoize(callable $provider)
217
- {
218
- return function () use($provider) {
219
- static $result;
220
- static $isConstant;
221
- // Constant config will be returned constantly.
222
- if ($isConstant) {
223
- return $result;
224
- }
225
- // Create the initial promise that will be used as the cached value
226
- // until it expires.
227
- if (null === $result) {
228
- $result = $provider();
229
- }
230
- // Return config and set flag that provider is already set
231
- return $result->then(function (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationInterface $config) use(&$isConstant) {
232
- $isConstant = true;
233
- return $config;
234
- });
235
  };
236
  }
237
- /**
238
- * Reject promise with standardized exception.
239
- *
240
- * @param $msg
241
- * @return Promise\RejectedPromise
242
- */
243
- private static function reject($msg)
244
- {
245
- return new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\RejectedPromise(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Exception\ConfigurationException($msg));
246
- }
247
  /**
248
  * Unwraps a configuration object in whatever valid form it is in,
249
  * always returning a ConfigurationInterface object.
@@ -264,8 +172,9 @@ class ConfigurationProvider
264
  return $config;
265
  } elseif (is_array($config) && isset($config['enabled'])) {
266
  $client_id = isset($config['client_id']) ? $config['client_id'] : self::DEFAULT_CLIENT_ID;
 
267
  $port = isset($config['port']) ? $config['port'] : self::DEFAULT_PORT;
268
- return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($config['enabled'], $port, $client_id);
269
  }
270
  throw new \InvalidArgumentException('Not a valid CSM configuration ' . 'argument.');
271
  }
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Exception\ConfigurationException;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
10
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
11
  /**
42
  * $config = $promise->wait();
43
  * </code>
44
  */
45
+ class ConfigurationProvider extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface
46
  {
 
47
  const DEFAULT_CLIENT_ID = '';
48
  const DEFAULT_ENABLED = false;
49
+ const DEFAULT_HOST = '127.0.0.1';
50
  const DEFAULT_PORT = 31000;
51
  const ENV_CLIENT_ID = 'AWS_CSM_CLIENT_ID';
52
  const ENV_ENABLED = 'AWS_CSM_ENABLED';
53
+ const ENV_HOST = 'AWS_CSM_HOST';
54
  const ENV_PORT = 'AWS_CSM_PORT';
55
  const ENV_PROFILE = 'AWS_PROFILE';
56
+ public static $cacheKey = 'aws_cached_csm_config';
57
+ protected static $interfaceClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationInterface::class;
58
+ protected static $exceptionClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Exception\ConfigurationException::class;
59
  /**
60
+ * Create a default config provider that first checks for environment
61
+ * variables, then checks for a specified profile in the environment-defined
62
+ * config file location (env variable is 'AWS_CONFIG_FILE', file location
63
+ * defaults to ~/.aws/config), then checks for the "default" profile in the
64
+ * environment-defined config file location, and failing those uses a default
65
+ * fallback set of configuration options.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  *
67
  * This provider is automatically wrapped in a memoize function that caches
68
  * previously provided config options.
69
  *
70
+ * @param array $config
 
71
  *
72
  * @return callable
73
  */
76
  $configProviders = [self::env(), self::ini(), self::fallback()];
77
  $memo = self::memoize(call_user_func_array('self::chain', $configProviders));
78
  if (isset($config['csm']) && $config['csm'] instanceof CacheInterface) {
79
+ return self::cache($memo, $config['csm'], self::$cacheKey);
80
  }
81
  return $memo;
82
  }
91
  // Use credentials from environment variables, if available
92
  $enabled = getenv(self::ENV_ENABLED);
93
  if ($enabled !== false) {
94
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($enabled, getenv(self::ENV_HOST) ?: self::DEFAULT_HOST, getenv(self::ENV_PORT) ?: self::DEFAULT_PORT, getenv(self::ENV_CLIENT_ID) ?: self::DEFAULT_CLIENT_ID));
95
  }
96
+ return self::reject('Could not find environment variable CSM config' . ' in ' . self::ENV_ENABLED . '/' . self::ENV_HOST . '/' . self::ENV_PORT . '/' . self::ENV_CLIENT_ID);
97
  };
98
  }
99
  /**
104
  public static function fallback()
105
  {
106
  return function () {
107
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration(self::DEFAULT_ENABLED, self::DEFAULT_HOST, self::DEFAULT_PORT, self::DEFAULT_CLIENT_ID));
108
  };
109
  }
110
  /**
111
+ * Config provider that creates config using a config file whose location
112
+ * is specified by an environment variable 'AWS_CONFIG_FILE', defaulting to
113
+ * ~/.aws/config if not specified
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  *
115
  * @param string|null $profile Profile to use. If not specified will use
116
+ * the "default" profile.
117
  * @param string|null $filename If provided, uses a custom filename rather
118
+ * than looking in the default directory.
119
  *
120
  * @return callable
121
  */
122
  public static function ini($profile = null, $filename = null)
123
  {
124
+ $filename = $filename ?: self::getDefaultConfigFilename();
125
  $profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'aws_csm');
126
  return function () use($profile, $filename) {
127
  if (!is_readable($filename)) {
128
  return self::reject("Cannot read CSM config from {$filename}");
129
  }
130
+ $data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true);
131
  if ($data === false) {
132
  return self::reject("Invalid config file: {$filename}");
133
  }
137
  if (!isset($data[$profile]['csm_enabled'])) {
138
  return self::reject("Required CSM config values not present in \n INI profile '{$profile}' ({$filename})");
139
  }
140
+ // host is optional
141
+ if (empty($data[$profile]['csm_host'])) {
142
+ $data[$profile]['csm_host'] = self::DEFAULT_HOST;
143
+ }
144
  // port is optional
145
  if (empty($data[$profile]['csm_port'])) {
146
  $data[$profile]['csm_port'] = self::DEFAULT_PORT;
149
  if (empty($data[$profile]['csm_client_id'])) {
150
  $data[$profile]['csm_client_id'] = self::DEFAULT_CLIENT_ID;
151
  }
152
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($data[$profile]['csm_enabled'], $data[$profile]['csm_host'], $data[$profile]['csm_port'], $data[$profile]['csm_client_id']));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  };
154
  }
 
 
 
 
 
 
 
 
 
 
155
  /**
156
  * Unwraps a configuration object in whatever valid form it is in,
157
  * always returning a ConfigurationInterface object.
172
  return $config;
173
  } elseif (is_array($config) && isset($config['enabled'])) {
174
  $client_id = isset($config['client_id']) ? $config['client_id'] : self::DEFAULT_CLIENT_ID;
175
+ $host = isset($config['host']) ? $config['host'] : self::DEFAULT_HOST;
176
  $port = isset($config['port']) ? $config['port'] : self::DEFAULT_PORT;
177
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($config['enabled'], $host, $port, $client_id);
178
  }
179
  throw new \InvalidArgumentException('Not a valid CSM configuration ' . 'argument.');
180
  }
vendor/Aws3/Aws/CloudFront/CloudFrontClient.php ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient;
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
+ * @method \Aws\Result createDistributionWithTags(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
54
+ * @method \GuzzleHttp\Promise\Promise createDistributionWithTagsAsync(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
55
+ * @method \Aws\Result createStreamingDistributionWithTags(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
56
+ * @method \GuzzleHttp\Promise\Promise createStreamingDistributionWithTagsAsync(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
57
+ * @method \Aws\Result listTagsForResource(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
58
+ * @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
59
+ * @method \Aws\Result tagResource(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
60
+ * @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
61
+ * @method \Aws\Result untagResource(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
62
+ * @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
63
+ * @method \Aws\Result deleteServiceLinkedRole(array $args = []) (supported in versions 2017-03-25)
64
+ * @method \GuzzleHttp\Promise\Promise deleteServiceLinkedRoleAsync(array $args = []) (supported in versions 2017-03-25)
65
+ * @method \Aws\Result createFieldLevelEncryptionConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
66
+ * @method \GuzzleHttp\Promise\Promise createFieldLevelEncryptionConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
67
+ * @method \Aws\Result createFieldLevelEncryptionProfile(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
68
+ * @method \GuzzleHttp\Promise\Promise createFieldLevelEncryptionProfileAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
69
+ * @method \Aws\Result createPublicKey(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
70
+ * @method \GuzzleHttp\Promise\Promise createPublicKeyAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
71
+ * @method \Aws\Result deleteFieldLevelEncryptionConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
72
+ * @method \GuzzleHttp\Promise\Promise deleteFieldLevelEncryptionConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
73
+ * @method \Aws\Result deleteFieldLevelEncryptionProfile(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
74
+ * @method \GuzzleHttp\Promise\Promise deleteFieldLevelEncryptionProfileAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
75
+ * @method \Aws\Result deletePublicKey(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
76
+ * @method \GuzzleHttp\Promise\Promise deletePublicKeyAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
77
+ * @method \Aws\Result getFieldLevelEncryption(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
78
+ * @method \GuzzleHttp\Promise\Promise getFieldLevelEncryptionAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
79
+ * @method \Aws\Result getFieldLevelEncryptionConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
80
+ * @method \GuzzleHttp\Promise\Promise getFieldLevelEncryptionConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
81
+ * @method \Aws\Result getFieldLevelEncryptionProfile(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
82
+ * @method \GuzzleHttp\Promise\Promise getFieldLevelEncryptionProfileAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
83
+ * @method \Aws\Result getFieldLevelEncryptionProfileConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
84
+ * @method \GuzzleHttp\Promise\Promise getFieldLevelEncryptionProfileConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
85
+ * @method \Aws\Result getPublicKey(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
86
+ * @method \GuzzleHttp\Promise\Promise getPublicKeyAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
87
+ * @method \Aws\Result getPublicKeyConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
88
+ * @method \GuzzleHttp\Promise\Promise getPublicKeyConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
89
+ * @method \Aws\Result listFieldLevelEncryptionConfigs(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
90
+ * @method \GuzzleHttp\Promise\Promise listFieldLevelEncryptionConfigsAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
91
+ * @method \Aws\Result listFieldLevelEncryptionProfiles(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
92
+ * @method \GuzzleHttp\Promise\Promise listFieldLevelEncryptionProfilesAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
93
+ * @method \Aws\Result listPublicKeys(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
94
+ * @method \GuzzleHttp\Promise\Promise listPublicKeysAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
95
+ * @method \Aws\Result updateFieldLevelEncryptionConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
96
+ * @method \GuzzleHttp\Promise\Promise updateFieldLevelEncryptionConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
97
+ * @method \Aws\Result updateFieldLevelEncryptionProfile(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
98
+ * @method \GuzzleHttp\Promise\Promise updateFieldLevelEncryptionProfileAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
99
+ * @method \Aws\Result updatePublicKey(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
100
+ * @method \GuzzleHttp\Promise\Promise updatePublicKeyAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
101
+ */
102
+ class CloudFrontClient extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient
103
+ {
104
+ /**
105
+ * Create a signed Amazon CloudFront URL.
106
+ *
107
+ * This method accepts an array of configuration options:
108
+ *
109
+ * - url: (string) URL of the resource being signed (can include query
110
+ * string and wildcards). For example: rtmp://s5c39gqb8ow64r.cloudfront.net/videos/mp3_name.mp3
111
+ * http://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes
112
+ * - policy: (string) JSON policy. Use this option when creating a signed
113
+ * URL for a custom policy.
114
+ * - expires: (int) UTC Unix timestamp used when signing with a canned
115
+ * policy. Not required when passing a custom 'policy' option.
116
+ * - key_pair_id: (string) The ID of the key pair used to sign CloudFront
117
+ * URLs for private distributions.
118
+ * - private_key: (string) The filepath ot the private key used to sign
119
+ * CloudFront URLs for private distributions.
120
+ *
121
+ * @param array $options Array of configuration options used when signing
122
+ *
123
+ * @return string Signed URL with authentication parameters
124
+ * @throws \InvalidArgumentException if url, key_pair_id, or private_key
125
+ * were not specified.
126
+ * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
127
+ */
128
+ public function getSignedUrl(array $options)
129
+ {
130
+ foreach (['url', 'key_pair_id', 'private_key'] as $required) {
131
+ if (!isset($options[$required])) {
132
+ throw new \InvalidArgumentException("{$required} is required");
133
+ }
134
+ }
135
+ $urlSigner = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront\UrlSigner($options['key_pair_id'], $options['private_key']);
136
+ return $urlSigner->getSignedUrl($options['url'], isset($options['expires']) ? $options['expires'] : null, isset($options['policy']) ? $options['policy'] : null);
137
+ }
138
+ /**
139
+ * Create a signed Amazon CloudFront cookie.
140
+ *
141
+ * This method accepts an array of configuration options:
142
+ *
143
+ * - url: (string) URL of the resource being signed (can include query
144
+ * string and wildcards). For example: http://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes
145
+ * - policy: (string) JSON policy. Use this option when creating a signed
146
+ * URL for a custom policy.
147
+ * - expires: (int) UTC Unix timestamp used when signing with a canned
148
+ * policy. Not required when passing a custom 'policy' option.
149
+ * - key_pair_id: (string) The ID of the key pair used to sign CloudFront
150
+ * URLs for private distributions.
151
+ * - private_key: (string) The filepath ot the private key used to sign
152
+ * CloudFront URLs for private distributions.
153
+ *
154
+ * @param array $options Array of configuration options used when signing
155
+ *
156
+ * @return array Key => value pairs of signed cookies to set
157
+ * @throws \InvalidArgumentException if url, key_pair_id, or private_key
158
+ * were not specified.
159
+ * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
160
+ */
161
+ public function getSignedCookie(array $options)
162
+ {
163
+ foreach (['key_pair_id', 'private_key'] as $required) {
164
+ if (!isset($options[$required])) {
165
+ throw new \InvalidArgumentException("{$required} is required");
166
+ }
167
+ }
168
+ $cookieSigner = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront\CookieSigner($options['key_pair_id'], $options['private_key']);
169
+ return $cookieSigner->getSignedCookie(isset($options['url']) ? $options['url'] : null, isset($options['expires']) ? $options['expires'] : null, isset($options['policy']) ? $options['policy'] : null);
170
+ }
171
+ }
vendor/Aws3/Aws/CloudFront/CookieSigner.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront;
4
+
5
+ class CookieSigner
6
+ {
7
+ /** @var Signer */
8
+ private $signer;
9
+ private static $schemes = ['http' => true, 'https' => true];
10
+ /**
11
+ * @param $keyPairId string ID of the key pair
12
+ * @param $privateKey string Path to the private key used for signing
13
+ *
14
+ * @throws \RuntimeException if the openssl extension is missing
15
+ * @throws \InvalidArgumentException if the private key cannot be found.
16
+ */
17
+ public function __construct($keyPairId, $privateKey)
18
+ {
19
+ $this->signer = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront\Signer($keyPairId, $privateKey);
20
+ }
21
+ /**
22
+ * Create a signed Amazon CloudFront Cookie.
23
+ *
24
+ * @param string $url URL to sign (can include query string
25
+ * and wildcards). Not required
26
+ * when passing a custom $policy.
27
+ * @param string|integer|null $expires UTC Unix timestamp used when signing
28
+ * with a canned policy. Not required
29
+ * when passing a custom $policy.
30
+ * @param string $policy JSON policy. Use this option when
31
+ * creating a signed cookie for a custom
32
+ * policy.
33
+ *
34
+ * @return array The authenticated cookie parameters
35
+ * @throws \InvalidArgumentException if the URL provided is invalid
36
+ * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html
37
+ */
38
+ public function getSignedCookie($url = null, $expires = null, $policy = null)
39
+ {
40
+ if ($url) {
41
+ $this->validateUrl($url);
42
+ }
43
+ $cookieParameters = [];
44
+ $signature = $this->signer->getSignature($url, $expires, $policy);
45
+ foreach ($signature as $key => $value) {
46
+ $cookieParameters["CloudFront-{$key}"] = $value;
47
+ }
48
+ return $cookieParameters;
49
+ }
50
+ private function validateUrl($url)
51
+ {
52
+ $scheme = str_replace('*', '', explode('://', $url)[0]);
53
+ if (empty(self::$schemes[strtolower($scheme)])) {
54
+ throw new \InvalidArgumentException('Invalid or missing URI scheme');
55
+ }
56
+ }
57
+ }
vendor/Aws3/Aws/CloudFront/Exception/CloudFrontException.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront\Exception;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException;
6
+ /**
7
+ * Represents an error interacting with the Amazon CloudFront service.
8
+ */
9
+ class CloudFrontException extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException
10
+ {
11
+ }
vendor/Aws3/Aws/CloudFront/Signer.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront;
4
+
5
+ /**
6
+ * @internal
7
+ */
8
+ class Signer
9
+ {
10
+ private $keyPairId;
11
+ private $pkHandle;
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
+ * @param $passphrase string Passphrase to private key file, if one exists
19
+ *
20
+ * @throws \RuntimeException if the openssl extension is missing
21
+ * @throws \InvalidArgumentException if the private key cannot be found.
22
+ */
23
+ public function __construct($keyPairId, $privateKey, $passphrase = "")
24
+ {
25
+ if (!extension_loaded('openssl')) {
26
+ //@codeCoverageIgnoreStart
27
+ throw new \RuntimeException('The openssl extension is required to ' . 'sign CloudFront urls.');
28
+ //@codeCoverageIgnoreEnd
29
+ }
30
+ $this->keyPairId = $keyPairId;
31
+ if (!($this->pkHandle = openssl_pkey_get_private($privateKey, $passphrase))) {
32
+ if (!file_exists($privateKey)) {
33
+ throw new \InvalidArgumentException("PK file not found: {$privateKey}");
34
+ } else {
35
+ $this->pkHandle = openssl_pkey_get_private("file://{$privateKey}", $passphrase);
36
+ if (!$this->pkHandle) {
37
+ throw new \InvalidArgumentException(openssl_error_string());
38
+ }
39
+ }
40
+ }
41
+ }
42
+ public function __destruct()
43
+ {
44
+ $this->pkHandle && openssl_pkey_free($this->pkHandle);
45
+ }
46
+ /**
47
+ * Create the values used to construct signed URLs and cookies.
48
+ *
49
+ * @param string $resource The CloudFront resource to which
50
+ * this signature will grant access.
51
+ * Not used when a custom policy is
52
+ * provided.
53
+ * @param string|integer|null $expires UTC Unix timestamp used when
54
+ * signing with a canned policy.
55
+ * Not required when passing a
56
+ * custom $policy.
57
+ * @param string $policy JSON policy. Use this option when
58
+ * creating a signature for a custom
59
+ * policy.
60
+ *
61
+ * @return array The values needed to construct a signed URL or cookie
62
+ * @throws \InvalidArgumentException when not provided either a policy or a
63
+ * resource and a expires
64
+ *
65
+ * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html
66
+ */
67
+ public function getSignature($resource = null, $expires = null, $policy = null)
68
+ {
69
+ $signatureHash = [];
70
+ if ($policy) {
71
+ $policy = preg_replace('/\\s/s', '', $policy);
72
+ $signatureHash['Policy'] = $this->encode($policy);
73
+ } elseif ($resource && $expires) {
74
+ $expires = (int) $expires;
75
+ // Handle epoch passed as string
76
+ $policy = $this->createCannedPolicy($resource, $expires);
77
+ $signatureHash['Expires'] = $expires;
78
+ } else {
79
+ throw new \InvalidArgumentException('Either a policy or a resource' . ' and an expiration time must be provided.');
80
+ }
81
+ $signatureHash['Signature'] = $this->encode($this->sign($policy));
82
+ $signatureHash['Key-Pair-Id'] = $this->keyPairId;
83
+ return $signatureHash;
84
+ }
85
+ private function createCannedPolicy($resource, $expiration)
86
+ {
87
+ return json_encode(['Statement' => [['Resource' => $resource, 'Condition' => ['DateLessThan' => ['AWS:EpochTime' => $expiration]]]]], JSON_UNESCAPED_SLASHES);
88
+ }
89
+ private function sign($policy)
90
+ {
91
+ $signature = '';
92
+ openssl_sign($policy, $signature, $this->pkHandle);
93
+ return $signature;
94
+ }
95
+ private function encode($policy)
96
+ {
97
+ return strtr(base64_encode($policy), '+=/', '-_~');
98
+ }
99
+ }
vendor/Aws3/Aws/CloudFront/UrlSigner.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface;
8
+ /**
9
+ * Creates signed URLs for Amazon CloudFront resources.
10
+ */
11
+ class UrlSigner
12
+ {
13
+ private $signer;
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 \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront\Signer($keyPairId, $privateKey);
24
+ }
25
+ /**
26
+ * Create a signed Amazon CloudFront URL.
27
+ *
28
+ * Keep in mind that URLs meant for use in media/flash players may have
29
+ * different requirements for URL formats (e.g. some require that the
30
+ * extension be removed, some require the file name to be prefixed
31
+ * - mp4:<path>, some require you to add "/cfx/st" into your URL).
32
+ *
33
+ * @param string $url URL to sign (can include query
34
+ * string string and wildcards)
35
+ * @param string|integer|null $expires UTC Unix timestamp used when signing
36
+ * with a canned policy. Not required
37
+ * when passing a custom $policy.
38
+ * @param string $policy JSON policy. Use this option when
39
+ * creating a signed URL for a custom
40
+ * policy.
41
+ *
42
+ * @return string The file URL with authentication parameters
43
+ * @throws \InvalidArgumentException if the URL provided is invalid
44
+ * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
45
+ */
46
+ public function getSignedUrl($url, $expires = null, $policy = null)
47
+ {
48
+ // Determine the scheme of the url
49
+ $urlSections = explode('://', $url);
50
+ if (count($urlSections) < 2) {
51
+ throw new \InvalidArgumentException("Invalid URL: {$url}");
52
+ }
53
+ // Get the real scheme by removing wildcards from the scheme
54
+ $scheme = str_replace('*', '', $urlSections[0]);
55
+ $uri = new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri($scheme . '://' . $urlSections[1]);
56
+ $query = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\parse_query($uri->getQuery(), PHP_QUERY_RFC3986);
57
+ $signature = $this->signer->getSignature($this->createResource($scheme, (string) $uri), $expires, $policy);
58
+ $uri = $uri->withQuery(http_build_query($query + $signature, null, '&', PHP_QUERY_RFC3986));
59
+ return $scheme === 'rtmp' ? $this->createRtmpUrl($uri) : (string) $uri;
60
+ }
61
+ private function createRtmpUrl(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface $uri)
62
+ {
63
+ // Use a relative URL when creating Flash player URLs
64
+ $result = ltrim($uri->getPath(), '/');
65
+ if ($query = $uri->getQuery()) {
66
+ $result .= '?' . $query;
67
+ }
68
+ return $result;
69
+ }
70
+ /**
71
+ * @param $scheme
72
+ * @param $url
73
+ *
74
+ * @return string
75
+ */
76
+ private function createResource($scheme, $url)
77
+ {
78
+ switch ($scheme) {
79
+ case 'http':
80
+ case 'http*':
81
+ case 'https':
82
+ return $url;
83
+ case 'rtmp':
84
+ $parts = parse_url($url);
85
+ $pathParts = pathinfo($parts['path']);
86
+ $resource = ltrim($pathParts['dirname'] . '/' . $pathParts['basename'], '/');
87
+ // Add a query string if present.
88
+ if (isset($parts['query'])) {
89
+ $resource .= "?{$parts['query']}";
90
+ }
91
+ return $resource;
92
+ }
93
+ throw new \InvalidArgumentException("Invalid URI scheme: {$scheme}. " . "Scheme must be one of: http, https, or rtmp");
94
+ }
95
+ }
vendor/Aws3/Aws/Command.php CHANGED
@@ -29,6 +29,9 @@ class Command implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInter
29
  if (!isset($this->data['@http'])) {
30
  $this->data['@http'] = [];
31
  }
 
 
 
32
  }
33
  public function __clone()
34
  {
29
  if (!isset($this->data['@http'])) {
30
  $this->data['@http'] = [];
31
  }
32
+ if (!isset($this->data['@context'])) {
33
+ $this->data['@context'] = [];
34
+ }
35
  }
36
  public function __clone()
37
  {
vendor/Aws3/Aws/ConfigurationProviderInterface.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
4
+
5
+ interface ConfigurationProviderInterface
6
+ {
7
+ /**
8
+ * Create a default config provider
9
+ *
10
+ * @param array $config
11
+ * @return callable
12
+ */
13
+ public static function defaultProvider(array $config = []);
14
+ }
vendor/Aws3/Aws/Credentials/AssumeRoleWithWebIdentityCredentialProvider.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\StsClient;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
10
+ /**
11
+ * Credential provider that provides credentials via assuming a role with a web identity
12
+ * More Information, see: https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-sts-2011-06-15.html#assumerolewithwebidentity
13
+ */
14
+ class AssumeRoleWithWebIdentityCredentialProvider
15
+ {
16
+ const ERROR_MSG = "Missing required 'AssumeRoleWithWebIdentityCredentialProvider' configuration option: ";
17
+ const ENV_RETRIES = 'AWS_METADATA_SERVICE_NUM_ATTEMPTS';
18
+ /** @var string */
19
+ private $tokenFile;
20
+ /** @var string */
21
+ private $arn;
22
+ /** @var string */
23
+ private $session;
24
+ /** @var StsClient */
25
+ private $client;
26
+ /** @var integer */
27
+ private $retries;
28
+ /** @var integer */
29
+ private $attempts;
30
+ /**
31
+ * The constructor attempts to load config from environment variables.
32
+ * If not set, the following config options are used:
33
+ * - WebIdentityTokenFile: full path of token filename
34
+ * - RoleArn: arn of role to be assumed
35
+ * - SessionName: (optional) set by SDK if not provided
36
+ *
37
+ * @param array $config Configuration options
38
+ * @throws \InvalidArgumentException
39
+ */
40
+ public function __construct(array $config = [])
41
+ {
42
+ if (!isset($config['RoleArn'])) {
43
+ throw new \InvalidArgumentException(self::ERROR_MSG . "'RoleArn'.");
44
+ }
45
+ $this->arn = $config['RoleArn'];
46
+ if (!isset($config['WebIdentityTokenFile'])) {
47
+ throw new \InvalidArgumentException(self::ERROR_MSG . "'WebIdentityTokenFile'.");
48
+ }
49
+ $this->tokenFile = $config['WebIdentityTokenFile'];
50
+ if (!preg_match("/^\\w\\:|^\\/|^\\\\/", $this->tokenFile)) {
51
+ throw new \InvalidArgumentException("'WebIdentityTokenFile' must be an absolute path.");
52
+ }
53
+ $this->retries = (int) getenv(self::ENV_RETRIES) ?: (isset($config['retries']) ? $config['retries'] : 3);
54
+ $this->attempts = 0;
55
+ $this->session = isset($config['SessionName']) ? $config['SessionName'] : 'aws-sdk-php-' . round(microtime(true) * 1000);
56
+ $region = isset($config['region']) ? $config['region'] : 'us-east-1';
57
+ if (isset($config['client'])) {
58
+ $this->client = $config['client'];
59
+ } else {
60
+ $this->client = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\StsClient(['credentials' => false, 'region' => $region, 'version' => 'latest']);
61
+ }
62
+ }
63
+ /**
64
+ * Loads assume role with web identity credentials.
65
+ *
66
+ * @return Promise\PromiseInterface
67
+ */
68
+ public function __invoke()
69
+ {
70
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\coroutine(function () {
71
+ $client = $this->client;
72
+ $result = null;
73
+ while ($result == null) {
74
+ try {
75
+ $token = file_get_contents($this->tokenFile);
76
+ } catch (\Exception $exception) {
77
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException("Error reading WebIdentityTokenFile from " . $this->tokenFile, 0, $exception);
78
+ }
79
+ $assumeParams = ['RoleArn' => $this->arn, 'RoleSessionName' => $this->session, 'WebIdentityToken' => $token];
80
+ try {
81
+ $result = $client->assumeRoleWithWebIdentity($assumeParams);
82
+ } catch (AwsException $e) {
83
+ if ($e->getAwsErrorCode() == 'InvalidIdentityToken') {
84
+ if ($this->attempts < $this->retries) {
85
+ sleep(pow(1.2, $this->attempts));
86
+ } else {
87
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException("InvalidIdentityToken, retries exhausted");
88
+ }
89
+ } else {
90
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException("Error assuming role from web identity credentials", 0, $e);
91
+ }
92
+ } catch (\Exception $e) {
93
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException("Error retrieving web identity credentials: " . $e->getMessage() . " (" . $e->getCode() . ")");
94
+ }
95
+ $this->attempts++;
96
+ }
97
+ (yield $this->client->createCredentials($result));
98
+ });
99
+ }
100
+ }
vendor/Aws3/Aws/Credentials/CredentialProvider.php CHANGED
@@ -3,8 +3,10 @@
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials;
4
 
5
  use Aws;
 
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException;
 
8
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
9
  /**
10
  * Credential providers are functions that accept no arguments and return a
@@ -42,17 +44,22 @@ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
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
  * Create a default credential provider that first checks for environment
51
  * variables, then checks for the "default" profile in ~/.aws/credentials,
52
  * then checks for "profile default" profile in ~/.aws/config (which is
53
  * the default profile of AWS CLI), then tries to make a GET Request to
54
- * fetch credentials if Ecs environment variable is presented, and finally
55
- * checks for EC2 instance profile credentials.
 
 
56
  *
57
  * This provider is automatically wrapped in a memoize function that caches
58
  * previously provided credentials.
@@ -64,9 +71,22 @@ class CredentialProvider
64
  */
65
  public static function defaultProvider(array $config = [])
66
  {
67
- $localCredentialProviders = self::localCredentialProviders();
68
- $remoteCredentialProviders = self::remoteCredentialProviders($config);
69
- return self::memoize(call_user_func_array('self::chain', array_merge($localCredentialProviders, $remoteCredentialProviders)));
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  }
71
  /**
72
  * Create a credential provider function from a set of static credentials.
@@ -153,8 +173,6 @@ class CredentialProvider
153
  * instance of Aws\CacheInterface. Forwards calls when no credentials found
154
  * in cache and updates cache with the results.
155
  *
156
- * Defaults to using a simple file-based cache when none provided.
157
- *
158
  * @param callable $provider Credentials provider function to wrap
159
  * @param CacheInterface $cache Cache to store credentials
160
  * @param string|null $cacheKey (optional) Cache key to use
@@ -231,6 +249,49 @@ class CredentialProvider
231
  {
232
  return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\AssumeRoleCredentialProvider($config);
233
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  /**
235
  * Credentials provider that creates credentials using an ini file stored
236
  * in the current user's home directory.
@@ -239,24 +300,51 @@ class CredentialProvider
239
  * the "default" profile in "~/.aws/credentials".
240
  * @param string|null $filename If provided, uses a custom filename rather
241
  * than looking in the home directory.
 
 
 
 
 
 
 
242
  *
243
  * @return callable
244
  */
245
- public static function ini($profile = null, $filename = null)
246
  {
247
  $filename = $filename ?: self::getHomeDir() . '/.aws/credentials';
248
  $profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
249
- return function () use($profile, $filename) {
 
 
 
250
  if (!is_readable($filename)) {
251
  return self::reject("Cannot read credentials from {$filename}");
252
  }
253
- $data = parse_ini_file($filename, true, INI_SCANNER_RAW);
254
  if ($data === false) {
255
  return self::reject("Invalid credentials file: {$filename}");
256
  }
257
  if (!isset($data[$profile])) {
258
  return self::reject("'{$profile}' not found in credentials file");
259
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  if (!isset($data[$profile]['aws_access_key_id']) || !isset($data[$profile]['aws_secret_access_key'])) {
261
  return self::reject("No credentials present in INI profile " . "'{$profile}' ({$filename})");
262
  }
@@ -267,40 +355,92 @@ class CredentialProvider
267
  };
268
  }
269
  /**
270
- * Local credential providers returns a list of local credential providers
271
- * in following order:
272
- * - credentials from environment variables
273
- * - 'default' profile in '.aws/credentials' file
274
- * - 'profile default' profile in '.aws/config' file
275
  *
276
- * @return array
 
 
 
 
 
277
  */
278
- private static function localCredentialProviders()
279
  {
280
- return [self::env(), self::ini(), self::ini('profile default', self::getHomeDir() . '/.aws/config')];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
  }
282
  /**
283
- * Remote credential providers returns a list of credentials providers
284
- * for the remote endpoints such as EC2 or ECS Roles.
285
- *
286
- * @param array $config Array of configuration data.
287
  *
288
- * @return array
289
- * @see Aws\Credentials\InstanceProfileProvider for $config details.
290
- * @see Aws\Credentials\EcsCredentialProvider for $config details.
291
  */
292
- private static function remoteCredentialProviders(array $config = [])
293
  {
294
- if (!empty(getenv(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\EcsCredentialProvider::ENV_URI))) {
295
- $providers['ecs'] = self::ecsCredentials($config);
 
 
 
296
  }
297
- $providers['instance'] = self::instanceProfile($config);
298
- if (isset($config['credentials']) && $config['credentials'] instanceof CacheInterface) {
299
- foreach ($providers as $key => $provider) {
300
- $providers[$key] = self::cache($provider, $config['credentials'], 'aws_cached_' . $key . '_credentials');
301
- }
 
 
 
 
302
  }
303
- return $providers;
 
 
304
  }
305
  /**
306
  * Gets the environment's HOME directory if available.
@@ -318,6 +458,49 @@ class CredentialProvider
318
  $homePath = getenv('HOMEPATH');
319
  return $homeDrive && $homePath ? $homeDrive . $homePath : null;
320
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  private static function reject($msg)
322
  {
323
  return new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\RejectedPromise(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($msg));
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials;
4
 
5
  use Aws;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\StsClient;
10
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
11
  /**
12
  * Credential providers are functions that accept no arguments and return a
44
  */
45
  class CredentialProvider
46
  {
47
+ const ENV_ARN = 'AWS_ROLE_ARN';
48
  const ENV_KEY = 'AWS_ACCESS_KEY_ID';
49
+ const ENV_PROFILE = 'AWS_PROFILE';
50
+ const ENV_ROLE_SESSION_NAME = 'AWS_ROLE_SESSION_NAME';
51
  const ENV_SECRET = 'AWS_SECRET_ACCESS_KEY';
52
  const ENV_SESSION = 'AWS_SESSION_TOKEN';
53
+ const ENV_TOKEN_FILE = 'AWS_WEB_IDENTITY_TOKEN_FILE';
54
  /**
55
  * Create a default credential provider that first checks for environment
56
  * variables, then checks for the "default" profile in ~/.aws/credentials,
57
  * then checks for "profile default" profile in ~/.aws/config (which is
58
  * the default profile of AWS CLI), then tries to make a GET Request to
59
+ * fetch credentials if Ecs environment variable is presented, then checks
60
+ * for credential_process in the "default" profile in ~/.aws/credentials,
61
+ * then for credential_process in the "default profile" profile in
62
+ * ~/.aws/config, and finally checks for EC2 instance profile credentials.
63
  *
64
  * This provider is automatically wrapped in a memoize function that caches
65
  * previously provided credentials.
71
  */
72
  public static function defaultProvider(array $config = [])
73
  {
74
+ $cacheable = ['web_identity', 'ecs', 'process_credentials', 'process_config', 'instance'];
75
+ $defaultChain = ['env' => self::env(), 'web_identity' => self::assumeRoleWithWebIdentityCredentialProvider($config), 'ini' => self::ini(), 'ini_config' => self::ini('profile default', self::getHomeDir() . '/.aws/config')];
76
+ if (!empty(getenv(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\EcsCredentialProvider::ENV_URI))) {
77
+ $defaultChain['ecs'] = self::ecsCredentials($config);
78
+ }
79
+ $defaultChain['process_credentials'] = self::process();
80
+ $defaultChain['process_config'] = self::process('profile default', self::getHomeDir() . '/.aws/config');
81
+ $defaultChain['instance'] = self::instanceProfile($config);
82
+ if (isset($config['credentials']) && $config['credentials'] instanceof CacheInterface) {
83
+ foreach ($cacheable as $provider) {
84
+ if (isset($defaultChain[$provider])) {
85
+ $defaultChain[$provider] = self::cache($defaultChain[$provider], $config['credentials'], 'aws_cached_' . $provider . '_credentials');
86
+ }
87
+ }
88
+ }
89
+ return self::memoize(call_user_func_array('self::chain', $defaultChain));
90
  }
91
  /**
92
  * Create a credential provider function from a set of static credentials.
173
  * instance of Aws\CacheInterface. Forwards calls when no credentials found
174
  * in cache and updates cache with the results.
175
  *
 
 
176
  * @param callable $provider Credentials provider function to wrap
177
  * @param CacheInterface $cache Cache to store credentials
178
  * @param string|null $cacheKey (optional) Cache key to use
249
  {
250
  return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\AssumeRoleCredentialProvider($config);
251
  }
252
+ /**
253
+ * Credential provider that creates credentials by assuming role from a
254
+ * Web Identity Token
255
+ *
256
+ * @param array $config Array of configuration data
257
+ * @return callable
258
+ * @see Aws\Credentials\AssumeRoleWithWebIdentityCredentialProvider for
259
+ * $config details.
260
+ */
261
+ public static function assumeRoleWithWebIdentityCredentialProvider(array $config = [])
262
+ {
263
+ return function () use($config) {
264
+ $arnFromEnv = getenv(self::ENV_ARN);
265
+ $tokenFromEnv = getenv(self::ENV_TOKEN_FILE);
266
+ $stsClient = isset($config['stsClient']) ? $config['stsClient'] : null;
267
+ $region = isset($config['region']) ? $config['region'] : null;
268
+ if ($tokenFromEnv && $arnFromEnv) {
269
+ $sessionName = getenv(self::ENV_ROLE_SESSION_NAME) ? getenv(self::ENV_ROLE_SESSION_NAME) : null;
270
+ $provider = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\AssumeRoleWithWebIdentityCredentialProvider(['RoleArn' => $arnFromEnv, 'WebIdentityTokenFile' => $tokenFromEnv, 'SessionName' => $sessionName, 'client' => $stsClient, 'region' => $region]);
271
+ return $provider();
272
+ }
273
+ $profileName = getenv(self::ENV_PROFILE) ?: 'default';
274
+ if (isset($config['filename'])) {
275
+ $profiles = self::loadProfiles($config['filename']);
276
+ } else {
277
+ $profiles = self::loadDefaultProfiles();
278
+ }
279
+ if (isset($profiles[$profileName])) {
280
+ $profile = $profiles[$profileName];
281
+ if (isset($profile['region'])) {
282
+ $region = $profile['region'];
283
+ }
284
+ if (isset($profile['web_identity_token_file']) && isset($profile['role_arn'])) {
285
+ $sessionName = isset($profile['role_session_name']) ? $profile['role_session_name'] : null;
286
+ $provider = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\AssumeRoleWithWebIdentityCredentialProvider(['RoleArn' => $profile['role_arn'], 'WebIdentityTokenFile' => $profile['web_identity_token_file'], 'SessionName' => $sessionName, 'client' => $stsClient, 'region' => $region]);
287
+ return $provider();
288
+ }
289
+ } else {
290
+ return self::reject("Unknown profile: {$profileName}");
291
+ }
292
+ return self::reject("No RoleArn or WebIdentityTokenFile specified");
293
+ };
294
+ }
295
  /**
296
  * Credentials provider that creates credentials using an ini file stored
297
  * in the current user's home directory.
300
  * the "default" profile in "~/.aws/credentials".
301
  * @param string|null $filename If provided, uses a custom filename rather
302
  * than looking in the home directory.
303
+ * @param array|null $config If provided, may contain the following:
304
+ * preferStaticCredentials: If true, prefer static
305
+ * credentials to role_arn if both are present
306
+ * disableAssumeRole: If true, disable support for
307
+ * roles that assume an IAM role. If true and role profile
308
+ * is selected, an error is raised.
309
+ * stsClient: StsClient used to assume role specified in profile
310
  *
311
  * @return callable
312
  */
313
+ public static function ini($profile = null, $filename = null, array $config = [])
314
  {
315
  $filename = $filename ?: self::getHomeDir() . '/.aws/credentials';
316
  $profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
317
+ return function () use($profile, $filename, $config) {
318
+ $preferStaticCredentials = isset($config['preferStaticCredentials']) ? $config['preferStaticCredentials'] : false;
319
+ $disableAssumeRole = isset($config['disableAssumeRole']) ? $config['disableAssumeRole'] : false;
320
+ $stsClient = isset($config['stsClient']) ? $config['stsClient'] : null;
321
  if (!is_readable($filename)) {
322
  return self::reject("Cannot read credentials from {$filename}");
323
  }
324
+ $data = self::loadProfiles($filename);
325
  if ($data === false) {
326
  return self::reject("Invalid credentials file: {$filename}");
327
  }
328
  if (!isset($data[$profile])) {
329
  return self::reject("'{$profile}' not found in credentials file");
330
  }
331
+ /*
332
+ In the CLI, the presence of both a role_arn and static credentials have
333
+ different meanings depending on how many profiles have been visited. For
334
+ the first profile processed, role_arn takes precedence over any static
335
+ credentials, but for all subsequent profiles, static credentials are
336
+ used if present, and only in their absence will the profile's
337
+ source_profile and role_arn keys be used to load another set of
338
+ credentials. This bool is intended to yield compatible behaviour in this
339
+ sdk.
340
+ */
341
+ $preferStaticCredentialsToRoleArn = $preferStaticCredentials && isset($data[$profile]['aws_access_key_id']) && isset($data[$profile]['aws_secret_access_key']);
342
+ if (isset($data[$profile]['role_arn']) && !$preferStaticCredentialsToRoleArn) {
343
+ if ($disableAssumeRole) {
344
+ return self::reject("Role assumption profiles are disabled. " . "Failed to load profile " . $profile);
345
+ }
346
+ return self::loadRoleProfile($data, $profile, $filename, $stsClient);
347
+ }
348
  if (!isset($data[$profile]['aws_access_key_id']) || !isset($data[$profile]['aws_secret_access_key'])) {
349
  return self::reject("No credentials present in INI profile " . "'{$profile}' ({$filename})");
350
  }
355
  };
356
  }
357
  /**
358
+ * Credentials provider that creates credentials using a process configured in
359
+ * ini file stored in the current user's home directory.
 
 
 
360
  *
361
+ * @param string|null $profile Profile to use. If not specified will use
362
+ * the "default" profile in "~/.aws/credentials".
363
+ * @param string|null $filename If provided, uses a custom filename rather
364
+ * than looking in the home directory.
365
+ *
366
+ * @return callable
367
  */
368
+ public static function process($profile = null, $filename = null)
369
  {
370
+ $filename = $filename ?: self::getHomeDir() . '/.aws/credentials';
371
+ $profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
372
+ return function () use($profile, $filename) {
373
+ if (!is_readable($filename)) {
374
+ return self::reject("Cannot read process credentials from {$filename}");
375
+ }
376
+ $data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true, INI_SCANNER_RAW);
377
+ if ($data === false) {
378
+ return self::reject("Invalid credentials file: {$filename}");
379
+ }
380
+ if (!isset($data[$profile])) {
381
+ return self::reject("'{$profile}' not found in credentials file");
382
+ }
383
+ if (!isset($data[$profile]['credential_process'])) {
384
+ return self::reject("No credential_process present in INI profile " . "'{$profile}' ({$filename})");
385
+ }
386
+ $credentialProcess = $data[$profile]['credential_process'];
387
+ $json = shell_exec($credentialProcess);
388
+ $processData = json_decode($json, true);
389
+ // Only support version 1
390
+ if (isset($processData['Version'])) {
391
+ if ($processData['Version'] !== 1) {
392
+ return self::reject("credential_process does not return Version == 1");
393
+ }
394
+ }
395
+ if (!isset($processData['AccessKeyId']) || !isset($processData['SecretAccessKey'])) {
396
+ return self::reject("credential_process does not return valid credentials");
397
+ }
398
+ if (isset($processData['Expiration'])) {
399
+ try {
400
+ $expiration = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult($processData['Expiration']);
401
+ } catch (\Exception $e) {
402
+ return self::reject("credential_process returned invalid expiration");
403
+ }
404
+ $now = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult();
405
+ if ($expiration < $now) {
406
+ return self::reject("credential_process returned expired credentials");
407
+ }
408
+ $expires = $expiration->getTimestamp();
409
+ } else {
410
+ $expires = null;
411
+ }
412
+ if (empty($processData['SessionToken'])) {
413
+ $processData['SessionToken'] = null;
414
+ }
415
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\Credentials($processData['AccessKeyId'], $processData['SecretAccessKey'], $processData['SessionToken'], $expires));
416
+ };
417
  }
418
  /**
419
+ * Assumes role for profile that includes role_arn
 
 
 
420
  *
421
+ * @return callable
 
 
422
  */
423
+ private static function loadRoleProfile($profiles, $profileName, $filename, $stsClient)
424
  {
425
+ $roleProfile = $profiles[$profileName];
426
+ $roleArn = isset($roleProfile['role_arn']) ? $roleProfile['role_arn'] : '';
427
+ $roleSessionName = isset($roleProfile['role_session_name']) ? $roleProfile['role_session_name'] : 'aws-sdk-php-' . round(microtime(true) * 1000);
428
+ if (empty($profiles[$profileName]['source_profile'])) {
429
+ return self::reject("source_profile is not set using profile " . $profileName);
430
  }
431
+ $sourceProfileName = $roleProfile['source_profile'];
432
+ if (!isset($profiles[$sourceProfileName])) {
433
+ return self::reject("source_profile " . $sourceProfileName . " using profile " . $profileName . " does not exist");
434
+ }
435
+ $sourceRegion = isset($profiles[$sourceProfileName]['region']) ? $profiles[$sourceProfileName]['region'] : 'us-east-1';
436
+ if (empty($stsClient)) {
437
+ $config = ['preferStaticCredentials' => true];
438
+ $sourceCredentials = call_user_func(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialProvider::ini($sourceProfileName, $filename, $config))->wait();
439
+ $stsClient = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\StsClient(['credentials' => $sourceCredentials, 'region' => $sourceRegion, 'version' => '2011-06-15']);
440
  }
441
+ $result = $stsClient->assumeRole(['RoleArn' => $roleArn, 'RoleSessionName' => $roleSessionName]);
442
+ $creds = $stsClient->createCredentials($result);
443
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for($creds);
444
  }
445
  /**
446
  * Gets the environment's HOME directory if available.
458
  $homePath = getenv('HOMEPATH');
459
  return $homeDrive && $homePath ? $homeDrive . $homePath : null;
460
  }
461
+ /**
462
+ * Gets profiles from specified $filename, or default ini files.
463
+ */
464
+ private static function loadProfiles($filename)
465
+ {
466
+ $profileData = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true, INI_SCANNER_RAW);
467
+ // If loading .aws/credentials, also load .aws/config when AWS_SDK_LOAD_NONDEFAULT_CONFIG is set
468
+ if ($filename === self::getHomeDir() . '/.aws/credentials' && getenv('AWS_SDK_LOAD_NONDEFAULT_CONFIG')) {
469
+ $configFilename = self::getHomeDir() . '/.aws/config';
470
+ $configProfileData = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($configFilename, true, INI_SCANNER_RAW);
471
+ foreach ($configProfileData as $name => $profile) {
472
+ // standardize config profile names
473
+ $name = str_replace('profile ', '', $name);
474
+ if (!isset($profileData[$name])) {
475
+ $profileData[$name] = $profile;
476
+ }
477
+ }
478
+ }
479
+ return $profileData;
480
+ }
481
+ /**
482
+ * Gets profiles from ~/.aws/credentials and ~/.aws/config ini files
483
+ */
484
+ private static function loadDefaultProfiles()
485
+ {
486
+ $profiles = [];
487
+ $credFile = self::getHomeDir() . '/.aws/credentials';
488
+ $configFile = self::getHomeDir() . '/.aws/config';
489
+ if (file_exists($credFile)) {
490
+ $profiles = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($credFile, true, INI_SCANNER_RAW);
491
+ }
492
+ if (file_exists($configFile)) {
493
+ $configProfileData = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($configFile, true, INI_SCANNER_RAW);
494
+ foreach ($configProfileData as $name => $profile) {
495
+ // standardize config profile names
496
+ $name = str_replace('profile ', '', $name);
497
+ if (!isset($profiles[$name])) {
498
+ $profiles[$name] = $profile;
499
+ }
500
+ }
501
+ }
502
+ return $profiles;
503
+ }
504
  private static function reject($msg)
505
  {
506
  return new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\RejectedPromise(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($msg));
vendor/Aws3/Aws/Credentials/EcsCredentialProvider.php CHANGED
@@ -14,8 +14,11 @@ class EcsCredentialProvider
14
  {
15
  const SERVER_URI = 'http://169.254.170.2';
16
  const ENV_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
 
17
  /** @var callable */
18
  private $client;
 
 
19
  /**
20
  * The constructor accepts following options:
21
  * - timeout: (optional) Connection timeout, in seconds, default 1.0
@@ -25,7 +28,7 @@ class EcsCredentialProvider
25
  */
26
  public function __construct(array $config = [])
27
  {
28
- $this->timeout = isset($config['timeout']) ? $config['timeout'] : 1.0;
29
  $this->client = isset($config['client']) ? $config['client'] : \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_http_handler();
30
  }
31
  /**
14
  {
15
  const SERVER_URI = 'http://169.254.170.2';
16
  const ENV_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
17
+ const ENV_TIMEOUT = 'AWS_METADATA_SERVICE_TIMEOUT';
18
  /** @var callable */
19
  private $client;
20
+ /** @var float|mixed */
21
+ private $timeout;
22
  /**
23
  * The constructor accepts following options:
24
  * - timeout: (optional) Connection timeout, in seconds, default 1.0
28
  */
29
  public function __construct(array $config = [])
30
  {
31
+ $this->timeout = (double) getenv(self::ENV_TIMEOUT) ?: (isset($config['timeout']) ? $config['timeout'] : 1.0);
32
  $this->client = isset($config['client']) ? $config['client'] : \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_http_handler();
33
  }
34
  /**
vendor/Aws3/Aws/Credentials/InstanceProfileProvider.php CHANGED
@@ -3,34 +3,51 @@
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials;
4
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException;
 
 
6
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
 
7
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
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
  const ENV_DISABLE = 'AWS_EC2_METADATA_DISABLED';
 
 
18
  /** @var string */
19
  private $profile;
20
  /** @var callable */
21
  private $client;
 
 
 
 
 
 
 
 
22
  /**
23
  * The constructor accepts the following options:
24
  *
25
  * - timeout: Connection timeout, in seconds.
26
  * - profile: Optional EC2 profile name, if known.
 
27
  *
28
  * @param array $config Configuration options.
29
  */
30
  public function __construct(array $config = [])
31
  {
32
- $this->timeout = isset($config['timeout']) ? $config['timeout'] : 1.0;
33
  $this->profile = isset($config['profile']) ? $config['profile'] : null;
 
 
34
  $this->client = isset($config['client']) ? $config['client'] : \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_http_handler();
35
  }
36
  /**
@@ -41,42 +58,124 @@ class InstanceProfileProvider
41
  public function __invoke()
42
  {
43
  return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\coroutine(function () {
44
- if (!$this->profile) {
45
- $this->profile = (yield $this->request(self::CRED_PATH));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  }
47
- $json = (yield $this->request(self::CRED_PATH . $this->profile));
48
- $result = $this->decodeResult($json);
49
  (yield new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\Credentials($result['AccessKeyId'], $result['SecretAccessKey'], $result['Token'], strtotime($result['Expiration'])));
50
  });
51
  }
52
  /**
53
  * @param string $url
 
 
54
  * @return PromiseInterface Returns a promise that is fulfilled with the
55
  * body of the response as a string.
56
  */
57
- private function request($url)
58
  {
59
  $disabled = getenv(self::ENV_DISABLE) ?: false;
60
  if (strcasecmp($disabled, 'true') === 0) {
61
- throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($this->createErrorMessage('EC2 metadata server access disabled'));
62
  }
63
  $fn = $this->client;
64
- $request = new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request('GET', self::SERVER_URI . $url);
 
 
 
 
 
 
 
 
 
65
  return $fn($request, ['timeout' => $this->timeout])->then(function (\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response) {
66
  return (string) $response->getBody();
67
  })->otherwise(function (array $reason) {
68
  $reason = $reason['exception'];
 
 
 
69
  $msg = $reason->getMessage();
70
  throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($this->createErrorMessage($msg));
71
  });
72
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  private function createErrorMessage($previous)
74
  {
75
- return "Error retrieving credentials from the instance profile " . "metadata server. ({$previous})";
76
  }
77
  private function decodeResult($response)
78
  {
79
  $result = json_decode($response, true);
 
 
 
80
  if ($result['Code'] !== 'Success') {
81
  throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException('Unexpected instance profile ' . 'response code: ' . $result['Code']);
82
  }
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials;
4
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidJsonException;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sdk;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Exception\RequestException;
10
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request;
11
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
12
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
13
  /**
14
+ * Credential provider that provides credentials from the EC2 metadata service.
15
  */
16
  class InstanceProfileProvider
17
  {
18
  const SERVER_URI = 'http://169.254.169.254/latest/';
19
  const CRED_PATH = 'meta-data/iam/security-credentials/';
20
+ const TOKEN_PATH = 'api/token';
21
  const ENV_DISABLE = 'AWS_EC2_METADATA_DISABLED';
22
+ const ENV_TIMEOUT = 'AWS_METADATA_SERVICE_TIMEOUT';
23
+ const ENV_RETRIES = 'AWS_METADATA_SERVICE_NUM_ATTEMPTS';
24
  /** @var string */
25
  private $profile;
26
  /** @var callable */
27
  private $client;
28
+ /** @var int */
29
+ private $retries;
30
+ /** @var int */
31
+ private $attempts;
32
+ /** @var float|mixed */
33
+ private $timeout;
34
+ /** @var bool */
35
+ private $secureMode = true;
36
  /**
37
  * The constructor accepts the following options:
38
  *
39
  * - timeout: Connection timeout, in seconds.
40
  * - profile: Optional EC2 profile name, if known.
41
+ * - retries: Optional number of retries to be attempted.
42
  *
43
  * @param array $config Configuration options.
44
  */
45
  public function __construct(array $config = [])
46
  {
47
+ $this->timeout = (double) getenv(self::ENV_TIMEOUT) ?: (isset($config['timeout']) ? $config['timeout'] : 1.0);
48
  $this->profile = isset($config['profile']) ? $config['profile'] : null;
49
+ $this->retries = (int) getenv(self::ENV_RETRIES) ?: (isset($config['retries']) ? $config['retries'] : 3);
50
+ $this->attempts = 0;
51
  $this->client = isset($config['client']) ? $config['client'] : \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_http_handler();
52
  }
53
  /**
58
  public function __invoke()
59
  {
60
  return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\coroutine(function () {
61
+ // Retrieve token or switch out of secure mode
62
+ $token = null;
63
+ while ($this->secureMode && is_null($token)) {
64
+ try {
65
+ $token = (yield $this->request(self::TOKEN_PATH, 'PUT', ['x-aws-ec2-metadata-token-ttl-seconds' => 21600]));
66
+ } catch (RequestException $e) {
67
+ if (empty($e->getResponse()) || !in_array($e->getResponse()->getStatusCode(), [400, 500, 502, 503, 504])) {
68
+ $this->secureMode = false;
69
+ } else {
70
+ $this->handleRetryableException($e, [], $this->createErrorMessage('Error retrieving metadata token'));
71
+ }
72
+ }
73
+ $this->attempts++;
74
+ }
75
+ // Set token header only for secure mode
76
+ $headers = [];
77
+ if ($this->secureMode) {
78
+ $headers = ['x-aws-ec2-metadata-token' => $token];
79
+ }
80
+ // Retrieve profile
81
+ while (!$this->profile) {
82
+ try {
83
+ $this->profile = (yield $this->request(self::CRED_PATH, 'GET', $headers));
84
+ } catch (RequestException $e) {
85
+ // 401 indicates insecure flow not supported, switch to
86
+ // attempting secure mode for subsequent calls
87
+ if (!empty($this->getExceptionStatusCode($e)) && $this->getExceptionStatusCode($e) === 401) {
88
+ $this->secureMode = true;
89
+ }
90
+ $this->handleRetryableException($e, ['blacklist' => [401, 403]], $this->createErrorMessage($e->getMessage()));
91
+ }
92
+ $this->attempts++;
93
+ }
94
+ // Retrieve credentials
95
+ $result = null;
96
+ while ($result == null) {
97
+ try {
98
+ $json = (yield $this->request(self::CRED_PATH . $this->profile, 'GET', $headers));
99
+ $result = $this->decodeResult($json);
100
+ } catch (InvalidJsonException $e) {
101
+ $this->handleRetryableException($e, ['blacklist' => [401, 403]], $this->createErrorMessage('Invalid JSON response, retries exhausted'));
102
+ } catch (RequestException $e) {
103
+ // 401 indicates insecure flow not supported, switch to
104
+ // attempting secure mode for subsequent calls
105
+ if (!empty($this->getExceptionStatusCode($e)) && $this->getExceptionStatusCode($e) === 401) {
106
+ $this->secureMode = true;
107
+ }
108
+ $this->handleRetryableException($e, ['blacklist' => [401, 403]], $this->createErrorMessage($e->getMessage()));
109
+ }
110
+ $this->attempts++;
111
  }
 
 
112
  (yield new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\Credentials($result['AccessKeyId'], $result['SecretAccessKey'], $result['Token'], strtotime($result['Expiration'])));
113
  });
114
  }
115
  /**
116
  * @param string $url
117
+ * @param string $method
118
+ * @param array $headers
119
  * @return PromiseInterface Returns a promise that is fulfilled with the
120
  * body of the response as a string.
121
  */
122
+ private function request($url, $method = 'GET', $headers = [])
123
  {
124
  $disabled = getenv(self::ENV_DISABLE) ?: false;
125
  if (strcasecmp($disabled, 'true') === 0) {
126
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($this->createErrorMessage('EC2 metadata service access disabled'));
127
  }
128
  $fn = $this->client;
129
+ $request = new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request($method, self::SERVER_URI . $url);
130
+ $userAgent = 'aws-sdk-php/' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sdk::VERSION;
131
+ if (defined('HHVM_VERSION')) {
132
+ $userAgent .= ' HHVM/' . HHVM_VERSION;
133
+ }
134
+ $userAgent .= ' ' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_user_agent();
135
+ $request = $request->withHeader('User-Agent', $userAgent);
136
+ foreach ($headers as $key => $value) {
137
+ $request = $request->withHeader($key, $value);
138
+ }
139
  return $fn($request, ['timeout' => $this->timeout])->then(function (\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response) {
140
  return (string) $response->getBody();
141
  })->otherwise(function (array $reason) {
142
  $reason = $reason['exception'];
143
+ if ($reason instanceof \GuzzleHttp\Exception\RequestException) {
144
+ throw $reason;
145
+ }
146
  $msg = $reason->getMessage();
147
  throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($this->createErrorMessage($msg));
148
  });
149
  }
150
+ private function handleRetryableException(\Exception $e, $retryOptions, $message)
151
+ {
152
+ $isRetryable = true;
153
+ if (!empty($status = $this->getExceptionStatusCode($e)) && isset($retryOptions['blacklist']) && in_array($status, $retryOptions['blacklist'])) {
154
+ $isRetryable = false;
155
+ }
156
+ if ($isRetryable && $this->attempts < $this->retries) {
157
+ sleep(pow(1.2, $this->attempts));
158
+ } else {
159
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($message);
160
+ }
161
+ }
162
+ private function getExceptionStatusCode(\Exception $e)
163
+ {
164
+ if (method_exists($e, 'getResponse') && !empty($e->getResponse())) {
165
+ return $e->getResponse()->getStatusCode();
166
+ }
167
+ return null;
168
+ }
169
  private function createErrorMessage($previous)
170
  {
171
+ return "Error retrieving credentials from the instance profile " . "metadata service. ({$previous})";
172
  }
173
  private function decodeResult($response)
174
  {
175
  $result = json_decode($response, true);
176
+ if (json_last_error() > 0) {
177
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidJsonException();
178
+ }
179
  if ($result['Code'] !== 'Success') {
180
  throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException('Unexpected instance profile ' . 'response code: ' . $result['Code']);
181
  }
vendor/Aws3/Aws/Crypto/DecryptionTrait.php CHANGED
@@ -4,6 +4,7 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto;
4
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\LimitStream;
 
7
  trait DecryptionTrait
8
  {
9
  /**
@@ -50,7 +51,7 @@ trait DecryptionTrait
50
  *
51
  * @internal
52
  */
53
- protected function decrypt($cipherText, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MaterialsProvider $provider, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope $envelope, array $cipherOptions = [])
54
  {
55
  $cipherOptions['Iv'] = base64_decode($envelope[\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope::IV_HEADER]);
56
  $cipherOptions['TagLength'] = $envelope[\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] / 8;
@@ -61,7 +62,7 @@ trait DecryptionTrait
61
  unset($cek);
62
  return $decryptionSteam;
63
  }
64
- private function getTagFromCiphertextStream(\DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Stream $cipherText, $tagLength)
65
  {
66
  $cipherTextSize = $cipherText->getSize();
67
  if ($cipherTextSize == null || $cipherTextSize <= 0) {
@@ -69,7 +70,7 @@ trait DecryptionTrait
69
  }
70
  return (string) new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\LimitStream($cipherText, $tagLength, $cipherTextSize - $tagLength);
71
  }
72
- private function getStrippedCiphertextStream(\DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Stream $cipherText, $tagLength)
73
  {
74
  $cipherTextSize = $cipherText->getSize();
75
  if ($cipherTextSize == null || $cipherTextSize <= 0) {
4
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\LimitStream;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\StreamInterface;
8
  trait DecryptionTrait
9
  {
10
  /**
51
  *
52
  * @internal
53
  */
54
+ public function decrypt($cipherText, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MaterialsProvider $provider, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope $envelope, array $cipherOptions = [])
55
  {
56
  $cipherOptions['Iv'] = base64_decode($envelope[\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope::IV_HEADER]);
57
  $cipherOptions['TagLength'] = $envelope[\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] / 8;
62
  unset($cek);
63
  return $decryptionSteam;
64
  }
65
+ private function getTagFromCiphertextStream(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\StreamInterface $cipherText, $tagLength)
66
  {
67
  $cipherTextSize = $cipherText->getSize();
68
  if ($cipherTextSize == null || $cipherTextSize <= 0) {
70
  }
71
  return (string) new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\LimitStream($cipherText, $tagLength, $cipherTextSize - $tagLength);
72
  }
73
+ private function getStrippedCiphertextStream(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\StreamInterface $cipherText, $tagLength)
74
  {
75
  $cipherTextSize = $cipherText->getSize();
76
  if ($cipherTextSize == null || $cipherTextSize <= 0) {
vendor/Aws3/Aws/Crypto/EncryptionTrait.php CHANGED
@@ -42,7 +42,7 @@ trait EncryptionTrait
42
  *
43
  * @internal
44
  */
45
- protected function encrypt(\DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Stream $plaintext, array $cipherOptions, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MaterialsProvider $provider, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope $envelope)
46
  {
47
  $materialsDescription = $provider->getMaterialsDescription();
48
  $cipherOptions = array_intersect_key($cipherOptions, self::$allowedOptions);
42
  *
43
  * @internal
44
  */
45
+ public function encrypt(\DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Stream $plaintext, array $cipherOptions, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MaterialsProvider $provider, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope $envelope)
46
  {
47
  $materialsDescription = $provider->getMaterialsDescription();
48
  $cipherOptions = array_intersect_key($cipherOptions, self::$allowedOptions);
vendor/Aws3/Aws/Endpoint/Partition.php CHANGED
@@ -4,6 +4,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint;
4
 
5
  use ArrayAccess;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasDataTrait;
 
 
7
  use InvalidArgumentException as Iae;
8
  /**
9
  * Default implementation of an AWS partition.
@@ -11,6 +13,7 @@ use InvalidArgumentException as Iae;
11
  final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionInterface
12
  {
13
  use HasDataTrait;
 
14
  /**
15
  * The partition constructor accepts the following options:
16
  *
@@ -48,6 +51,14 @@ final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media
48
  {
49
  return $this->data['partition'];
50
  }
 
 
 
 
 
 
 
 
51
  public function isRegionMatch($region, $service)
52
  {
53
  if (isset($this->data['regions'][$region]) || isset($this->data['services'][$service]['endpoints'][$region])) {
@@ -74,12 +85,13 @@ final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media
74
  $service = isset($args['service']) ? $args['service'] : '';
75
  $region = isset($args['region']) ? $args['region'] : '';
76
  $scheme = isset($args['scheme']) ? $args['scheme'] : 'https';
77
- $data = $this->getEndpointData($service, $region);
 
78
  return ['endpoint' => "{$scheme}://" . $this->formatEndpoint(isset($data['hostname']) ? $data['hostname'] : '', $service, $region), 'signatureVersion' => $this->getSignatureVersion($data), 'signingRegion' => isset($data['credentialScope']['region']) ? $data['credentialScope']['region'] : $region, 'signingName' => isset($data['credentialScope']['service']) ? $data['credentialScope']['service'] : $service];
79
  }
80
- private function getEndpointData($service, $region)
81
  {
82
- $resolved = $this->resolveRegion($service, $region);
83
  $data = isset($this->data['services'][$service]['endpoints'][$resolved]) ? $this->data['services'][$service]['endpoints'][$resolved] : [];
84
  $data += isset($this->data['services'][$service]['defaults']) ? $this->data['services'][$service]['defaults'] : [];
85
  $data += isset($this->data['defaults']) ? $this->data['defaults'] : [];
@@ -91,9 +103,9 @@ final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media
91
  $possibilities = array_intersect($supportedBySdk, isset($data['signatureVersions']) ? $data['signatureVersions'] : ['v4']);
92
  return array_shift($possibilities);
93
  }
94
- private function resolveRegion($service, $region)
95
  {
96
- if ($this->isServicePartitionGlobal($service)) {
97
  return $this->getPartitionEndpoint($service);
98
  }
99
  return $region;
@@ -102,6 +114,32 @@ final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media
102
  {
103
  return isset($this->data['services'][$service]['isRegionalized']) && false === $this->data['services'][$service]['isRegionalized'] && isset($this->data['services'][$service]['partitionEndpoint']);
104
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  private function getPartitionEndpoint($service)
106
  {
107
  return $this->data['services'][$service]['partitionEndpoint'];
4
 
5
  use ArrayAccess;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasDataTrait;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\RegionalEndpoints\ConfigurationProvider;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationProvider as S3ConfigurationProvider;
9
  use InvalidArgumentException as Iae;
10
  /**
11
  * Default implementation of an AWS partition.
13
  final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionInterface
14
  {
15
  use HasDataTrait;
16
+ private $stsLegacyGlobalRegions = ['ap-northeast-1', 'ap-south-1', 'ap-southeast-1', 'ap-southeast-2', 'aws-global', 'ca-central-1', 'eu-central-1', 'eu-north-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'sa-east-1', 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2'];
17
  /**
18
  * The partition constructor accepts the following options:
19
  *
51
  {
52
  return $this->data['partition'];
53
  }
54
+ /**
55
+ * @internal
56
+ * @return mixed
57
+ */
58
+ public function getDnsSuffix()
59
+ {
60
+ return $this->data['dnsSuffix'];
61
+ }
62
  public function isRegionMatch($region, $service)
63
  {
64
  if (isset($this->data['regions'][$region]) || isset($this->data['services'][$service]['endpoints'][$region])) {
85
  $service = isset($args['service']) ? $args['service'] : '';
86
  $region = isset($args['region']) ? $args['region'] : '';
87
  $scheme = isset($args['scheme']) ? $args['scheme'] : 'https';
88
+ $options = isset($args['options']) ? $args['options'] : [];
89
+ $data = $this->getEndpointData($service, $region, $options);
90
  return ['endpoint' => "{$scheme}://" . $this->formatEndpoint(isset($data['hostname']) ? $data['hostname'] : '', $service, $region), 'signatureVersion' => $this->getSignatureVersion($data), 'signingRegion' => isset($data['credentialScope']['region']) ? $data['credentialScope']['region'] : $region, 'signingName' => isset($data['credentialScope']['service']) ? $data['credentialScope']['service'] : $service];
91
  }
92
+ private function getEndpointData($service, $region, $options)
93
  {
94
+ $resolved = $this->resolveRegion($service, $region, $options);
95
  $data = isset($this->data['services'][$service]['endpoints'][$resolved]) ? $this->data['services'][$service]['endpoints'][$resolved] : [];
96
  $data += isset($this->data['services'][$service]['defaults']) ? $this->data['services'][$service]['defaults'] : [];
97
  $data += isset($this->data['defaults']) ? $this->data['defaults'] : [];
103
  $possibilities = array_intersect($supportedBySdk, isset($data['signatureVersions']) ? $data['signatureVersions'] : ['v4']);
104
  return array_shift($possibilities);
105
  }
106
+ private function resolveRegion($service, $region, $options)
107
  {
108
+ if ($this->isServicePartitionGlobal($service) || $this->isStsLegacyEndpointUsed($service, $region, $options) || $this->isS3LegacyEndpointUsed($service, $region, $options)) {
109
  return $this->getPartitionEndpoint($service);
110
  }
111
  return $region;
114
  {
115
  return isset($this->data['services'][$service]['isRegionalized']) && false === $this->data['services'][$service]['isRegionalized'] && isset($this->data['services'][$service]['partitionEndpoint']);
116
  }
117
+ /**
118
+ * STS legacy endpoints used for valid regions unless option is explicitly
119
+ * set to 'regional'
120
+ *
121
+ * @param string $service
122
+ * @param string $region
123
+ * @param array $options
124
+ * @return bool
125
+ */
126
+ private function isStsLegacyEndpointUsed($service, $region, $options)
127
+ {
128
+ return $service === 'sts' && in_array($region, $this->stsLegacyGlobalRegions) && (empty($options['sts_regional_endpoints']) || \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\RegionalEndpoints\ConfigurationProvider::unwrap($options['sts_regional_endpoints'])->getEndpointsType() !== 'regional');
129
+ }
130
+ /**
131
+ * S3 legacy us-east-1 endpoint used for valid regions unless option is explicitly
132
+ * set to 'regional'
133
+ *
134
+ * @param string $service
135
+ * @param string $region
136
+ * @param array $options
137
+ * @return bool
138
+ */
139
+ private function isS3LegacyEndpointUsed($service, $region, $options)
140
+ {
141
+ return $service === 's3' && $region === 'us-east-1' && (empty($options['s3_us_east_1_regional_endpoint']) || \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationProvider::unwrap($options['s3_us_east_1_regional_endpoint'])->getEndpointsType() !== 'regional');
142
+ }
143
  private function getPartitionEndpoint($service)
144
  {
145
  return $this->data['services'][$service]['partitionEndpoint'];
vendor/Aws3/Aws/Endpoint/PartitionEndpointProvider.php CHANGED
@@ -9,16 +9,34 @@ class PartitionEndpointProvider
9
  private $partitions;
10
  /** @var string */
11
  private $defaultPartition;
12
- public function __construct(array $partitions, $defaultPartition = 'aws')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  {
14
  $this->partitions = array_map(function (array $definition) {
15
  return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\Partition($definition);
16
  }, array_values($partitions));
17
  $this->defaultPartition = $defaultPartition;
 
18
  }
19
  public function __invoke(array $args = [])
20
  {
21
  $partition = $this->getPartition(isset($args['region']) ? $args['region'] : '', isset($args['service']) ? $args['service'] : '');
 
22
  return $partition($args);
23
  }
24
  /**
@@ -58,14 +76,15 @@ class PartitionEndpointProvider
58
  /**
59
  * Creates and returns the default SDK partition provider.
60
  *
 
61
  * @return PartitionEndpointProvider
62
  */
63
- public static function defaultProvider()
64
  {
65
  $data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json(__DIR__ . '/../data/endpoints.json');
66
  $prefixData = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json(__DIR__ . '/../data/endpoints_prefix_history.json');
67
  $mergedData = self::mergePrefixData($data, $prefixData);
68
- return new self($mergedData['partitions']);
69
  }
70
  /**
71
  * Copy endpoint data for other prefixes used by a given service
9
  private $partitions;
10
  /** @var string */
11
  private $defaultPartition;
12
+ /** @var array */
13
+ private $options;
14
+ /**
15
+ * The 'options' parameter accepts the following arguments:
16
+ *
17
+ * - sts_regional_endpoints: For STS legacy regions, set to 'regional' to
18
+ * use regional endpoints, 'legacy' to use the legacy global endpoint.
19
+ * Defaults to 'legacy'.
20
+ * - s3_us_east_1_regional_endpoint: For S3 us-east-1 region, set to 'regional'
21
+ * to use the regional endpoint, 'legacy' to use the legacy global endpoint.
22
+ * Defaults to 'legacy'.
23
+ *
24
+ * @param array $partitions
25
+ * @param string $defaultPartition
26
+ * @param array $options
27
+ */
28
+ public function __construct(array $partitions, $defaultPartition = 'aws', $options = [])
29
  {
30
  $this->partitions = array_map(function (array $definition) {
31
  return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\Partition($definition);
32
  }, array_values($partitions));
33
  $this->defaultPartition = $defaultPartition;
34
+ $this->options = $options;
35
  }
36
  public function __invoke(array $args = [])
37
  {
38
  $partition = $this->getPartition(isset($args['region']) ? $args['region'] : '', isset($args['service']) ? $args['service'] : '');
39
+ $args['options'] = $this->options;
40
  return $partition($args);
41
  }
42
  /**
76
  /**
77
  * Creates and returns the default SDK partition provider.
78
  *
79
+ * @param array $options
80
  * @return PartitionEndpointProvider
81
  */
82
+ public static function defaultProvider($options = [])
83
  {
84
  $data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json(__DIR__ . '/../data/endpoints.json');
85
  $prefixData = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json(__DIR__ . '/../data/endpoints_prefix_history.json');
86
  $mergedData = self::mergePrefixData($data, $prefixData);
87
+ return new self($mergedData['partitions'], 'aws', $options);
88
  }
89
  /**
90
  * Copy endpoint data for other prefixes used by a given service
vendor/Aws3/Aws/EndpointDiscovery/Configuration.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery;
4
+
5
+ class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationInterface
6
+ {
7
+ private $cacheLimit;
8
+ private $enabled;
9
+ public function __construct($enabled, $cacheLimit = 1000)
10
+ {
11
+ $this->cacheLimit = filter_var($cacheLimit, FILTER_VALIDATE_INT);
12
+ if ($this->cacheLimit == false || $this->cacheLimit < 1) {
13
+ throw new \InvalidArgumentException("'cache_limit' value must be a positive integer.");
14
+ }
15
+ // Unparsable $enabled flag errs on the side of disabling endpoint discovery
16
+ $this->enabled = filter_var($enabled, FILTER_VALIDATE_BOOLEAN);
17
+ }
18
+ /**
19
+ * {@inheritdoc}
20
+ */
21
+ public function isEnabled()
22
+ {
23
+ return $this->enabled;
24
+ }
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ public function getCacheLimit()
29
+ {
30
+ return $this->cacheLimit;
31
+ }
32
+ /**
33
+ * {@inheritdoc}
34
+ */
35
+ public function toArray()
36
+ {
37
+ return ['enabled' => $this->isEnabled(), 'cache_limit' => $this->getCacheLimit()];
38
+ }
39
+ }
vendor/Aws3/Aws/EndpointDiscovery/ConfigurationInterface.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery;
4
+
5
+ /**
6
+ * Provides access to endpoint discovery configuration options:
7
+ * 'enabled', 'cache_limit'
8
+ */
9
+ interface ConfigurationInterface
10
+ {
11
+ /**
12
+ * Checks whether or not endpoint discovery is enabled.
13
+ *
14
+ * @return bool
15
+ */
16
+ public function isEnabled();
17
+ /**
18
+ * Returns the cache limit, if available.
19
+ *
20
+ * @return string|null
21
+ */
22
+ public function getCacheLimit();
23
+ /**
24
+ * Returns the configuration as an associative array
25
+ *
26
+ * @return array
27
+ */
28
+ public function toArray();
29
+ }
vendor/Aws3/Aws/EndpointDiscovery/ConfigurationProvider.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Exception\ConfigurationException;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
10
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
11
+ /**
12
+ * A configuration provider is a function that returns a promise that is
13
+ * fulfilled with a {@see \Aws\EndpointDiscovery\ConfigurationInterface}
14
+ * or rejected with an {@see \Aws\EndpointDiscovery\Exception\ConfigurationException}.
15
+ *
16
+ * <code>
17
+ * use Aws\EndpointDiscovery\ConfigurationProvider;
18
+ * $provider = ConfigurationProvider::defaultProvider();
19
+ * // Returns a ConfigurationInterface or throws.
20
+ * $config = $provider()->wait();
21
+ * </code>
22
+ *
23
+ * Configuration providers can be composed to create configuration using
24
+ * conditional logic that can create different configurations in different
25
+ * environments. You can compose multiple providers into a single provider using
26
+ * {@see Aws\EndpointDiscovery\ConfigurationProvider::chain}. This function
27
+ * accepts providers as variadic arguments and returns a new function that will
28
+ * invoke each provider until a successful configuration is returned.
29
+ *
30
+ * <code>
31
+ * // First try an INI file at this location.
32
+ * $a = ConfigurationProvider::ini(null, '/path/to/file.ini');
33
+ * // Then try an INI file at this location.
34
+ * $b = ConfigurationProvider::ini(null, '/path/to/other-file.ini');
35
+ * // Then try loading from environment variables.
36
+ * $c = ConfigurationProvider::env();
37
+ * // Combine the three providers together.
38
+ * $composed = ConfigurationProvider::chain($a, $b, $c);
39
+ * // Returns a promise that is fulfilled with a configuration or throws.
40
+ * $promise = $composed();
41
+ * // Wait on the configuration to resolve.
42
+ * $config = $promise->wait();
43
+ * </code>
44
+ */
45
+ class ConfigurationProvider extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface
46
+ {
47
+ const DEFAULT_ENABLED = false;
48
+ const DEFAULT_CACHE_LIMIT = 1000;
49
+ const ENV_ENABLED = 'AWS_ENDPOINT_DISCOVERY_ENABLED';
50
+ const ENV_ENABLED_ALT = 'AWS_ENABLE_ENDPOINT_DISCOVERY';
51
+ const ENV_PROFILE = 'AWS_PROFILE';
52
+ public static $cacheKey = 'aws_cached_endpoint_discovery_config';
53
+ protected static $interfaceClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationInterface::class;
54
+ protected static $exceptionClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Exception\ConfigurationException::class;
55
+ /**
56
+ * Create a default config provider that first checks for environment
57
+ * variables, then checks for a specified profile in the environment-defined
58
+ * config file location (env variable is 'AWS_CONFIG_FILE', file location
59
+ * defaults to ~/.aws/config), then checks for the "default" profile in the
60
+ * environment-defined config file location, and failing those uses a default
61
+ * fallback set of configuration options.
62
+ *
63
+ * This provider is automatically wrapped in a memoize function that caches
64
+ * previously provided config options.
65
+ *
66
+ * @param array $config
67
+ *
68
+ * @return callable
69
+ */
70
+ public static function defaultProvider(array $config = [])
71
+ {
72
+ $configProviders = [self::env(), self::ini(), self::fallback()];
73
+ $memo = self::memoize(call_user_func_array('self::chain', $configProviders));
74
+ if (isset($config['endpoint_discovery']) && $config['endpoint_discovery'] instanceof CacheInterface) {
75
+ return self::cache($memo, $config['endpoint_discovery'], self::$cacheKey);
76
+ }
77
+ return $memo;
78
+ }
79
+ /**
80
+ * Provider that creates config from environment variables.
81
+ *
82
+ * @param $cacheLimit
83
+ * @return callable
84
+ */
85
+ public static function env($cacheLimit = self::DEFAULT_CACHE_LIMIT)
86
+ {
87
+ return function () use($cacheLimit) {
88
+ // Use config from environment variables, if available
89
+ $enabled = getenv(self::ENV_ENABLED);
90
+ if ($enabled === false || $enabled === '') {
91
+ $enabled = getenv(self::ENV_ENABLED_ALT);
92
+ }
93
+ if ($enabled !== false && $enabled !== '') {
94
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Configuration($enabled, $cacheLimit));
95
+ }
96
+ return self::reject('Could not find environment variable config' . ' in ' . self::ENV_ENABLED);
97
+ };
98
+ }
99
+ /**
100
+ * Fallback config options when other sources are not set.
101
+ *
102
+ * @return callable
103
+ */
104
+ public static function fallback()
105
+ {
106
+ return function () {
107
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Configuration(self::DEFAULT_ENABLED, self::DEFAULT_CACHE_LIMIT));
108
+ };
109
+ }
110
+ /**
111
+ * Config provider that creates config using a config file whose location
112
+ * is specified by an environment variable 'AWS_CONFIG_FILE', defaulting to
113
+ * ~/.aws/config if not specified
114
+ *
115
+ * @param string|null $profile Profile to use. If not specified will use
116
+ * the "default" profile.
117
+ * @param string|null $filename If provided, uses a custom filename rather
118
+ * than looking in the default directory.
119
+ * @param int $cacheLimit
120
+ *
121
+ * @return callable
122
+ */
123
+ public static function ini($profile = null, $filename = null, $cacheLimit = self::DEFAULT_CACHE_LIMIT)
124
+ {
125
+ $filename = $filename ?: self::getDefaultConfigFilename();
126
+ $profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
127
+ return function () use($profile, $filename, $cacheLimit) {
128
+ if (!is_readable($filename)) {
129
+ return self::reject("Cannot read configuration from {$filename}");
130
+ }
131
+ $data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true);
132
+ if ($data === false) {
133
+ return self::reject("Invalid config file: {$filename}");
134
+ }
135
+ if (!isset($data[$profile])) {
136
+ return self::reject("'{$profile}' not found in config file");
137
+ }
138
+ if (!isset($data[$profile]['endpoint_discovery_enabled'])) {
139
+ return self::reject("Required endpoint discovery config values \n not present in INI profile '{$profile}' ({$filename})");
140
+ }
141
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Configuration($data[$profile]['endpoint_discovery_enabled'], $cacheLimit));
142
+ };
143
+ }
144
+ /**
145
+ * Unwraps a configuration object in whatever valid form it is in,
146
+ * always returning a ConfigurationInterface object.
147
+ *
148
+ * @param mixed $config
149
+ * @return ConfigurationInterface
150
+ * @throws \InvalidArgumentException
151
+ */
152
+ public static function unwrap($config)
153
+ {
154
+ if (is_callable($config)) {
155
+ $config = $config();
156
+ }
157
+ if ($config instanceof PromiseInterface) {
158
+ $config = $config->wait();
159
+ }
160
+ if ($config instanceof ConfigurationInterface) {
161
+ return $config;
162
+ } elseif (is_array($config) && isset($config['enabled'])) {
163
+ if (isset($config['cache_limit'])) {
164
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Configuration($config['enabled'], $config['cache_limit']);
165
+ }
166
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Configuration($config['enabled'], self::DEFAULT_CACHE_LIMIT);
167
+ }
168
+ throw new \InvalidArgumentException('Not a valid endpoint_discovery ' . 'configuration argument.');
169
+ }
170
+ }
vendor/Aws3/Aws/EndpointDiscovery/EndpointDiscoveryMiddleware.php ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException;
10
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException;
11
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\LruArrayCache;
12
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware;
13
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
14
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface;
15
+ class EndpointDiscoveryMiddleware
16
+ {
17
+ /**
18
+ * @var CacheInterface
19
+ */
20
+ private static $cache;
21
+ private static $discoveryCooldown = 60;
22
+ private $args;
23
+ private $client;
24
+ private $config;
25
+ private $discoveryTimes = [];
26
+ private $nextHandler;
27
+ private $service;
28
+ public static function wrap($client, $args, $config)
29
+ {
30
+ return function (callable $handler) use($client, $args, $config) {
31
+ return new static($handler, $client, $args, $config);
32
+ };
33
+ }
34
+ public function __construct(callable $handler, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient $client, array $args, $config)
35
+ {
36
+ $this->nextHandler = $handler;
37
+ $this->client = $client;
38
+ $this->args = $args;
39
+ $this->service = $client->getApi();
40
+ $this->config = $config;
41
+ }
42
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
43
+ {
44
+ $nextHandler = $this->nextHandler;
45
+ $op = $this->service->getOperation($cmd->getName())->toArray();
46
+ // Continue only if endpointdiscovery trait is set
47
+ if (isset($op['endpointdiscovery'])) {
48
+ $config = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationProvider::unwrap($this->config);
49
+ $isRequired = !empty($op['endpointdiscovery']['required']);
50
+ // Continue only if required by operation or enabled by config
51
+ if ($isRequired || $config->isEnabled()) {
52
+ if (isset($op['endpointoperation'])) {
53
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('This operation is ' . 'contradictorily marked both as using endpoint discovery ' . 'and being the endpoint discovery operation. Please ' . 'verify the accuracy of your model files.');
54
+ }
55
+ // Original endpoint may be used if discovery optional
56
+ $originalUri = $request->getUri();
57
+ $identifiers = $this->getIdentifiers($op);
58
+ $cacheKey = $this->getCacheKey($this->client->getCredentials()->wait(), $cmd, $identifiers);
59
+ // Check/create cache
60
+ if (!isset(self::$cache)) {
61
+ self::$cache = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\LruArrayCache($config->getCacheLimit());
62
+ }
63
+ if (empty($endpointList = self::$cache->get($cacheKey))) {
64
+ $endpointList = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\EndpointList([]);
65
+ }
66
+ $endpoint = $endpointList->getActive();
67
+ // Retrieve endpoints if there is no active endpoint
68
+ if (empty($endpoint)) {
69
+ try {
70
+ $endpoint = $this->discoverEndpoint($cacheKey, $cmd, $identifiers);
71
+ } catch (\Exception $e) {
72
+ // Use cached endpoint, expired or active, if any remain
73
+ $endpoint = $endpointList->getEndpoint();
74
+ if (empty($endpoint)) {
75
+ return $this->handleDiscoveryException($isRequired, $originalUri, $e, $cmd, $request);
76
+ }
77
+ }
78
+ }
79
+ $request = $this->modifyRequest($request, $endpoint);
80
+ $g = function ($value) use($cacheKey, $cmd, $identifiers, $isRequired, $originalUri, $request, &$endpoint, &$g) {
81
+ if ($value instanceof AwsException && ($value->getAwsErrorCode() == 'InvalidEndpointException' || $value->getStatusCode() == 421)) {
82
+ return $this->handleInvalidEndpoint($cacheKey, $cmd, $identifiers, $isRequired, $originalUri, $request, $value, $endpoint, $g);
83
+ }
84
+ return $value;
85
+ };
86
+ return $nextHandler($cmd, $request)->otherwise($g);
87
+ }
88
+ }
89
+ return $nextHandler($cmd, $request);
90
+ }
91
+ private function discoverEndpoint($cacheKey, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, array $identifiers)
92
+ {
93
+ $discCmd = $this->getDiscoveryCommand($cmd, $identifiers);
94
+ $this->discoveryTimes[$cacheKey] = time();
95
+ $result = $this->client->execute($discCmd);
96
+ if (isset($result['Endpoints'])) {
97
+ $endpointData = [];
98
+ foreach ($result['Endpoints'] as $datum) {
99
+ $endpointData[$datum['Address']] = time() + $datum['CachePeriodInMinutes'] * 60;
100
+ }
101
+ $endpointList = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\EndpointList($endpointData);
102
+ self::$cache->set($cacheKey, $endpointList);
103
+ return $endpointList->getEndpoint();
104
+ }
105
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('The endpoint discovery operation ' . 'yielded a response that did not contain properly formatted ' . 'endpoint data.');
106
+ }
107
+ private function getCacheKey(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface $creds, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, array $identifiers)
108
+ {
109
+ $key = $this->service->getServiceName() . '_' . $creds->getAccessKeyId();
110
+ if (!empty($identifiers)) {
111
+ $key .= '_' . $cmd->getName();
112
+ foreach ($identifiers as $identifier) {
113
+ $key .= "_{$cmd[$identifier]}";
114
+ }
115
+ }
116
+ return $key;
117
+ }
118
+ private function getDiscoveryCommand(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, array $identifiers)
119
+ {
120
+ foreach ($this->service->getOperations() as $op) {
121
+ if (isset($op['endpointoperation'])) {
122
+ $endpointOperation = $op->toArray()['name'];
123
+ break;
124
+ }
125
+ }
126
+ if (!isset($endpointOperation)) {
127
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('This command is set to use ' . 'endpoint discovery, but no endpoint discovery operation was ' . 'found. Please verify the accuracy of your model files.');
128
+ }
129
+ $params = [];
130
+ if (!empty($identifiers)) {
131
+ $params['Operation'] = $cmd->getName();
132
+ $params['Identifiers'] = [];
133
+ foreach ($identifiers as $identifier) {
134
+ $params['Identifiers'][$identifier] = $cmd[$identifier];
135
+ }
136
+ }
137
+ $command = $this->client->getCommand($endpointOperation, $params);
138
+ $command->getHandlerList()->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::mapRequest(function (\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $r) {
139
+ return $r->withHeader('x-amz-api-version', $this->service->getApiVersion());
140
+ }), 'x-amz-api-version-header');
141
+ return $command;
142
+ }
143
+ private function getIdentifiers(array $operation)
144
+ {
145
+ $inputShape = $this->service->getShapeMap()->resolve($operation['input'])->toArray();
146
+ $identifiers = [];
147
+ foreach ($inputShape['members'] as $key => $member) {
148
+ if (!empty($member['endpointdiscoveryid'])) {
149
+ $identifiers[] = $key;
150
+ }
151
+ }
152
+ return $identifiers;
153
+ }
154
+ private function handleDiscoveryException($isRequired, $originalUri, \Exception $e, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
155
+ {
156
+ // If no cached endpoints and discovery required,
157
+ // throw exception
158
+ if ($isRequired) {
159
+ $message = 'The endpoint required for this service is currently ' . 'unable to be retrieved, and your request can not be fulfilled ' . 'unless you manually specify an endpoint.';
160
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException($message, $cmd, ['code' => 'EndpointDiscoveryException', 'message' => $message], $e);
161
+ }
162
+ // If discovery isn't required, use original endpoint
163
+ return $this->useOriginalUri($originalUri, $cmd, $request);
164
+ }
165
+ private function handleInvalidEndpoint($cacheKey, $cmd, $identifiers, $isRequired, $originalUri, $request, $value, &$endpoint, &$g)
166
+ {
167
+ $nextHandler = $this->nextHandler;
168
+ $endpointList = self::$cache->get($cacheKey);
169
+ if ($endpointList instanceof EndpointList) {
170
+ // Remove invalid endpoint from cached list
171
+ $endpointList->remove($endpoint);
172
+ // If possible, get another cached endpoint
173
+ $newEndpoint = $endpointList->getEndpoint();
174
+ }
175
+ if (empty($newEndpoint)) {
176
+ // If no more cached endpoints, make discovery call
177
+ // if none made within cooldown for given key
178
+ if (time() - $this->discoveryTimes[$cacheKey] < self::$discoveryCooldown) {
179
+ // If no more cached endpoints and it's required,
180
+ // fail with original exception
181
+ if ($isRequired) {
182
+ return $value;
183
+ }
184
+ // Use original endpoint if not required
185
+ return $this->useOriginalUri($originalUri, $cmd, $request);
186
+ }
187
+ $newEndpoint = $this->discoverEndpoint($cacheKey, $cmd, $identifiers);
188
+ }
189
+ $endpoint = $newEndpoint;
190
+ $request = $this->modifyRequest($request, $endpoint);
191
+ return $nextHandler($cmd, $request)->otherwise($g);
192
+ }
193
+ private function modifyRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, $endpoint)
194
+ {
195
+ $parsed = $this->parseEndpoint($endpoint);
196
+ if (!empty($request->getHeader('User-Agent'))) {
197
+ $userAgent = $request->getHeader('User-Agent')[0];
198
+ if (strpos($userAgent, 'endpoint-discovery') === false) {
199
+ $userAgent = $userAgent . ' endpoint-discovery';
200
+ }
201
+ } else {
202
+ $userAgent = 'endpoint-discovery';
203
+ }
204
+ return $request->withUri($request->getUri()->withHost($parsed['host'])->withPath($parsed['path']))->withHeader('User-Agent', $userAgent);
205
+ }
206
+ /**
207
+ * Parses an endpoint returned from the discovery API into an array with
208
+ * 'host' and 'path' keys.
209
+ *
210
+ * @param $endpoint
211
+ * @return array
212
+ */
213
+ private function parseEndpoint($endpoint)
214
+ {
215
+ $parsed = parse_url($endpoint);
216
+ // parse_url() will correctly parse full URIs with schemes
217
+ if (isset($parsed['host'])) {
218
+ return $parsed;
219
+ }
220
+ // parse_url() will put host & path in 'path' if scheme is not provided
221
+ if (isset($parsed['path'])) {
222
+ $split = explode('/', $parsed['path'], 2);
223
+ $parsed['host'] = $split[0];
224
+ if (isset($split[1])) {
225
+ $parsed['path'] = $split[1];
226
+ } else {
227
+ $parsed['path'] = '';
228
+ }
229
+ return $parsed;
230
+ }
231
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException("The supplied endpoint '" . "{$endpoint}' is invalid.");
232
+ }
233
+ private function useOriginalUri(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface $uri, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
234
+ {
235
+ $nextHandler = $this->nextHandler;
236
+ $endpoint = $uri->getHost() . $uri->getPath();
237
+ $request = $this->modifyRequest($request, $endpoint);
238
+ return $nextHandler($cmd, $request);
239
+ }
240
+ }
vendor/Aws3/Aws/EndpointDiscovery/EndpointList.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery;
4
+
5
+ class EndpointList
6
+ {
7
+ private $active;
8
+ private $expired = [];
9
+ public function __construct(array $endpoints)
10
+ {
11
+ $this->active = $endpoints;
12
+ reset($this->active);
13
+ }
14
+ /**
15
+ * Gets an active (unexpired) endpoint. Returns null if none found.
16
+ *
17
+ * @return null|string
18
+ */
19
+ public function getActive()
20
+ {
21
+ if (count($this->active) < 1) {
22
+ return null;
23
+ }
24
+ while (time() > current($this->active)) {
25
+ $key = key($this->active);
26
+ $this->expired[$key] = current($this->active);
27
+ $this->increment($this->active);
28
+ unset($this->active[$key]);
29
+ if (count($this->active) < 1) {
30
+ return null;
31
+ }
32
+ }
33
+ $active = key($this->active);
34
+ $this->increment($this->active);
35
+ return $active;
36
+ }
37
+ /**
38
+ * Gets an active endpoint if possible, then an expired endpoint if possible.
39
+ * Returns null if no endpoints found.
40
+ *
41
+ * @return null|string
42
+ */
43
+ public function getEndpoint()
44
+ {
45
+ if (!empty($active = $this->getActive())) {
46
+ return $active;
47
+ }
48
+ return $this->getExpired();
49
+ }
50
+ /**
51
+ * Removes an endpoint from both lists.
52
+ *
53
+ * @param string $key
54
+ */
55
+ public function remove($key)
56
+ {
57
+ unset($this->active[$key]);
58
+ unset($this->expired[$key]);
59
+ }
60
+ /**
61
+ * Get an expired endpoint. Returns null if none found.
62
+ *
63
+ * @return null|string
64
+ */
65
+ private function getExpired()
66
+ {
67
+ if (count($this->expired) < 1) {
68
+ return null;
69
+ }
70
+ $expired = key($this->expired);
71
+ $this->increment($this->expired);
72
+ return $expired;
73
+ }
74
+ private function increment(&$array)
75
+ {
76
+ if (next($array) === false) {
77
+ reset($array);
78
+ }
79
+ }
80
+ }
vendor/Aws3/Aws/EndpointDiscovery/Exception/ConfigurationException.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Exception;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
7
+ /**
8
+ * Represents an error interacting with configuration for endpoint discovery
9
+ */
10
+ class ConfigurationException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
11
+ {
12
+ use HasMonitoringEventsTrait;
13
+ }
vendor/Aws3/Aws/EndpointParameterMiddleware.php CHANGED
@@ -14,6 +14,10 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Log\InvalidArgumentException;
14
  */
15
  class EndpointParameterMiddleware
16
  {
 
 
 
 
17
  /**
18
  * Create a middleware wrapper function
19
  *
14
  */
15
  class EndpointParameterMiddleware
16
  {
17
+ /** @var callable */
18
+ private $nextHandler;
19
+ /** @var Service */
20
+ private $service;
21
  /**
22
  * Create a middleware wrapper function
23
  *
vendor/Aws3/Aws/Exception/AwsException.php CHANGED
@@ -2,18 +2,21 @@
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception;
4
 
 
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface;
 
 
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
10
- use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
11
- use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
12
  /**
13
  * Represents an AWS exception that is thrown when a command fails.
14
  */
15
- class AwsException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface
16
  {
 
17
  use HasMonitoringEventsTrait;
18
  /** @var ResponseInterface */
19
  private $response;
@@ -35,6 +38,7 @@ class AwsException extends \RuntimeException implements \DeliciousBrains\WP_Offl
35
  */
36
  public function __construct($message, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, array $context = [], \Exception $previous = null)
37
  {
 
38
  $this->command = $command;
39
  $this->response = isset($context['response']) ? $context['response'] : null;
40
  $this->request = isset($context['request']) ? $context['request'] : null;
@@ -195,4 +199,16 @@ class AwsException extends \RuntimeException implements \DeliciousBrains\WP_Offl
195
  {
196
  $this->maxRetriesExceeded = true;
197
  }
 
 
 
 
 
 
 
 
 
 
 
 
198
  }
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasDataTrait;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface;
10
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
11
+ use DeliciousBrains\WP_Offload_Media\Aws3\JmesPath\Env as JmesPath;
12
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
13
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
 
 
14
  /**
15
  * Represents an AWS exception that is thrown when a command fails.
16
  */
17
+ class AwsException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface, \ArrayAccess
18
  {
19
+ use HasDataTrait;
20
  use HasMonitoringEventsTrait;
21
  /** @var ResponseInterface */
22
  private $response;
38
  */
39
  public function __construct($message, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, array $context = [], \Exception $previous = null)
40
  {
41
+ $this->data = isset($context['body']) ? $context['body'] : [];
42
  $this->command = $command;
43
  $this->response = isset($context['response']) ? $context['response'] : null;
44
  $this->request = isset($context['request']) ? $context['request'] : null;
199
  {
200
  $this->maxRetriesExceeded = true;
201
  }
202
+ public function hasKey($name)
203
+ {
204
+ return isset($this->data[$name]);
205
+ }
206
+ public function get($key)
207
+ {
208
+ return $this[$key];
209
+ }
210
+ public function search($expression)
211
+ {
212
+ return \DeliciousBrains\WP_Offload_Media\Aws3\JmesPath\Env::search($expression, $this->toArray());
213
+ }
214
  }
vendor/Aws3/Aws/Exception/IncalculablePayloadException.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
7
+ class IncalculablePayloadException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
8
+ {
9
+ use HasMonitoringEventsTrait;
10
+ }
vendor/Aws3/Aws/Exception/InvalidJsonException.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
7
+ class InvalidJsonException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
8
+ {
9
+ use HasMonitoringEventsTrait;
10
+ }
vendor/Aws3/Aws/Exception/InvalidRegionException.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
7
+ class InvalidRegionException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
8
+ {
9
+ use HasMonitoringEventsTrait;
10
+ }
vendor/Aws3/Aws/Handler/GuzzleV5/GuzzleHandler.php CHANGED
@@ -25,7 +25,7 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\StreamInterface as Ps
25
  */
26
  class GuzzleHandler
27
  {
28
- private static $validOptions = ['proxy' => true, 'verify' => true, 'timeout' => true, 'debug' => true, 'connect_timeout' => true, 'stream' => true, 'delay' => true, 'sink' => true];
29
  /** @var ClientInterface */
30
  private $client;
31
  /**
@@ -37,9 +37,9 @@ class GuzzleHandler
37
  }
38
  /**
39
  * @param Psr7Request $request
40
- * @param array $options
41
- *
42
- * @return Promise\Promise
43
  */
44
  public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, array $options = [])
45
  {
25
  */
26
  class GuzzleHandler
27
  {
28
+ private static $validOptions = ['proxy' => true, 'expect' => true, 'cert' => true, 'verify' => true, 'timeout' => true, 'debug' => true, 'connect_timeout' => true, 'stream' => true, 'delay' => true, 'sink' => true];
29
  /** @var ClientInterface */
30
  private $client;
31
  /**
37
  }
38
  /**
39
  * @param Psr7Request $request
40
+ * @param array $options
41
+ * @return Promise\Promise|Promise\PromiseInterface
42
+ * @throws \GuzzleHttp\Exception\GuzzleException
43
  */
44
  public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, array $options = [])
45
  {
vendor/Aws3/Aws/MultiRegionClient.php CHANGED
@@ -19,6 +19,8 @@ class MultiRegionClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Aw
19
  private $config;
20
  /** @var HandlerList */
21
  private $handlerList;
 
 
22
  public static function getArguments()
23
  {
24
  $args = array_intersect_key(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver::getDefaultArguments(), ['service' => true, 'region' => true]);
19
  private $config;
20
  /** @var HandlerList */
21
  private $handlerList;
22
+ /** @var array */
23
+ private $aliases;
24
  public static function getArguments()
25
  {
26
  $args = array_intersect_key(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver::getDefaultArguments(), ['service' => true, 'region' => true]);
vendor/Aws3/Aws/Multipart/AbstractUploadManager.php CHANGED
@@ -100,13 +100,27 @@ abstract class AbstractUploadManager implements \DeliciousBrains\WP_Offload_Medi
100
  // Complete the multipart upload.
101
  (yield $this->execCommand('complete', $this->getCompleteParams()));
102
  $this->state->setStatus(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multipart\UploadState::COMPLETED);
103
- })->otherwise(function (\Exception $e) {
104
- // Throw errors from the operations as a specific Multipart error.
105
- if ($e instanceof AwsException) {
106
- $e = new $this->config['exception_class']($this->state, $e);
107
- }
108
- throw $e;
109
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  }
111
  protected function getConfig()
112
  {
100
  // Complete the multipart upload.
101
  (yield $this->execCommand('complete', $this->getCompleteParams()));
102
  $this->state->setStatus(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multipart\UploadState::COMPLETED);
103
+ })->otherwise($this->buildFailureCatch());
104
+ }
105
+ private function transformException($e)
106
+ {
107
+ // Throw errors from the operations as a specific Multipart error.
108
+ if ($e instanceof AwsException) {
109
+ $e = new $this->config['exception_class']($this->state, $e);
110
+ }
111
+ throw $e;
112
+ }
113
+ private function buildFailureCatch()
114
+ {
115
+ if (interface_exists("Throwable")) {
116
+ return function (\Throwable $e) {
117
+ return $this->transformException($e);
118
+ };
119
+ } else {
120
+ return function (\Exception $e) {
121
+ return $this->transformException($e);
122
+ };
123
+ }
124
  }
125
  protected function getConfig()
126
  {
vendor/Aws3/Aws/Psr16CacheAdapter.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\SimpleCache\CacheInterface as SimpleCacheInterface;
6
+ class Psr16CacheAdapter implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface
7
+ {
8
+ /** @var SimpleCacheInterface */
9
+ private $cache;
10
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\SimpleCache\CacheInterface $cache)
11
+ {
12
+ $this->cache = $cache;
13
+ }
14
+ public function get($key)
15
+ {
16
+ return $this->cache->get($key);
17
+ }
18
+ public function set($key, $value, $ttl = 0)
19
+ {
20
+ $this->cache->set($key, $value, $ttl);
21
+ }
22
+ public function remove($key)
23
+ {
24
+ $this->cache->delete($key);
25
+ }
26
+ }
vendor/Aws3/Aws/ResponseContainerInterface.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
4
 
 
5
  interface ResponseContainerInterface
6
  {
7
  /**
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
6
  interface ResponseContainerInterface
7
  {
8
  /**
vendor/Aws3/Aws/RetryMiddleware.php CHANGED
@@ -23,6 +23,9 @@ class RetryMiddleware
23
  'RequestThrottled' => true,
24
  'BandwidthLimitExceeded' => true,
25
  'RequestThrottledException' => true,
 
 
 
26
  ];
27
  private $decider;
28
  private $delay;
@@ -92,6 +95,9 @@ class RetryMiddleware
92
  }
93
  }
94
  if (!$error) {
 
 
 
95
  return isset($statusCodes[$result['@metadata']['statusCode']]);
96
  }
97
  if (!$error instanceof AwsException) {
23
  'RequestThrottled' => true,
24
  'BandwidthLimitExceeded' => true,
25
  'RequestThrottledException' => true,
26
+ 'TooManyRequestsException' => true,
27
+ 'IDPCommunicationError' => true,
28
+ 'EC2ThrottledException' => true,
29
  ];
30
  private $decider;
31
  private $delay;
95
  }
96
  }
97
  if (!$error) {
98
+ if (!isset($result['@metadata']['statusCode'])) {
99
+ return false;
100
+ }
101
  return isset($statusCodes[$result['@metadata']['statusCode']]);
102
  }
103
  if (!$error instanceof AwsException) {
vendor/Aws3/Aws/S3/BucketEndpointArnMiddleware.php ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn;
10
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
11
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider;
12
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidRegionException;
13
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException;
14
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception;
15
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
16
+ /**
17
+ * Checks for access point ARN in members targeting BucketName, modifying
18
+ * endpoint as appropriate
19
+ *
20
+ * @internal
21
+ */
22
+ class BucketEndpointArnMiddleware
23
+ {
24
+ /** @var Service */
25
+ private $service;
26
+ /** @var callable */
27
+ private $nextHandler;
28
+ /** @var string */
29
+ private $region;
30
+ /** @var $config */
31
+ private $config;
32
+ /** @var PartitionEndpointProvider */
33
+ private $partitionProvider;
34
+ /** @var array */
35
+ private $nonArnableCommands = ['CreateBucket'];
36
+ /**
37
+ * Create a middleware wrapper function.
38
+ *
39
+ * @param Service $service
40
+ * @param $region
41
+ * @param array $config
42
+ * @return callable
43
+ */
44
+ public static function wrap(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $service, $region, array $config)
45
+ {
46
+ return function (callable $handler) use($service, $region, $config) {
47
+ return new self($handler, $service, $region, $config);
48
+ };
49
+ }
50
+ public function __construct(callable $nextHandler, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $service, $region, array $config = [])
51
+ {
52
+ $this->partitionProvider = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider::defaultProvider();
53
+ $this->region = $region;
54
+ $this->service = $service;
55
+ $this->config = $config;
56
+ $this->nextHandler = $nextHandler;
57
+ }
58
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $req)
59
+ {
60
+ $nextHandler = $this->nextHandler;
61
+ $op = $this->service->getOperation($cmd->getName())->toArray();
62
+ if (!empty($op['input']['shape'])) {
63
+ $service = $this->service->toArray();
64
+ if (!empty($input = $service['shapes'][$op['input']['shape']])) {
65
+ foreach ($input['members'] as $key => $member) {
66
+ if ($member['shape'] === 'BucketName') {
67
+ $arnableKey = $key;
68
+ break;
69
+ }
70
+ }
71
+ if (!empty($arnableKey) && \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser::isArn($cmd[$arnableKey])) {
72
+ try {
73
+ // Throw for commands that do not support ARN inputs
74
+ if (in_array($cmd->getName(), $this->nonArnableCommands)) {
75
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception('ARN values cannot be used in the bucket field for' . ' the ' . $cmd->getName() . ' operation.', $cmd);
76
+ }
77
+ $arn = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser::parse($cmd[$arnableKey]);
78
+ $partition = $this->validateArn($arn);
79
+ $host = $this->generateAccessPointHost($arn, $req);
80
+ // Remove encoded bucket string from path
81
+ $path = $req->getUri()->getPath();
82
+ $encoded = rawurlencode($cmd[$arnableKey]);
83
+ $len = strlen($encoded) + 1;
84
+ if (substr($path, 0, $len) === "/{$encoded}") {
85
+ $path = substr($path, $len);
86
+ }
87
+ if (empty($path)) {
88
+ $path = '';
89
+ }
90
+ // Set modified request
91
+ $req = $req->withUri($req->getUri()->withHost($host)->withPath($path));
92
+ // Update signing region based on ARN data if configured to do so
93
+ if ($this->config['use_arn_region']->isUseArnRegion()) {
94
+ $region = $arn->getRegion();
95
+ } else {
96
+ $region = $this->region;
97
+ }
98
+ $endpointData = $partition(['region' => $region, 'service' => $arn->getService()]);
99
+ $cmd['@context']['signing_region'] = $endpointData['signingRegion'];
100
+ } catch (InvalidArnException $e) {
101
+ // Add context to ARN exception
102
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception('Bucket parameter parsed as ARN and failed with: ' . $e->getMessage(), $cmd, [], $e);
103
+ }
104
+ }
105
+ }
106
+ }
107
+ return $nextHandler($cmd, $req);
108
+ }
109
+ private function generateAccessPointHost(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn $arn, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $req)
110
+ {
111
+ $host = $arn->getResourceId() . '-' . $arn->getAccountId() . '.s3-accesspoint';
112
+ if (!empty($this->config['dual_stack'])) {
113
+ $host .= '.dualstack';
114
+ }
115
+ if (!empty($this->config['use_arn_region']->isUseArnRegion())) {
116
+ $region = $arn->getRegion();
117
+ } else {
118
+ $region = $this->region;
119
+ }
120
+ $host .= '.' . $region . '.' . $this->getPartitionSuffix($arn);
121
+ return $host;
122
+ }
123
+ private function getPartitionSuffix(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface $arn)
124
+ {
125
+ $partition = $this->partitionProvider->getPartition($arn->getRegion(), $arn->getService());
126
+ return $partition->getDnsSuffix();
127
+ }
128
+ private function getSigningRegion($region)
129
+ {
130
+ $partition = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider::defaultProvider()->getPartition($region, 's3');
131
+ $data = $partition->toArray();
132
+ if (isset($data['services']['s3']['endpoints'][$region]['credentialScope']['region'])) {
133
+ return $data['services']['s3']['endpoints'][$region]['credentialScope']['region'];
134
+ }
135
+ return $region;
136
+ }
137
+ private function isMatchingSigningRegion($arnRegion, $clientRegion)
138
+ {
139
+ $arnRegion = strtolower($arnRegion);
140
+ $clientRegion = $this->stripPseudoRegions(strtolower($clientRegion));
141
+ if ($arnRegion === $clientRegion) {
142
+ return true;
143
+ }
144
+ if ($this->getSigningRegion($clientRegion) === $arnRegion) {
145
+ return true;
146
+ }
147
+ return false;
148
+ }
149
+ private function stripPseudoRegions($region)
150
+ {
151
+ return str_replace(['fips-', '-fips'], ['', ''], $region);
152
+ }
153
+ /**
154
+ * Validates an ARN, returning a partition object corresponding to the ARN
155
+ * if successful
156
+ *
157
+ * @param $arn
158
+ * @return \Aws\Endpoint\Partition
159
+ */
160
+ private function validateArn($arn)
161
+ {
162
+ if ($arn instanceof AccessPointArn) {
163
+ // Accelerate is not supported with access points
164
+ if (!empty($this->config['accelerate'])) {
165
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('Accelerate is currently not supported with access points.' . ' Please disable accelerate or do not supply an access' . ' point ARN.');
166
+ }
167
+ // Path-style is not supported with access points
168
+ if (!empty($this->config['path_style'])) {
169
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('Path-style addressing is currently not supported with' . ' access points. Please disable path-style or do not' . ' supply an access point ARN.');
170
+ }
171
+ // Custom endpoint is not supported with access points
172
+ if (!is_null($this->config['endpoint'])) {
173
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('A custom endpoint has been supplied along with an access' . ' point ARN, and these are not compatible with each other.' . ' Please only use one or the other.');
174
+ }
175
+ // Get partitions for ARN and client region
176
+ $arnPart = $this->partitionProvider->getPartition($arn->getRegion(), 's3');
177
+ $clientPart = $this->partitionProvider->getPartition($this->region, 's3');
178
+ // If client partition not found, try removing pseudo-region qualifiers
179
+ if (!$clientPart->isRegionMatch($this->region, 's3')) {
180
+ $clientPart = $this->partitionProvider->getPartition($this->stripPseudoRegions($this->region), 's3');
181
+ }
182
+ // Verify that the partition matches for supplied partition and region
183
+ if ($arn->getPartition() !== $clientPart->getName()) {
184
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidRegionException('The supplied ARN partition' . " does not match the client's partition.");
185
+ }
186
+ if ($clientPart->getName() !== $arnPart->getName()) {
187
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidRegionException('The corresponding partition' . ' for the supplied ARN region does not match the' . " client's partition.");
188
+ }
189
+ // Ensure ARN region matches client region unless
190
+ // configured for using ARN region over client region
191
+ if (!$this->isMatchingSigningRegion($arn->getRegion(), $this->region)) {
192
+ if (empty($this->config['use_arn_region']) || !$this->config['use_arn_region']->isUseArnRegion()) {
193
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidRegionException('The region' . " specified in the ARN (" . $arn->getRegion() . ") does not match the client region (" . "{$this->region}).");
194
+ }
195
+ }
196
+ return $arnPart;
197
+ }
198
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException('Provided ARN was not' . ' a valid S3 access point ARN');
199
+ }
200
+ }
vendor/Aws3/Aws/S3/MultipartCopy.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
4
 
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multipart\AbstractUploadManager;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
@@ -54,7 +55,12 @@ class MultipartCopy extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multipart
54
  */
55
  public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3ClientInterface $client, $source, array $config = [])
56
  {
57
- $this->source = '/' . ltrim($source, '/');
 
 
 
 
 
58
  parent::__construct($client, array_change_key_case($config) + ['source_metadata' => null]);
59
  }
60
  /**
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multipart\AbstractUploadManager;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
55
  */
56
  public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3ClientInterface $client, $source, array $config = [])
57
  {
58
+ if (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser::isArn($source)) {
59
+ $this->source = '';
60
+ } else {
61
+ $this->source = "/";
62
+ }
63
+ $this->source .= ltrim($source, '/');
64
  parent::__construct($client, array_change_key_case($config) + ['source_metadata' => null]);
65
  }
66
  /**
vendor/Aws3/Aws/S3/MultipartUploader.php CHANGED
@@ -35,7 +35,7 @@ class MultipartUploader extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multi
35
  * operations. The callback should have a function signature like
36
  * `function (Aws\Command $command) {...}`.
37
  * - bucket: (string, required) Name of the bucket to which the object is
38
- * being uploaded.
39
  * - concurrency: (int, default=int(5)) Maximum number of concurrent
40
  * `UploadPart` operations allowed during the multipart upload.
41
  * - key: (string, required) Key to use for the object being uploaded.
35
  * operations. The callback should have a function signature like
36
  * `function (Aws\Command $command) {...}`.
37
  * - bucket: (string, required) Name of the bucket to which the object is
38
+ * being uploaded, or an S3 access point ARN.
39
  * - concurrency: (int, default=int(5)) Maximum number of concurrent
40
  * `UploadPart` operations allowed during the multipart upload.
41
  * - key: (string, required) Key to use for the object being uploaded.
vendor/Aws3/Aws/S3/ObjectCopier.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
4
 
 
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\MultipartUploadException;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception;
@@ -95,6 +97,13 @@ class ObjectCopier implements \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\
95
  }
96
  private function getSourcePath()
97
  {
 
 
 
 
 
 
 
98
  $sourcePath = "/{$this->source['Bucket']}/" . rawurlencode($this->source['Key']);
99
  if (isset($this->source['VersionId'])) {
100
  $sourcePath .= "?versionId={$this->source['VersionId']}";
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\MultipartUploadException;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception;
97
  }
98
  private function getSourcePath()
99
  {
100
+ if (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser::isArn($this->source['Bucket'])) {
101
+ try {
102
+ new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn($this->source['Bucket']);
103
+ } catch (\Exception $e) {
104
+ throw new \InvalidArgumentException('Provided ARN was a not a valid S3 access point ARN (' . $e->getMessage() . ')', 0, $e);
105
+ }
106
+ }
107
  $sourcePath = "/{$this->source['Bucket']}/" . rawurlencode($this->source['Key']);
108
  if (isset($this->source['VersionId'])) {
109
  $sourcePath .= "?versionId={$this->source['VersionId']}";
vendor/Aws3/Aws/S3/ObjectUploader.php CHANGED
@@ -22,7 +22,8 @@ class ObjectUploader implements \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHtt
22
  /**
23
  * @param S3ClientInterface $client The S3 Client used to execute
24
  * the upload command(s).
25
- * @param string $bucket Bucket to upload the object.
 
26
  * @param string $key Key of the object.
27
  * @param mixed $body Object data to upload. Can be a
28
  * StreamInterface, PHP stream
@@ -93,7 +94,7 @@ class ObjectUploader implements \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHtt
93
  return false;
94
  }
95
  // If body >= 5 MB, then use multipart. [YES]
96
- if ($body->isSeekable()) {
97
  // If the body is seekable, just rewind the body.
98
  $body->seek(0);
99
  } else {
22
  /**
23
  * @param S3ClientInterface $client The S3 Client used to execute
24
  * the upload command(s).
25
+ * @param string $bucket Bucket to upload the object, or
26
+ * an S3 access point ARN.
27
  * @param string $key Key of the object.
28
  * @param mixed $body Object data to upload. Can be a
29
  * StreamInterface, PHP stream
94
  return false;
95
  }
96
  // If body >= 5 MB, then use multipart. [YES]
97
+ if ($body->isSeekable() && $body->getMetadata('uri') !== 'php://input') {
98
  // If the body is seekable, just rewind the body.
99
  $body->seek(0);
100
  } else {
vendor/Aws3/Aws/S3/PutObjectUrlMiddleware.php CHANGED
@@ -40,7 +40,7 @@ class PutObjectUrlMiddleware
40
  switch ($name) {
41
  case 'PutObject':
42
  case 'CopyObject':
43
- $result['ObjectURL'] = $result['@metadata']['effectiveUri'];
44
  break;
45
  case 'CompleteMultipartUpload':
46
  $result['ObjectURL'] = $result['Location'];
40
  switch ($name) {
41
  case 'PutObject':
42
  case 'CopyObject':
43
+ $result['ObjectURL'] = isset($result['@metadata']['effectiveUri']) ? $result['@metadata']['effectiveUri'] : null;
44
  break;
45
  case 'CompleteMultipartUpload':
46
  $result['ObjectURL'] = $result['Location'];
vendor/Aws3/Aws/S3/RegionalEndpoint/Configuration.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint;
4
+
5
+ class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationInterface
6
+ {
7
+ private $endpointsType;
8
+ public function __construct($endpointsType)
9
+ {
10
+ $this->endpointsType = strtolower($endpointsType);
11
+ if (!in_array($this->endpointsType, ['legacy', 'regional'])) {
12
+ throw new \InvalidArgumentException("Configuration parameter must either be 'legacy' or 'regional'.");
13
+ }
14
+ }
15
+ /**
16
+ * {@inheritdoc}
17
+ */
18
+ public function getEndpointsType()
19
+ {
20
+ return $this->endpointsType;
21
+ }
22
+ /**
23
+ * {@inheritdoc}
24
+ */
25
+ public function toArray()
26
+ {
27
+ return ['endpoints_type' => $this->getEndpointsType()];
28
+ }
29
+ }
vendor/Aws3/Aws/S3/RegionalEndpoint/ConfigurationInterface.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint;
4
+
5
+ /**
6
+ * Provides access to S3 regional endpoints configuration options: endpoints_type
7
+ */
8
+ interface ConfigurationInterface
9
+ {
10
+ /**
11
+ * Returns the endpoints type
12
+ *
13
+ * @return string
14
+ */
15
+ public function getEndpointsType();
16
+ /**
17
+ * Returns the configuration as an associative array
18
+ *
19
+ * @return array
20
+ */
21
+ public function toArray();
22
+ }
vendor/Aws3/Aws/S3/RegionalEndpoint/ConfigurationProvider.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Exception\ConfigurationException;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
10
+ /**
11
+ * A configuration provider is a function that returns a promise that is
12
+ * fulfilled with a {@see \Aws\S3\RegionalEndpoint\ConfigurationInterface}
13
+ * or rejected with an {@see \Aws\S3\RegionalEndpoint\Exception\ConfigurationException}.
14
+ *
15
+ * <code>
16
+ * use Aws\S3\RegionalEndpoint\ConfigurationProvider;
17
+ * $provider = ConfigurationProvider::defaultProvider();
18
+ * // Returns a ConfigurationInterface or throws.
19
+ * $config = $provider()->wait();
20
+ * </code>
21
+ *
22
+ * Configuration providers can be composed to create configuration using
23
+ * conditional logic that can create different configurations in different
24
+ * environments. You can compose multiple providers into a single provider using
25
+ * {@see \Aws\S3\RegionalEndpoint\ConfigurationProvider::chain}. This function
26
+ * accepts providers as variadic arguments and returns a new function that will
27
+ * invoke each provider until a successful configuration is returned.
28
+ *
29
+ * <code>
30
+ * // First try an INI file at this location.
31
+ * $a = ConfigurationProvider::ini(null, '/path/to/file.ini');
32
+ * // Then try an INI file at this location.
33
+ * $b = ConfigurationProvider::ini(null, '/path/to/other-file.ini');
34
+ * // Then try loading from environment variables.
35
+ * $c = ConfigurationProvider::env();
36
+ * // Combine the three providers together.
37
+ * $composed = ConfigurationProvider::chain($a, $b, $c);
38
+ * // Returns a promise that is fulfilled with a configuration or throws.
39
+ * $promise = $composed();
40
+ * // Wait on the configuration to resolve.
41
+ * $config = $promise->wait();
42
+ * </code>
43
+ */
44
+ class ConfigurationProvider extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface
45
+ {
46
+ const ENV_ENDPOINTS_TYPE = 'AWS_S3_US_EAST_1_REGIONAL_ENDPOINT';
47
+ const INI_ENDPOINTS_TYPE = 's3_us_east_1_regional_endpoint';
48
+ const DEFAULT_ENDPOINTS_TYPE = 'legacy';
49
+ public static $cacheKey = 'aws_s3_us_east_1_regional_endpoint_config';
50
+ protected static $interfaceClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationInterface::class;
51
+ protected static $exceptionClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Exception\ConfigurationException::class;
52
+ /**
53
+ * Create a default config provider that first checks for environment
54
+ * variables, then checks for a specified profile in the environment-defined
55
+ * config file location (env variable is 'AWS_CONFIG_FILE', file location
56
+ * defaults to ~/.aws/config), then checks for the "default" profile in the
57
+ * environment-defined config file location, and failing those uses a default
58
+ * fallback set of configuration options.
59
+ *
60
+ * This provider is automatically wrapped in a memoize function that caches
61
+ * previously provided config options.
62
+ *
63
+ * @param array $config
64
+ *
65
+ * @return callable
66
+ */
67
+ public static function defaultProvider(array $config = [])
68
+ {
69
+ $configProviders = [self::env(), self::ini(), self::fallback()];
70
+ $memo = self::memoize(call_user_func_array('self::chain', $configProviders));
71
+ if (isset($config['s3_us_east_1_regional_endpoint']) && $config['s3_us_east_1_regional_endpoint'] instanceof CacheInterface) {
72
+ return self::cache($memo, $config['s3_us_east_1_regional_endpoint'], self::$cacheKey);
73
+ }
74
+ return $memo;
75
+ }
76
+ public static function env()
77
+ {
78
+ return function () {
79
+ // Use config from environment variables, if available
80
+ $endpointsType = getenv(self::ENV_ENDPOINTS_TYPE);
81
+ if (!empty($endpointsType)) {
82
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Configuration($endpointsType));
83
+ }
84
+ return self::reject('Could not find environment variable config' . ' in ' . self::ENV_ENDPOINTS_TYPE);
85
+ };
86
+ }
87
+ /**
88
+ * Config provider that creates config using a config file whose location
89
+ * is specified by an environment variable 'AWS_CONFIG_FILE', defaulting to
90
+ * ~/.aws/config if not specified
91
+ *
92
+ * @param string|null $profile Profile to use. If not specified will use
93
+ * the "default" profile.
94
+ * @param string|null $filename If provided, uses a custom filename rather
95
+ * than looking in the default directory.
96
+ *
97
+ * @return callable
98
+ */
99
+ public static function ini($profile = null, $filename = null)
100
+ {
101
+ $filename = $filename ?: self::getDefaultConfigFilename();
102
+ $profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
103
+ return function () use($profile, $filename) {
104
+ if (!is_readable($filename)) {
105
+ return self::reject("Cannot read configuration from {$filename}");
106
+ }
107
+ $data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true);
108
+ if ($data === false) {
109
+ return self::reject("Invalid config file: {$filename}");
110
+ }
111
+ if (!isset($data[$profile])) {
112
+ return self::reject("'{$profile}' not found in config file");
113
+ }
114
+ if (!isset($data[$profile][self::INI_ENDPOINTS_TYPE])) {
115
+ return self::reject("Required S3 regional endpoint config values \n not present in INI profile '{$profile}' ({$filename})");
116
+ }
117
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Configuration($data[$profile][self::INI_ENDPOINTS_TYPE]));
118
+ };
119
+ }
120
+ /**
121
+ * Fallback config options when other sources are not set.
122
+ *
123
+ * @return callable
124
+ */
125
+ public static function fallback()
126
+ {
127
+ return function () {
128
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Configuration(self::DEFAULT_ENDPOINTS_TYPE));
129
+ };
130
+ }
131
+ /**
132
+ * Unwraps a configuration object in whatever valid form it is in,
133
+ * always returning a ConfigurationInterface object.
134
+ *
135
+ * @param mixed $config
136
+ * @return ConfigurationInterface
137
+ * @throws \InvalidArgumentException
138
+ */
139
+ public static function unwrap($config)
140
+ {
141
+ if (is_callable($config)) {
142
+ $config = $config();
143
+ }
144
+ if ($config instanceof Promise\PromiseInterface) {
145
+ $config = $config->wait();
146
+ }
147
+ if ($config instanceof ConfigurationInterface) {
148
+ return $config;
149
+ }
150
+ if (is_string($config)) {
151
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Configuration($config);
152
+ }
153
+ if (is_array($config) && isset($config['endpoints_type'])) {
154
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Configuration($config['endpoints_type']);
155
+ }
156
+ throw new \InvalidArgumentException('Not a valid S3 regional endpoint ' . 'configuration argument.');
157
+ }
158
+ }
vendor/Aws3/Aws/S3/RegionalEndpoint/Exception/ConfigurationException.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Exception;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
7
+ /**
8
+ * Represents an error interacting with configuration for sts regional endpoints
9
+ */
10
+ class ConfigurationException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
11
+ {
12
+ use HasMonitoringEventsTrait;
13
+ }
vendor/Aws3/Aws/S3/S3Client.php CHANGED
@@ -6,6 +6,7 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient;
 
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver;
10
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Command;
11
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException;
@@ -14,7 +15,13 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware;
14
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\RetryMiddleware;
15
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
16
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
 
 
 
 
17
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Exception\RequestException;
 
 
18
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
19
  /**
20
  * Client used to interact with **Amazon Simple Storage Service (Amazon S3)**.
@@ -204,7 +211,7 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
204
  $args = parent::getArguments();
205
  $args['retries']['fn'] = [__CLASS__, '_applyRetryConfig'];
206
  $args['api_provider']['fn'] = [__CLASS__, '_applyApiProvider'];
207
- return $args + ['bucket_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to a hardcoded ' . 'bucket endpoint rather than create an endpoint as a ' . 'result of injecting the bucket into the URL. This ' . 'option is useful for interacting with CNAME endpoints.'], 'use_accelerate_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 Accelerate' . ' endpoint by default. Can be enabled or disabled on' . ' individual operations by setting' . ' \'@use_accelerate_endpoint\' to true or false. Note:' . ' you must enable S3 Accelerate on a bucket before it can' . ' be accessed via an Accelerate endpoint.', 'default' => false], 'use_dual_stack_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 Dual Stack' . ' endpoint by default, which enables IPv6 Protocol.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@use_dual_stack_endpoint\' to true or false.', 'default' => false], 'use_path_style_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 path style' . ' endpoint by default.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@use_path_style_endpoint\' to true or false.', 'default' => false]];
208
  }
209
  /**
210
  * {@inheritdoc}
@@ -219,11 +226,28 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
219
  * interacting with CNAME endpoints.
220
  * - calculate_md5: (bool) Set to false to disable calculating an MD5
221
  * for all Amazon S3 signed uploads.
 
 
 
 
 
 
 
 
 
222
  * - use_accelerate_endpoint: (bool) Set to true to send requests to an S3
223
  * Accelerate endpoint by default. Can be enabled or disabled on
224
  * individual operations by setting '@use_accelerate_endpoint' to true or
225
  * false. Note: you must enable S3 Accelerate on a bucket before it can be
226
  * accessed via an Accelerate endpoint.
 
 
 
 
 
 
 
 
227
  * - use_dual_stack_endpoint: (bool) Set to true to send requests to an S3
228
  * Dual Stack endpoint by default, which enables IPv6 Protocol.
229
  * Can be enabled or disabled on individual operations by setting
@@ -239,6 +263,11 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
239
  */
240
  public function __construct(array $args)
241
  {
 
 
 
 
 
242
  parent::__construct($args);
243
  $stack = $this->getHandlerList();
244
  $stack->appendInit(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\SSECMiddleware::wrap($this->getEndpoint()->getScheme()), 's3.ssec');
@@ -250,6 +279,7 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
250
  } else {
251
  $stack->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3EndpointMiddleware::wrap($this->getRegion(), ['dual_stack' => $this->getConfig('use_dual_stack_endpoint'), 'accelerate' => $this->getConfig('use_accelerate_endpoint'), 'path_style' => $this->getConfig('use_path_style_endpoint')]), 's3.endpoint_middleware');
252
  }
 
253
  $stack->appendSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\PutObjectUrlMiddleware::wrap(), 's3.put_object_url');
254
  $stack->appendSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\PermanentRedirectMiddleware::wrap(), 's3.permanent_redirect');
255
  $stack->appendInit(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::sourceFile($this->getApi()), 's3.source_file');
@@ -274,14 +304,45 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
274
  $bucketLen = strlen($bucket);
275
  return $bucketLen >= 3 && $bucketLen <= 63 && !filter_var($bucket, FILTER_VALIDATE_IP) && preg_match('/^[a-z0-9]([a-z0-9\\-\\.]*[a-z0-9])?$/', $bucket);
276
  }
277
- public function createPresignedRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, $expires)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  {
279
  $command = clone $command;
280
  $command->getHandlerList()->remove('signer');
281
  /** @var \Aws\Signature\SignatureInterface $signer */
282
  $signer = call_user_func($this->getSignatureProvider(), $this->getConfig('signature_version'), $this->getConfig('signing_name'), $this->getConfig('signing_region'));
283
- return $signer->presign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\serialize($command), $this->getCredentials()->wait(), $expires);
284
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  public function getObjectUrl($bucket, $key)
286
  {
287
  $command = $this->getCommand('GetObject', ['Bucket' => $bucket, 'Key' => $key]);
@@ -424,7 +485,7 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
424
  /** @internal */
425
  public static function _applyApiProvider($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
426
  {
427
- \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver::_apply_api_provider($value, $args, $list);
428
  $args['parser'] = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\GetBucketLocationParser(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\AmbiguousSuccessParser(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RetryableMalformedResponseParser($args['parser'], $args['exception_class']), $args['error_parser'], $args['exception_class']));
429
  }
430
  /**
@@ -469,4 +530,24 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
469
  $docs['shapes']['ContentMD5']['append'] = '<div class="alert alert-info">The value will be computed on ' . 'your behalf.</div>';
470
  return [new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service($api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::defaultProvider()), new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel($docs)];
471
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472
  }
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel;
7
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
10
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver;
11
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Command;
12
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException;
15
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\RetryMiddleware;
16
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
17
  use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
18
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration;
19
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationInterface;
20
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationProvider as UseArnRegionConfigurationProvider;
21
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationProvider;
22
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Exception\RequestException;
23
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\Promise;
24
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
25
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
26
  /**
27
  * Client used to interact with **Amazon Simple Storage Service (Amazon S3)**.
211
  $args = parent::getArguments();
212
  $args['retries']['fn'] = [__CLASS__, '_applyRetryConfig'];
213
  $args['api_provider']['fn'] = [__CLASS__, '_applyApiProvider'];
214
+ return $args + ['bucket_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to a hardcoded ' . 'bucket endpoint rather than create an endpoint as a ' . 'result of injecting the bucket into the URL. This ' . 'option is useful for interacting with CNAME endpoints.'], 'use_arn_region' => ['type' => 'config', 'valid' => ['bool', \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration::class, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface::class, 'callable'], 'doc' => 'Set to true to allow passed in ARNs to override' . ' client region. Accepts...', 'fn' => [__CLASS__, '_apply_use_arn_region'], 'default' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationProvider::class, 'defaultProvider']], 'use_accelerate_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 Accelerate' . ' endpoint by default. Can be enabled or disabled on' . ' individual operations by setting' . ' \'@use_accelerate_endpoint\' to true or false. Note:' . ' you must enable S3 Accelerate on a bucket before it can' . ' be accessed via an Accelerate endpoint.', 'default' => false], 'use_dual_stack_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 Dual Stack' . ' endpoint by default, which enables IPv6 Protocol.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@use_dual_stack_endpoint\' to true or false.', 'default' => false], 'use_path_style_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 path style' . ' endpoint by default.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@use_path_style_endpoint\' to true or false.', 'default' => false]];
215
  }
216
  /**
217
  * {@inheritdoc}
226
  * interacting with CNAME endpoints.
227
  * - calculate_md5: (bool) Set to false to disable calculating an MD5
228
  * for all Amazon S3 signed uploads.
229
+ * - s3_us_east_1_regional_endpoint:
230
+ * (Aws\S3\RegionalEndpoint\ConfigurationInterface|Aws\CacheInterface\|callable|string|array)
231
+ * Specifies whether to use regional or legacy endpoints for the us-east-1
232
+ * region. Provide an Aws\S3\RegionalEndpoint\ConfigurationInterface object, an
233
+ * instance of Aws\CacheInterface, a callable configuration provider used
234
+ * to create endpoint configuration, a string value of `legacy` or
235
+ * `regional`, or an associative array with the following keys:
236
+ * endpoint_types: (string) Set to `legacy` or `regional`, defaults to
237
+ * `legacy`
238
  * - use_accelerate_endpoint: (bool) Set to true to send requests to an S3
239
  * Accelerate endpoint by default. Can be enabled or disabled on
240
  * individual operations by setting '@use_accelerate_endpoint' to true or
241
  * false. Note: you must enable S3 Accelerate on a bucket before it can be
242
  * accessed via an Accelerate endpoint.
243
+ * - use_arn_region: (Aws\S3\UseArnRegion\ConfigurationInterface,
244
+ * Aws\CacheInterface, bool, callable) Set to true to enable the client
245
+ * to use the region from a supplied ARN argument instead of the client's
246
+ * region. Provide an instance of Aws\S3\UseArnRegion\ConfigurationInterface,
247
+ * an instance of Aws\CacheInterface, a callable that provides a promise for
248
+ * a Configuration object, or a boolean value. Defaults to false (i.e.
249
+ * the SDK will not follow the ARN region if it conflicts with the client
250
+ * region and instead throw an error).
251
  * - use_dual_stack_endpoint: (bool) Set to true to send requests to an S3
252
  * Dual Stack endpoint by default, which enables IPv6 Protocol.
253
  * Can be enabled or disabled on individual operations by setting
263
  */
264
  public function __construct(array $args)
265
  {
266
+ if (!isset($args['s3_us_east_1_regional_endpoint'])) {
267
+ $args['s3_us_east_1_regional_endpoint'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationProvider::defaultProvider();
268
+ } elseif ($args['s3_us_east_1_regional_endpoint'] instanceof CacheInterface) {
269
+ $args['s3_us_east_1_regional_endpoint'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationProvider::defaultProvider($args);
270
+ }
271
  parent::__construct($args);
272
  $stack = $this->getHandlerList();
273
  $stack->appendInit(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\SSECMiddleware::wrap($this->getEndpoint()->getScheme()), 's3.ssec');
279
  } else {
280
  $stack->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3EndpointMiddleware::wrap($this->getRegion(), ['dual_stack' => $this->getConfig('use_dual_stack_endpoint'), 'accelerate' => $this->getConfig('use_accelerate_endpoint'), 'path_style' => $this->getConfig('use_path_style_endpoint')]), 's3.endpoint_middleware');
281
  }
282
+ $stack->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\BucketEndpointArnMiddleware::wrap($this->getApi(), $this->getRegion(), ['use_arn_region' => $this->getConfig('use_arn_region'), 'dual_stack' => $this->getConfig('use_dual_stack_endpoint'), 'accelerate' => $this->getConfig('use_accelerate_endpoint'), 'path_style' => $this->getConfig('use_path_style_endpoint'), 'endpoint' => isset($args['endpoint']) ? $args['endpoint'] : null]), 's3.bucket_endpoint_arn');
283
  $stack->appendSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\PutObjectUrlMiddleware::wrap(), 's3.put_object_url');
284
  $stack->appendSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\PermanentRedirectMiddleware::wrap(), 's3.permanent_redirect');
285
  $stack->appendInit(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::sourceFile($this->getApi()), 's3.source_file');
304
  $bucketLen = strlen($bucket);
305
  return $bucketLen >= 3 && $bucketLen <= 63 && !filter_var($bucket, FILTER_VALIDATE_IP) && preg_match('/^[a-z0-9]([a-z0-9\\-\\.]*[a-z0-9])?$/', $bucket);
306
  }
307
+ public static function _apply_use_arn_region($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
308
+ {
309
+ if ($value instanceof CacheInterface) {
310
+ $value = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationProvider::defaultProvider($args);
311
+ }
312
+ if (is_callable($value)) {
313
+ $value = $value();
314
+ }
315
+ if ($value instanceof PromiseInterface) {
316
+ $value = $value->wait();
317
+ }
318
+ if ($value instanceof ConfigurationInterface) {
319
+ $args['use_arn_region'] = $value;
320
+ } else {
321
+ // The Configuration class itself will validate other inputs
322
+ $args['use_arn_region'] = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration($value);
323
+ }
324
+ }
325
+ public function createPresignedRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, $expires, array $options = [])
326
  {
327
  $command = clone $command;
328
  $command->getHandlerList()->remove('signer');
329
  /** @var \Aws\Signature\SignatureInterface $signer */
330
  $signer = call_user_func($this->getSignatureProvider(), $this->getConfig('signature_version'), $this->getConfig('signing_name'), $this->getConfig('signing_region'));
331
+ return $signer->presign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\serialize($command), $this->getCredentials()->wait(), $expires, $options);
332
  }
333
+ /**
334
+ * Returns the URL to an object identified by its bucket and key.
335
+ *
336
+ * The URL returned by this method is not signed nor does it ensure that the
337
+ * bucket and key given to the method exist. If you need a signed URL, then
338
+ * use the {@see \Aws\S3\S3Client::createPresignedRequest} method and get
339
+ * the URI of the signed request.
340
+ *
341
+ * @param string $bucket The name of the bucket where the object is located
342
+ * @param string $key The key of the object
343
+ *
344
+ * @return string The URL to the object
345
+ */
346
  public function getObjectUrl($bucket, $key)
347
  {
348
  $command = $this->getCommand('GetObject', ['Bucket' => $bucket, 'Key' => $key]);
485
  /** @internal */
486
  public static function _applyApiProvider($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
487
  {
488
+ \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver::_apply_api_provider($value, $args);
489
  $args['parser'] = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\GetBucketLocationParser(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\AmbiguousSuccessParser(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RetryableMalformedResponseParser($args['parser'], $args['exception_class']), $args['error_parser'], $args['exception_class']));
490
  }
491
  /**
530
  $docs['shapes']['ContentMD5']['append'] = '<div class="alert alert-info">The value will be computed on ' . 'your behalf.</div>';
531
  return [new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service($api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::defaultProvider()), new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel($docs)];
532
  }
533
+ /**
534
+ * @internal
535
+ * @codeCoverageIgnore
536
+ */
537
+ public static function addDocExamples($examples)
538
+ {
539
+ $getObjectExample = ['input' => ['Bucket' => 'arn:aws:s3:us-east-1:123456789012:accesspoint:myaccesspoint', 'Key' => 'my-key'], 'output' => ['Body' => 'class GuzzleHttp\\Psr7\\Stream#208 (7) {...}', 'ContentLength' => '11', 'ContentType' => 'application/octet-stream'], 'comments' => ['input' => '', 'output' => 'Simplified example output'], 'description' => 'The following example retrieves an object by referencing the bucket via an S3 accesss point ARN. Result output is simplified for the example.', 'id' => '', 'title' => 'To get an object via an S3 access point ARN'];
540
+ if (isset($examples['GetObject'])) {
541
+ $examples['GetObject'][] = $getObjectExample;
542
+ } else {
543
+ $examples['GetObject'] = [$getObjectExample];
544
+ }
545
+ $putObjectExample = ['input' => ['Bucket' => 'arn:aws:s3:us-east-1:123456789012:accesspoint:myaccesspoint', 'Key' => 'my-key', 'Body' => 'my-body'], 'output' => ['ObjectURL' => 'https://my-bucket.s3.us-east-1.amazonaws.com/my-key'], 'comments' => ['input' => '', 'output' => 'Simplified example output'], 'description' => 'The following example uploads an object by referencing the bucket via an S3 accesss point ARN. Result output is simplified for the example.', 'id' => '', 'title' => 'To upload an object via an S3 access point ARN'];
546
+ if (isset($examples['PutObject'])) {
547
+ $examples['PutObject'][] = $putObjectExample;
548
+ } else {
549
+ $examples['PutObject'] = [$putObjectExample];
550
+ }
551
+ return $examples;
552
+ }
553
  }
vendor/Aws3/Aws/S3/S3ClientInterface.php CHANGED
@@ -22,11 +22,11 @@ interface S3ClientInterface extends AwsClientInterface
22
  *
23
  * @return RequestInterface
24
  */
25
- public function createPresignedRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, $expires);
26
  /**
27
  * Returns the URL to an object identified by its bucket and key.
28
  *
29
- * The URL returned by this method is not signed nor does it ensure the the
30
  * bucket and key given to the method exist. If you need a signed URL, then
31
  * use the {@see \Aws\S3\S3Client::createPresignedRequest} method and get
32
  * the URI of the signed request.
22
  *
23
  * @return RequestInterface
24
  */
25
+ public function createPresignedRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, $expires, array $options = []);
26
  /**
27
  * Returns the URL to an object identified by its bucket and key.
28
  *
29
+ * The URL returned by this method is not signed nor does it ensure that the
30
  * bucket and key given to the method exist. If you need a signed URL, then
31
  * use the {@see \Aws\S3\S3Client::createPresignedRequest} method and get
32
  * the URI of the signed request.
vendor/Aws3/Aws/S3/S3EndpointMiddleware.php CHANGED
@@ -79,7 +79,7 @@ class S3EndpointMiddleware
79
  }
80
  private static function isRequestHostStyleCompatible(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
81
  {
82
- return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3Client::isBucketDnsCompatible($command['Bucket']) && ($request->getUri()->getScheme() === 'http' || strpos($command['Bucket'], '.') === false);
83
  }
84
  private function endpointPatternDecider(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
85
  {
79
  }
80
  private static function isRequestHostStyleCompatible(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
81
  {
82
+ return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3Client::isBucketDnsCompatible($command['Bucket']) && ($request->getUri()->getScheme() === 'http' || strpos($command['Bucket'], '.') === false) && filter_var($request->getUri()->getHost(), FILTER_VALIDATE_IP) === false;
83
  }
84
  private function endpointPatternDecider(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
85
  {
vendor/Aws3/Aws/S3/S3MultiRegionClient.php CHANGED
@@ -255,7 +255,7 @@ class S3MultiRegionClient extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Mul
255
  };
256
  };
257
  }
258
- public function createPresignedRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, $expires)
259
  {
260
  if (empty($command['Bucket'])) {
261
  throw new \InvalidArgumentException('The S3\\MultiRegionClient' . ' cannot create presigned requests for commands without a' . ' specified bucket.');
255
  };
256
  };
257
  }
258
+ public function createPresignedRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, $expires, array $options = [])
259
  {
260
  if (empty($command['Bucket'])) {
261
  throw new \InvalidArgumentException('The S3\\MultiRegionClient' . ' cannot create presigned requests for commands without a' . ' specified bucket.');
vendor/Aws3/Aws/S3/S3UriParser.php CHANGED
@@ -2,6 +2,9 @@
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
4
 
 
 
 
5
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
6
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface;
7
  /**
@@ -24,10 +27,18 @@ class S3UriParser
24
  * @param string|UriInterface $uri
25
  *
26
  * @return array
27
- * @throws \InvalidArgumentException
28
  */
29
  public function parse($uri)
30
  {
 
 
 
 
 
 
 
 
31
  $url = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\uri_for($uri);
32
  if ($url->getScheme() == $this->streamWrapperScheme) {
33
  return $this->parseStreamWrapper($url);
@@ -44,6 +55,14 @@ class S3UriParser
44
  $result['region'] = $matches[2] == 'amazonaws' ? null : $matches[2];
45
  return $result;
46
  }
 
 
 
 
 
 
 
 
47
  private function parseStreamWrapper(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface $url)
48
  {
49
  $result = self::$defaultResult;
2
 
3
  namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser;
8
  use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
9
  use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface;
10
  /**
27
  * @param string|UriInterface $uri
28
  *
29
  * @return array
30
+ * @throws \InvalidArgumentException|InvalidArnException
31
  */
32
  public function parse($uri)
33
  {
34
+ // Attempt to parse host component of uri as an ARN
35
+ $components = $this->parseS3UrlComponents($uri);
36
+ if (!empty($components)) {
37
+ if (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser::isArn($components['host'])) {
38
+ $arn = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn($components['host']);
39
+ return ['bucket' => $components['host'], 'key' => $components['path'], 'path_style' => false, 'region' => $arn->getRegion()];
40
+ }
41
+ }
42
  $url = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\uri_for($uri);
43
  if ($url->getScheme() == $this->streamWrapperScheme) {
44
  return $this->parseStreamWrapper($url);
55
  $result['region'] = $matches[2] == 'amazonaws' ? null : $matches[2];
56
  return $result;
57
  }
58
+ private function parseS3UrlComponents($uri)
59
+ {
60
+ preg_match("/^([a-zA-Z0-9]*):\\/\\/([a-zA-Z0-9:-]*)\\/(.*)/", $uri, $components);
61
+ if (empty($components)) {
62
+ return [];
63
+ }
64
+ return ['scheme' => $components[1], 'host' => $components[2], 'path' => $components[3]];
65
+ }
66
  private function parseStreamWrapper(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface $url)
67
  {
68
  $result = self::$defaultResult;
vendor/Aws3/Aws/S3/StreamWrapper.php CHANGED
@@ -83,6 +83,8 @@ class StreamWrapper
83
  private $cache;
84
  /** @var string The opened protocol (e.g., "s3") */
85
  private $protocol = 's3';
 
 
86
  /**
87
  * Register the 's3://' stream wrapper
88
  *
@@ -109,24 +111,28 @@ class StreamWrapper
109
  }
110
  public function stream_close()
111
  {
 
 
 
112
  $this->body = $this->cache = null;
113
  }
114
  public function stream_open($path, $mode, $options, &$opened_path)
115
  {
116
  $this->initProtocol($path);
 
117
  $this->params = $this->getBucketKey($path);
118
  $this->mode = rtrim($mode, 'bt');
119
  if ($errors = $this->validate($path, $this->mode)) {
120
  return $this->triggerError($errors);
121
  }
122
- return $this->boolCall(function () use($path) {
123
  switch ($this->mode) {
124
  case 'r':
125
- return $this->openReadStream($path);
126
  case 'a':
127
- return $this->openAppendStream($path);
128
  default:
129
- return $this->openWriteStream($path);
130
  }
131
  });
132
  }
@@ -136,6 +142,7 @@ class StreamWrapper
136
  }
137
  public function stream_flush()
138
  {
 
139
  if ($this->mode == 'r') {
140
  return false;
141
  }
@@ -367,7 +374,7 @@ class StreamWrapper
367
  */
368
  public function dir_rewinddir()
369
  {
370
- $this->boolCall(function () {
371
  $this->objectIterator = null;
372
  $this->dir_opendir($this->openedPath, null);
373
  return true;
@@ -760,6 +767,6 @@ class StreamWrapper
760
  private function getSize()
761
  {
762
  $size = $this->body->getSize();
763
- return $size !== null ? $size : $this->size;
764
  }
765
  }
83
  private $cache;
84
  /** @var string The opened protocol (e.g., "s3") */
85
  private $protocol = 's3';
86
+ /** @var bool Keeps track of whether stream has been flushed since opening */
87
+ private $isFlushed = false;
88
  /**
89
  * Register the 's3://' stream wrapper
90
  *
111
  }
112
  public function stream_close()
113
  {
114
+ if ($this->body->getSize() === 0 && !$this->isFlushed) {
115
+ $this->stream_flush();
116
+ }
117
  $this->body = $this->cache = null;
118
  }
119
  public function stream_open($path, $mode, $options, &$opened_path)
120
  {
121
  $this->initProtocol($path);
122
+ $this->isFlushed = false;
123
  $this->params = $this->getBucketKey($path);
124
  $this->mode = rtrim($mode, 'bt');
125
  if ($errors = $this->validate($path, $this->mode)) {
126
  return $this->triggerError($errors);
127
  }
128
+ return $this->boolCall(function () {
129
  switch ($this->mode) {
130
  case 'r':
131
+ return $this->openReadStream();
132
  case 'a':
133
+ return $this->openAppendStream();
134
  default:
135
+ return $this->openWriteStream();
136
  }
137
  });
138
  }
142
  }
143
  public function stream_flush()
144
  {
145
+ $this->isFlushed = true;
146
  if ($this->mode == 'r') {
147
  return false;
148
  }
374
  */
375
  public function dir_rewinddir()
376
  {
377
+ return $this->boolCall(function () {
378
  $this->objectIterator = null;
379
  $this->dir_opendir($this->openedPath, null);
380
  return true;
767
  private function getSize()
768
  {
769
  $size = $this->body->getSize();
770
+ return !empty($size) ? $size : $this->size;
771
  }
772
  }
vendor/Aws3/Aws/S3/Transfer.php CHANGED
@@ -31,7 +31,8 @@ class Transfer implements \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Prom
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.
@@ -107,7 +108,9 @@ class Transfer implements \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Prom
107
  if ($options['debug'] === true) {
108
  $options['debug'] = fopen('php://output', 'w');
109
  }
110
- $this->addDebugToBefore($options['debug']);
 
 
111
  }
112
  }
113
  /**
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 bucket portion of the s3 URI may be an S3
35
+ * access point ARN. The "/key" portion of an s3 URI is optional.
36
  *
37
  * When providing an iterator for the $source argument, you must also
38
  * provide a 'base_dir' key value pair in the $options argument.
108
  if ($options['debug'] === true) {
109
  $options['debug'] = fopen('php://output', 'w');
110
  }
111
+ if (is_resource($options['debug'])) {
112
+ $this->addDebugToBefore($options['debug']);
113
+ }
114
  }
115
  }
116
  /**
vendor/Aws3/Aws/S3/UseArnRegion/Configuration.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion;
4
+
5
+ use Aws;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Exception\ConfigurationException;
7
+ class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationInterface
8
+ {
9
+ private $useArnRegion;
10
+ public function __construct($useArnRegion)
11
+ {
12
+ $this->useArnRegion = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\boolean_value($useArnRegion);
13
+ if (is_null($this->useArnRegion)) {
14
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Exception\ConfigurationException("'use_arn_region' config option" . " must be a boolean value.");
15
+ }
16
+ }
17
+ /**
18
+ * {@inheritdoc}
19
+ */
20
+ public function isUseArnRegion()
21
+ {
22
+ return $this->useArnRegion;
23
+ }
24
+ /**
25
+ * {@inheritdoc}
26
+ */
27
+ public function toArray()
28
+ {
29
+ return ['use_arn_region' => $this->isUseArnRegion()];
30
+ }
31
+ }
vendor/Aws3/Aws/S3/UseArnRegion/ConfigurationInterface.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion;
4
+
5
+ interface ConfigurationInterface
6
+ {
7
+ /**
8
+ * Returns whether or not to use the ARN region if it differs from client
9
+ *
10
+ * @return bool
11
+ */
12
+ public function isUseArnRegion();
13
+ /**
14
+ * Returns the configuration as an associative array
15
+ *
16
+ * @return array
17
+ */
18
+ public function toArray();
19
+ }
vendor/Aws3/Aws/S3/UseArnRegion/ConfigurationProvider.php ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Exception\ConfigurationException;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
10
+ /**
11
+ * A configuration provider is a function that returns a promise that is
12
+ * fulfilled with a {@see \Aws\S3\UseArnRegion\ConfigurationInterface}
13
+ * or rejected with an {@see \Aws\S3\UseArnRegion\Exception\ConfigurationException}.
14
+ *
15
+ * <code>
16
+ * use Aws\S3\UseArnRegion\ConfigurationProvider;
17
+ * $provider = ConfigurationProvider::defaultProvider();
18
+ * // Returns a ConfigurationInterface or throws.
19
+ * $config = $provider()->wait();
20
+ * </code>
21
+ *
22
+ * Configuration providers can be composed to create configuration using
23
+ * conditional logic that can create different configurations in different
24
+ * environments. You can compose multiple providers into a single provider using
25
+ * {@see Aws\S3\UseArnRegion\ConfigurationProvider::chain}. This function
26
+ * accepts providers as variadic arguments and returns a new function that will
27
+ * invoke each provider until a successful configuration is returned.
28
+ *
29
+ * <code>
30
+ * // First try an INI file at this location.
31
+ * $a = ConfigurationProvider::ini(null, '/path/to/file.ini');
32
+ * // Then try an INI file at this location.
33
+ * $b = ConfigurationProvider::ini(null, '/path/to/other-file.ini');
34
+ * // Then try loading from environment variables.
35
+ * $c = ConfigurationProvider::env();
36
+ * // Combine the three providers together.
37
+ * $composed = ConfigurationProvider::chain($a, $b, $c);
38
+ * // Returns a promise that is fulfilled with a configuration or throws.
39
+ * $promise = $composed();
40
+ * // Wait on the configuration to resolve.
41
+ * $config = $promise->wait();
42
+ * </code>
43
+ */
44
+ class ConfigurationProvider extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface
45
+ {
46
+ const ENV_USE_ARN_REGION = 'AWS_S3_USE_ARN_REGION';
47
+ const INI_USE_ARN_REGION = 's3_use_arn_region';
48
+ const DEFAULT_USE_ARN_REGION = false;
49
+ public static $cacheKey = 'aws_s3_use_arn_region_config';
50
+ protected static $interfaceClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationInterface::class;
51
+ protected static $exceptionClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Exception\ConfigurationException::class;
52
+ /**
53
+ * Create a default config provider that first checks for environment
54
+ * variables, then checks for a specified profile in the environment-defined
55
+ * config file location (env variable is 'AWS_CONFIG_FILE', file location
56
+ * defaults to ~/.aws/config), then checks for the "default" profile in the
57
+ * environment-defined config file location, and failing those uses a default
58
+ * fallback set of configuration options.
59
+ *
60
+ * This provider is automatically wrapped in a memoize function that caches
61
+ * previously provided config options.
62
+ *
63
+ * @param array $config
64
+ *
65
+ * @return callable
66
+ */
67
+ public static function defaultProvider(array $config = [])
68
+ {
69
+ $configProviders = [self::env(), self::ini(), self::fallback()];
70
+ $memo = self::memoize(call_user_func_array('self::chain', $configProviders));
71
+ if (isset($config['use_arn_region']) && $config['use_arn_region'] instanceof CacheInterface) {
72
+ return self::cache($memo, $config['use_arn_region'], self::$cacheKey);
73
+ }
74
+ return $memo;
75
+ }
76
+ /**
77
+ * Provider that creates config from environment variables.
78
+ *
79
+ * @return callable
80
+ */
81
+ public static function env()
82
+ {
83
+ return function () {
84
+ // Use config from environment variables, if available
85
+ $useArnRegion = getenv(self::ENV_USE_ARN_REGION);
86
+ if (!empty($useArnRegion)) {
87
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration($useArnRegion));
88
+ }
89
+ return self::reject('Could not find environment variable config' . ' in ' . self::ENV_USE_ARN_REGION);
90
+ };
91
+ }
92
+ /**
93
+ * Config provider that creates config using a config file whose location
94
+ * is specified by an environment variable 'AWS_CONFIG_FILE', defaulting to
95
+ * ~/.aws/config if not specified
96
+ *
97
+ * @param string|null $profile Profile to use. If not specified will use
98
+ * the "default" profile.
99
+ * @param string|null $filename If provided, uses a custom filename rather
100
+ * than looking in the default directory.
101
+ *
102
+ * @return callable
103
+ */
104
+ public static function ini($profile = null, $filename = null)
105
+ {
106
+ $filename = $filename ?: self::getDefaultConfigFilename();
107
+ $profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
108
+ return function () use($profile, $filename) {
109
+ if (!is_readable($filename)) {
110
+ return self::reject("Cannot read configuration from {$filename}");
111
+ }
112
+ // Use INI_SCANNER_NORMAL instead of INI_SCANNER_TYPED for PHP 5.5 compatibility
113
+ $data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true, INI_SCANNER_NORMAL);
114
+ if ($data === false) {
115
+ return self::reject("Invalid config file: {$filename}");
116
+ }
117
+ if (!isset($data[$profile])) {
118
+ return self::reject("'{$profile}' not found in config file");
119
+ }
120
+ if (!isset($data[$profile][self::INI_USE_ARN_REGION])) {
121
+ return self::reject("Required S3 Use Arn Region config values \n not present in INI profile '{$profile}' ({$filename})");
122
+ }
123
+ // INI_SCANNER_NORMAL parses false-y values as an empty string
124
+ if ($data[$profile][self::INI_USE_ARN_REGION] === "") {
125
+ $data[$profile][self::INI_USE_ARN_REGION] = false;
126
+ }
127
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration($data[$profile][self::INI_USE_ARN_REGION]));
128
+ };
129
+ }
130
+ /**
131
+ * Fallback config options when other sources are not set.
132
+ *
133
+ * @return callable
134
+ */
135
+ public static function fallback()
136
+ {
137
+ return function () {
138
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration(self::DEFAULT_USE_ARN_REGION));
139
+ };
140
+ }
141
+ }
vendor/Aws3/Aws/S3/UseArnRegion/Exception/ConfigurationException.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Exception;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
7
+ /**
8
+ * Represents an error interacting with configuration for S3's UseArnRegion
9
+ */
10
+ class ConfigurationException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
11
+ {
12
+ use HasMonitoringEventsTrait;
13
+ }
vendor/Aws3/Aws/Sdk.php CHANGED
@@ -7,6 +7,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
7
  *
8
  * @method \Aws\ACMPCA\ACMPCAClient createACMPCA(array $args = [])
9
  * @method \Aws\MultiRegionClient createMultiRegionACMPCA(array $args = [])
 
 
10
  * @method \Aws\Acm\AcmClient createAcm(array $args = [])
11
  * @method \Aws\MultiRegionClient createMultiRegionAcm(array $args = [])
12
  * @method \Aws\AlexaForBusiness\AlexaForBusinessClient createAlexaForBusiness(array $args = [])
@@ -19,6 +21,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
19
  * @method \Aws\MultiRegionClient createMultiRegionApiGatewayManagementApi(array $args = [])
20
  * @method \Aws\ApiGatewayV2\ApiGatewayV2Client createApiGatewayV2(array $args = [])
21
  * @method \Aws\MultiRegionClient createMultiRegionApiGatewayV2(array $args = [])
 
 
22
  * @method \Aws\AppMesh\AppMeshClient createAppMesh(array $args = [])
23
  * @method \Aws\MultiRegionClient createMultiRegionAppMesh(array $args = [])
24
  * @method \Aws\AppSync\AppSyncClient createAppSync(array $args = [])
@@ -27,14 +31,20 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
27
  * @method \Aws\MultiRegionClient createMultiRegionApplicationAutoScaling(array $args = [])
28
  * @method \Aws\ApplicationDiscoveryService\ApplicationDiscoveryServiceClient createApplicationDiscoveryService(array $args = [])
29
  * @method \Aws\MultiRegionClient createMultiRegionApplicationDiscoveryService(array $args = [])
 
 
30
  * @method \Aws\Appstream\AppstreamClient createAppstream(array $args = [])
31
  * @method \Aws\MultiRegionClient createMultiRegionAppstream(array $args = [])
32
  * @method \Aws\Athena\AthenaClient createAthena(array $args = [])
33
  * @method \Aws\MultiRegionClient createMultiRegionAthena(array $args = [])
 
 
34
  * @method \Aws\AutoScaling\AutoScalingClient createAutoScaling(array $args = [])
35
  * @method \Aws\MultiRegionClient createMultiRegionAutoScaling(array $args = [])
36
  * @method \Aws\AutoScalingPlans\AutoScalingPlansClient createAutoScalingPlans(array $args = [])
37
  * @method \Aws\MultiRegionClient createMultiRegionAutoScalingPlans(array $args = [])
 
 
38
  * @method \Aws\Batch\BatchClient createBatch(array $args = [])
39
  * @method \Aws\MultiRegionClient createMultiRegionBatch(array $args = [])
40
  * @method \Aws\Budgets\BudgetsClient createBudgets(array $args = [])
@@ -71,10 +81,18 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
71
  * @method \Aws\MultiRegionClient createMultiRegionCodeCommit(array $args = [])
72
  * @method \Aws\CodeDeploy\CodeDeployClient createCodeDeploy(array $args = [])
73
  * @method \Aws\MultiRegionClient createMultiRegionCodeDeploy(array $args = [])
 
 
 
 
74
  * @method \Aws\CodePipeline\CodePipelineClient createCodePipeline(array $args = [])
75
  * @method \Aws\MultiRegionClient createMultiRegionCodePipeline(array $args = [])
76
  * @method \Aws\CodeStar\CodeStarClient createCodeStar(array $args = [])
77
  * @method \Aws\MultiRegionClient createMultiRegionCodeStar(array $args = [])
 
 
 
 
78
  * @method \Aws\CognitoIdentity\CognitoIdentityClient createCognitoIdentity(array $args = [])
79
  * @method \Aws\MultiRegionClient createMultiRegionCognitoIdentity(array $args = [])
80
  * @method \Aws\CognitoIdentityProvider\CognitoIdentityProviderClient createCognitoIdentityProvider(array $args = [])
@@ -85,10 +103,14 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
85
  * @method \Aws\MultiRegionClient createMultiRegionComprehend(array $args = [])
86
  * @method \Aws\ComprehendMedical\ComprehendMedicalClient createComprehendMedical(array $args = [])
87
  * @method \Aws\MultiRegionClient createMultiRegionComprehendMedical(array $args = [])
 
 
88
  * @method \Aws\ConfigService\ConfigServiceClient createConfigService(array $args = [])
89
  * @method \Aws\MultiRegionClient createMultiRegionConfigService(array $args = [])
90
  * @method \Aws\Connect\ConnectClient createConnect(array $args = [])
91
  * @method \Aws\MultiRegionClient createMultiRegionConnect(array $args = [])
 
 
92
  * @method \Aws\CostExplorer\CostExplorerClient createCostExplorer(array $args = [])
93
  * @method \Aws\MultiRegionClient createMultiRegionCostExplorer(array $args = [])
94
  * @method \Aws\CostandUsageReportService\CostandUsageReportServiceClient createCostandUsageReportService(array $args = [])
@@ -97,12 +119,16 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
97
  * @method \Aws\MultiRegionClient createMultiRegionDAX(array $args = [])
98
  * @method \Aws\DLM\DLMClient createDLM(array $args = [])
99
  * @method \Aws\MultiRegionClient createMultiRegionDLM(array $args = [])
 
 
100
  * @method \Aws\DataPipeline\DataPipelineClient createDataPipeline(array $args = [])
101
  * @method \Aws\MultiRegionClient createMultiRegionDataPipeline(array $args = [])
102
  * @method \Aws\DataSync\DataSyncClient createDataSync(array $args = [])
103
  * @method \Aws\MultiRegionClient createMultiRegionDataSync(array $args = [])
104
  * @method \Aws\DatabaseMigrationService\DatabaseMigrationServiceClient createDatabaseMigrationService(array $args = [])
105
  * @method \Aws\MultiRegionClient createMultiRegionDatabaseMigrationService(array $args = [])
 
 
106
  * @method \Aws\DeviceFarm\DeviceFarmClient createDeviceFarm(array $args = [])
107
  * @method \Aws\MultiRegionClient createMultiRegionDeviceFarm(array $args = [])
108
  * @method \Aws\DirectConnect\DirectConnectClient createDirectConnect(array $args = [])
@@ -115,6 +141,10 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
115
  * @method \Aws\MultiRegionClient createMultiRegionDynamoDb(array $args = [])
116
  * @method \Aws\DynamoDbStreams\DynamoDbStreamsClient createDynamoDbStreams(array $args = [])
117
  * @method \Aws\MultiRegionClient createMultiRegionDynamoDbStreams(array $args = [])
 
 
 
 
118
  * @method \Aws\EKS\EKSClient createEKS(array $args = [])
119
  * @method \Aws\MultiRegionClient createMultiRegionEKS(array $args = [])
120
  * @method \Aws\Ec2\Ec2Client createEc2(array $args = [])
@@ -129,6 +159,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
129
  * @method \Aws\MultiRegionClient createMultiRegionElastiCache(array $args = [])
130
  * @method \Aws\ElasticBeanstalk\ElasticBeanstalkClient createElasticBeanstalk(array $args = [])
131
  * @method \Aws\MultiRegionClient createMultiRegionElasticBeanstalk(array $args = [])
 
 
132
  * @method \Aws\ElasticLoadBalancing\ElasticLoadBalancingClient createElasticLoadBalancing(array $args = [])
133
  * @method \Aws\MultiRegionClient createMultiRegionElasticLoadBalancing(array $args = [])
134
  * @method \Aws\ElasticLoadBalancingV2\ElasticLoadBalancingV2Client createElasticLoadBalancingV2(array $args = [])
@@ -139,12 +171,20 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
139
  * @method \Aws\MultiRegionClient createMultiRegionElasticsearchService(array $args = [])
140
  * @method \Aws\Emr\EmrClient createEmr(array $args = [])
141
  * @method \Aws\MultiRegionClient createMultiRegionEmr(array $args = [])
 
 
142
  * @method \Aws\FMS\FMSClient createFMS(array $args = [])
143
  * @method \Aws\MultiRegionClient createMultiRegionFMS(array $args = [])
144
  * @method \Aws\FSx\FSxClient createFSx(array $args = [])
145
  * @method \Aws\MultiRegionClient createMultiRegionFSx(array $args = [])
146
  * @method \Aws\Firehose\FirehoseClient createFirehose(array $args = [])
147
  * @method \Aws\MultiRegionClient createMultiRegionFirehose(array $args = [])
 
 
 
 
 
 
148
  * @method \Aws\GameLift\GameLiftClient createGameLift(array $args = [])
149
  * @method \Aws\MultiRegionClient createMultiRegionGameLift(array $args = [])
150
  * @method \Aws\Glacier\GlacierClient createGlacier(array $args = [])
@@ -155,6 +195,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
155
  * @method \Aws\MultiRegionClient createMultiRegionGlue(array $args = [])
156
  * @method \Aws\Greengrass\GreengrassClient createGreengrass(array $args = [])
157
  * @method \Aws\MultiRegionClient createMultiRegionGreengrass(array $args = [])
 
 
158
  * @method \Aws\GuardDuty\GuardDutyClient createGuardDuty(array $args = [])
159
  * @method \Aws\MultiRegionClient createMultiRegionGuardDuty(array $args = [])
160
  * @method \Aws\Health\HealthClient createHealth(array $args = [])
@@ -171,8 +213,16 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
171
  * @method \Aws\MultiRegionClient createMultiRegionIoT1ClickProjects(array $args = [])
172
  * @method \Aws\IoTAnalytics\IoTAnalyticsClient createIoTAnalytics(array $args = [])
173
  * @method \Aws\MultiRegionClient createMultiRegionIoTAnalytics(array $args = [])
 
 
 
 
174
  * @method \Aws\IoTJobsDataPlane\IoTJobsDataPlaneClient createIoTJobsDataPlane(array $args = [])
175
  * @method \Aws\MultiRegionClient createMultiRegionIoTJobsDataPlane(array $args = [])
 
 
 
 
176
  * @method \Aws\Iot\IotClient createIot(array $args = [])
177
  * @method \Aws\MultiRegionClient createMultiRegionIot(array $args = [])
178
  * @method \Aws\IotDataPlane\IotDataPlaneClient createIotDataPlane(array $args = [])
@@ -191,8 +241,12 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
191
  * @method \Aws\MultiRegionClient createMultiRegionKinesisVideoArchivedMedia(array $args = [])
192
  * @method \Aws\KinesisVideoMedia\KinesisVideoMediaClient createKinesisVideoMedia(array $args = [])
193
  * @method \Aws\MultiRegionClient createMultiRegionKinesisVideoMedia(array $args = [])
 
 
194
  * @method \Aws\Kms\KmsClient createKms(array $args = [])
195
  * @method \Aws\MultiRegionClient createMultiRegionKms(array $args = [])
 
 
196
  * @method \Aws\Lambda\LambdaClient createLambda(array $args = [])
197
  * @method \Aws\MultiRegionClient createMultiRegionLambda(array $args = [])
198
  * @method \Aws\LexModelBuildingService\LexModelBuildingServiceClient createLexModelBuildingService(array $args = [])
@@ -211,6 +265,10 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
211
  * @method \Aws\MultiRegionClient createMultiRegionMachineLearning(array $args = [])
212
  * @method \Aws\Macie\MacieClient createMacie(array $args = [])
213
  * @method \Aws\MultiRegionClient createMultiRegionMacie(array $args = [])
 
 
 
 
214
  * @method \Aws\MarketplaceCommerceAnalytics\MarketplaceCommerceAnalyticsClient createMarketplaceCommerceAnalytics(array $args = [])
215
  * @method \Aws\MultiRegionClient createMultiRegionMarketplaceCommerceAnalytics(array $args = [])
216
  * @method \Aws\MarketplaceEntitlementService\MarketplaceEntitlementServiceClient createMarketplaceEntitlementService(array $args = [])
@@ -225,6 +283,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
225
  * @method \Aws\MultiRegionClient createMultiRegionMediaLive(array $args = [])
226
  * @method \Aws\MediaPackage\MediaPackageClient createMediaPackage(array $args = [])
227
  * @method \Aws\MultiRegionClient createMultiRegionMediaPackage(array $args = [])
 
 
228
  * @method \Aws\MediaStore\MediaStoreClient createMediaStore(array $args = [])
229
  * @method \Aws\MultiRegionClient createMultiRegionMediaStore(array $args = [])
230
  * @method \Aws\MediaStoreData\MediaStoreDataClient createMediaStoreData(array $args = [])
@@ -233,18 +293,30 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
233
  * @method \Aws\MultiRegionClient createMultiRegionMediaTailor(array $args = [])
234
  * @method \Aws\MigrationHub\MigrationHubClient createMigrationHub(array $args = [])
235
  * @method \Aws\MultiRegionClient createMultiRegionMigrationHub(array $args = [])
 
 
236
  * @method \Aws\Mobile\MobileClient createMobile(array $args = [])
237
  * @method \Aws\MultiRegionClient createMultiRegionMobile(array $args = [])
238
  * @method \Aws\Neptune\NeptuneClient createNeptune(array $args = [])
239
  * @method \Aws\MultiRegionClient createMultiRegionNeptune(array $args = [])
 
 
240
  * @method \Aws\OpsWorks\OpsWorksClient createOpsWorks(array $args = [])
241
  * @method \Aws\MultiRegionClient createMultiRegionOpsWorks(array $args = [])
242
  * @method \Aws\OpsWorksCM\OpsWorksCMClient createOpsWorksCM(array $args = [])
243
  * @method \Aws\MultiRegionClient createMultiRegionOpsWorksCM(array $args = [])
244
  * @method \Aws\Organizations\OrganizationsClient createOrganizations(array $args = [])
245
  * @method \Aws\MultiRegionClient createMultiRegionOrganizations(array $args = [])
 
 
246
  * @method \Aws\PI\PIClient createPI(array $args = [])
247
  * @method \Aws\MultiRegionClient createMultiRegionPI(array $args = [])
 
 
 
 
 
 
248
  * @method \Aws\Pinpoint\PinpointClient createPinpoint(array $args = [])
249
  * @method \Aws\MultiRegionClient createMultiRegionPinpoint(array $args = [])
250
  * @method \Aws\PinpointEmail\PinpointEmailClient createPinpointEmail(array $args = [])
@@ -255,6 +327,10 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
255
  * @method \Aws\MultiRegionClient createMultiRegionPolly(array $args = [])
256
  * @method \Aws\Pricing\PricingClient createPricing(array $args = [])
257
  * @method \Aws\MultiRegionClient createMultiRegionPricing(array $args = [])
 
 
 
 
258
  * @method \Aws\QuickSight\QuickSightClient createQuickSight(array $args = [])
259
  * @method \Aws\MultiRegionClient createMultiRegionQuickSight(array $args = [])
260
  * @method \Aws\RAM\RAMClient createRAM(array $args = [])
@@ -283,10 +359,18 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
283
  * @method \Aws\S3\S3MultiRegionClient createMultiRegionS3(array $args = [])
284
  * @method \Aws\S3Control\S3ControlClient createS3Control(array $args = [])
285
  * @method \Aws\MultiRegionClient createMultiRegionS3Control(array $args = [])
 
 
 
 
286
  * @method \Aws\SageMaker\SageMakerClient createSageMaker(array $args = [])
287
  * @method \Aws\MultiRegionClient createMultiRegionSageMaker(array $args = [])
288
  * @method \Aws\SageMakerRuntime\SageMakerRuntimeClient createSageMakerRuntime(array $args = [])
289
  * @method \Aws\MultiRegionClient createMultiRegionSageMakerRuntime(array $args = [])
 
 
 
 
290
  * @method \Aws\SecretsManager\SecretsManagerClient createSecretsManager(array $args = [])
291
  * @method \Aws\MultiRegionClient createMultiRegionSecretsManager(array $args = [])
292
  * @method \Aws\SecurityHub\SecurityHubClient createSecurityHub(array $args = [])
@@ -297,8 +381,12 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
297
  * @method \Aws\MultiRegionClient createMultiRegionServiceCatalog(array $args = [])
298
  * @method \Aws\ServiceDiscovery\ServiceDiscoveryClient createServiceDiscovery(array $args = [])
299
  * @method \Aws\MultiRegionClient createMultiRegionServiceDiscovery(array $args = [])
 
 
300
  * @method \Aws\Ses\SesClient createSes(array $args = [])
301
  * @method \Aws\MultiRegionClient createMultiRegionSes(array $args = [])
 
 
302
  * @method \Aws\Sfn\SfnClient createSfn(array $args = [])
303
  * @method \Aws\MultiRegionClient createMultiRegionSfn(array $args = [])
304
  * @method \Aws\Shield\ShieldClient createShield(array $args = [])
@@ -321,30 +409,42 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
321
  * @method \Aws\MultiRegionClient createMultiRegionSupport(array $args = [])
322
  * @method \Aws\Swf\SwfClient createSwf(array $args = [])
323
  * @method \Aws\MultiRegionClient createMultiRegionSwf(array $args = [])
 
 
324
  * @method \Aws\TranscribeService\TranscribeServiceClient createTranscribeService(array $args = [])
325
  * @method \Aws\MultiRegionClient createMultiRegionTranscribeService(array $args = [])
326
  * @method \Aws\Transfer\TransferClient createTransfer(array $args = [])
327
  * @method \Aws\MultiRegionClient createMultiRegionTransfer(array $args = [])
328
  * @method \Aws\Translate\TranslateClient createTranslate(array $args = [])
329
  * @method \Aws\MultiRegionClient createMultiRegionTranslate(array $args = [])
 
 
330
  * @method \Aws\Waf\WafClient createWaf(array $args = [])
331
  * @method \Aws\MultiRegionClient createMultiRegionWaf(array $args = [])
332
  * @method \Aws\WafRegional\WafRegionalClient createWafRegional(array $args = [])
333
  * @method \Aws\MultiRegionClient createMultiRegionWafRegional(array $args = [])
334
  * @method \Aws\WorkDocs\WorkDocsClient createWorkDocs(array $args = [])
335
  * @method \Aws\MultiRegionClient createMultiRegionWorkDocs(array $args = [])
 
 
336
  * @method \Aws\WorkMail\WorkMailClient createWorkMail(array $args = [])
337
  * @method \Aws\MultiRegionClient createMultiRegionWorkMail(array $args = [])
 
 
338
  * @method \Aws\WorkSpaces\WorkSpacesClient createWorkSpaces(array $args = [])
339
  * @method \Aws\MultiRegionClient createMultiRegionWorkSpaces(array $args = [])
340
  * @method \Aws\XRay\XRayClient createXRay(array $args = [])
341
  * @method \Aws\MultiRegionClient createMultiRegionXRay(array $args = [])
 
 
 
 
342
  * @method \Aws\signer\signerClient createsigner(array $args = [])
343
  * @method \Aws\MultiRegionClient createMultiRegionsigner(array $args = [])
344
  */
345
  class Sdk
346
  {
347
- const VERSION = '3.84.0';
348
  /** @var array Arguments for creating clients */
349
  private $args;
350
  /**
@@ -403,6 +503,18 @@ class Sdk
403
  $klass = class_exists($klass) ? $klass : 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\MultiRegionClient';
404
  return new $klass($this->mergeArgs($namespace, $service, $args));
405
  }
 
 
 
 
 
 
 
 
 
 
 
 
406
  private function mergeArgs($namespace, array $manifest, array $args = [])
407
  {
408
  // Merge provided args with stored, service-specific args.
7
  *
8
  * @method \Aws\ACMPCA\ACMPCAClient createACMPCA(array $args = [])
9
  * @method \Aws\MultiRegionClient createMultiRegionACMPCA(array $args = [])
10
+ * @method \Aws\AccessAnalyzer\AccessAnalyzerClient createAccessAnalyzer(array $args = [])
11
+ * @method \Aws\MultiRegionClient createMultiRegionAccessAnalyzer(array $args = [])
12
  * @method \Aws\Acm\AcmClient createAcm(array $args = [])
13
  * @method \Aws\MultiRegionClient createMultiRegionAcm(array $args = [])
14
  * @method \Aws\AlexaForBusiness\AlexaForBusinessClient createAlexaForBusiness(array $args = [])
21
  * @method \Aws\MultiRegionClient createMultiRegionApiGatewayManagementApi(array $args = [])
22
  * @method \Aws\ApiGatewayV2\ApiGatewayV2Client createApiGatewayV2(array $args = [])
23
  * @method \Aws\MultiRegionClient createMultiRegionApiGatewayV2(array $args = [])
24
+ * @method \Aws\AppConfig\AppConfigClient createAppConfig(array $args = [])
25
+ * @method \Aws\MultiRegionClient createMultiRegionAppConfig(array $args = [])
26
  * @method \Aws\AppMesh\AppMeshClient createAppMesh(array $args = [])
27
  * @method \Aws\MultiRegionClient createMultiRegionAppMesh(array $args = [])
28
  * @method \Aws\AppSync\AppSyncClient createAppSync(array $args = [])
31
  * @method \Aws\MultiRegionClient createMultiRegionApplicationAutoScaling(array $args = [])
32
  * @method \Aws\ApplicationDiscoveryService\ApplicationDiscoveryServiceClient createApplicationDiscoveryService(array $args = [])
33
  * @method \Aws\MultiRegionClient createMultiRegionApplicationDiscoveryService(array $args = [])
34
+ * @method \Aws\ApplicationInsights\ApplicationInsightsClient createApplicationInsights(array $args = [])
35
+ * @method \Aws\MultiRegionClient createMultiRegionApplicationInsights(array $args = [])
36
  * @method \Aws\Appstream\AppstreamClient createAppstream(array $args = [])
37
  * @method \Aws\MultiRegionClient createMultiRegionAppstream(array $args = [])
38
  * @method \Aws\Athena\AthenaClient createAthena(array $args = [])
39
  * @method \Aws\MultiRegionClient createMultiRegionAthena(array $args = [])
40
+ * @method \Aws\AugmentedAIRuntime\AugmentedAIRuntimeClient createAugmentedAIRuntime(array $args = [])
41
+ * @method \Aws\MultiRegionClient createMultiRegionAugmentedAIRuntime(array $args = [])
42
  * @method \Aws\AutoScaling\AutoScalingClient createAutoScaling(array $args = [])
43
  * @method \Aws\MultiRegionClient createMultiRegionAutoScaling(array $args = [])
44
  * @method \Aws\AutoScalingPlans\AutoScalingPlansClient createAutoScalingPlans(array $args = [])
45
  * @method \Aws\MultiRegionClient createMultiRegionAutoScalingPlans(array $args = [])
46
+ * @method \Aws\Backup\BackupClient createBackup(array $args = [])
47
+ * @method \Aws\MultiRegionClient createMultiRegionBackup(array $args = [])
48
  * @method \Aws\Batch\BatchClient createBatch(array $args = [])
49
  * @method \Aws\MultiRegionClient createMultiRegionBatch(array $args = [])
50
  * @method \Aws\Budgets\BudgetsClient createBudgets(array $args = [])
81
  * @method \Aws\MultiRegionClient createMultiRegionCodeCommit(array $args = [])
82
  * @method \Aws\CodeDeploy\CodeDeployClient createCodeDeploy(array $args = [])
83
  * @method \Aws\MultiRegionClient createMultiRegionCodeDeploy(array $args = [])
84
+ * @method \Aws\CodeGuruProfiler\CodeGuruProfilerClient createCodeGuruProfiler(array $args = [])
85
+ * @method \Aws\MultiRegionClient createMultiRegionCodeGuruProfiler(array $args = [])
86
+ * @method \Aws\CodeGuruReviewer\CodeGuruReviewerClient createCodeGuruReviewer(array $args = [])
87
+ * @method \Aws\MultiRegionClient createMultiRegionCodeGuruReviewer(array $args = [])
88
  * @method \Aws\CodePipeline\CodePipelineClient createCodePipeline(array $args = [])
89
  * @method \Aws\MultiRegionClient createMultiRegionCodePipeline(array $args = [])
90
  * @method \Aws\CodeStar\CodeStarClient createCodeStar(array $args = [])
91
  * @method \Aws\MultiRegionClient createMultiRegionCodeStar(array $args = [])
92
+ * @method \Aws\CodeStarNotifications\CodeStarNotificationsClient createCodeStarNotifications(array $args = [])
93
+ * @method \Aws\MultiRegionClient createMultiRegionCodeStarNotifications(array $args = [])
94
+ * @method \Aws\CodeStarconnections\CodeStarconnectionsClient createCodeStarconnections(array $args = [])
95
+ * @method \Aws\MultiRegionClient createMultiRegionCodeStarconnections(array $args = [])
96
  * @method \Aws\CognitoIdentity\CognitoIdentityClient createCognitoIdentity(array $args = [])
97
  * @method \Aws\MultiRegionClient createMultiRegionCognitoIdentity(array $args = [])
98
  * @method \Aws\CognitoIdentityProvider\CognitoIdentityProviderClient createCognitoIdentityProvider(array $args = [])
103
  * @method \Aws\MultiRegionClient createMultiRegionComprehend(array $args = [])
104
  * @method \Aws\ComprehendMedical\ComprehendMedicalClient createComprehendMedical(array $args = [])
105
  * @method \Aws\MultiRegionClient createMultiRegionComprehendMedical(array $args = [])
106
+ * @method \Aws\ComputeOptimizer\ComputeOptimizerClient createComputeOptimizer(array $args = [])
107
+ * @method \Aws\MultiRegionClient createMultiRegionComputeOptimizer(array $args = [])
108
  * @method \Aws\ConfigService\ConfigServiceClient createConfigService(array $args = [])
109
  * @method \Aws\MultiRegionClient createMultiRegionConfigService(array $args = [])
110
  * @method \Aws\Connect\ConnectClient createConnect(array $args = [])
111
  * @method \Aws\MultiRegionClient createMultiRegionConnect(array $args = [])
112
+ * @method \Aws\ConnectParticipant\ConnectParticipantClient createConnectParticipant(array $args = [])
113
+ * @method \Aws\MultiRegionClient createMultiRegionConnectParticipant(array $args = [])
114
  * @method \Aws\CostExplorer\CostExplorerClient createCostExplorer(array $args = [])
115
  * @method \Aws\MultiRegionClient createMultiRegionCostExplorer(array $args = [])
116
  * @method \Aws\CostandUsageReportService\CostandUsageReportServiceClient createCostandUsageReportService(array $args = [])
119
  * @method \Aws\MultiRegionClient createMultiRegionDAX(array $args = [])
120
  * @method \Aws\DLM\DLMClient createDLM(array $args = [])
121
  * @method \Aws\MultiRegionClient createMultiRegionDLM(array $args = [])
122
+ * @method \Aws\DataExchange\DataExchangeClient createDataExchange(array $args = [])
123
+ * @method \Aws\MultiRegionClient createMultiRegionDataExchange(array $args = [])
124
  * @method \Aws\DataPipeline\DataPipelineClient createDataPipeline(array $args = [])
125
  * @method \Aws\MultiRegionClient createMultiRegionDataPipeline(array $args = [])
126
  * @method \Aws\DataSync\DataSyncClient createDataSync(array $args = [])
127
  * @method \Aws\MultiRegionClient createMultiRegionDataSync(array $args = [])
128
  * @method \Aws\DatabaseMigrationService\DatabaseMigrationServiceClient createDatabaseMigrationService(array $args = [])
129
  * @method \Aws\MultiRegionClient createMultiRegionDatabaseMigrationService(array $args = [])
130
+ * @method \Aws\Detective\DetectiveClient createDetective(array $args = [])
131
+ * @method \Aws\MultiRegionClient createMultiRegionDetective(array $args = [])
132
  * @method \Aws\DeviceFarm\DeviceFarmClient createDeviceFarm(array $args = [])
133
  * @method \Aws\MultiRegionClient createMultiRegionDeviceFarm(array $args = [])
134
  * @method \Aws\DirectConnect\DirectConnectClient createDirectConnect(array $args = [])
141
  * @method \Aws\MultiRegionClient createMultiRegionDynamoDb(array $args = [])
142
  * @method \Aws\DynamoDbStreams\DynamoDbStreamsClient createDynamoDbStreams(array $args = [])
143
  * @method \Aws\MultiRegionClient createMultiRegionDynamoDbStreams(array $args = [])
144
+ * @method \Aws\EBS\EBSClient createEBS(array $args = [])
145
+ * @method \Aws\MultiRegionClient createMultiRegionEBS(array $args = [])
146
+ * @method \Aws\EC2InstanceConnect\EC2InstanceConnectClient createEC2InstanceConnect(array $args = [])
147
+ * @method \Aws\MultiRegionClient createMultiRegionEC2InstanceConnect(array $args = [])
148
  * @method \Aws\EKS\EKSClient createEKS(array $args = [])
149
  * @method \Aws\MultiRegionClient createMultiRegionEKS(array $args = [])
150
  * @method \Aws\Ec2\Ec2Client createEc2(array $args = [])
159
  * @method \Aws\MultiRegionClient createMultiRegionElastiCache(array $args = [])
160
  * @method \Aws\ElasticBeanstalk\ElasticBeanstalkClient createElasticBeanstalk(array $args = [])
161
  * @method \Aws\MultiRegionClient createMultiRegionElasticBeanstalk(array $args = [])
162
+ * @method \Aws\ElasticInference\ElasticInferenceClient createElasticInference(array $args = [])
163
+ * @method \Aws\MultiRegionClient createMultiRegionElasticInference(array $args = [])
164
  * @method \Aws\ElasticLoadBalancing\ElasticLoadBalancingClient createElasticLoadBalancing(array $args = [])
165
  * @method \Aws\MultiRegionClient createMultiRegionElasticLoadBalancing(array $args = [])
166
  * @method \Aws\ElasticLoadBalancingV2\ElasticLoadBalancingV2Client createElasticLoadBalancingV2(array $args = [])
171
  * @method \Aws\MultiRegionClient createMultiRegionElasticsearchService(array $args = [])
172
  * @method \Aws\Emr\EmrClient createEmr(array $args = [])
173
  * @method \Aws\MultiRegionClient createMultiRegionEmr(array $args = [])
174
+ * @method \Aws\EventBridge\EventBridgeClient createEventBridge(array $args = [])
175
+ * @method \Aws\MultiRegionClient createMultiRegionEventBridge(array $args = [])
176
  * @method \Aws\FMS\FMSClient createFMS(array $args = [])
177
  * @method \Aws\MultiRegionClient createMultiRegionFMS(array $args = [])
178
  * @method \Aws\FSx\FSxClient createFSx(array $args = [])
179
  * @method \Aws\MultiRegionClient createMultiRegionFSx(array $args = [])
180
  * @method \Aws\Firehose\FirehoseClient createFirehose(array $args = [])
181
  * @method \Aws\MultiRegionClient createMultiRegionFirehose(array $args = [])
182
+ * @method \Aws\ForecastQueryService\ForecastQueryServiceClient createForecastQueryService(array $args = [])
183
+ * @method \Aws\MultiRegionClient createMultiRegionForecastQueryService(array $args = [])
184
+ * @method \Aws\ForecastService\ForecastServiceClient createForecastService(array $args = [])
185
+ * @method \Aws\MultiRegionClient createMultiRegionForecastService(array $args = [])
186
+ * @method \Aws\FraudDetector\FraudDetectorClient createFraudDetector(array $args = [])
187
+ * @method \Aws\MultiRegionClient createMultiRegionFraudDetector(array $args = [])
188
  * @method \Aws\GameLift\GameLiftClient createGameLift(array $args = [])
189
  * @method \Aws\MultiRegionClient createMultiRegionGameLift(array $args = [])
190
  * @method \Aws\Glacier\GlacierClient createGlacier(array $args = [])
195
  * @method \Aws\MultiRegionClient createMultiRegionGlue(array $args = [])
196
  * @method \Aws\Greengrass\GreengrassClient createGreengrass(array $args = [])
197
  * @method \Aws\MultiRegionClient createMultiRegionGreengrass(array $args = [])
198
+ * @method \Aws\GroundStation\GroundStationClient createGroundStation(array $args = [])
199
+ * @method \Aws\MultiRegionClient createMultiRegionGroundStation(array $args = [])
200
  * @method \Aws\GuardDuty\GuardDutyClient createGuardDuty(array $args = [])
201
  * @method \Aws\MultiRegionClient createMultiRegionGuardDuty(array $args = [])
202
  * @method \Aws\Health\HealthClient createHealth(array $args = [])
213
  * @method \Aws\MultiRegionClient createMultiRegionIoT1ClickProjects(array $args = [])
214
  * @method \Aws\IoTAnalytics\IoTAnalyticsClient createIoTAnalytics(array $args = [])
215
  * @method \Aws\MultiRegionClient createMultiRegionIoTAnalytics(array $args = [])
216
+ * @method \Aws\IoTEvents\IoTEventsClient createIoTEvents(array $args = [])
217
+ * @method \Aws\MultiRegionClient createMultiRegionIoTEvents(array $args = [])
218
+ * @method \Aws\IoTEventsData\IoTEventsDataClient createIoTEventsData(array $args = [])
219
+ * @method \Aws\MultiRegionClient createMultiRegionIoTEventsData(array $args = [])
220
  * @method \Aws\IoTJobsDataPlane\IoTJobsDataPlaneClient createIoTJobsDataPlane(array $args = [])
221
  * @method \Aws\MultiRegionClient createMultiRegionIoTJobsDataPlane(array $args = [])
222
+ * @method \Aws\IoTSecureTunneling\IoTSecureTunnelingClient createIoTSecureTunneling(array $args = [])
223
+ * @method \Aws\MultiRegionClient createMultiRegionIoTSecureTunneling(array $args = [])
224
+ * @method \Aws\IoTThingsGraph\IoTThingsGraphClient createIoTThingsGraph(array $args = [])
225
+ * @method \Aws\MultiRegionClient createMultiRegionIoTThingsGraph(array $args = [])
226
  * @method \Aws\Iot\IotClient createIot(array $args = [])
227
  * @method \Aws\MultiRegionClient createMultiRegionIot(array $args = [])
228
  * @method \Aws\IotDataPlane\IotDataPlaneClient createIotDataPlane(array $args = [])
241
  * @method \Aws\MultiRegionClient createMultiRegionKinesisVideoArchivedMedia(array $args = [])
242
  * @method \Aws\KinesisVideoMedia\KinesisVideoMediaClient createKinesisVideoMedia(array $args = [])
243
  * @method \Aws\MultiRegionClient createMultiRegionKinesisVideoMedia(array $args = [])
244
+ * @method \Aws\KinesisVideoSignalingChannels\KinesisVideoSignalingChannelsClient createKinesisVideoSignalingChannels(array $args = [])
245
+ * @method \Aws\MultiRegionClient createMultiRegionKinesisVideoSignalingChannels(array $args = [])
246
  * @method \Aws\Kms\KmsClient createKms(array $args = [])
247
  * @method \Aws\MultiRegionClient createMultiRegionKms(array $args = [])
248
+ * @method \Aws\LakeFormation\LakeFormationClient createLakeFormation(array $args = [])
249
+ * @method \Aws\MultiRegionClient createMultiRegionLakeFormation(array $args = [])
250
  * @method \Aws\Lambda\LambdaClient createLambda(array $args = [])
251
  * @method \Aws\MultiRegionClient createMultiRegionLambda(array $args = [])
252
  * @method \Aws\LexModelBuildingService\LexModelBuildingServiceClient createLexModelBuildingService(array $args = [])
265
  * @method \Aws\MultiRegionClient createMultiRegionMachineLearning(array $args = [])
266
  * @method \Aws\Macie\MacieClient createMacie(array $args = [])
267
  * @method \Aws\MultiRegionClient createMultiRegionMacie(array $args = [])
268
+ * @method \Aws\ManagedBlockchain\ManagedBlockchainClient createManagedBlockchain(array $args = [])
269
+ * @method \Aws\MultiRegionClient createMultiRegionManagedBlockchain(array $args = [])
270
+ * @method \Aws\MarketplaceCatalog\MarketplaceCatalogClient createMarketplaceCatalog(array $args = [])
271
+ * @method \Aws\MultiRegionClient createMultiRegionMarketplaceCatalog(array $args = [])
272
  * @method \Aws\MarketplaceCommerceAnalytics\MarketplaceCommerceAnalyticsClient createMarketplaceCommerceAnalytics(array $args = [])
273
  * @method \Aws\MultiRegionClient createMultiRegionMarketplaceCommerceAnalytics(array $args = [])
274
  * @method \Aws\MarketplaceEntitlementService\MarketplaceEntitlementServiceClient createMarketplaceEntitlementService(array $args = [])
283
  * @method \Aws\MultiRegionClient createMultiRegionMediaLive(array $args = [])
284
  * @method \Aws\MediaPackage\MediaPackageClient createMediaPackage(array $args = [])
285
  * @method \Aws\MultiRegionClient createMultiRegionMediaPackage(array $args = [])
286
+ * @method \Aws\MediaPackageVod\MediaPackageVodClient createMediaPackageVod(array $args = [])
287
+ * @method \Aws\MultiRegionClient createMultiRegionMediaPackageVod(array $args = [])
288
  * @method \Aws\MediaStore\MediaStoreClient createMediaStore(array $args = [])
289
  * @method \Aws\MultiRegionClient createMultiRegionMediaStore(array $args = [])
290
  * @method \Aws\MediaStoreData\MediaStoreDataClient createMediaStoreData(array $args = [])
293
  * @method \Aws\MultiRegionClient createMultiRegionMediaTailor(array $args = [])
294
  * @method \Aws\MigrationHub\MigrationHubClient createMigrationHub(array $args = [])
295
  * @method \Aws\MultiRegionClient createMultiRegionMigrationHub(array $args = [])
296
+ * @method \Aws\MigrationHubConfig\MigrationHubConfigClient createMigrationHubConfig(array $args = [])
297
+ * @method \Aws\MultiRegionClient createMultiRegionMigrationHubConfig(array $args = [])
298
  * @method \Aws\Mobile\MobileClient createMobile(array $args = [])
299
  * @method \Aws\MultiRegionClient createMultiRegionMobile(array $args = [])
300
  * @method \Aws\Neptune\NeptuneClient createNeptune(array $args = [])
301
  * @method \Aws\MultiRegionClient createMultiRegionNeptune(array $args = [])
302
+ * @method \Aws\NetworkManager\NetworkManagerClient createNetworkManager(array $args = [])
303
+ * @method \Aws\MultiRegionClient createMultiRegionNetworkManager(array $args = [])
304
  * @method \Aws\OpsWorks\OpsWorksClient createOpsWorks(array $args = [])
305
  * @method \Aws\MultiRegionClient createMultiRegionOpsWorks(array $args = [])
306
  * @method \Aws\OpsWorksCM\OpsWorksCMClient createOpsWorksCM(array $args = [])
307
  * @method \Aws\MultiRegionClient createMultiRegionOpsWorksCM(array $args = [])
308
  * @method \Aws\Organizations\OrganizationsClient createOrganizations(array $args = [])
309
  * @method \Aws\MultiRegionClient createMultiRegionOrganizations(array $args = [])
310
+ * @method \Aws\Outposts\OutpostsClient createOutposts(array $args = [])
311
+ * @method \Aws\MultiRegionClient createMultiRegionOutposts(array $args = [])
312
  * @method \Aws\PI\PIClient createPI(array $args = [])
313
  * @method \Aws\MultiRegionClient createMultiRegionPI(array $args = [])
314
+ * @method \Aws\Personalize\PersonalizeClient createPersonalize(array $args = [])
315
+ * @method \Aws\MultiRegionClient createMultiRegionPersonalize(array $args = [])
316
+ * @method \Aws\PersonalizeEvents\PersonalizeEventsClient createPersonalizeEvents(array $args = [])
317
+ * @method \Aws\MultiRegionClient createMultiRegionPersonalizeEvents(array $args = [])
318
+ * @method \Aws\PersonalizeRuntime\PersonalizeRuntimeClient createPersonalizeRuntime(array $args = [])
319
+ * @method \Aws\MultiRegionClient createMultiRegionPersonalizeRuntime(array $args = [])
320
  * @method \Aws\Pinpoint\PinpointClient createPinpoint(array $args = [])
321
  * @method \Aws\MultiRegionClient createMultiRegionPinpoint(array $args = [])
322
  * @method \Aws\PinpointEmail\PinpointEmailClient createPinpointEmail(array $args = [])
327
  * @method \Aws\MultiRegionClient createMultiRegionPolly(array $args = [])
328
  * @method \Aws\Pricing\PricingClient createPricing(array $args = [])
329
  * @method \Aws\MultiRegionClient createMultiRegionPricing(array $args = [])
330
+ * @method \Aws\QLDB\QLDBClient createQLDB(array $args = [])
331
+ * @method \Aws\MultiRegionClient createMultiRegionQLDB(array $args = [])
332
+ * @method \Aws\QLDBSession\QLDBSessionClient createQLDBSession(array $args = [])
333
+ * @method \Aws\MultiRegionClient createMultiRegionQLDBSession(array $args = [])
334
  * @method \Aws\QuickSight\QuickSightClient createQuickSight(array $args = [])
335
  * @method \Aws\MultiRegionClient createMultiRegionQuickSight(array $args = [])
336
  * @method \Aws\RAM\RAMClient createRAM(array $args = [])
359
  * @method \Aws\S3\S3MultiRegionClient createMultiRegionS3(array $args = [])
360
  * @method \Aws\S3Control\S3ControlClient createS3Control(array $args = [])
361
  * @method \Aws\MultiRegionClient createMultiRegionS3Control(array $args = [])
362
+ * @method \Aws\SSO\SSOClient createSSO(array $args = [])
363
+ * @method \Aws\MultiRegionClient createMultiRegionSSO(array $args = [])
364
+ * @method \Aws\SSOOIDC\SSOOIDCClient createSSOOIDC(array $args = [])
365
+ * @method \Aws\MultiRegionClient createMultiRegionSSOOIDC(array $args = [])
366
  * @method \Aws\SageMaker\SageMakerClient createSageMaker(array $args = [])
367
  * @method \Aws\MultiRegionClient createMultiRegionSageMaker(array $args = [])
368
  * @method \Aws\SageMakerRuntime\SageMakerRuntimeClient createSageMakerRuntime(array $args = [])
369
  * @method \Aws\MultiRegionClient createMultiRegionSageMakerRuntime(array $args = [])
370
+ * @method \Aws\SavingsPlans\SavingsPlansClient createSavingsPlans(array $args = [])
371
+ * @method \Aws\MultiRegionClient createMultiRegionSavingsPlans(array $args = [])
372
+ * @method \Aws\Schemas\SchemasClient createSchemas(array $args = [])
373
+ * @method \Aws\MultiRegionClient createMultiRegionSchemas(array $args = [])
374
  * @method \Aws\SecretsManager\SecretsManagerClient createSecretsManager(array $args = [])
375
  * @method \Aws\MultiRegionClient createMultiRegionSecretsManager(array $args = [])
376
  * @method \Aws\SecurityHub\SecurityHubClient createSecurityHub(array $args = [])
381
  * @method \Aws\MultiRegionClient createMultiRegionServiceCatalog(array $args = [])
382
  * @method \Aws\ServiceDiscovery\ServiceDiscoveryClient createServiceDiscovery(array $args = [])
383
  * @method \Aws\MultiRegionClient createMultiRegionServiceDiscovery(array $args = [])
384
+ * @method \Aws\ServiceQuotas\ServiceQuotasClient createServiceQuotas(array $args = [])
385
+ * @method \Aws\MultiRegionClient createMultiRegionServiceQuotas(array $args = [])
386
  * @method \Aws\Ses\SesClient createSes(array $args = [])
387
  * @method \Aws\MultiRegionClient createMultiRegionSes(array $args = [])
388
+ * @method \Aws\SesV2\SesV2Client createSesV2(array $args = [])
389
+ * @method \Aws\MultiRegionClient createMultiRegionSesV2(array $args = [])
390
  * @method \Aws\Sfn\SfnClient createSfn(array $args = [])
391
  * @method \Aws\MultiRegionClient createMultiRegionSfn(array $args = [])
392
  * @method \Aws\Shield\ShieldClient createShield(array $args = [])
409
  * @method \Aws\MultiRegionClient createMultiRegionSupport(array $args = [])
410
  * @method \Aws\Swf\SwfClient createSwf(array $args = [])
411
  * @method \Aws\MultiRegionClient createMultiRegionSwf(array $args = [])
412
+ * @method \Aws\Textract\TextractClient createTextract(array $args = [])
413
+ * @method \Aws\MultiRegionClient createMultiRegionTextract(array $args = [])
414
  * @method \Aws\TranscribeService\TranscribeServiceClient createTranscribeService(array $args = [])
415
  * @method \Aws\MultiRegionClient createMultiRegionTranscribeService(array $args = [])
416
  * @method \Aws\Transfer\TransferClient createTransfer(array $args = [])
417
  * @method \Aws\MultiRegionClient createMultiRegionTransfer(array $args = [])
418
  * @method \Aws\Translate\TranslateClient createTranslate(array $args = [])
419
  * @method \Aws\MultiRegionClient createMultiRegionTranslate(array $args = [])
420
+ * @method \Aws\WAFV2\WAFV2Client createWAFV2(array $args = [])
421
+ * @method \Aws\MultiRegionClient createMultiRegionWAFV2(array $args = [])
422
  * @method \Aws\Waf\WafClient createWaf(array $args = [])
423
  * @method \Aws\MultiRegionClient createMultiRegionWaf(array $args = [])
424
  * @method \Aws\WafRegional\WafRegionalClient createWafRegional(array $args = [])
425
  * @method \Aws\MultiRegionClient createMultiRegionWafRegional(array $args = [])
426
  * @method \Aws\WorkDocs\WorkDocsClient createWorkDocs(array $args = [])
427
  * @method \Aws\MultiRegionClient createMultiRegionWorkDocs(array $args = [])
428
+ * @method \Aws\WorkLink\WorkLinkClient createWorkLink(array $args = [])
429
+ * @method \Aws\MultiRegionClient createMultiRegionWorkLink(array $args = [])
430
  * @method \Aws\WorkMail\WorkMailClient createWorkMail(array $args = [])
431
  * @method \Aws\MultiRegionClient createMultiRegionWorkMail(array $args = [])
432
+ * @method \Aws\WorkMailMessageFlow\WorkMailMessageFlowClient createWorkMailMessageFlow(array $args = [])
433
+ * @method \Aws\MultiRegionClient createMultiRegionWorkMailMessageFlow(array $args = [])
434
  * @method \Aws\WorkSpaces\WorkSpacesClient createWorkSpaces(array $args = [])
435
  * @method \Aws\MultiRegionClient createMultiRegionWorkSpaces(array $args = [])
436
  * @method \Aws\XRay\XRayClient createXRay(array $args = [])
437
  * @method \Aws\MultiRegionClient createMultiRegionXRay(array $args = [])
438
+ * @method \Aws\imagebuilder\imagebuilderClient createimagebuilder(array $args = [])
439
+ * @method \Aws\MultiRegionClient createMultiRegionimagebuilder(array $args = [])
440
+ * @method \Aws\kendra\kendraClient createkendra(array $args = [])
441
+ * @method \Aws\MultiRegionClient createMultiRegionkendra(array $args = [])
442
  * @method \Aws\signer\signerClient createsigner(array $args = [])
443
  * @method \Aws\MultiRegionClient createMultiRegionsigner(array $args = [])
444
  */
445
  class Sdk
446
  {
447
+ const VERSION = '3.133.40';
448
  /** @var array Arguments for creating clients */
449
  private $args;
450
  /**
503
  $klass = class_exists($klass) ? $klass : 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\MultiRegionClient';
504
  return new $klass($this->mergeArgs($namespace, $service, $args));
505
  }
506
+ /**
507
+ * Clone existing SDK instance with ability to pass an associative array
508
+ * of extra client settings.
509
+ *
510
+ * @param array $args
511
+ *
512
+ * @return self
513
+ */
514
+ public function copy(array $args = [])
515
+ {
516
+ return new self($args + $this->args);
517
+ }
518
  private function mergeArgs($namespace, array $manifest, array $args = [])
519
  {
520
  // Merge provided args with stored, service-specific args.
vendor/Aws3/Aws/Signature/AnonymousSignature.php CHANGED
@@ -13,7 +13,7 @@ class AnonymousSignature implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S
13
  {
14
  return $request;
15
  }
16
- public function presign(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface $credentials, $expires)
17
  {
18
  return $request;
19
  }
13
  {
14
  return $request;
15
  }
16
+ public function presign(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface $credentials, $expires, array $options = [])
17
  {
18
  return $request;
19
  }
vendor/Aws3/Aws/Signature/SignatureInterface.php CHANGED
@@ -32,5 +32,5 @@ interface SignatureInterface
32
  *
33
  * @return RequestInterface
34
  */
35
- public function presign(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface $credentials, $expires);
36
  }
32
  *
33
  * @return RequestInterface
34
  */
35
+ public function presign(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface $credentials, $expires, array $options = []);
36
  }
vendor/Aws3/Aws/StreamRequestPayloadMiddleware.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
4
+
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\IncalculablePayloadException;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
8
+ /**
9
+ * @internal
10
+ */
11
+ class StreamRequestPayloadMiddleware
12
+ {
13
+ private $nextHandler;
14
+ private $service;
15
+ /**
16
+ * Create a middleware wrapper function
17
+ *
18
+ * @param Service $service
19
+ * @return \Closure
20
+ */
21
+ public static function wrap(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $service)
22
+ {
23
+ return function (callable $handler) use($service) {
24
+ return new self($handler, $service);
25
+ };
26
+ }
27
+ public function __construct(callable $nextHandler, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $service)
28
+ {
29
+ $this->nextHandler = $nextHandler;
30
+ $this->service = $service;
31
+ }
32
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
33
+ {
34
+ $nextHandler = $this->nextHandler;
35
+ $operation = $this->service->getOperation($command->getName());
36
+ $contentLength = $request->getHeader('content-length');
37
+ $hasStreaming = false;
38
+ $requiresLength = false;
39
+ // Check if any present input member is a stream and requires the
40
+ // content length
41
+ foreach ($operation->getInput()->getMembers() as $name => $member) {
42
+ if (!empty($member['streaming']) && isset($command[$name])) {
43
+ $hasStreaming = true;
44
+ if (!empty($member['requiresLength'])) {
45
+ $requiresLength = true;
46
+ }
47
+ }
48
+ }
49
+ if ($hasStreaming) {
50
+ // Add 'transfer-encoding' header if payload size not required to
51
+ // to be calculated and not already known
52
+ if (empty($requiresLength) && empty($contentLength) && isset($operation['authtype']) && $operation['authtype'] == 'v4-unsigned-body') {
53
+ $request = $request->withHeader('transfer-encoding', 'chunked');
54
+ // Otherwise, make sure 'content-length' header is added
55
+ } else {
56
+ if (empty($contentLength)) {
57
+ $size = $request->getBody()->getSize();
58
+ if (is_null($size)) {
59
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\IncalculablePayloadException('Payload' . ' content length is required and can not be' . ' calculated.');
60
+ }
61
+ $request = $request->withHeader('content-length', $size);
62
+ }
63
+ }
64
+ }
65
+ return $nextHandler($command, $request);
66
+ }
67
+ }
vendor/Aws3/Aws/WrappedHttpHandler.php CHANGED
@@ -124,7 +124,7 @@ class WrappedHttpHandler
124
  $parts = ['response' => null];
125
  } else {
126
  try {
127
- $parts = call_user_func($this->errorParser, $err['response']);
128
  $serviceError .= " {$parts['code']} ({$parts['type']}): " . "{$parts['message']} - " . $err['response']->getBody();
129
  } catch (ParserException $e) {
130
  $parts = [];
124
  $parts = ['response' => null];
125
  } else {
126
  try {
127
+ $parts = call_user_func($this->errorParser, $err['response'], $command);
128
  $serviceError .= " {$parts['code']} ({$parts['type']}): " . "{$parts['message']} - " . $err['response']->getBody();
129
  } catch (ParserException $e) {
130
  $parts = [];
vendor/Aws3/Aws/data/accessanalyzer/2019-11-01/api-2.json.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+
3
+ // This file was auto-generated from sdk-root/src/data/accessanalyzer/2019-11-01/api-2.json
4
+ return ['version' => '2.0', 'metadata' => ['apiVersion' => '2019-11-01', 'endpointPrefix' => 'access-analyzer', 'jsonVersion' => '1.1', 'protocol' => 'rest-json', 'serviceFullName' => 'Access Analyzer', 'serviceId' => 'AccessAnalyzer', 'signatureVersion' => 'v4', 'signingName' => 'access-analyzer', 'uid' => 'accessanalyzer-2019-11-01'], 'operations' => ['CreateAnalyzer' => ['name' => 'CreateAnalyzer', 'http' => ['method' => 'PUT', 'requestUri' => '/analyzer', 'responseCode' => 200], 'input' => ['shape' => 'CreateAnalyzerRequest'], 'output' => ['shape' => 'CreateAnalyzerResponse'], 'errors' => [['shape' => 'ConflictException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ServiceQuotaExceededException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'CreateArchiveRule' => ['name' => 'CreateArchiveRule', 'http' => ['method' => 'PUT', 'requestUri' => '/analyzer/{analyzerName}/archive-rule', 'responseCode' => 200], 'input' => ['shape' => 'CreateArchiveRuleRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ConflictException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ServiceQuotaExceededException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'DeleteAnalyzer' => ['name' => 'DeleteAnalyzer', 'http' => ['method' => 'DELETE', 'requestUri' => '/analyzer/{analyzerName}', 'responseCode' => 200], 'input' => ['shape' => 'DeleteAnalyzerRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'DeleteArchiveRule' => ['name' => 'DeleteArchiveRule', 'http' => ['method' => 'DELETE', 'requestUri' => '/analyzer/{analyzerName}/archive-rule/{ruleName}', 'responseCode' => 200], 'input' => ['shape' => 'DeleteArchiveRuleRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'GetAnalyzedResource' => ['name' => 'GetAnalyzedResource', 'http' => ['method' => 'GET', 'requestUri' => '/analyzed-resource', 'responseCode' => 200], 'input' => ['shape' => 'GetAnalyzedResourceRequest'], 'output' => ['shape' => 'GetAnalyzedResourceResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'GetAnalyzer' => ['name' => 'GetAnalyzer', 'http' => ['method' => 'GET', 'requestUri' => '/analyzer/{analyzerName}', 'responseCode' => 200], 'input' => ['shape' => 'GetAnalyzerRequest'], 'output' => ['shape' => 'GetAnalyzerResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'GetArchiveRule' => ['name' => 'GetArchiveRule', 'http' => ['method' => 'GET', 'requestUri' => '/analyzer/{analyzerName}/archive-rule/{ruleName}', 'responseCode' => 200], 'input' => ['shape' => 'GetArchiveRuleRequest'], 'output' => ['shape' => 'GetArchiveRuleResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'GetFinding' => ['name' => 'GetFinding', 'http' => ['method' => 'GET', 'requestUri' => '/finding/{id}', 'responseCode' => 200], 'input' => ['shape' => 'GetFindingRequest'], 'output' => ['shape' => 'GetFindingResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'ListAnalyzedResources' => ['name' => 'ListAnalyzedResources', 'http' => ['method' => 'POST', 'requestUri' => '/analyzed-resource', 'responseCode' => 200], 'input' => ['shape' => 'ListAnalyzedResourcesRequest'], 'output' => ['shape' => 'ListAnalyzedResourcesResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'ListAnalyzers' => ['name' => 'ListAnalyzers', 'http' => ['method' => 'GET', 'requestUri' => '/analyzer', 'responseCode' => 200], 'input' => ['shape' => 'ListAnalyzersRequest'], 'output' => ['shape' => 'ListAnalyzersResponse'], 'errors' => [['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'ListArchiveRules' => ['name' => 'ListArchiveRules', 'http' => ['method' => 'GET', 'requestUri' => '/analyzer/{analyzerName}/archive-rule', 'responseCode' => 200], 'input' => ['shape' => 'ListArchiveRulesRequest'], 'output' => ['shape' => 'ListArchiveRulesResponse'], 'errors' => [['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'ListFindings' => ['name' => 'ListFindings', 'http' => ['method' => 'POST', 'requestUri' => '/finding', 'responseCode' => 200], 'input' => ['shape' => 'ListFindingsRequest'], 'output' => ['shape' => 'ListFindingsResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'ListTagsForResource' => ['name' => 'ListTagsForResource', 'http' => ['method' => 'GET', 'requestUri' => '/tags/{resourceArn}', 'responseCode' => 200], 'input' => ['shape' => 'ListTagsForResourceRequest'], 'output' => ['shape' => 'ListTagsForResourceResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'StartResourceScan' => ['name' => 'StartResourceScan', 'http' => ['method' => 'POST', 'requestUri' => '/resource/scan', 'responseCode' => 200], 'input' => ['shape' => 'StartResourceScanRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'TagResource' => ['name' => 'TagResource', 'http' => ['method' => 'POST', 'requestUri' => '/tags/{resourceArn}', 'responseCode' => 200], 'input' => ['shape' => 'TagResourceRequest'], 'output' => ['shape' => 'TagResourceResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'UntagResource' => ['name' => 'UntagResource', 'http' => ['method' => 'DELETE', 'requestUri' => '/tags/{resourceArn}', 'responseCode' => 200], 'input' => ['shape' => 'UntagResourceRequest'], 'output' => ['shape' => 'UntagResourceResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'UpdateArchiveRule' => ['name' => 'UpdateArchiveRule', 'http' => ['method' => 'PUT', 'requestUri' => '/analyzer/{analyzerName}/archive-rule/{ruleName}', 'responseCode' => 200], 'input' => ['shape' => 'UpdateArchiveRuleRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'UpdateFindings' => ['name' => 'UpdateFindings', 'http' => ['method' => 'PUT', 'requestUri' => '/finding', 'responseCode' => 200], 'input' => ['shape' => 'UpdateFindingsRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true]], 'shapes' => ['AccessDeniedException' => ['type' => 'structure', 'required' => ['message'], 'members' => ['message' => ['shape' => 'String']], 'error' => ['httpStatusCode' => 403, 'senderFault' => \true], 'exception' => \true], 'ActionList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'AnalyzedResource' => ['type' => 'structure', 'required' => ['analyzedAt', 'createdAt', 'isPublic', 'resourceArn', 'resourceType', 'updatedAt'], 'members' => ['actions' => ['shape' => 'ActionList'], 'analyzedAt' => ['shape' => 'Timestamp'], 'createdAt' => ['shape' => 'Timestamp'], 'error' => ['shape' => 'String'], 'isPublic' => ['shape' => 'Boolean'], 'resourceArn' => ['shape' => 'ResourceArn'], 'resourceType' => ['shape' => 'ResourceType'], 'sharedVia' => ['shape' => 'SharedViaList'], 'status' => ['shape' => 'FindingStatus'], 'updatedAt' => ['shape' => 'Timestamp']]], 'AnalyzedResourceSummary' => ['type' => 'structure', 'required' => ['resourceArn', 'resourceType'], 'members' => ['resourceArn' => ['shape' => 'ResourceArn'], 'resourceType' => ['shape' => 'ResourceType']]], 'AnalyzedResourcesList' => ['type' => 'list', 'member' => ['shape' => 'AnalyzedResourceSummary']], 'AnalyzerArn' => ['type' => 'string', 'pattern' => '^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:analyzer/.{1,255}$'], 'AnalyzerSummary' => ['type' => 'structure', 'required' => ['arn', 'createdAt', 'name', 'type'], 'members' => ['arn' => ['shape' => 'AnalyzerArn'], 'createdAt' => ['shape' => 'Timestamp'], 'lastResourceAnalyzed' => ['shape' => 'String'], 'lastResourceAnalyzedAt' => ['shape' => 'Timestamp'], 'name' => ['shape' => 'Name'], 'tags' => ['shape' => 'TagsMap'], 'type' => ['shape' => 'Type']]], 'AnalyzersList' => ['type' => 'list', 'member' => ['shape' => 'AnalyzerSummary']], 'ArchiveRuleSummary' => ['type' => 'structure', 'required' => ['createdAt', 'filter', 'ruleName', 'updatedAt'], 'members' => ['createdAt' => ['shape' => 'Timestamp'], 'filter' => ['shape' => 'FilterCriteriaMap'], 'ruleName' => ['shape' => 'Name'], 'updatedAt' => ['shape' => 'Timestamp']]], 'ArchiveRulesList' => ['type' => 'list', 'member' => ['shape' => 'ArchiveRuleSummary']], 'Boolean' => ['type' => 'boolean', 'box' => \true], 'ConditionKeyMap' => ['type' => 'map', 'key' => ['shape' => 'String'], 'value' => ['shape' => 'String']], 'ConflictException' => ['type' => 'structure', 'required' => ['message', 'resourceId', 'resourceType'], 'members' => ['message' => ['shape' => 'String'], 'resourceId' => ['shape' => 'String'], 'resourceType' => ['shape' => 'String']], 'error' => ['httpStatusCode' => 409, 'senderFault' => \true], 'exception' => \true], 'CreateAnalyzerRequest' => ['type' => 'structure', 'required' => ['analyzerName', 'type'], 'members' => ['analyzerName' => ['shape' => 'Name'], 'archiveRules' => ['shape' => 'InlineArchiveRulesList'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true], 'tags' => ['shape' => 'TagsMap'], 'type' => ['shape' => 'Type']]], 'CreateAnalyzerResponse' => ['type' => 'structure', 'members' => ['arn' => ['shape' => 'AnalyzerArn']]], 'CreateArchiveRuleRequest' => ['type' => 'structure', 'required' => ['analyzerName', 'filter', 'ruleName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true], 'filter' => ['shape' => 'FilterCriteriaMap'], 'ruleName' => ['shape' => 'Name']]], 'Criterion' => ['type' => 'structure', 'members' => ['contains' => ['shape' => 'ValueList'], 'eq' => ['shape' => 'ValueList'], 'exists' => ['shape' => 'Boolean'], 'neq' => ['shape' => 'ValueList']]], 'DeleteAnalyzerRequest' => ['type' => 'structure', 'required' => ['analyzerName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true, 'location' => 'querystring', 'locationName' => 'clientToken']]], 'DeleteArchiveRuleRequest' => ['type' => 'structure', 'required' => ['analyzerName', 'ruleName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true, 'location' => 'querystring', 'locationName' => 'clientToken'], 'ruleName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'ruleName']]], 'FilterCriteriaMap' => ['type' => 'map', 'key' => ['shape' => 'String'], 'value' => ['shape' => 'Criterion']], 'Finding' => ['type' => 'structure', 'required' => ['analyzedAt', 'condition', 'createdAt', 'id', 'resourceType', 'status', 'updatedAt'], 'members' => ['action' => ['shape' => 'ActionList'], 'analyzedAt' => ['shape' => 'Timestamp'], 'condition' => ['shape' => 'ConditionKeyMap'], 'createdAt' => ['shape' => 'Timestamp'], 'error' => ['shape' => 'String'], 'id' => ['shape' => 'FindingId'], 'isPublic' => ['shape' => 'Boolean'], 'principal' => ['shape' => 'PrincipalMap'], 'resource' => ['shape' => 'String'], 'resourceType' => ['shape' => 'ResourceType'], 'status' => ['shape' => 'FindingStatus'], 'updatedAt' => ['shape' => 'Timestamp']]], 'FindingId' => ['type' => 'string'], 'FindingIdList' => ['type' => 'list', 'member' => ['shape' => 'FindingId']], 'FindingStatus' => ['type' => 'string', 'enum' => ['ACTIVE', 'ARCHIVED', 'RESOLVED']], 'FindingStatusUpdate' => ['type' => 'string', 'enum' => ['ACTIVE', 'ARCHIVED']], 'FindingSummary' => ['type' => 'structure', 'required' => ['analyzedAt', 'condition', 'createdAt', 'id', 'resourceType', 'status', 'updatedAt'], 'members' => ['action' => ['shape' => 'ActionList'], 'analyzedAt' => ['shape' => 'Timestamp'], 'condition' => ['shape' => 'ConditionKeyMap'], 'createdAt' => ['shape' => 'Timestamp'], 'error' => ['shape' => 'String'], 'id' => ['shape' => 'FindingId'], 'isPublic' => ['shape' => 'Boolean'], 'principal' => ['shape' => 'PrincipalMap'], 'resource' => ['shape' => 'String'], 'resourceType' => ['shape' => 'ResourceType'], 'status' => ['shape' => 'FindingStatus'], 'updatedAt' => ['shape' => 'Timestamp']]], 'FindingsList' => ['type' => 'list', 'member' => ['shape' => 'FindingSummary']], 'GetAnalyzedResourceRequest' => ['type' => 'structure', 'required' => ['analyzerArn', 'resourceArn'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn', 'location' => 'querystring', 'locationName' => 'analyzerArn'], 'resourceArn' => ['shape' => 'ResourceArn', 'location' => 'querystring', 'locationName' => 'resourceArn']]], 'GetAnalyzedResourceResponse' => ['type' => 'structure', 'members' => ['resource' => ['shape' => 'AnalyzedResource']]], 'GetAnalyzerRequest' => ['type' => 'structure', 'required' => ['analyzerName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName']]], 'GetAnalyzerResponse' => ['type' => 'structure', 'required' => ['analyzer'], 'members' => ['analyzer' => ['shape' => 'AnalyzerSummary']]], 'GetArchiveRuleRequest' => ['type' => 'structure', 'required' => ['analyzerName', 'ruleName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'ruleName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'ruleName']]], 'GetArchiveRuleResponse' => ['type' => 'structure', 'required' => ['archiveRule'], 'members' => ['archiveRule' => ['shape' => 'ArchiveRuleSummary']]], 'GetFindingRequest' => ['type' => 'structure', 'required' => ['analyzerArn', 'id'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn', 'location' => 'querystring', 'locationName' => 'analyzerArn'], 'id' => ['shape' => 'FindingId', 'location' => 'uri', 'locationName' => 'id']]], 'GetFindingResponse' => ['type' => 'structure', 'members' => ['finding' => ['shape' => 'Finding']]], 'InlineArchiveRule' => ['type' => 'structure', 'required' => ['filter', 'ruleName'], 'members' => ['filter' => ['shape' => 'FilterCriteriaMap'], 'ruleName' => ['shape' => 'Name']]], 'InlineArchiveRulesList' => ['type' => 'list', 'member' => ['shape' => 'InlineArchiveRule']], 'Integer' => ['type' => 'integer', 'box' => \true], 'InternalServerException' => ['type' => 'structure', 'required' => ['message'], 'members' => ['message' => ['shape' => 'String'], 'retryAfterSeconds' => ['shape' => 'Integer', 'location' => 'header', 'locationName' => 'Retry-After']], 'error' => ['httpStatusCode' => 500], 'exception' => \true, 'fault' => \true], 'ListAnalyzedResourcesRequest' => ['type' => 'structure', 'required' => ['analyzerArn'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn'], 'maxResults' => ['shape' => 'Integer'], 'nextToken' => ['shape' => 'Token'], 'resourceType' => ['shape' => 'ResourceType']]], 'ListAnalyzedResourcesResponse' => ['type' => 'structure', 'required' => ['analyzedResources'], 'members' => ['analyzedResources' => ['shape' => 'AnalyzedResourcesList'], 'nextToken' => ['shape' => 'Token']]], 'ListAnalyzersRequest' => ['type' => 'structure', 'members' => ['maxResults' => ['shape' => 'Integer', 'location' => 'querystring', 'locationName' => 'maxResults'], 'nextToken' => ['shape' => 'Token', 'location' => 'querystring', 'locationName' => 'nextToken'], 'type' => ['shape' => 'Type', 'location' => 'querystring', 'locationName' => 'type']]], 'ListAnalyzersResponse' => ['type' => 'structure', 'required' => ['analyzers'], 'members' => ['analyzers' => ['shape' => 'AnalyzersList'], 'nextToken' => ['shape' => 'Token']]], 'ListArchiveRulesRequest' => ['type' => 'structure', 'required' => ['analyzerName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'maxResults' => ['shape' => 'Integer', 'location' => 'querystring', 'locationName' => 'maxResults'], 'nextToken' => ['shape' => 'Token', 'location' => 'querystring', 'locationName' => 'nextToken']]], 'ListArchiveRulesResponse' => ['type' => 'structure', 'required' => ['archiveRules'], 'members' => ['archiveRules' => ['shape' => 'ArchiveRulesList'], 'nextToken' => ['shape' => 'Token']]], 'ListFindingsRequest' => ['type' => 'structure', 'required' => ['analyzerArn'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn'], 'filter' => ['shape' => 'FilterCriteriaMap'], 'maxResults' => ['shape' => 'Integer'], 'nextToken' => ['shape' => 'Token'], 'sort' => ['shape' => 'SortCriteria']]], 'ListFindingsResponse' => ['type' => 'structure', 'required' => ['findings'], 'members' => ['findings' => ['shape' => 'FindingsList'], 'nextToken' => ['shape' => 'Token']]], 'ListTagsForResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn'], 'members' => ['resourceArn' => ['shape' => 'String', 'location' => 'uri', 'locationName' => 'resourceArn']]], 'ListTagsForResourceResponse' => ['type' => 'structure', 'members' => ['tags' => ['shape' => 'TagsMap']]], 'Name' => ['type' => 'string', 'max' => 255, 'min' => 1, 'pattern' => '^[A-Za-z][A-Za-z0-9_.-]*$'], 'OrderBy' => ['type' => 'string', 'enum' => ['ASC', 'DESC']], 'PrincipalMap' => ['type' => 'map', 'key' => ['shape' => 'String'], 'value' => ['shape' => 'String']], 'ResourceArn' => ['type' => 'string', 'pattern' => 'arn:[^:]*:[^:]*:[^:]*:[^:]*:.*$'], 'ResourceNotFoundException' => ['type' => 'structure', 'required' => ['message', 'resourceId', 'resourceType'], 'members' => ['message' => ['shape' => 'String'], 'resourceId' => ['shape' => 'String'], 'resourceType' => ['shape' => 'String']], 'error' => ['httpStatusCode' => 404, 'senderFault' => \true], 'exception' => \true], 'ResourceType' => ['type' => 'string', 'enum' => ['AWS::IAM::Role', 'AWS::KMS::Key', 'AWS::Lambda::Function', 'AWS::Lambda::LayerVersion', 'AWS::S3::Bucket', 'AWS::SQS::Queue']], 'ServiceQuotaExceededException' => ['type' => 'structure', 'required' => ['message', 'resourceId', 'resourceType'], 'members' => ['message' => ['shape' => 'String'], 'resourceId' => ['shape' => 'String'], 'resourceType' => ['shape' => 'String']], 'error' => ['httpStatusCode' => 402, 'senderFault' => \true], 'exception' => \true], 'SharedViaList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'SortCriteria' => ['type' => 'structure', 'members' => ['attributeName' => ['shape' => 'String'], 'orderBy' => ['shape' => 'OrderBy']]], 'StartResourceScanRequest' => ['type' => 'structure', 'required' => ['analyzerArn', 'resourceArn'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn'], 'resourceArn' => ['shape' => 'ResourceArn']]], 'String' => ['type' => 'string'], 'TagKeys' => ['type' => 'list', 'member' => ['shape' => 'String']], 'TagResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn', 'tags'], 'members' => ['resourceArn' => ['shape' => 'String', 'location' => 'uri', 'locationName' => 'resourceArn'], 'tags' => ['shape' => 'TagsMap']]], 'TagResourceResponse' => ['type' => 'structure', 'members' => []], 'TagsMap' => ['type' => 'map', 'key' => ['shape' => 'String'], 'value' => ['shape' => 'String']], 'ThrottlingException' => ['type' => 'structure', 'required' => ['message'], 'members' => ['message' => ['shape' => 'String'], 'retryAfterSeconds' => ['shape' => 'Integer', 'location' => 'header', 'locationName' => 'Retry-After']], 'error' => ['httpStatusCode' => 429, 'senderFault' => \true], 'exception' => \true], 'Timestamp' => ['type' => 'timestamp', 'timestampFormat' => 'iso8601'], 'Token' => ['type' => 'string'], 'Type' => ['type' => 'string', 'enum' => ['ACCOUNT']], 'UntagResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn', 'tagKeys'], 'members' => ['resourceArn' => ['shape' => 'String', 'location' => 'uri', 'locationName' => 'resourceArn'], 'tagKeys' => ['shape' => 'TagKeys', 'location' => 'querystring', 'locationName' => 'tagKeys']]], 'UntagResourceResponse' => ['type' => 'structure', 'members' => []], 'UpdateArchiveRuleRequest' => ['type' => 'structure', 'required' => ['analyzerName', 'filter', 'ruleName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true], 'filter' => ['shape' => 'FilterCriteriaMap'], 'ruleName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'ruleName']]], 'UpdateFindingsRequest' => ['type' => 'structure', 'required' => ['analyzerArn', 'status'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true], 'ids' => ['shape' => 'FindingIdList'], 'resourceArn' => ['shape' => 'ResourceArn'], 'status' => ['shape' => 'FindingStatusUpdate']]], 'ValidationException' => ['type' => 'structure', 'required' => ['message', 'reason'], 'members' => ['fieldList' => ['shape' => 'ValidationExceptionFieldList'], 'message' => ['shape' => 'String'], 'reason' => ['shape' => 'ValidationExceptionReason']], 'error' => ['httpStatusCode' => 400, 'senderFault' => \true], 'exception' => \true], 'ValidationExceptionField' => ['type' => 'structure', 'required' => ['message', 'name'], 'members' => ['message' => ['shape' => 'String'], 'name' => ['shape' => 'String']]], 'ValidationExceptionFieldList' => ['type' => 'list', 'member' => ['shape' => 'ValidationExceptionField']], 'ValidationExceptionReason' => ['type' => 'string', 'enum' => ['cannotParse', 'fieldValidationFailed', 'other', 'unknownOperation']], 'ValueList' => ['type' => 'list', 'member' => ['shape' => 'String'], 'max' => 20, 'min' => 1]]];
vendor/Aws3/Aws/data/accessanalyzer/2019-11-01/paginators-1.json.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+
3
+ // This file was auto-generated from sdk-root/src/data/accessanalyzer/2019-11-01/paginators-1.json
4
+ return ['pagination' => ['ListAnalyzedResources' => ['input_token' => 'nextToken', 'output_token' => 'nextToken', 'limit_key' => 'maxResults', 'result_key' => 'analyzedResources'], 'ListAnalyzers' => ['input_token' => 'nextToken', 'output_token' => 'nextToken', 'limit_key' => 'maxResults', 'result_key' => 'analyzers'], 'ListArchiveRules' => ['input_token' => 'nextToken', 'output_token' => 'nextToken', 'limit_key' => 'maxResults', 'result_key' => 'archiveRules'], 'ListFindings' => ['input_token' => 'nextToken', 'output_token' => 'nextToken', 'limit_key' => 'maxResults', 'result_key' => 'findings']]];
vendor/Aws3/Aws/data/acm-pca/2017-08-22/api-2.json.php CHANGED
@@ -1,4 +1,4 @@
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/api-2.json
4
- return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-08-22', 'endpointPrefix' => 'acm-pca', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceAbbreviation' => 'ACM-PCA', 'serviceFullName' => 'AWS Certificate Manager Private Certificate Authority', 'serviceId' => 'ACM PCA', 'signatureVersion' => 'v4', 'targetPrefix' => 'ACMPrivateCA', 'uid' => 'acm-pca-2017-08-22'], 'operations' => ['CreateCertificateAuthority' => ['name' => 'CreateCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateCertificateAuthorityRequest'], 'output' => ['shape' => 'CreateCertificateAuthorityResponse'], 'errors' => [['shape' => 'InvalidArgsException'], ['shape' => 'InvalidPolicyException'], ['shape' => 'LimitExceededException']], 'idempotent' => \true], 'CreateCertificateAuthorityAuditReport' => ['name' => 'CreateCertificateAuthorityAuditReport', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateCertificateAuthorityAuditReportRequest'], 'output' => ['shape' => 'CreateCertificateAuthorityAuditReportResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException'], ['shape' => 'InvalidStateException']], 'idempotent' => \true], 'DeleteCertificateAuthority' => ['name' => 'DeleteCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteCertificateAuthorityRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'DescribeCertificateAuthority' => ['name' => 'DescribeCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateAuthorityRequest'], 'output' => ['shape' => 'DescribeCertificateAuthorityResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'DescribeCertificateAuthorityAuditReport' => ['name' => 'DescribeCertificateAuthorityAuditReport', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateAuthorityAuditReportRequest'], 'output' => ['shape' => 'DescribeCertificateAuthorityAuditReportResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException']]], 'GetCertificate' => ['name' => 'GetCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateRequest'], 'output' => ['shape' => 'GetCertificateResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'GetCertificateAuthorityCertificate' => ['name' => 'GetCertificateAuthorityCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateAuthorityCertificateRequest'], 'output' => ['shape' => 'GetCertificateAuthorityCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]], 'GetCertificateAuthorityCsr' => ['name' => 'GetCertificateAuthorityCsr', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateAuthorityCsrRequest'], 'output' => ['shape' => 'GetCertificateAuthorityCsrResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'ImportCertificateAuthorityCertificate' => ['name' => 'ImportCertificateAuthorityCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ImportCertificateAuthorityCertificateRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'MalformedCertificateException'], ['shape' => 'CertificateMismatchException']]], 'IssueCertificate' => ['name' => 'IssueCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'IssueCertificateRequest'], 'output' => ['shape' => 'IssueCertificateResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException'], ['shape' => 'MalformedCSRException']], 'idempotent' => \true], 'ListCertificateAuthorities' => ['name' => 'ListCertificateAuthorities', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListCertificateAuthoritiesRequest'], 'output' => ['shape' => 'ListCertificateAuthoritiesResponse'], 'errors' => [['shape' => 'InvalidNextTokenException']]], 'ListTags' => ['name' => 'ListTags', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsRequest'], 'output' => ['shape' => 'ListTagsResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'RestoreCertificateAuthority' => ['name' => 'RestoreCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RestoreCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]], 'RevokeCertificate' => ['name' => 'RevokeCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RevokeCertificateRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestAlreadyProcessedException'], ['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException']]], 'TagCertificateAuthority' => ['name' => 'TagCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'TagCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException']]], 'UntagCertificateAuthority' => ['name' => 'UntagCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UntagCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidTagException']]], 'UpdateCertificateAuthority' => ['name' => 'UpdateCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateCertificateAuthorityRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArgsException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidPolicyException']]]], 'shapes' => ['ASN1Subject' => ['type' => 'structure', 'members' => ['Country' => ['shape' => 'CountryCodeString'], 'Organization' => ['shape' => 'String64'], 'OrganizationalUnit' => ['shape' => 'String64'], 'DistinguishedNameQualifier' => ['shape' => 'DistinguishedNameQualifierString'], 'State' => ['shape' => 'String128'], 'CommonName' => ['shape' => 'String64'], 'SerialNumber' => ['shape' => 'String64'], 'Locality' => ['shape' => 'String128'], 'Title' => ['shape' => 'String64'], 'Surname' => ['shape' => 'String40'], 'GivenName' => ['shape' => 'String16'], 'Initials' => ['shape' => 'String5'], 'Pseudonym' => ['shape' => 'String128'], 'GenerationQualifier' => ['shape' => 'String3']]], 'Arn' => ['type' => 'string', 'max' => 200, 'min' => 5, 'pattern' => 'arn:[\\w+=/,.@-]+:[\\w+=/,.@-]+:[\\w+=/,.@-]*:[0-9]+:[\\w+=,.@-]+(/[\\w+=/,.@-]+)*'], 'AuditReportId' => ['type' => 'string', 'max' => 36, 'min' => 36, 'pattern' => '[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}'], 'AuditReportResponseFormat' => ['type' => 'string', 'enum' => ['JSON', 'CSV']], 'AuditReportStatus' => ['type' => 'string', 'enum' => ['CREATING', 'SUCCESS', 'FAILED']], 'Boolean' => ['type' => 'boolean'], 'CertificateAuthorities' => ['type' => 'list', 'member' => ['shape' => 'CertificateAuthority']], 'CertificateAuthority' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'CreatedAt' => ['shape' => 'TStamp'], 'LastStateChangeAt' => ['shape' => 'TStamp'], 'Type' => ['shape' => 'CertificateAuthorityType'], 'Serial' => ['shape' => 'String'], 'Status' => ['shape' => 'CertificateAuthorityStatus'], 'NotBefore' => ['shape' => 'TStamp'], 'NotAfter' => ['shape' => 'TStamp'], 'FailureReason' => ['shape' => 'FailureReason'], 'CertificateAuthorityConfiguration' => ['shape' => 'CertificateAuthorityConfiguration'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'RestorableUntil' => ['shape' => 'TStamp']]], 'CertificateAuthorityConfiguration' => ['type' => 'structure', 'required' => ['KeyAlgorithm', 'SigningAlgorithm', 'Subject'], 'members' => ['KeyAlgorithm' => ['shape' => 'KeyAlgorithm'], 'SigningAlgorithm' => ['shape' => 'SigningAlgorithm'], 'Subject' => ['shape' => 'ASN1Subject']]], 'CertificateAuthorityStatus' => ['type' => 'string', 'enum' => ['CREATING', 'PENDING_CERTIFICATE', 'ACTIVE', 'DELETED', 'DISABLED', 'EXPIRED', 'FAILED']], 'CertificateAuthorityType' => ['type' => 'string', 'enum' => ['SUBORDINATE']], 'CertificateBody' => ['type' => 'string'], 'CertificateBodyBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CertificateChain' => ['type' => 'string'], 'CertificateChainBlob' => ['type' => 'blob', 'max' => 2097152, 'min' => 0], 'CertificateMismatchException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ConcurrentModificationException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'CountryCodeString' => ['type' => 'string', 'pattern' => '[A-Za-z]{2}'], 'CreateCertificateAuthorityAuditReportRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'S3BucketName', 'AuditReportResponseFormat'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'S3BucketName' => ['shape' => 'String'], 'AuditReportResponseFormat' => ['shape' => 'AuditReportResponseFormat']]], 'CreateCertificateAuthorityAuditReportResponse' => ['type' => 'structure', 'members' => ['AuditReportId' => ['shape' => 'AuditReportId'], 'S3Key' => ['shape' => 'String']]], 'CreateCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityConfiguration', 'CertificateAuthorityType'], 'members' => ['CertificateAuthorityConfiguration' => ['shape' => 'CertificateAuthorityConfiguration'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'CertificateAuthorityType' => ['shape' => 'CertificateAuthorityType'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken']]], 'CreateCertificateAuthorityResponse' => ['type' => 'structure', 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'CrlConfiguration' => ['type' => 'structure', 'required' => ['Enabled'], 'members' => ['Enabled' => ['shape' => 'Boolean', 'box' => \true], 'ExpirationInDays' => ['shape' => 'Integer1To5000', 'box' => \true], 'CustomCname' => ['shape' => 'String253'], 'S3BucketName' => ['shape' => 'String3To255']]], 'CsrBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CsrBody' => ['type' => 'string'], 'DeleteCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'PermanentDeletionTimeInDays' => ['shape' => 'PermanentDeletionTimeInDays']]], 'DescribeCertificateAuthorityAuditReportRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'AuditReportId'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'AuditReportId' => ['shape' => 'AuditReportId']]], 'DescribeCertificateAuthorityAuditReportResponse' => ['type' => 'structure', 'members' => ['AuditReportStatus' => ['shape' => 'AuditReportStatus'], 'S3BucketName' => ['shape' => 'String'], 'S3Key' => ['shape' => 'String'], 'CreatedAt' => ['shape' => 'TStamp']]], 'DescribeCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'DescribeCertificateAuthorityResponse' => ['type' => 'structure', 'members' => ['CertificateAuthority' => ['shape' => 'CertificateAuthority']]], 'DistinguishedNameQualifierString' => ['type' => 'string', 'max' => 64, 'min' => 0, 'pattern' => '[a-zA-Z0-9\'()+-.?:/= ]*'], 'FailureReason' => ['type' => 'string', 'enum' => ['REQUEST_TIMED_OUT', 'UNSUPPORTED_ALGORITHM', 'OTHER']], 'GetCertificateAuthorityCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'GetCertificateAuthorityCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'GetCertificateAuthorityCsrRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'GetCertificateAuthorityCsrResponse' => ['type' => 'structure', 'members' => ['Csr' => ['shape' => 'CsrBody']]], 'GetCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'CertificateArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'CertificateArn' => ['shape' => 'Arn']]], 'GetCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'IdempotencyToken' => ['type' => 'string', 'max' => 36, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u00FF]*'], 'ImportCertificateAuthorityCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Certificate', 'CertificateChain'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Certificate' => ['shape' => 'CertificateBodyBlob'], 'CertificateChain' => ['shape' => 'CertificateChainBlob']]], 'Integer1To5000' => ['type' => 'integer', 'max' => 5000, 'min' => 1], 'InvalidArgsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidArnException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidNextTokenException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidPolicyException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidStateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidTagException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'IssueCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Csr', 'SigningAlgorithm', 'Validity'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Csr' => ['shape' => 'CsrBlob'], 'SigningAlgorithm' => ['shape' => 'SigningAlgorithm'], 'Validity' => ['shape' => 'Validity'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken']]], 'IssueCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'KeyAlgorithm' => ['type' => 'string', 'enum' => ['RSA_2048', 'RSA_4096', 'EC_prime256v1', 'EC_secp384r1']], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ListCertificateAuthoritiesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListCertificateAuthoritiesResponse' => ['type' => 'structure', 'members' => ['CertificateAuthorities' => ['shape' => 'CertificateAuthorities'], 'NextToken' => ['shape' => 'NextToken']]], 'ListTagsRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListTagsResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList'], 'NextToken' => ['shape' => 'NextToken']]], 'MalformedCSRException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'MalformedCertificateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'MaxResults' => ['type' => 'integer', 'max' => 1000, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 500, 'min' => 1], 'PermanentDeletionTimeInDays' => ['type' => 'integer', 'max' => 30, 'min' => 7], 'PositiveLong' => ['type' => 'long', 'min' => 1], 'RequestAlreadyProcessedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RequestFailedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RequestInProgressException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceNotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RestoreCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'RevocationConfiguration' => ['type' => 'structure', 'members' => ['CrlConfiguration' => ['shape' => 'CrlConfiguration']]], 'RevocationReason' => ['type' => 'string', 'enum' => ['UNSPECIFIED', 'KEY_COMPROMISE', 'CERTIFICATE_AUTHORITY_COMPROMISE', 'AFFILIATION_CHANGED', 'SUPERSEDED', 'CESSATION_OF_OPERATION', 'PRIVILEGE_WITHDRAWN', 'A_A_COMPROMISE']], 'RevokeCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'CertificateSerial', 'RevocationReason'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'CertificateSerial' => ['shape' => 'String128'], 'RevocationReason' => ['shape' => 'RevocationReason']]], 'SigningAlgorithm' => ['type' => 'string', 'enum' => ['SHA256WITHECDSA', 'SHA384WITHECDSA', 'SHA512WITHECDSA', 'SHA256WITHRSA', 'SHA384WITHRSA', 'SHA512WITHRSA']], 'String' => ['type' => 'string'], 'String128' => ['type' => 'string', 'max' => 128, 'min' => 0], 'String16' => ['type' => 'string', 'max' => 16, 'min' => 0], 'String253' => ['type' => 'string', 'max' => 253, 'min' => 0], 'String3' => ['type' => 'string', 'max' => 3, 'min' => 0], 'String3To255' => ['type' => 'string', 'max' => 255, 'min' => 3], 'String40' => ['type' => 'string', 'max' => 40, 'min' => 0], 'String5' => ['type' => 'string', 'max' => 5, 'min' => 0], 'String64' => ['type' => 'string', 'max' => 64, 'min' => 0], 'TStamp' => ['type' => 'timestamp'], 'Tag' => ['type' => 'structure', 'required' => ['Key'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Tags'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag'], 'max' => 50, 'min' => 1], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TooManyTagsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'UntagCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Tags'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'UpdateCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'Status' => ['shape' => 'CertificateAuthorityStatus']]], 'Validity' => ['type' => 'structure', 'required' => ['Value', 'Type'], 'members' => ['Value' => ['shape' => 'PositiveLong', 'box' => \true], 'Type' => ['shape' => 'ValidityPeriodType']]], 'ValidityPeriodType' => ['type' => 'string', 'enum' => ['END_DATE', 'ABSOLUTE', 'DAYS', 'MONTHS', 'YEARS']]]];
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/api-2.json
4
+ return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-08-22', 'endpointPrefix' => 'acm-pca', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceAbbreviation' => 'ACM-PCA', 'serviceFullName' => 'AWS Certificate Manager Private Certificate Authority', 'serviceId' => 'ACM PCA', 'signatureVersion' => 'v4', 'targetPrefix' => 'ACMPrivateCA', 'uid' => 'acm-pca-2017-08-22'], 'operations' => ['CreateCertificateAuthority' => ['name' => 'CreateCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateCertificateAuthorityRequest'], 'output' => ['shape' => 'CreateCertificateAuthorityResponse'], 'errors' => [['shape' => 'InvalidArgsException'], ['shape' => 'InvalidPolicyException'], ['shape' => 'InvalidTagException'], ['shape' => 'LimitExceededException']], 'idempotent' => \true], 'CreateCertificateAuthorityAuditReport' => ['name' => 'CreateCertificateAuthorityAuditReport', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateCertificateAuthorityAuditReportRequest'], 'output' => ['shape' => 'CreateCertificateAuthorityAuditReportResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException'], ['shape' => 'InvalidStateException']], 'idempotent' => \true], 'CreatePermission' => ['name' => 'CreatePermission', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreatePermissionRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'PermissionAlreadyExistsException'], ['shape' => 'LimitExceededException'], ['shape' => 'InvalidStateException'], ['shape' => 'RequestFailedException']]], 'DeleteCertificateAuthority' => ['name' => 'DeleteCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteCertificateAuthorityRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'DeletePermission' => ['name' => 'DeletePermission', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeletePermissionRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'RequestFailedException']]], 'DescribeCertificateAuthority' => ['name' => 'DescribeCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateAuthorityRequest'], 'output' => ['shape' => 'DescribeCertificateAuthorityResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'DescribeCertificateAuthorityAuditReport' => ['name' => 'DescribeCertificateAuthorityAuditReport', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateAuthorityAuditReportRequest'], 'output' => ['shape' => 'DescribeCertificateAuthorityAuditReportResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException']]], 'GetCertificate' => ['name' => 'GetCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateRequest'], 'output' => ['shape' => 'GetCertificateResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'GetCertificateAuthorityCertificate' => ['name' => 'GetCertificateAuthorityCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateAuthorityCertificateRequest'], 'output' => ['shape' => 'GetCertificateAuthorityCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]], 'GetCertificateAuthorityCsr' => ['name' => 'GetCertificateAuthorityCsr', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateAuthorityCsrRequest'], 'output' => ['shape' => 'GetCertificateAuthorityCsrResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'ImportCertificateAuthorityCertificate' => ['name' => 'ImportCertificateAuthorityCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ImportCertificateAuthorityCertificateRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidRequestException'], ['shape' => 'InvalidStateException'], ['shape' => 'MalformedCertificateException'], ['shape' => 'CertificateMismatchException']]], 'IssueCertificate' => ['name' => 'IssueCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'IssueCertificateRequest'], 'output' => ['shape' => 'IssueCertificateResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException'], ['shape' => 'MalformedCSRException']], 'idempotent' => \true], 'ListCertificateAuthorities' => ['name' => 'ListCertificateAuthorities', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListCertificateAuthoritiesRequest'], 'output' => ['shape' => 'ListCertificateAuthoritiesResponse'], 'errors' => [['shape' => 'InvalidNextTokenException']]], 'ListPermissions' => ['name' => 'ListPermissions', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListPermissionsRequest'], 'output' => ['shape' => 'ListPermissionsResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidNextTokenException'], ['shape' => 'InvalidStateException'], ['shape' => 'RequestFailedException']]], 'ListTags' => ['name' => 'ListTags', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsRequest'], 'output' => ['shape' => 'ListTagsResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'RestoreCertificateAuthority' => ['name' => 'RestoreCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RestoreCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]], 'RevokeCertificate' => ['name' => 'RevokeCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RevokeCertificateRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidRequestException'], ['shape' => 'InvalidStateException'], ['shape' => 'LimitExceededException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestAlreadyProcessedException'], ['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException']]], 'TagCertificateAuthority' => ['name' => 'TagCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'TagCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException']]], 'UntagCertificateAuthority' => ['name' => 'UntagCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UntagCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidTagException']]], 'UpdateCertificateAuthority' => ['name' => 'UpdateCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateCertificateAuthorityRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArgsException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidPolicyException']]]], 'shapes' => ['ASN1Subject' => ['type' => 'structure', 'members' => ['Country' => ['shape' => 'CountryCodeString'], 'Organization' => ['shape' => 'String64'], 'OrganizationalUnit' => ['shape' => 'String64'], 'DistinguishedNameQualifier' => ['shape' => 'DistinguishedNameQualifierString'], 'State' => ['shape' => 'String128'], 'CommonName' => ['shape' => 'String64'], 'SerialNumber' => ['shape' => 'String64'], 'Locality' => ['shape' => 'String128'], 'Title' => ['shape' => 'String64'], 'Surname' => ['shape' => 'String40'], 'GivenName' => ['shape' => 'String16'], 'Initials' => ['shape' => 'String5'], 'Pseudonym' => ['shape' => 'String128'], 'GenerationQualifier' => ['shape' => 'String3']]], 'AccountId' => ['type' => 'string', 'max' => 12, 'min' => 12, 'pattern' => '[0-9]+'], 'ActionList' => ['type' => 'list', 'member' => ['shape' => 'ActionType'], 'max' => 3, 'min' => 1], 'ActionType' => ['type' => 'string', 'enum' => ['IssueCertificate', 'GetCertificate', 'ListPermissions']], 'Arn' => ['type' => 'string', 'max' => 200, 'min' => 5, 'pattern' => 'arn:[\\w+=/,.@-]+:[\\w+=/,.@-]+:[\\w+=/,.@-]*:[0-9]*:[\\w+=,.@-]+(/[\\w+=/,.@-]+)*'], 'AuditReportId' => ['type' => 'string', 'max' => 36, 'min' => 36, 'pattern' => '[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}'], 'AuditReportResponseFormat' => ['type' => 'string', 'enum' => ['JSON', 'CSV']], 'AuditReportStatus' => ['type' => 'string', 'enum' => ['CREATING', 'SUCCESS', 'FAILED']], 'Boolean' => ['type' => 'boolean'], 'CertificateAuthorities' => ['type' => 'list', 'member' => ['shape' => 'CertificateAuthority']], 'CertificateAuthority' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'CreatedAt' => ['shape' => 'TStamp'], 'LastStateChangeAt' => ['shape' => 'TStamp'], 'Type' => ['shape' => 'CertificateAuthorityType'], 'Serial' => ['shape' => 'String'], 'Status' => ['shape' => 'CertificateAuthorityStatus'], 'NotBefore' => ['shape' => 'TStamp'], 'NotAfter' => ['shape' => 'TStamp'], 'FailureReason' => ['shape' => 'FailureReason'], 'CertificateAuthorityConfiguration' => ['shape' => 'CertificateAuthorityConfiguration'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'RestorableUntil' => ['shape' => 'TStamp']]], 'CertificateAuthorityConfiguration' => ['type' => 'structure', 'required' => ['KeyAlgorithm', 'SigningAlgorithm', 'Subject'], 'members' => ['KeyAlgorithm' => ['shape' => 'KeyAlgorithm'], 'SigningAlgorithm' => ['shape' => 'SigningAlgorithm'], 'Subject' => ['shape' => 'ASN1Subject']]], 'CertificateAuthorityStatus' => ['type' => 'string', 'enum' => ['CREATING', 'PENDING_CERTIFICATE', 'ACTIVE', 'DELETED', 'DISABLED', 'EXPIRED', 'FAILED']], 'CertificateAuthorityType' => ['type' => 'string', 'enum' => ['ROOT', 'SUBORDINATE']], 'CertificateBody' => ['type' => 'string'], 'CertificateBodyBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CertificateChain' => ['type' => 'string'], 'CertificateChainBlob' => ['type' => 'blob', 'max' => 2097152, 'min' => 0], 'CertificateMismatchException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ConcurrentModificationException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'CountryCodeString' => ['type' => 'string', 'pattern' => '[A-Za-z]{2}'], 'CreateCertificateAuthorityAuditReportRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'S3BucketName', 'AuditReportResponseFormat'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'S3BucketName' => ['shape' => 'String'], 'AuditReportResponseFormat' => ['shape' => 'AuditReportResponseFormat']]], 'CreateCertificateAuthorityAuditReportResponse' => ['type' => 'structure', 'members' => ['AuditReportId' => ['shape' => 'AuditReportId'], 'S3Key' => ['shape' => 'String']]], 'CreateCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityConfiguration', 'CertificateAuthorityType'], 'members' => ['CertificateAuthorityConfiguration' => ['shape' => 'CertificateAuthorityConfiguration'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'CertificateAuthorityType' => ['shape' => 'CertificateAuthorityType'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken'], 'Tags' => ['shape' => 'TagList']]], 'CreateCertificateAuthorityResponse' => ['type' => 'structure', 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'CreatePermissionRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Principal', 'Actions'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Principal' => ['shape' => 'Principal'], 'SourceAccount' => ['shape' => 'AccountId'], 'Actions' => ['shape' => 'ActionList']]], 'CrlConfiguration' => ['type' => 'structure', 'required' => ['Enabled'], 'members' => ['Enabled' => ['shape' => 'Boolean', 'box' => \true], 'ExpirationInDays' => ['shape' => 'Integer1To5000', 'box' => \true], 'CustomCname' => ['shape' => 'String253'], 'S3BucketName' => ['shape' => 'String3To255']]], 'CsrBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CsrBody' => ['type' => 'string'], 'DeleteCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'PermanentDeletionTimeInDays' => ['shape' => 'PermanentDeletionTimeInDays']]], 'DeletePermissionRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Principal'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Principal' => ['shape' => 'Principal'], 'SourceAccount' => ['shape' => 'AccountId']]], 'DescribeCertificateAuthorityAuditReportRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'AuditReportId'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'AuditReportId' => ['shape' => 'AuditReportId']]], 'DescribeCertificateAuthorityAuditReportResponse' => ['type' => 'structure', 'members' => ['AuditReportStatus' => ['shape' => 'AuditReportStatus'], 'S3BucketName' => ['shape' => 'String'], 'S3Key' => ['shape' => 'String'], 'CreatedAt' => ['shape' => 'TStamp']]], 'DescribeCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'DescribeCertificateAuthorityResponse' => ['type' => 'structure', 'members' => ['CertificateAuthority' => ['shape' => 'CertificateAuthority']]], 'DistinguishedNameQualifierString' => ['type' => 'string', 'max' => 64, 'min' => 0, 'pattern' => '[a-zA-Z0-9\'()+-.?:/= ]*'], 'FailureReason' => ['type' => 'string', 'enum' => ['REQUEST_TIMED_OUT', 'UNSUPPORTED_ALGORITHM', 'OTHER']], 'GetCertificateAuthorityCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'GetCertificateAuthorityCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'GetCertificateAuthorityCsrRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'GetCertificateAuthorityCsrResponse' => ['type' => 'structure', 'members' => ['Csr' => ['shape' => 'CsrBody']]], 'GetCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'CertificateArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'CertificateArn' => ['shape' => 'Arn']]], 'GetCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'IdempotencyToken' => ['type' => 'string', 'max' => 36, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u00FF]*'], 'ImportCertificateAuthorityCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Certificate'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Certificate' => ['shape' => 'CertificateBodyBlob'], 'CertificateChain' => ['shape' => 'CertificateChainBlob']]], 'Integer1To5000' => ['type' => 'integer', 'max' => 5000, 'min' => 1], 'InvalidArgsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidArnException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidNextTokenException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidPolicyException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidRequestException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidStateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidTagException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'IssueCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Csr', 'SigningAlgorithm', 'Validity'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Csr' => ['shape' => 'CsrBlob'], 'SigningAlgorithm' => ['shape' => 'SigningAlgorithm'], 'TemplateArn' => ['shape' => 'Arn'], 'Validity' => ['shape' => 'Validity'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken']]], 'IssueCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'KeyAlgorithm' => ['type' => 'string', 'enum' => ['RSA_2048', 'RSA_4096', 'EC_prime256v1', 'EC_secp384r1']], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ListCertificateAuthoritiesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListCertificateAuthoritiesResponse' => ['type' => 'structure', 'members' => ['CertificateAuthorities' => ['shape' => 'CertificateAuthorities'], 'NextToken' => ['shape' => 'NextToken']]], 'ListPermissionsRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListPermissionsResponse' => ['type' => 'structure', 'members' => ['Permissions' => ['shape' => 'PermissionList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListTagsRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListTagsResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList'], 'NextToken' => ['shape' => 'NextToken']]], 'MalformedCSRException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'MalformedCertificateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'MaxResults' => ['type' => 'integer', 'max' => 1000, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 500, 'min' => 1], 'PermanentDeletionTimeInDays' => ['type' => 'integer', 'max' => 30, 'min' => 7], 'Permission' => ['type' => 'structure', 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'CreatedAt' => ['shape' => 'TStamp'], 'Principal' => ['shape' => 'String'], 'SourceAccount' => ['shape' => 'String'], 'Actions' => ['shape' => 'ActionList'], 'Policy' => ['shape' => 'String']]], 'PermissionAlreadyExistsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'PermissionList' => ['type' => 'list', 'member' => ['shape' => 'Permission'], 'min' => 0], 'PositiveLong' => ['type' => 'long', 'min' => 1], 'Principal' => ['type' => 'string', 'max' => 128, 'min' => 0, 'pattern' => '^[^*]+$'], 'RequestAlreadyProcessedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RequestFailedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RequestInProgressException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceNotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RestoreCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'RevocationConfiguration' => ['type' => 'structure', 'members' => ['CrlConfiguration' => ['shape' => 'CrlConfiguration']]], 'RevocationReason' => ['type' => 'string', 'enum' => ['UNSPECIFIED', 'KEY_COMPROMISE', 'CERTIFICATE_AUTHORITY_COMPROMISE', 'AFFILIATION_CHANGED', 'SUPERSEDED', 'CESSATION_OF_OPERATION', 'PRIVILEGE_WITHDRAWN', 'A_A_COMPROMISE']], 'RevokeCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'CertificateSerial', 'RevocationReason'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'CertificateSerial' => ['shape' => 'String128'], 'RevocationReason' => ['shape' => 'RevocationReason']]], 'SigningAlgorithm' => ['type' => 'string', 'enum' => ['SHA256WITHECDSA', 'SHA384WITHECDSA', 'SHA512WITHECDSA', 'SHA256WITHRSA', 'SHA384WITHRSA', 'SHA512WITHRSA']], 'String' => ['type' => 'string'], 'String128' => ['type' => 'string', 'max' => 128, 'min' => 0], 'String16' => ['type' => 'string', 'max' => 16, 'min' => 0], 'String253' => ['type' => 'string', 'max' => 253, 'min' => 0], 'String3' => ['type' => 'string', 'max' => 3, 'min' => 0], 'String3To255' => ['type' => 'string', 'max' => 255, 'min' => 3], 'String40' => ['type' => 'string', 'max' => 40, 'min' => 0], 'String5' => ['type' => 'string', 'max' => 5, 'min' => 0], 'String64' => ['type' => 'string', 'max' => 64, 'min' => 0], 'TStamp' => ['type' => 'timestamp'], 'Tag' => ['type' => 'structure', 'required' => ['Key'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Tags'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag'], 'max' => 50, 'min' => 1], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TooManyTagsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'UntagCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Tags'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'UpdateCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'Status' => ['shape' => 'CertificateAuthorityStatus']]], 'Validity' => ['type' => 'structure', 'required' => ['Value', 'Type'], 'members' => ['Value' => ['shape' => 'PositiveLong', 'box' => \true], 'Type' => ['shape' => 'ValidityPeriodType']]], 'ValidityPeriodType' => ['type' => 'string', 'enum' => ['END_DATE', 'ABSOLUTE', 'DAYS', 'MONTHS', 'YEARS']]]];
vendor/Aws3/Aws/data/acm-pca/2017-08-22/paginators-1.json.php CHANGED
@@ -1,4 +1,4 @@
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/paginators-1.json
4
- return ['pagination' => ['ListCertificateAuthorities' => ['input_token' => 'NextToken', 'limit_key' => 'MaxResults', 'output_token' => 'NextToken', 'result_key' => 'CertificateAuthorities']]];
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/paginators-1.json
4
+ return ['pagination' => ['ListCertificateAuthorities' => ['input_token' => 'NextToken', 'limit_key' => 'MaxResults', 'output_token' => 'NextToken', 'result_key' => 'CertificateAuthorities'], 'ListPermissions' => ['input_token' => 'NextToken', 'limit_key' => 'MaxResults', 'output_token' => 'NextToken', 'result_key' => 'Permissions'], 'ListTags' => ['input_token' => 'NextToken', 'limit_key' => 'MaxResults', 'output_token' => 'NextToken', 'result_key' => 'Tags']]];
vendor/Aws3/Aws/data/acm-pca/2017-08-22/waiters-2.json.php CHANGED
@@ -1,4 +1,4 @@
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/waiters-2.json
4
- return ['version' => 2, 'waiters' => ['CertificateAuthorityCSRCreated' => ['description' => 'Wait until a Certificate Authority CSR is created', 'operation' => 'GetCertificateAuthorityCsr', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'status', 'expected' => 200], ['state' => 'retry', 'matcher' => 'error', 'expected' => 'RequestInProgressException']]], 'CertificateIssued' => ['description' => 'Wait until a certificate is issued', 'operation' => 'GetCertificate', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'status', 'expected' => 200], ['state' => 'retry', 'matcher' => 'error', 'expected' => 'RequestInProgressException']]], 'AuditReportCreated' => ['description' => 'Wait until a Audit Report is created', 'operation' => 'DescribeCertificateAuthorityAuditReport', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'path', 'argument' => 'AuditReportStatus', 'expected' => 'SUCCESS']]]]];
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/waiters-2.json
4
+ return ['version' => 2, 'waiters' => ['CertificateAuthorityCSRCreated' => ['description' => 'Wait until a Certificate Authority CSR is created', 'operation' => 'GetCertificateAuthorityCsr', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'status', 'expected' => 200], ['state' => 'retry', 'matcher' => 'error', 'expected' => 'RequestInProgressException']]], 'CertificateIssued' => ['description' => 'Wait until a certificate is issued', 'operation' => 'GetCertificate', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'status', 'expected' => 200], ['state' => 'retry', 'matcher' => 'error', 'expected' => 'RequestInProgressException']]], 'AuditReportCreated' => ['description' => 'Wait until a Audit Report is created', 'operation' => 'DescribeCertificateAuthorityAuditReport', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'path', 'argument' => 'AuditReportStatus', 'expected' => 'SUCCESS'], ['state' => 'failure', 'matcher' => 'path', 'argument' => 'AuditReportStatus', 'expected' => 'FAILED']]]]];
vendor/Aws3/Aws/data/acm/2015-12-08/api-2.json.php CHANGED
@@ -1,4 +1,4 @@
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/acm/2015-12-08/api-2.json
4
- return ['version' => '2.0', 'metadata' => ['apiVersion' => '2015-12-08', 'endpointPrefix' => 'acm', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceAbbreviation' => 'ACM', 'serviceFullName' => 'AWS Certificate Manager', 'serviceId' => 'ACM', 'signatureVersion' => 'v4', 'targetPrefix' => 'CertificateManager', 'uid' => 'acm-2015-12-08'], 'operations' => ['AddTagsToCertificate' => ['name' => 'AddTagsToCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AddTagsToCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException']]], 'DeleteCertificate' => ['name' => 'DeleteCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ResourceInUseException'], ['shape' => 'InvalidArnException']]], 'DescribeCertificate' => ['name' => 'DescribeCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateRequest'], 'output' => ['shape' => 'DescribeCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'ExportCertificate' => ['name' => 'ExportCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ExportCertificateRequest'], 'output' => ['shape' => 'ExportCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestInProgressException'], ['shape' => 'InvalidArnException']]], 'GetCertificate' => ['name' => 'GetCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateRequest'], 'output' => ['shape' => 'GetCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestInProgressException'], ['shape' => 'InvalidArnException']]], 'ImportCertificate' => ['name' => 'ImportCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ImportCertificateRequest'], 'output' => ['shape' => 'ImportCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'LimitExceededException']]], 'ListCertificates' => ['name' => 'ListCertificates', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListCertificatesRequest'], 'output' => ['shape' => 'ListCertificatesResponse']], 'ListTagsForCertificate' => ['name' => 'ListTagsForCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsForCertificateRequest'], 'output' => ['shape' => 'ListTagsForCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'RemoveTagsFromCertificate' => ['name' => 'RemoveTagsFromCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RemoveTagsFromCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidTagException']]], 'RequestCertificate' => ['name' => 'RequestCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RequestCertificateRequest'], 'output' => ['shape' => 'RequestCertificateResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'InvalidDomainValidationOptionsException'], ['shape' => 'InvalidArnException']]], 'ResendValidationEmail' => ['name' => 'ResendValidationEmail', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ResendValidationEmailRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidDomainValidationOptionsException']]], 'UpdateCertificateOptions' => ['name' => 'UpdateCertificateOptions', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateCertificateOptionsRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'LimitExceededException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]]], 'shapes' => ['AddTagsToCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Tags'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'Arn' => ['type' => 'string', 'max' => 2048, 'min' => 20, 'pattern' => 'arn:[\\w+=/,.@-]+:[\\w+=/,.@-]+:[\\w+=/,.@-]*:[0-9]+:[\\w+=,.@-]+(/[\\w+=,.@-]+)*'], 'CertificateBody' => ['type' => 'string', 'max' => 32768, 'min' => 1, 'pattern' => '-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}(\\u000D?\\u000A)?'], 'CertificateBodyBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CertificateChain' => ['type' => 'string', 'max' => 2097152, 'min' => 1, 'pattern' => '(-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}\\u000D?\\u000A)*-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}(\\u000D?\\u000A)?'], 'CertificateChainBlob' => ['type' => 'blob', 'max' => 2097152, 'min' => 1], 'CertificateDetail' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'DomainName' => ['shape' => 'DomainNameString'], 'SubjectAlternativeNames' => ['shape' => 'DomainList'], 'DomainValidationOptions' => ['shape' => 'DomainValidationList'], 'Serial' => ['shape' => 'String'], 'Subject' => ['shape' => 'String'], 'Issuer' => ['shape' => 'String'], 'CreatedAt' => ['shape' => 'TStamp'], 'IssuedAt' => ['shape' => 'TStamp'], 'ImportedAt' => ['shape' => 'TStamp'], 'Status' => ['shape' => 'CertificateStatus'], 'RevokedAt' => ['shape' => 'TStamp'], 'RevocationReason' => ['shape' => 'RevocationReason'], 'NotBefore' => ['shape' => 'TStamp'], 'NotAfter' => ['shape' => 'TStamp'], 'KeyAlgorithm' => ['shape' => 'KeyAlgorithm'], 'SignatureAlgorithm' => ['shape' => 'String'], 'InUseBy' => ['shape' => 'InUseList'], 'FailureReason' => ['shape' => 'FailureReason'], 'Type' => ['shape' => 'CertificateType'], 'RenewalSummary' => ['shape' => 'RenewalSummary'], 'KeyUsages' => ['shape' => 'KeyUsageList'], 'ExtendedKeyUsages' => ['shape' => 'ExtendedKeyUsageList'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'RenewalEligibility' => ['shape' => 'RenewalEligibility'], 'Options' => ['shape' => 'CertificateOptions']]], 'CertificateOptions' => ['type' => 'structure', 'members' => ['CertificateTransparencyLoggingPreference' => ['shape' => 'CertificateTransparencyLoggingPreference']]], 'CertificateStatus' => ['type' => 'string', 'enum' => ['PENDING_VALIDATION', 'ISSUED', 'INACTIVE', 'EXPIRED', 'VALIDATION_TIMED_OUT', 'REVOKED', 'FAILED']], 'CertificateStatuses' => ['type' => 'list', 'member' => ['shape' => 'CertificateStatus']], 'CertificateSummary' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'DomainName' => ['shape' => 'DomainNameString']]], 'CertificateSummaryList' => ['type' => 'list', 'member' => ['shape' => 'CertificateSummary']], 'CertificateTransparencyLoggingPreference' => ['type' => 'string', 'enum' => ['ENABLED', 'DISABLED']], 'CertificateType' => ['type' => 'string', 'enum' => ['IMPORTED', 'AMAZON_ISSUED', 'PRIVATE']], 'DeleteCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'DescribeCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'DescribeCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateDetail']]], 'DomainList' => ['type' => 'list', 'member' => ['shape' => 'DomainNameString'], 'max' => 100, 'min' => 1], 'DomainNameString' => ['type' => 'string', 'max' => 253, 'min' => 1, 'pattern' => '^(\\*\\.)?(((?!-)[A-Za-z0-9-]{0,62}[A-Za-z0-9])\\.)+((?!-)[A-Za-z0-9-]{1,62}[A-Za-z0-9])$'], 'DomainStatus' => ['type' => 'string', 'enum' => ['PENDING_VALIDATION', 'SUCCESS', 'FAILED']], 'DomainValidation' => ['type' => 'structure', 'required' => ['DomainName'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationEmails' => ['shape' => 'ValidationEmailList'], 'ValidationDomain' => ['shape' => 'DomainNameString'], 'ValidationStatus' => ['shape' => 'DomainStatus'], 'ResourceRecord' => ['shape' => 'ResourceRecord'], 'ValidationMethod' => ['shape' => 'ValidationMethod']]], 'DomainValidationList' => ['type' => 'list', 'member' => ['shape' => 'DomainValidation'], 'max' => 1000, 'min' => 1], 'DomainValidationOption' => ['type' => 'structure', 'required' => ['DomainName', 'ValidationDomain'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationDomain' => ['shape' => 'DomainNameString']]], 'DomainValidationOptionList' => ['type' => 'list', 'member' => ['shape' => 'DomainValidationOption'], 'max' => 100, 'min' => 1], 'ExportCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Passphrase'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Passphrase' => ['shape' => 'PassphraseBlob']]], 'ExportCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain'], 'PrivateKey' => ['shape' => 'PrivateKey']]], 'ExtendedKeyUsage' => ['type' => 'structure', 'members' => ['Name' => ['shape' => 'ExtendedKeyUsageName'], 'OID' => ['shape' => 'String']]], 'ExtendedKeyUsageFilterList' => ['type' => 'list', 'member' => ['shape' => 'ExtendedKeyUsageName']], 'ExtendedKeyUsageList' => ['type' => 'list', 'member' => ['shape' => 'ExtendedKeyUsage']], 'ExtendedKeyUsageName' => ['type' => 'string', 'enum' => ['TLS_WEB_SERVER_AUTHENTICATION', 'TLS_WEB_CLIENT_AUTHENTICATION', 'CODE_SIGNING', 'EMAIL_PROTECTION', 'TIME_STAMPING', 'OCSP_SIGNING', 'IPSEC_END_SYSTEM', 'IPSEC_TUNNEL', 'IPSEC_USER', 'ANY', 'NONE', 'CUSTOM']], 'FailureReason' => ['type' => 'string', 'enum' => ['NO_AVAILABLE_CONTACTS', 'ADDITIONAL_VERIFICATION_REQUIRED', 'DOMAIN_NOT_ALLOWED', 'INVALID_PUBLIC_DOMAIN', 'CAA_ERROR', 'PCA_LIMIT_EXCEEDED', 'PCA_INVALID_ARN', 'PCA_INVALID_STATE', 'PCA_REQUEST_FAILED', 'PCA_RESOURCE_NOT_FOUND', 'PCA_INVALID_ARGS', 'OTHER']], 'Filters' => ['type' => 'structure', 'members' => ['extendedKeyUsage' => ['shape' => 'ExtendedKeyUsageFilterList'], 'keyUsage' => ['shape' => 'KeyUsageFilterList'], 'keyTypes' => ['shape' => 'KeyAlgorithmList']]], 'GetCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'GetCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'IdempotencyToken' => ['type' => 'string', 'max' => 32, 'min' => 1, 'pattern' => '\\w+'], 'ImportCertificateRequest' => ['type' => 'structure', 'required' => ['Certificate', 'PrivateKey'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Certificate' => ['shape' => 'CertificateBodyBlob'], 'PrivateKey' => ['shape' => 'PrivateKeyBlob'], 'CertificateChain' => ['shape' => 'CertificateChainBlob']]], 'ImportCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'InUseList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'InvalidArnException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidDomainValidationOptionsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidStateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidTagException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'KeyAlgorithm' => ['type' => 'string', 'enum' => ['RSA_2048', 'RSA_1024', 'RSA_4096', 'EC_prime256v1', 'EC_secp384r1', 'EC_secp521r1']], 'KeyAlgorithmList' => ['type' => 'list', 'member' => ['shape' => 'KeyAlgorithm']], 'KeyUsage' => ['type' => 'structure', 'members' => ['Name' => ['shape' => 'KeyUsageName']]], 'KeyUsageFilterList' => ['type' => 'list', 'member' => ['shape' => 'KeyUsageName']], 'KeyUsageList' => ['type' => 'list', 'member' => ['shape' => 'KeyUsage']], 'KeyUsageName' => ['type' => 'string', 'enum' => ['DIGITAL_SIGNATURE', 'NON_REPUDIATION', 'KEY_ENCIPHERMENT', 'DATA_ENCIPHERMENT', 'KEY_AGREEMENT', 'CERTIFICATE_SIGNING', 'CRL_SIGNING', 'ENCIPHER_ONLY', 'DECIPHER_ONLY', 'ANY', 'CUSTOM']], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ListCertificatesRequest' => ['type' => 'structure', 'members' => ['CertificateStatuses' => ['shape' => 'CertificateStatuses'], 'Includes' => ['shape' => 'Filters'], 'NextToken' => ['shape' => 'NextToken'], 'MaxItems' => ['shape' => 'MaxItems']]], 'ListCertificatesResponse' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'CertificateSummaryList' => ['shape' => 'CertificateSummaryList']]], 'ListTagsForCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'ListTagsForCertificateResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList']]], 'MaxItems' => ['type' => 'integer', 'max' => 1000, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 320, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u00FF]*'], 'PassphraseBlob' => ['type' => 'blob', 'max' => 128, 'min' => 4, 'sensitive' => \true], 'PrivateKey' => ['type' => 'string', 'max' => 524288, 'min' => 1, 'pattern' => '-{5}BEGIN PRIVATE KEY-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END PRIVATE KEY-{5}(\\u000D?\\u000A)?', 'sensitive' => \true], 'PrivateKeyBlob' => ['type' => 'blob', 'max' => 524288, 'min' => 1, 'sensitive' => \true], 'RecordType' => ['type' => 'string', 'enum' => ['CNAME']], 'RemoveTagsFromCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Tags'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'RenewalEligibility' => ['type' => 'string', 'enum' => ['ELIGIBLE', 'INELIGIBLE']], 'RenewalStatus' => ['type' => 'string', 'enum' => ['PENDING_AUTO_RENEWAL', 'PENDING_VALIDATION', 'SUCCESS', 'FAILED']], 'RenewalSummary' => ['type' => 'structure', 'required' => ['RenewalStatus', 'DomainValidationOptions'], 'members' => ['RenewalStatus' => ['shape' => 'RenewalStatus'], 'DomainValidationOptions' => ['shape' => 'DomainValidationList']]], 'RequestCertificateRequest' => ['type' => 'structure', 'required' => ['DomainName'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationMethod' => ['shape' => 'ValidationMethod'], 'SubjectAlternativeNames' => ['shape' => 'DomainList'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken'], 'DomainValidationOptions' => ['shape' => 'DomainValidationOptionList'], 'Options' => ['shape' => 'CertificateOptions'], 'CertificateAuthorityArn' => ['shape' => 'Arn']]], 'RequestCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'RequestInProgressException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResendValidationEmailRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Domain', 'ValidationDomain'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Domain' => ['shape' => 'DomainNameString'], 'ValidationDomain' => ['shape' => 'DomainNameString']]], 'ResourceInUseException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceNotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceRecord' => ['type' => 'structure', 'required' => ['Name', 'Type', 'Value'], 'members' => ['Name' => ['shape' => 'String'], 'Type' => ['shape' => 'RecordType'], 'Value' => ['shape' => 'String']]], 'RevocationReason' => ['type' => 'string', 'enum' => ['UNSPECIFIED', 'KEY_COMPROMISE', 'CA_COMPROMISE', 'AFFILIATION_CHANGED', 'SUPERCEDED', 'CESSATION_OF_OPERATION', 'CERTIFICATE_HOLD', 'REMOVE_FROM_CRL', 'PRIVILEGE_WITHDRAWN', 'A_A_COMPROMISE']], 'String' => ['type' => 'string'], 'TStamp' => ['type' => 'timestamp'], 'Tag' => ['type' => 'structure', 'required' => ['Key'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag'], 'max' => 50, 'min' => 1], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TooManyTagsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'UpdateCertificateOptionsRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Options'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Options' => ['shape' => 'CertificateOptions']]], 'ValidationEmailList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'ValidationMethod' => ['type' => 'string', 'enum' => ['EMAIL', 'DNS']]]];
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/acm/2015-12-08/api-2.json
4
+ return ['version' => '2.0', 'metadata' => ['apiVersion' => '2015-12-08', 'endpointPrefix' => 'acm', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceAbbreviation' => 'ACM', 'serviceFullName' => 'AWS Certificate Manager', 'serviceId' => 'ACM', 'signatureVersion' => 'v4', 'targetPrefix' => 'CertificateManager', 'uid' => 'acm-2015-12-08'], 'operations' => ['AddTagsToCertificate' => ['name' => 'AddTagsToCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AddTagsToCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException'], ['shape' => 'TagPolicyException'], ['shape' => 'InvalidParameterException']]], 'DeleteCertificate' => ['name' => 'DeleteCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ResourceInUseException'], ['shape' => 'InvalidArnException']]], 'DescribeCertificate' => ['name' => 'DescribeCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateRequest'], 'output' => ['shape' => 'DescribeCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'ExportCertificate' => ['name' => 'ExportCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ExportCertificateRequest'], 'output' => ['shape' => 'ExportCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestInProgressException'], ['shape' => 'InvalidArnException']]], 'GetCertificate' => ['name' => 'GetCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateRequest'], 'output' => ['shape' => 'GetCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestInProgressException'], ['shape' => 'InvalidArnException']]], 'ImportCertificate' => ['name' => 'ImportCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ImportCertificateRequest'], 'output' => ['shape' => 'ImportCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'LimitExceededException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException'], ['shape' => 'TagPolicyException'], ['shape' => 'InvalidParameterException']]], 'ListCertificates' => ['name' => 'ListCertificates', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListCertificatesRequest'], 'output' => ['shape' => 'ListCertificatesResponse'], 'errors' => [['shape' => 'InvalidArgsException']]], 'ListTagsForCertificate' => ['name' => 'ListTagsForCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsForCertificateRequest'], 'output' => ['shape' => 'ListTagsForCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'RemoveTagsFromCertificate' => ['name' => 'RemoveTagsFromCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RemoveTagsFromCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidTagException'], ['shape' => 'TagPolicyException'], ['shape' => 'InvalidParameterException']]], 'RenewCertificate' => ['name' => 'RenewCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RenewCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'RequestCertificate' => ['name' => 'RequestCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RequestCertificateRequest'], 'output' => ['shape' => 'RequestCertificateResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'InvalidDomainValidationOptionsException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException'], ['shape' => 'TagPolicyException'], ['shape' => 'InvalidParameterException']]], 'ResendValidationEmail' => ['name' => 'ResendValidationEmail', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ResendValidationEmailRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidDomainValidationOptionsException']]], 'UpdateCertificateOptions' => ['name' => 'UpdateCertificateOptions', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateCertificateOptionsRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'LimitExceededException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]]], 'shapes' => ['AddTagsToCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Tags'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'Arn' => ['type' => 'string', 'max' => 2048, 'min' => 20, 'pattern' => 'arn:[\\w+=/,.@-]+:[\\w+=/,.@-]+:[\\w+=/,.@-]*:[0-9]+:[\\w+=,.@-]+(/[\\w+=,.@-]+)*'], 'CertificateBody' => ['type' => 'string', 'max' => 32768, 'min' => 1, 'pattern' => '-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}(\\u000D?\\u000A)?'], 'CertificateBodyBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CertificateChain' => ['type' => 'string', 'max' => 2097152, 'min' => 1, 'pattern' => '(-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}\\u000D?\\u000A)*-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}(\\u000D?\\u000A)?'], 'CertificateChainBlob' => ['type' => 'blob', 'max' => 2097152, 'min' => 1], 'CertificateDetail' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'DomainName' => ['shape' => 'DomainNameString'], 'SubjectAlternativeNames' => ['shape' => 'DomainList'], 'DomainValidationOptions' => ['shape' => 'DomainValidationList'], 'Serial' => ['shape' => 'String'], 'Subject' => ['shape' => 'String'], 'Issuer' => ['shape' => 'String'], 'CreatedAt' => ['shape' => 'TStamp'], 'IssuedAt' => ['shape' => 'TStamp'], 'ImportedAt' => ['shape' => 'TStamp'], 'Status' => ['shape' => 'CertificateStatus'], 'RevokedAt' => ['shape' => 'TStamp'], 'RevocationReason' => ['shape' => 'RevocationReason'], 'NotBefore' => ['shape' => 'TStamp'], 'NotAfter' => ['shape' => 'TStamp'], 'KeyAlgorithm' => ['shape' => 'KeyAlgorithm'], 'SignatureAlgorithm' => ['shape' => 'String'], 'InUseBy' => ['shape' => 'InUseList'], 'FailureReason' => ['shape' => 'FailureReason'], 'Type' => ['shape' => 'CertificateType'], 'RenewalSummary' => ['shape' => 'RenewalSummary'], 'KeyUsages' => ['shape' => 'KeyUsageList'], 'ExtendedKeyUsages' => ['shape' => 'ExtendedKeyUsageList'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'RenewalEligibility' => ['shape' => 'RenewalEligibility'], 'Options' => ['shape' => 'CertificateOptions']]], 'CertificateOptions' => ['type' => 'structure', 'members' => ['CertificateTransparencyLoggingPreference' => ['shape' => 'CertificateTransparencyLoggingPreference']]], 'CertificateStatus' => ['type' => 'string', 'enum' => ['PENDING_VALIDATION', 'ISSUED', 'INACTIVE', 'EXPIRED', 'VALIDATION_TIMED_OUT', 'REVOKED', 'FAILED']], 'CertificateStatuses' => ['type' => 'list', 'member' => ['shape' => 'CertificateStatus']], 'CertificateSummary' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'DomainName' => ['shape' => 'DomainNameString']]], 'CertificateSummaryList' => ['type' => 'list', 'member' => ['shape' => 'CertificateSummary']], 'CertificateTransparencyLoggingPreference' => ['type' => 'string', 'enum' => ['ENABLED', 'DISABLED']], 'CertificateType' => ['type' => 'string', 'enum' => ['IMPORTED', 'AMAZON_ISSUED', 'PRIVATE']], 'DeleteCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'DescribeCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'DescribeCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateDetail']]], 'DomainList' => ['type' => 'list', 'member' => ['shape' => 'DomainNameString'], 'max' => 100, 'min' => 1], 'DomainNameString' => ['type' => 'string', 'max' => 253, 'min' => 1, 'pattern' => '^(\\*\\.)?(((?!-)[A-Za-z0-9-]{0,62}[A-Za-z0-9])\\.)+((?!-)[A-Za-z0-9-]{1,62}[A-Za-z0-9])$'], 'DomainStatus' => ['type' => 'string', 'enum' => ['PENDING_VALIDATION', 'SUCCESS', 'FAILED']], 'DomainValidation' => ['type' => 'structure', 'required' => ['DomainName'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationEmails' => ['shape' => 'ValidationEmailList'], 'ValidationDomain' => ['shape' => 'DomainNameString'], 'ValidationStatus' => ['shape' => 'DomainStatus'], 'ResourceRecord' => ['shape' => 'ResourceRecord'], 'ValidationMethod' => ['shape' => 'ValidationMethod']]], 'DomainValidationList' => ['type' => 'list', 'member' => ['shape' => 'DomainValidation'], 'max' => 1000, 'min' => 1], 'DomainValidationOption' => ['type' => 'structure', 'required' => ['DomainName', 'ValidationDomain'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationDomain' => ['shape' => 'DomainNameString']]], 'DomainValidationOptionList' => ['type' => 'list', 'member' => ['shape' => 'DomainValidationOption'], 'max' => 100, 'min' => 1], 'ExportCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Passphrase'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Passphrase' => ['shape' => 'PassphraseBlob']]], 'ExportCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain'], 'PrivateKey' => ['shape' => 'PrivateKey']]], 'ExtendedKeyUsage' => ['type' => 'structure', 'members' => ['Name' => ['shape' => 'ExtendedKeyUsageName'], 'OID' => ['shape' => 'String']]], 'ExtendedKeyUsageFilterList' => ['type' => 'list', 'member' => ['shape' => 'ExtendedKeyUsageName']], 'ExtendedKeyUsageList' => ['type' => 'list', 'member' => ['shape' => 'ExtendedKeyUsage']], 'ExtendedKeyUsageName' => ['type' => 'string', 'enum' => ['TLS_WEB_SERVER_AUTHENTICATION', 'TLS_WEB_CLIENT_AUTHENTICATION', 'CODE_SIGNING', 'EMAIL_PROTECTION', 'TIME_STAMPING', 'OCSP_SIGNING', 'IPSEC_END_SYSTEM', 'IPSEC_TUNNEL', 'IPSEC_USER', 'ANY', 'NONE', 'CUSTOM']], 'FailureReason' => ['type' => 'string', 'enum' => ['NO_AVAILABLE_CONTACTS', 'ADDITIONAL_VERIFICATION_REQUIRED', 'DOMAIN_NOT_ALLOWED', 'INVALID_PUBLIC_DOMAIN', 'DOMAIN_VALIDATION_DENIED', 'CAA_ERROR', 'PCA_LIMIT_EXCEEDED', 'PCA_INVALID_ARN', 'PCA_INVALID_STATE', 'PCA_REQUEST_FAILED', 'PCA_NAME_CONSTRAINTS_VALIDATION', 'PCA_RESOURCE_NOT_FOUND', 'PCA_INVALID_ARGS', 'PCA_INVALID_DURATION', 'PCA_ACCESS_DENIED', 'OTHER']], 'Filters' => ['type' => 'structure', 'members' => ['extendedKeyUsage' => ['shape' => 'ExtendedKeyUsageFilterList'], 'keyUsage' => ['shape' => 'KeyUsageFilterList'], 'keyTypes' => ['shape' => 'KeyAlgorithmList']]], 'GetCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'GetCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'IdempotencyToken' => ['type' => 'string', 'max' => 32, 'min' => 1, 'pattern' => '\\w+'], 'ImportCertificateRequest' => ['type' => 'structure', 'required' => ['Certificate', 'PrivateKey'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Certificate' => ['shape' => 'CertificateBodyBlob'], 'PrivateKey' => ['shape' => 'PrivateKeyBlob'], 'CertificateChain' => ['shape' => 'CertificateChainBlob'], 'Tags' => ['shape' => 'TagList']]], 'ImportCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'InUseList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'InvalidArgsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidArnException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidDomainValidationOptionsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidParameterException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidStateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidTagException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'KeyAlgorithm' => ['type' => 'string', 'enum' => ['RSA_2048', 'RSA_1024', 'RSA_4096', 'EC_prime256v1', 'EC_secp384r1', 'EC_secp521r1']], 'KeyAlgorithmList' => ['type' => 'list', 'member' => ['shape' => 'KeyAlgorithm']], 'KeyUsage' => ['type' => 'structure', 'members' => ['Name' => ['shape' => 'KeyUsageName']]], 'KeyUsageFilterList' => ['type' => 'list', 'member' => ['shape' => 'KeyUsageName']], 'KeyUsageList' => ['type' => 'list', 'member' => ['shape' => 'KeyUsage']], 'KeyUsageName' => ['type' => 'string', 'enum' => ['DIGITAL_SIGNATURE', 'NON_REPUDIATION', 'KEY_ENCIPHERMENT', 'DATA_ENCIPHERMENT', 'KEY_AGREEMENT', 'CERTIFICATE_SIGNING', 'CRL_SIGNING', 'ENCIPHER_ONLY', 'DECIPHER_ONLY', 'ANY', 'CUSTOM']], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ListCertificatesRequest' => ['type' => 'structure', 'members' => ['CertificateStatuses' => ['shape' => 'CertificateStatuses'], 'Includes' => ['shape' => 'Filters'], 'NextToken' => ['shape' => 'NextToken'], 'MaxItems' => ['shape' => 'MaxItems']]], 'ListCertificatesResponse' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'CertificateSummaryList' => ['shape' => 'CertificateSummaryList']]], 'ListTagsForCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'ListTagsForCertificateResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList']]], 'MaxItems' => ['type' => 'integer', 'max' => 1000, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 10000, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u00FF]*'], 'PassphraseBlob' => ['type' => 'blob', 'max' => 128, 'min' => 4, 'sensitive' => \true], 'PrivateKey' => ['type' => 'string', 'max' => 524288, 'min' => 1, 'pattern' => '-{5}BEGIN PRIVATE KEY-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END PRIVATE KEY-{5}(\\u000D?\\u000A)?', 'sensitive' => \true], 'PrivateKeyBlob' => ['type' => 'blob', 'max' => 5120, 'min' => 1, 'sensitive' => \true], 'RecordType' => ['type' => 'string', 'enum' => ['CNAME']], 'RemoveTagsFromCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Tags'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'RenewCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'RenewalEligibility' => ['type' => 'string', 'enum' => ['ELIGIBLE', 'INELIGIBLE']], 'RenewalStatus' => ['type' => 'string', 'enum' => ['PENDING_AUTO_RENEWAL', 'PENDING_VALIDATION', 'SUCCESS', 'FAILED']], 'RenewalSummary' => ['type' => 'structure', 'required' => ['RenewalStatus', 'DomainValidationOptions', 'UpdatedAt'], 'members' => ['RenewalStatus' => ['shape' => 'RenewalStatus'], 'DomainValidationOptions' => ['shape' => 'DomainValidationList'], 'RenewalStatusReason' => ['shape' => 'FailureReason'], 'UpdatedAt' => ['shape' => 'TStamp']]], 'RequestCertificateRequest' => ['type' => 'structure', 'required' => ['DomainName'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationMethod' => ['shape' => 'ValidationMethod'], 'SubjectAlternativeNames' => ['shape' => 'DomainList'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken'], 'DomainValidationOptions' => ['shape' => 'DomainValidationOptionList'], 'Options' => ['shape' => 'CertificateOptions'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'RequestCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'RequestInProgressException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResendValidationEmailRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Domain', 'ValidationDomain'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Domain' => ['shape' => 'DomainNameString'], 'ValidationDomain' => ['shape' => 'DomainNameString']]], 'ResourceInUseException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceNotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceRecord' => ['type' => 'structure', 'required' => ['Name', 'Type', 'Value'], 'members' => ['Name' => ['shape' => 'String'], 'Type' => ['shape' => 'RecordType'], 'Value' => ['shape' => 'String']]], 'RevocationReason' => ['type' => 'string', 'enum' => ['UNSPECIFIED', 'KEY_COMPROMISE', 'CA_COMPROMISE', 'AFFILIATION_CHANGED', 'SUPERCEDED', 'CESSATION_OF_OPERATION', 'CERTIFICATE_HOLD', 'REMOVE_FROM_CRL', 'PRIVILEGE_WITHDRAWN', 'A_A_COMPROMISE']], 'String' => ['type' => 'string'], 'TStamp' => ['type' => 'timestamp'], 'Tag' => ['type' => 'structure', 'required' => ['Key'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag'], 'max' => 50, 'min' => 1], 'TagPolicyException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TooManyTagsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'UpdateCertificateOptionsRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Options'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Options' => ['shape' => 'CertificateOptions']]], 'ValidationEmailList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'ValidationMethod' => ['type' => 'string', 'enum' => ['EMAIL', 'DNS']]]];
vendor/Aws3/Aws/data/alexaforbusiness/2017-11-09/api-2.json.php CHANGED
@@ -1,4 +1,4 @@
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/alexaforbusiness/2017-11-09/api-2.json
4
- return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-11-09', 'endpointPrefix' => 'a4b', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceFullName' => 'Alexa For Business', 'serviceId' => 'Alexa For Business', 'signatureVersion' => 'v4', 'targetPrefix' => 'AlexaForBusiness', 'uid' => 'alexaforbusiness-2017-11-09'], 'operations' => ['ApproveSkill' => ['name' => 'ApproveSkill', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ApproveSkillRequest'], 'output' => ['shape' => 'ApproveSkillResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'AssociateContactWithAddressBook' => ['name' => 'AssociateContactWithAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateContactWithAddressBookRequest'], 'output' => ['shape' => 'AssociateContactWithAddressBookResponse'], 'errors' => [['shape' => 'LimitExceededException']]], 'AssociateDeviceWithRoom' => ['name' => 'AssociateDeviceWithRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateDeviceWithRoomRequest'], 'output' => ['shape' => 'AssociateDeviceWithRoomResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'AssociateSkillGroupWithRoom' => ['name' => 'AssociateSkillGroupWithRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillGroupWithRoomRequest'], 'output' => ['shape' => 'AssociateSkillGroupWithRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'AssociateSkillWithSkillGroup' => ['name' => 'AssociateSkillWithSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillWithSkillGroupRequest'], 'output' => ['shape' => 'AssociateSkillWithSkillGroupResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException'], ['shape' => 'SkillNotLinkedException']]], 'AssociateSkillWithUsers' => ['name' => 'AssociateSkillWithUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillWithUsersRequest'], 'output' => ['shape' => 'AssociateSkillWithUsersResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'CreateAddressBook' => ['name' => 'CreateAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateAddressBookRequest'], 'output' => ['shape' => 'CreateAddressBookResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateBusinessReportSchedule' => ['name' => 'CreateBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateBusinessReportScheduleRequest'], 'output' => ['shape' => 'CreateBusinessReportScheduleResponse'], 'errors' => [['shape' => 'AlreadyExistsException']]], 'CreateConferenceProvider' => ['name' => 'CreateConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateConferenceProviderRequest'], 'output' => ['shape' => 'CreateConferenceProviderResponse'], 'errors' => [['shape' => 'AlreadyExistsException']]], 'CreateContact' => ['name' => 'CreateContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateContactRequest'], 'output' => ['shape' => 'CreateContactResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateProfile' => ['name' => 'CreateProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateProfileRequest'], 'output' => ['shape' => 'CreateProfileResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'AlreadyExistsException'], ['shape' => 'ConcurrentModificationException']]], 'CreateRoom' => ['name' => 'CreateRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateRoomRequest'], 'output' => ['shape' => 'CreateRoomResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateSkillGroup' => ['name' => 'CreateSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateSkillGroupRequest'], 'output' => ['shape' => 'CreateSkillGroupResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException']]], 'CreateUser' => ['name' => 'CreateUser', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateUserRequest'], 'output' => ['shape' => 'CreateUserResponse'], 'errors' => [['shape' => 'ResourceInUseException'], ['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteAddressBook' => ['name' => 'DeleteAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteAddressBookRequest'], 'output' => ['shape' => 'DeleteAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteBusinessReportSchedule' => ['name' => 'DeleteBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteBusinessReportScheduleRequest'], 'output' => ['shape' => 'DeleteBusinessReportScheduleResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteConferenceProvider' => ['name' => 'DeleteConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteConferenceProviderRequest'], 'output' => ['shape' => 'DeleteConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'DeleteContact' => ['name' => 'DeleteContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteContactRequest'], 'output' => ['shape' => 'DeleteContactResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteDevice' => ['name' => 'DeleteDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteDeviceRequest'], 'output' => ['shape' => 'DeleteDeviceResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidCertificateAuthorityException']]], 'DeleteProfile' => ['name' => 'DeleteProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteProfileRequest'], 'output' => ['shape' => 'DeleteProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteRoom' => ['name' => 'DeleteRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteRoomRequest'], 'output' => ['shape' => 'DeleteRoomResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteRoomSkillParameter' => ['name' => 'DeleteRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteRoomSkillParameterRequest'], 'output' => ['shape' => 'DeleteRoomSkillParameterResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'DeleteSkillAuthorization' => ['name' => 'DeleteSkillAuthorization', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteSkillAuthorizationRequest'], 'output' => ['shape' => 'DeleteSkillAuthorizationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteSkillGroup' => ['name' => 'DeleteSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteSkillGroupRequest'], 'output' => ['shape' => 'DeleteSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteUser' => ['name' => 'DeleteUser', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteUserRequest'], 'output' => ['shape' => 'DeleteUserResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DisassociateContactFromAddressBook' => ['name' => 'DisassociateContactFromAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateContactFromAddressBookRequest'], 'output' => ['shape' => 'DisassociateContactFromAddressBookResponse']], 'DisassociateDeviceFromRoom' => ['name' => 'DisassociateDeviceFromRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateDeviceFromRoomRequest'], 'output' => ['shape' => 'DisassociateDeviceFromRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'DisassociateSkillFromSkillGroup' => ['name' => 'DisassociateSkillFromSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillFromSkillGroupRequest'], 'output' => ['shape' => 'DisassociateSkillFromSkillGroupResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'DisassociateSkillFromUsers' => ['name' => 'DisassociateSkillFromUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillFromUsersRequest'], 'output' => ['shape' => 'DisassociateSkillFromUsersResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'DisassociateSkillGroupFromRoom' => ['name' => 'DisassociateSkillGroupFromRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillGroupFromRoomRequest'], 'output' => ['shape' => 'DisassociateSkillGroupFromRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'ForgetSmartHomeAppliances' => ['name' => 'ForgetSmartHomeAppliances', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ForgetSmartHomeAppliancesRequest'], 'output' => ['shape' => 'ForgetSmartHomeAppliancesResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetAddressBook' => ['name' => 'GetAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetAddressBookRequest'], 'output' => ['shape' => 'GetAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetConferencePreference' => ['name' => 'GetConferencePreference', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetConferencePreferenceRequest'], 'output' => ['shape' => 'GetConferencePreferenceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetConferenceProvider' => ['name' => 'GetConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetConferenceProviderRequest'], 'output' => ['shape' => 'GetConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetContact' => ['name' => 'GetContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetContactRequest'], 'output' => ['shape' => 'GetContactResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetDevice' => ['name' => 'GetDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetDeviceRequest'], 'output' => ['shape' => 'GetDeviceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetProfile' => ['name' => 'GetProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetProfileRequest'], 'output' => ['shape' => 'GetProfileResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetRoom' => ['name' => 'GetRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetRoomRequest'], 'output' => ['shape' => 'GetRoomResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetRoomSkillParameter' => ['name' => 'GetRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetRoomSkillParameterRequest'], 'output' => ['shape' => 'GetRoomSkillParameterResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetSkillGroup' => ['name' => 'GetSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetSkillGroupRequest'], 'output' => ['shape' => 'GetSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListBusinessReportSchedules' => ['name' => 'ListBusinessReportSchedules', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListBusinessReportSchedulesRequest'], 'output' => ['shape' => 'ListBusinessReportSchedulesResponse']], 'ListConferenceProviders' => ['name' => 'ListConferenceProviders', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListConferenceProvidersRequest'], 'output' => ['shape' => 'ListConferenceProvidersResponse']], 'ListDeviceEvents' => ['name' => 'ListDeviceEvents', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListDeviceEventsRequest'], 'output' => ['shape' => 'ListDeviceEventsResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListSkills' => ['name' => 'ListSkills', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsRequest'], 'output' => ['shape' => 'ListSkillsResponse']], 'ListSkillsStoreCategories' => ['name' => 'ListSkillsStoreCategories', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsStoreCategoriesRequest'], 'output' => ['shape' => 'ListSkillsStoreCategoriesResponse']], 'ListSkillsStoreSkillsByCategory' => ['name' => 'ListSkillsStoreSkillsByCategory', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsStoreSkillsByCategoryRequest'], 'output' => ['shape' => 'ListSkillsStoreSkillsByCategoryResponse']], 'ListSmartHomeAppliances' => ['name' => 'ListSmartHomeAppliances', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSmartHomeAppliancesRequest'], 'output' => ['shape' => 'ListSmartHomeAppliancesResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListTags' => ['name' => 'ListTags', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsRequest'], 'output' => ['shape' => 'ListTagsResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'PutConferencePreference' => ['name' => 'PutConferencePreference', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutConferencePreferenceRequest'], 'output' => ['shape' => 'PutConferencePreferenceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'PutRoomSkillParameter' => ['name' => 'PutRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutRoomSkillParameterRequest'], 'output' => ['shape' => 'PutRoomSkillParameterResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'PutSkillAuthorization' => ['name' => 'PutSkillAuthorization', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutSkillAuthorizationRequest'], 'output' => ['shape' => 'PutSkillAuthorizationResponse'], 'errors' => [['shape' => 'UnauthorizedException'], ['shape' => 'ConcurrentModificationException']]], 'RegisterAVSDevice' => ['name' => 'RegisterAVSDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RegisterAVSDeviceRequest'], 'output' => ['shape' => 'RegisterAVSDeviceResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidDeviceException']]], 'RejectSkill' => ['name' => 'RejectSkill', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RejectSkillRequest'], 'output' => ['shape' => 'RejectSkillResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'ResolveRoom' => ['name' => 'ResolveRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ResolveRoomRequest'], 'output' => ['shape' => 'ResolveRoomResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'RevokeInvitation' => ['name' => 'RevokeInvitation', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RevokeInvitationRequest'], 'output' => ['shape' => 'RevokeInvitationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'SearchAddressBooks' => ['name' => 'SearchAddressBooks', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchAddressBooksRequest'], 'output' => ['shape' => 'SearchAddressBooksResponse']], 'SearchContacts' => ['name' => 'SearchContacts', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchContactsRequest'], 'output' => ['shape' => 'SearchContactsResponse']], 'SearchDevices' => ['name' => 'SearchDevices', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchDevicesRequest'], 'output' => ['shape' => 'SearchDevicesResponse']], 'SearchProfiles' => ['name' => 'SearchProfiles', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchProfilesRequest'], 'output' => ['shape' => 'SearchProfilesResponse']], 'SearchRooms' => ['name' => 'SearchRooms', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchRoomsRequest'], 'output' => ['shape' => 'SearchRoomsResponse']], 'SearchSkillGroups' => ['name' => 'SearchSkillGroups', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchSkillGroupsRequest'], 'output' => ['shape' => 'SearchSkillGroupsResponse']], 'SearchUsers' => ['name' => 'SearchUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchUsersRequest'], 'output' => ['shape' => 'SearchUsersResponse']], 'SendInvitation' => ['name' => 'SendInvitation', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SendInvitationRequest'], 'output' => ['shape' => 'SendInvitationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'InvalidUserStatusException'], ['shape' => 'ConcurrentModificationException']]], 'StartDeviceSync' => ['name' => 'StartDeviceSync', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'StartDeviceSyncRequest'], 'output' => ['shape' => 'StartDeviceSyncResponse'], 'errors' => [['shape' => 'DeviceNotRegisteredException']]], 'StartSmartHomeApplianceDiscovery' => ['name' => 'StartSmartHomeApplianceDiscovery', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'StartSmartHomeApplianceDiscoveryRequest'], 'output' => ['shape' => 'StartSmartHomeApplianceDiscoveryResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'TagResource' => ['name' => 'TagResource', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'TagResourceRequest'], 'output' => ['shape' => 'TagResourceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UntagResource' => ['name' => 'UntagResource', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UntagResourceRequest'], 'output' => ['shape' => 'UntagResourceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UpdateAddressBook' => ['name' => 'UpdateAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateAddressBookRequest'], 'output' => ['shape' => 'UpdateAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateBusinessReportSchedule' => ['name' => 'UpdateBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateBusinessReportScheduleRequest'], 'output' => ['shape' => 'UpdateBusinessReportScheduleResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateConferenceProvider' => ['name' => 'UpdateConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateConferenceProviderRequest'], 'output' => ['shape' => 'UpdateConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UpdateContact' => ['name' => 'UpdateContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateContactRequest'], 'output' => ['shape' => 'UpdateContactResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateDevice' => ['name' => 'UpdateDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateDeviceRequest'], 'output' => ['shape' => 'UpdateDeviceResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'UpdateProfile' => ['name' => 'UpdateProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateProfileRequest'], 'output' => ['shape' => 'UpdateProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateRoom' => ['name' => 'UpdateRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateRoomRequest'], 'output' => ['shape' => 'UpdateRoomResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException']]], 'UpdateSkillGroup' => ['name' => 'UpdateSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateSkillGroupRequest'], 'output' => ['shape' => 'UpdateSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]]], 'shapes' => ['Address' => ['type' => 'string', 'max' => 500, 'min' => 1], 'AddressBook' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'AddressBookData' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'AddressBookDataList' => ['type' => 'list', 'member' => ['shape' => 'AddressBookData']], 'AddressBookDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'AddressBookName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'AlreadyExistsException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'AmazonId' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,18}'], 'ApplianceDescription' => ['type' => 'string'], 'ApplianceFriendlyName' => ['type' => 'string'], 'ApplianceManufacturerName' => ['type' => 'string'], 'ApproveSkillRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'ApproveSkillResponse' => ['type' => 'structure', 'members' => []], 'Arn' => ['type' => 'string', 'pattern' => 'arn:[a-z0-9-\\.]{1,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[^/].{0,1023}'], 'AssociateContactWithAddressBookRequest' => ['type' => 'structure', 'required' => ['ContactArn', 'AddressBookArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'AddressBookArn' => ['shape' => 'Arn']]], 'AssociateContactWithAddressBookResponse' => ['type' => 'structure', 'members' => []], 'AssociateDeviceWithRoomRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'AssociateDeviceWithRoomResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillGroupWithRoomRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'AssociateSkillGroupWithRoomResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillWithSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'AssociateSkillWithSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillWithUsersRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['OrganizationArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'AssociateSkillWithUsersResponse' => ['type' => 'structure', 'members' => []], 'AuthorizationResult' => ['type' => 'map', 'key' => ['shape' => 'Key'], 'value' => ['shape' => 'Value'], 'sensitive' => \true], 'Boolean' => ['type' => 'boolean'], 'BulletPoint' => ['type' => 'string'], 'BulletPoints' => ['type' => 'list', 'member' => ['shape' => 'BulletPoint']], 'BusinessReport' => ['type' => 'structure', 'members' => ['Status' => ['shape' => 'BusinessReportStatus'], 'FailureCode' => ['shape' => 'BusinessReportFailureCode'], 'S3Location' => ['shape' => 'BusinessReportS3Location'], 'DeliveryTime' => ['shape' => 'Timestamp'], 'DownloadUrl' => ['shape' => 'BusinessReportDownloadUrl']]], 'BusinessReportContentRange' => ['type' => 'structure', 'members' => ['Interval' => ['shape' => 'BusinessReportInterval']]], 'BusinessReportDownloadUrl' => ['type' => 'string'], 'BusinessReportFailureCode' => ['type' => 'string', 'enum' => ['ACCESS_DENIED', 'NO_SUCH_BUCKET', 'INTERNAL_FAILURE']], 'BusinessReportFormat' => ['type' => 'string', 'enum' => ['CSV', 'CSV_ZIP']], 'BusinessReportInterval' => ['type' => 'string', 'enum' => ['ONE_DAY', 'ONE_WEEK']], 'BusinessReportRecurrence' => ['type' => 'structure', 'members' => ['StartDate' => ['shape' => 'Date']]], 'BusinessReportS3Location' => ['type' => 'structure', 'members' => ['Path' => ['shape' => 'BusinessReportS3Path'], 'BucketName' => ['shape' => 'CustomerS3BucketName']]], 'BusinessReportS3Path' => ['type' => 'string'], 'BusinessReportSchedule' => ['type' => 'structure', 'members' => ['ScheduleArn' => ['shape' => 'Arn'], 'ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ContentRange' => ['shape' => 'BusinessReportContentRange'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence'], 'LastBusinessReport' => ['shape' => 'BusinessReport']]], 'BusinessReportScheduleList' => ['type' => 'list', 'member' => ['shape' => 'BusinessReportSchedule']], 'BusinessReportScheduleName' => ['type' => 'string', 'max' => 64, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'BusinessReportStatus' => ['type' => 'string', 'enum' => ['RUNNING', 'SUCCEEDED', 'FAILED']], 'Category' => ['type' => 'structure', 'members' => ['CategoryId' => ['shape' => 'CategoryId'], 'CategoryName' => ['shape' => 'CategoryName']]], 'CategoryId' => ['type' => 'long', 'min' => 1], 'CategoryList' => ['type' => 'list', 'member' => ['shape' => 'Category']], 'CategoryName' => ['type' => 'string'], 'ClientId' => ['type' => 'string', 'pattern' => '^\\S+{1,256}$'], 'ClientRequestToken' => ['type' => 'string', 'max' => 150, 'min' => 10, 'pattern' => '[a-zA-Z0-9][a-zA-Z0-9_-]*'], 'CommsProtocol' => ['type' => 'string', 'enum' => ['SIP', 'SIPS', 'H323']], 'ConcurrentModificationException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'ConferencePreference' => ['type' => 'structure', 'members' => ['DefaultConferenceProviderArn' => ['shape' => 'Arn']]], 'ConferenceProvider' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'ConferenceProviderName'], 'Type' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting']]], 'ConferenceProviderName' => ['type' => 'string', 'max' => 50, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'ConferenceProviderType' => ['type' => 'string', 'enum' => ['CHIME', 'BLUEJEANS', 'FUZE', 'GOOGLE_HANGOUTS', 'POLYCOM', 'RINGCENTRAL', 'SKYPE_FOR_BUSINESS', 'WEBEX', 'ZOOM', 'CUSTOM']], 'ConferenceProvidersList' => ['type' => 'list', 'member' => ['shape' => 'ConferenceProvider']], 'ConnectionStatus' => ['type' => 'string', 'enum' => ['ONLINE', 'OFFLINE']], 'Contact' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'E164PhoneNumber']]], 'ContactData' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'E164PhoneNumber']]], 'ContactDataList' => ['type' => 'list', 'member' => ['shape' => 'ContactData']], 'ContactName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'CountryCode' => ['type' => 'string', 'pattern' => '\\d{1,3}'], 'CreateAddressBookRequest' => ['type' => 'structure', 'required' => ['Name'], 'members' => ['Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateAddressBookResponse' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'CreateBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['Format', 'ContentRange'], 'members' => ['ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ContentRange' => ['shape' => 'BusinessReportContentRange'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => ['ScheduleArn' => ['shape' => 'Arn']]], 'CreateConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderName', 'ConferenceProviderType', 'MeetingSetting'], 'members' => ['ConferenceProviderName' => ['shape' => 'ConferenceProviderName'], 'ConferenceProviderType' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateConferenceProviderResponse' => ['type' => 'structure', 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'CreateContactRequest' => ['type' => 'structure', 'required' => ['FirstName'], 'members' => ['DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'E164PhoneNumber'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateContactResponse' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'CreateProfileRequest' => ['type' => 'structure', 'required' => ['ProfileName', 'Timezone', 'Address', 'DistanceUnit', 'TemperatureUnit', 'WakeWord'], 'members' => ['ProfileName' => ['shape' => 'ProfileName'], 'Timezone' => ['shape' => 'Timezone'], 'Address' => ['shape' => 'Address'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean']]], 'CreateProfileResponse' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'CreateRoomRequest' => ['type' => 'structure', 'required' => ['RoomName'], 'members' => ['RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProfileArn' => ['shape' => 'Arn'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'Tags' => ['shape' => 'TagList']]], 'CreateRoomResponse' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'CreateSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillGroupName'], 'members' => ['SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateSkillGroupResponse' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'CreateUserRequest' => ['type' => 'structure', 'required' => ['UserId'], 'members' => ['UserId' => ['shape' => 'user_UserId'], 'FirstName' => ['shape' => 'user_FirstName'], 'LastName' => ['shape' => 'user_LastName'], 'Email' => ['shape' => 'Email'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'Tags' => ['shape' => 'TagList']]], 'CreateUserResponse' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn']]], 'CustomerS3BucketName' => ['type' => 'string', 'pattern' => '[a-z0-9-\\.]{3,63}'], 'Date' => ['type' => 'string', 'pattern' => '^\\d{4}\\-(0?[1-9]|1[012])\\-(0?[1-9]|[12][0-9]|3[01])$'], 'DeleteAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'DeleteAddressBookResponse' => ['type' => 'structure', 'members' => []], 'DeleteBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['ScheduleArn'], 'members' => ['ScheduleArn' => ['shape' => 'Arn']]], 'DeleteBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => []], 'DeleteConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'DeleteConferenceProviderResponse' => ['type' => 'structure', 'members' => []], 'DeleteContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'DeleteContactResponse' => ['type' => 'structure', 'members' => []], 'DeleteDeviceRequest' => ['type' => 'structure', 'required' => ['DeviceArn'], 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'DeleteDeviceResponse' => ['type' => 'structure', 'members' => []], 'DeleteProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'DeleteProfileResponse' => ['type' => 'structure', 'members' => []], 'DeleteRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'DeleteRoomResponse' => ['type' => 'structure', 'members' => []], 'DeleteRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'ParameterKey'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'ParameterKey' => ['shape' => 'RoomSkillParameterKey']]], 'DeleteRoomSkillParameterResponse' => ['type' => 'structure', 'members' => []], 'DeleteSkillAuthorizationRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId'], 'RoomArn' => ['shape' => 'Arn']]], 'DeleteSkillAuthorizationResponse' => ['type' => 'structure', 'members' => []], 'DeleteSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'DeleteSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'DeleteUserRequest' => ['type' => 'structure', 'required' => ['EnrollmentId'], 'members' => ['UserArn' => ['shape' => 'Arn'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'DeleteUserResponse' => ['type' => 'structure', 'members' => []], 'DeveloperInfo' => ['type' => 'structure', 'members' => ['DeveloperName' => ['shape' => 'DeveloperName'], 'PrivacyPolicy' => ['shape' => 'PrivacyPolicy'], 'Email' => ['shape' => 'Email'], 'Url' => ['shape' => 'Url']]], 'DeveloperName' => ['type' => 'string'], 'Device' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumber'], 'DeviceType' => ['shape' => 'DeviceType'], 'DeviceName' => ['shape' => 'DeviceName'], 'SoftwareVersion' => ['shape' => 'SoftwareVersion'], 'MacAddress' => ['shape' => 'MacAddress'], 'RoomArn' => ['shape' => 'Arn'], 'DeviceStatus' => ['shape' => 'DeviceStatus'], 'DeviceStatusInfo' => ['shape' => 'DeviceStatusInfo']]], 'DeviceData' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumber'], 'DeviceType' => ['shape' => 'DeviceType'], 'DeviceName' => ['shape' => 'DeviceName'], 'SoftwareVersion' => ['shape' => 'SoftwareVersion'], 'MacAddress' => ['shape' => 'MacAddress'], 'DeviceStatus' => ['shape' => 'DeviceStatus'], 'RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'DeviceStatusInfo' => ['shape' => 'DeviceStatusInfo']]], 'DeviceDataList' => ['type' => 'list', 'member' => ['shape' => 'DeviceData']], 'DeviceEvent' => ['type' => 'structure', 'members' => ['Type' => ['shape' => 'DeviceEventType'], 'Value' => ['shape' => 'DeviceEventValue'], 'Timestamp' => ['shape' => 'Timestamp']]], 'DeviceEventList' => ['type' => 'list', 'member' => ['shape' => 'DeviceEvent']], 'DeviceEventType' => ['type' => 'string', 'enum' => ['CONNECTION_STATUS', 'DEVICE_STATUS']], 'DeviceEventValue' => ['type' => 'string'], 'DeviceName' => ['type' => 'string', 'max' => 100, 'min' => 2, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'DeviceNotRegisteredException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'DeviceSerialNumber' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,200}'], 'DeviceSerialNumberForAVS' => ['type' => 'string', 'pattern' => '^[a-zA-Z0-9]{1,50}$'], 'DeviceStatus' => ['type' => 'string', 'enum' => ['READY', 'PENDING', 'WAS_OFFLINE', 'DEREGISTERED']], 'DeviceStatusDetail' => ['type' => 'structure', 'members' => ['Code' => ['shape' => 'DeviceStatusDetailCode']]], 'DeviceStatusDetailCode' => ['type' => 'string', 'enum' => ['DEVICE_SOFTWARE_UPDATE_NEEDED', 'DEVICE_WAS_OFFLINE']], 'DeviceStatusDetails' => ['type' => 'list', 'member' => ['shape' => 'DeviceStatusDetail']], 'DeviceStatusInfo' => ['type' => 'structure', 'members' => ['DeviceStatusDetails' => ['shape' => 'DeviceStatusDetails'], 'ConnectionStatus' => ['shape' => 'ConnectionStatus']]], 'DeviceType' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,200}'], 'DisassociateContactFromAddressBookRequest' => ['type' => 'structure', 'required' => ['ContactArn', 'AddressBookArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'AddressBookArn' => ['shape' => 'Arn']]], 'DisassociateContactFromAddressBookResponse' => ['type' => 'structure', 'members' => []], 'DisassociateDeviceFromRoomRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'DisassociateDeviceFromRoomResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillFromSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'DisassociateSkillFromSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillFromUsersRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['OrganizationArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'DisassociateSkillFromUsersResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillGroupFromRoomRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'DisassociateSkillGroupFromRoomResponse' => ['type' => 'structure', 'members' => []], 'DistanceUnit' => ['type' => 'string', 'enum' => ['METRIC', 'IMPERIAL']], 'E164PhoneNumber' => ['type' => 'string', 'pattern' => '^\\+\\d{8,}$', 'sensitive' => \true], 'Email' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '([0-9a-zA-Z]([+-.\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\\.)+[a-zA-Z]{2,9})'], 'EnablementType' => ['type' => 'string', 'enum' => ['ENABLED', 'PENDING']], 'EnablementTypeFilter' => ['type' => 'string', 'enum' => ['ENABLED', 'PENDING']], 'EndUserLicenseAgreement' => ['type' => 'string'], 'Endpoint' => ['type' => 'string', 'max' => 256, 'min' => 1], 'EnrollmentId' => ['type' => 'string', 'max' => 128, 'min' => 0], 'EnrollmentStatus' => ['type' => 'string', 'enum' => ['INITIALIZED', 'PENDING', 'REGISTERED', 'DISASSOCIATING', 'DEREGISTERING']], 'ErrorMessage' => ['type' => 'string'], 'Feature' => ['type' => 'string', 'enum' => ['BLUETOOTH', 'VOLUME', 'NOTIFICATIONS', 'LISTS', 'SKILLS', 'ALL']], 'Features' => ['type' => 'list', 'member' => ['shape' => 'Feature']], 'Filter' => ['type' => 'structure', 'required' => ['Key', 'Values'], 'members' => ['Key' => ['shape' => 'FilterKey'], 'Values' => ['shape' => 'FilterValueList']]], 'FilterKey' => ['type' => 'string', 'max' => 500, 'min' => 1], 'FilterList' => ['type' => 'list', 'member' => ['shape' => 'Filter'], 'max' => 25], 'FilterValue' => ['type' => 'string', 'max' => 500, 'min' => 1], 'FilterValueList' => ['type' => 'list', 'member' => ['shape' => 'FilterValue'], 'max' => 5], 'ForgetSmartHomeAppliancesRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'ForgetSmartHomeAppliancesResponse' => ['type' => 'structure', 'members' => []], 'GenericKeyword' => ['type' => 'string'], 'GenericKeywords' => ['type' => 'list', 'member' => ['shape' => 'GenericKeyword']], 'GetAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'GetAddressBookResponse' => ['type' => 'structure', 'members' => ['AddressBook' => ['shape' => 'AddressBook']]], 'GetConferencePreferenceRequest' => ['type' => 'structure', 'members' => []], 'GetConferencePreferenceResponse' => ['type' => 'structure', 'members' => ['Preference' => ['shape' => 'ConferencePreference']]], 'GetConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'GetConferenceProviderResponse' => ['type' => 'structure', 'members' => ['ConferenceProvider' => ['shape' => 'ConferenceProvider']]], 'GetContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'GetContactResponse' => ['type' => 'structure', 'members' => ['Contact' => ['shape' => 'Contact']]], 'GetDeviceRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'GetDeviceResponse' => ['type' => 'structure', 'members' => ['Device' => ['shape' => 'Device']]], 'GetProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'GetProfileResponse' => ['type' => 'structure', 'members' => ['Profile' => ['shape' => 'Profile']]], 'GetRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'GetRoomResponse' => ['type' => 'structure', 'members' => ['Room' => ['shape' => 'Room']]], 'GetRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'ParameterKey'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'ParameterKey' => ['shape' => 'RoomSkillParameterKey']]], 'GetRoomSkillParameterResponse' => ['type' => 'structure', 'members' => ['RoomSkillParameter' => ['shape' => 'RoomSkillParameter']]], 'GetSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'GetSkillGroupResponse' => ['type' => 'structure', 'members' => ['SkillGroup' => ['shape' => 'SkillGroup']]], 'IPDialIn' => ['type' => 'structure', 'required' => ['Endpoint', 'CommsProtocol'], 'members' => ['Endpoint' => ['shape' => 'Endpoint'], 'CommsProtocol' => ['shape' => 'CommsProtocol']]], 'IconUrl' => ['type' => 'string'], 'InvalidCertificateAuthorityException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidDeviceException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidUserStatusException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvocationPhrase' => ['type' => 'string'], 'Key' => ['type' => 'string', 'min' => 1], 'LimitExceededException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'ListBusinessReportSchedulesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListBusinessReportSchedulesResponse' => ['type' => 'structure', 'members' => ['BusinessReportSchedules' => ['shape' => 'BusinessReportScheduleList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListConferenceProvidersRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListConferenceProvidersResponse' => ['type' => 'structure', 'members' => ['ConferenceProviders' => ['shape' => 'ConferenceProvidersList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListDeviceEventsRequest' => ['type' => 'structure', 'required' => ['DeviceArn'], 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'EventType' => ['shape' => 'DeviceEventType'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListDeviceEventsResponse' => ['type' => 'structure', 'members' => ['DeviceEvents' => ['shape' => 'DeviceEventList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'EnablementType' => ['shape' => 'EnablementTypeFilter'], 'SkillType' => ['shape' => 'SkillTypeFilter'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'SkillListMaxResults']]], 'ListSkillsResponse' => ['type' => 'structure', 'members' => ['SkillSummaries' => ['shape' => 'SkillSummaryList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsStoreCategoriesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListSkillsStoreCategoriesResponse' => ['type' => 'structure', 'members' => ['CategoryList' => ['shape' => 'CategoryList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsStoreSkillsByCategoryRequest' => ['type' => 'structure', 'required' => ['CategoryId'], 'members' => ['CategoryId' => ['shape' => 'CategoryId'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'SkillListMaxResults']]], 'ListSkillsStoreSkillsByCategoryResponse' => ['type' => 'structure', 'members' => ['SkillsStoreSkills' => ['shape' => 'SkillsStoreSkillList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSmartHomeAppliancesRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'MaxResults' => ['shape' => 'MaxResults'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSmartHomeAppliancesResponse' => ['type' => 'structure', 'members' => ['SmartHomeAppliances' => ['shape' => 'SmartHomeApplianceList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListTagsRequest' => ['type' => 'structure', 'required' => ['Arn'], 'members' => ['Arn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListTagsResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList'], 'NextToken' => ['shape' => 'NextToken']]], 'MacAddress' => ['type' => 'string'], 'MaxResults' => ['type' => 'integer', 'max' => 50, 'min' => 1], 'MaxVolumeLimit' => ['type' => 'integer'], 'MeetingSetting' => ['type' => 'structure', 'required' => ['RequirePin'], 'members' => ['RequirePin' => ['shape' => 'RequirePin']]], 'NameInUseException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'NewInThisVersionBulletPoints' => ['type' => 'list', 'member' => ['shape' => 'BulletPoint']], 'NextToken' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'NotFoundException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'OneClickIdDelay' => ['type' => 'string', 'max' => 2, 'min' => 1], 'OneClickPinDelay' => ['type' => 'string', 'max' => 2, 'min' => 1], 'OutboundPhoneNumber' => ['type' => 'string', 'pattern' => '\\d{10}'], 'PSTNDialIn' => ['type' => 'structure', 'required' => ['CountryCode', 'PhoneNumber', 'OneClickIdDelay', 'OneClickPinDelay'], 'members' => ['CountryCode' => ['shape' => 'CountryCode'], 'PhoneNumber' => ['shape' => 'OutboundPhoneNumber'], 'OneClickIdDelay' => ['shape' => 'OneClickIdDelay'], 'OneClickPinDelay' => ['shape' => 'OneClickPinDelay']]], 'PrivacyPolicy' => ['type' => 'string'], 'ProductDescription' => ['type' => 'string'], 'ProductId' => ['type' => 'string', 'pattern' => '^[a-zA-Z0-9_]{1,256}$'], 'Profile' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Address' => ['shape' => 'Address'], 'Timezone' => ['shape' => 'Timezone'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean'], 'AddressBookArn' => ['shape' => 'Arn']]], 'ProfileData' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Address' => ['shape' => 'Address'], 'Timezone' => ['shape' => 'Timezone'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord']]], 'ProfileDataList' => ['type' => 'list', 'member' => ['shape' => 'ProfileData']], 'ProfileName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'ProviderCalendarId' => ['type' => 'string', 'max' => 100, 'min' => 0], 'PutConferencePreferenceRequest' => ['type' => 'structure', 'required' => ['ConferencePreference'], 'members' => ['ConferencePreference' => ['shape' => 'ConferencePreference']]], 'PutConferencePreferenceResponse' => ['type' => 'structure', 'members' => []], 'PutRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'RoomSkillParameter'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'RoomSkillParameter' => ['shape' => 'RoomSkillParameter']]], 'PutRoomSkillParameterResponse' => ['type' => 'structure', 'members' => []], 'PutSkillAuthorizationRequest' => ['type' => 'structure', 'required' => ['AuthorizationResult', 'SkillId'], 'members' => ['AuthorizationResult' => ['shape' => 'AuthorizationResult'], 'SkillId' => ['shape' => 'SkillId'], 'RoomArn' => ['shape' => 'Arn']]], 'PutSkillAuthorizationResponse' => ['type' => 'structure', 'members' => []], 'RegisterAVSDeviceRequest' => ['type' => 'structure', 'required' => ['ClientId', 'UserCode', 'ProductId', 'DeviceSerialNumber', 'AmazonId'], 'members' => ['ClientId' => ['shape' => 'ClientId'], 'UserCode' => ['shape' => 'UserCode'], 'ProductId' => ['shape' => 'ProductId'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumberForAVS'], 'AmazonId' => ['shape' => 'AmazonId']]], 'RegisterAVSDeviceResponse' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'RejectSkillRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'RejectSkillResponse' => ['type' => 'structure', 'members' => []], 'ReleaseDate' => ['type' => 'string'], 'RequirePin' => ['type' => 'string', 'enum' => ['YES', 'NO', 'OPTIONAL']], 'ResolveRoomRequest' => ['type' => 'structure', 'required' => ['UserId', 'SkillId'], 'members' => ['UserId' => ['shape' => 'UserId'], 'SkillId' => ['shape' => 'SkillId']]], 'ResolveRoomResponse' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'RoomSkillParameters' => ['shape' => 'RoomSkillParameters']]], 'ResourceInUseException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken']], 'exception' => \true], 'ReviewKey' => ['type' => 'string'], 'ReviewValue' => ['type' => 'string'], 'Reviews' => ['type' => 'map', 'key' => ['shape' => 'ReviewKey'], 'value' => ['shape' => 'ReviewValue']], 'RevokeInvitationRequest' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'RevokeInvitationResponse' => ['type' => 'structure', 'members' => []], 'Room' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn']]], 'RoomData' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName']]], 'RoomDataList' => ['type' => 'list', 'member' => ['shape' => 'RoomData']], 'RoomDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'RoomName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'RoomSkillParameter' => ['type' => 'structure', 'required' => ['ParameterKey', 'ParameterValue'], 'members' => ['ParameterKey' => ['shape' => 'RoomSkillParameterKey'], 'ParameterValue' => ['shape' => 'RoomSkillParameterValue']]], 'RoomSkillParameterKey' => ['type' => 'string', 'max' => 256, 'min' => 1], 'RoomSkillParameterValue' => ['type' => 'string', 'max' => 512, 'min' => 1], 'RoomSkillParameters' => ['type' => 'list', 'member' => ['shape' => 'RoomSkillParameter']], 'S3KeyPrefix' => ['type' => 'string', 'max' => 100, 'min' => 0, 'pattern' => '[A-Za-z0-9!_\\-\\.\\*\'()/]*'], 'SampleUtterances' => ['type' => 'list', 'member' => ['shape' => 'Utterance']], 'SearchAddressBooksRequest' => ['type' => 'structure', 'members' => ['Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'SearchAddressBooksResponse' => ['type' => 'structure', 'members' => ['AddressBooks' => ['shape' => 'AddressBookDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchContactsRequest' => ['type' => 'structure', 'members' => ['Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'SearchContactsResponse' => ['type' => 'structure', 'members' => ['Contacts' => ['shape' => 'ContactDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchDevicesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchDevicesResponse' => ['type' => 'structure', 'members' => ['Devices' => ['shape' => 'DeviceDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchProfilesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchProfilesResponse' => ['type' => 'structure', 'members' => ['Profiles' => ['shape' => 'ProfileDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchRoomsRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchRoomsResponse' => ['type' => 'structure', 'members' => ['Rooms' => ['shape' => 'RoomDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchSkillGroupsRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchSkillGroupsResponse' => ['type' => 'structure', 'members' => ['SkillGroups' => ['shape' => 'SkillGroupDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchUsersRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchUsersResponse' => ['type' => 'structure', 'members' => ['Users' => ['shape' => 'UserDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SendInvitationRequest' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn']]], 'SendInvitationResponse' => ['type' => 'structure', 'members' => []], 'ShortDescription' => ['type' => 'string'], 'SkillDetails' => ['type' => 'structure', 'members' => ['ProductDescription' => ['shape' => 'ProductDescription'], 'InvocationPhrase' => ['shape' => 'InvocationPhrase'], 'ReleaseDate' => ['shape' => 'ReleaseDate'], 'EndUserLicenseAgreement' => ['shape' => 'EndUserLicenseAgreement'], 'GenericKeywords' => ['shape' => 'GenericKeywords'], 'BulletPoints' => ['shape' => 'BulletPoints'], 'NewInThisVersionBulletPoints' => ['shape' => 'NewInThisVersionBulletPoints'], 'SkillTypes' => ['shape' => 'SkillTypes'], 'Reviews' => ['shape' => 'Reviews'], 'DeveloperInfo' => ['shape' => 'DeveloperInfo']]], 'SkillGroup' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'SkillGroupData' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'SkillGroupDataList' => ['type' => 'list', 'member' => ['shape' => 'SkillGroupData']], 'SkillGroupDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillGroupName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillId' => ['type' => 'string', 'pattern' => '(^amzn1\\.ask\\.skill\\.[0-9a-f\\-]{1,200})|(^amzn1\\.echo-sdk-ams\\.app\\.[0-9a-f\\-]{1,200})'], 'SkillListMaxResults' => ['type' => 'integer', 'max' => 10, 'min' => 1], 'SkillName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillNotLinkedException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'SkillStoreType' => ['type' => 'string'], 'SkillSummary' => ['type' => 'structure', 'members' => ['SkillId' => ['shape' => 'SkillId'], 'SkillName' => ['shape' => 'SkillName'], 'SupportsLinking' => ['shape' => 'boolean'], 'EnablementType' => ['shape' => 'EnablementType'], 'SkillType' => ['shape' => 'SkillType']]], 'SkillSummaryList' => ['type' => 'list', 'member' => ['shape' => 'SkillSummary']], 'SkillType' => ['type' => 'string', 'enum' => ['PUBLIC', 'PRIVATE'], 'max' => 100, 'min' => 1, 'pattern' => '[a-zA-Z0-9][a-zA-Z0-9_-]*'], 'SkillTypeFilter' => ['type' => 'string', 'enum' => ['PUBLIC', 'PRIVATE', 'ALL']], 'SkillTypes' => ['type' => 'list', 'member' => ['shape' => 'SkillStoreType']], 'SkillsStoreSkill' => ['type' => 'structure', 'members' => ['SkillId' => ['shape' => 'SkillId'], 'SkillName' => ['shape' => 'SkillName'], 'ShortDescription' => ['shape' => 'ShortDescription'], 'IconUrl' => ['shape' => 'IconUrl'], 'SampleUtterances' => ['shape' => 'SampleUtterances'], 'SkillDetails' => ['shape' => 'SkillDetails'], 'SupportsLinking' => ['shape' => 'boolean']]], 'SkillsStoreSkillList' => ['type' => 'list', 'member' => ['shape' => 'SkillsStoreSkill']], 'SmartHomeAppliance' => ['type' => 'structure', 'members' => ['FriendlyName' => ['shape' => 'ApplianceFriendlyName'], 'Description' => ['shape' => 'ApplianceDescription'], 'ManufacturerName' => ['shape' => 'ApplianceManufacturerName']]], 'SmartHomeApplianceList' => ['type' => 'list', 'member' => ['shape' => 'SmartHomeAppliance']], 'SoftwareVersion' => ['type' => 'string'], 'Sort' => ['type' => 'structure', 'required' => ['Key', 'Value'], 'members' => ['Key' => ['shape' => 'SortKey'], 'Value' => ['shape' => 'SortValue']]], 'SortKey' => ['type' => 'string', 'max' => 500, 'min' => 1], 'SortList' => ['type' => 'list', 'member' => ['shape' => 'Sort'], 'max' => 25], 'SortValue' => ['type' => 'string', 'enum' => ['ASC', 'DESC']], 'StartDeviceSyncRequest' => ['type' => 'structure', 'required' => ['Features'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'DeviceArn' => ['shape' => 'Arn'], 'Features' => ['shape' => 'Features']]], 'StartDeviceSyncResponse' => ['type' => 'structure', 'members' => []], 'StartSmartHomeApplianceDiscoveryRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'StartSmartHomeApplianceDiscoveryResponse' => ['type' => 'structure', 'members' => []], 'Tag' => ['type' => 'structure', 'required' => ['Key', 'Value'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TagKeyList' => ['type' => 'list', 'member' => ['shape' => 'TagKey']], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag']], 'TagResourceRequest' => ['type' => 'structure', 'required' => ['Arn', 'Tags'], 'members' => ['Arn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'TagResourceResponse' => ['type' => 'structure', 'members' => []], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TemperatureUnit' => ['type' => 'string', 'enum' => ['FAHRENHEIT', 'CELSIUS']], 'Timestamp' => ['type' => 'timestamp'], 'Timezone' => ['type' => 'string', 'max' => 100, 'min' => 1], 'TotalCount' => ['type' => 'integer'], 'UnauthorizedException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'UntagResourceRequest' => ['type' => 'structure', 'required' => ['Arn', 'TagKeys'], 'members' => ['Arn' => ['shape' => 'Arn'], 'TagKeys' => ['shape' => 'TagKeyList']]], 'UntagResourceResponse' => ['type' => 'structure', 'members' => []], 'UpdateAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'UpdateAddressBookResponse' => ['type' => 'structure', 'members' => []], 'UpdateBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['ScheduleArn'], 'members' => ['ScheduleArn' => ['shape' => 'Arn'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence']]], 'UpdateBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => []], 'UpdateConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn', 'ConferenceProviderType', 'MeetingSetting'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn'], 'ConferenceProviderType' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting']]], 'UpdateConferenceProviderResponse' => ['type' => 'structure', 'members' => []], 'UpdateContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'E164PhoneNumber']]], 'UpdateContactResponse' => ['type' => 'structure', 'members' => []], 'UpdateDeviceRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceName' => ['shape' => 'DeviceName']]], 'UpdateDeviceResponse' => ['type' => 'structure', 'members' => []], 'UpdateProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Timezone' => ['shape' => 'Timezone'], 'Address' => ['shape' => 'Address'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean']]], 'UpdateProfileResponse' => ['type' => 'structure', 'members' => []], 'UpdateRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn']]], 'UpdateRoomResponse' => ['type' => 'structure', 'members' => []], 'UpdateSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'UpdateSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'Url' => ['type' => 'string'], 'UserCode' => ['type' => 'string', 'max' => 128, 'min' => 1], 'UserData' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn'], 'FirstName' => ['shape' => 'user_FirstName'], 'LastName' => ['shape' => 'user_LastName'], 'Email' => ['shape' => 'Email'], 'EnrollmentStatus' => ['shape' => 'EnrollmentStatus'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'UserDataList' => ['type' => 'list', 'member' => ['shape' => 'UserData']], 'UserId' => ['type' => 'string', 'pattern' => 'amzn1\\.[A-Za-z0-9+-\\/=.]{1,300}'], 'Utterance' => ['type' => 'string'], 'Value' => ['type' => 'string', 'min' => 1], 'WakeWord' => ['type' => 'string', 'enum' => ['ALEXA', 'AMAZON', 'ECHO', 'COMPUTER']], 'boolean' => ['type' => 'boolean'], 'user_FirstName' => ['type' => 'string', 'max' => 30, 'min' => 0, 'pattern' => '([A-Za-z\\-\' 0-9._]|\\p{IsLetter})*'], 'user_LastName' => ['type' => 'string', 'max' => 30, 'min' => 0, 'pattern' => '([A-Za-z\\-\' 0-9._]|\\p{IsLetter})*'], 'user_UserId' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '[a-zA-Z0-9@_+.-]*']]];
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/alexaforbusiness/2017-11-09/api-2.json
4
+ return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-11-09', 'endpointPrefix' => 'a4b', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceFullName' => 'Alexa For Business', 'serviceId' => 'Alexa For Business', 'signatureVersion' => 'v4', 'targetPrefix' => 'AlexaForBusiness', 'uid' => 'alexaforbusiness-2017-11-09'], 'operations' => ['ApproveSkill' => ['name' => 'ApproveSkill', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ApproveSkillRequest'], 'output' => ['shape' => 'ApproveSkillResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'AssociateContactWithAddressBook' => ['name' => 'AssociateContactWithAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateContactWithAddressBookRequest'], 'output' => ['shape' => 'AssociateContactWithAddressBookResponse'], 'errors' => [['shape' => 'LimitExceededException']]], 'AssociateDeviceWithNetworkProfile' => ['name' => 'AssociateDeviceWithNetworkProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateDeviceWithNetworkProfileRequest'], 'output' => ['shape' => 'AssociateDeviceWithNetworkProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'AssociateDeviceWithRoom' => ['name' => 'AssociateDeviceWithRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateDeviceWithRoomRequest'], 'output' => ['shape' => 'AssociateDeviceWithRoomResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'AssociateSkillGroupWithRoom' => ['name' => 'AssociateSkillGroupWithRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillGroupWithRoomRequest'], 'output' => ['shape' => 'AssociateSkillGroupWithRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'AssociateSkillWithSkillGroup' => ['name' => 'AssociateSkillWithSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillWithSkillGroupRequest'], 'output' => ['shape' => 'AssociateSkillWithSkillGroupResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException'], ['shape' => 'SkillNotLinkedException']]], 'AssociateSkillWithUsers' => ['name' => 'AssociateSkillWithUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillWithUsersRequest'], 'output' => ['shape' => 'AssociateSkillWithUsersResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'CreateAddressBook' => ['name' => 'CreateAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateAddressBookRequest'], 'output' => ['shape' => 'CreateAddressBookResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateBusinessReportSchedule' => ['name' => 'CreateBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateBusinessReportScheduleRequest'], 'output' => ['shape' => 'CreateBusinessReportScheduleResponse'], 'errors' => [['shape' => 'AlreadyExistsException']]], 'CreateConferenceProvider' => ['name' => 'CreateConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateConferenceProviderRequest'], 'output' => ['shape' => 'CreateConferenceProviderResponse'], 'errors' => [['shape' => 'AlreadyExistsException']]], 'CreateContact' => ['name' => 'CreateContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateContactRequest'], 'output' => ['shape' => 'CreateContactResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateGatewayGroup' => ['name' => 'CreateGatewayGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateGatewayGroupRequest'], 'output' => ['shape' => 'CreateGatewayGroupResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateNetworkProfile' => ['name' => 'CreateNetworkProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateNetworkProfileRequest'], 'output' => ['shape' => 'CreateNetworkProfileResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidCertificateAuthorityException'], ['shape' => 'InvalidServiceLinkedRoleStateException']]], 'CreateProfile' => ['name' => 'CreateProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateProfileRequest'], 'output' => ['shape' => 'CreateProfileResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'AlreadyExistsException'], ['shape' => 'ConcurrentModificationException']]], 'CreateRoom' => ['name' => 'CreateRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateRoomRequest'], 'output' => ['shape' => 'CreateRoomResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateSkillGroup' => ['name' => 'CreateSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateSkillGroupRequest'], 'output' => ['shape' => 'CreateSkillGroupResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException']]], 'CreateUser' => ['name' => 'CreateUser', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateUserRequest'], 'output' => ['shape' => 'CreateUserResponse'], 'errors' => [['shape' => 'ResourceInUseException'], ['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteAddressBook' => ['name' => 'DeleteAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteAddressBookRequest'], 'output' => ['shape' => 'DeleteAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteBusinessReportSchedule' => ['name' => 'DeleteBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteBusinessReportScheduleRequest'], 'output' => ['shape' => 'DeleteBusinessReportScheduleResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteConferenceProvider' => ['name' => 'DeleteConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteConferenceProviderRequest'], 'output' => ['shape' => 'DeleteConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'DeleteContact' => ['name' => 'DeleteContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteContactRequest'], 'output' => ['shape' => 'DeleteContactResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteDevice' => ['name' => 'DeleteDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteDeviceRequest'], 'output' => ['shape' => 'DeleteDeviceResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidCertificateAuthorityException']]], 'DeleteDeviceUsageData' => ['name' => 'DeleteDeviceUsageData', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteDeviceUsageDataRequest'], 'output' => ['shape' => 'DeleteDeviceUsageDataResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'DeviceNotRegisteredException'], ['shape' => 'LimitExceededException']]], 'DeleteGatewayGroup' => ['name' => 'DeleteGatewayGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteGatewayGroupRequest'], 'output' => ['shape' => 'DeleteGatewayGroupResponse'], 'errors' => [['shape' => 'ResourceAssociatedException']]], 'DeleteNetworkProfile' => ['name' => 'DeleteNetworkProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteNetworkProfileRequest'], 'output' => ['shape' => 'DeleteNetworkProfileResponse'], 'errors' => [['shape' => 'ResourceInUseException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'DeleteProfile' => ['name' => 'DeleteProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteProfileRequest'], 'output' => ['shape' => 'DeleteProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteRoom' => ['name' => 'DeleteRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteRoomRequest'], 'output' => ['shape' => 'DeleteRoomResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteRoomSkillParameter' => ['name' => 'DeleteRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteRoomSkillParameterRequest'], 'output' => ['shape' => 'DeleteRoomSkillParameterResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'DeleteSkillAuthorization' => ['name' => 'DeleteSkillAuthorization', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteSkillAuthorizationRequest'], 'output' => ['shape' => 'DeleteSkillAuthorizationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteSkillGroup' => ['name' => 'DeleteSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteSkillGroupRequest'], 'output' => ['shape' => 'DeleteSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteUser' => ['name' => 'DeleteUser', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteUserRequest'], 'output' => ['shape' => 'DeleteUserResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DisassociateContactFromAddressBook' => ['name' => 'DisassociateContactFromAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateContactFromAddressBookRequest'], 'output' => ['shape' => 'DisassociateContactFromAddressBookResponse']], 'DisassociateDeviceFromRoom' => ['name' => 'DisassociateDeviceFromRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateDeviceFromRoomRequest'], 'output' => ['shape' => 'DisassociateDeviceFromRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'DisassociateSkillFromSkillGroup' => ['name' => 'DisassociateSkillFromSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillFromSkillGroupRequest'], 'output' => ['shape' => 'DisassociateSkillFromSkillGroupResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'DisassociateSkillFromUsers' => ['name' => 'DisassociateSkillFromUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillFromUsersRequest'], 'output' => ['shape' => 'DisassociateSkillFromUsersResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'DisassociateSkillGroupFromRoom' => ['name' => 'DisassociateSkillGroupFromRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillGroupFromRoomRequest'], 'output' => ['shape' => 'DisassociateSkillGroupFromRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'ForgetSmartHomeAppliances' => ['name' => 'ForgetSmartHomeAppliances', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ForgetSmartHomeAppliancesRequest'], 'output' => ['shape' => 'ForgetSmartHomeAppliancesResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetAddressBook' => ['name' => 'GetAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetAddressBookRequest'], 'output' => ['shape' => 'GetAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetConferencePreference' => ['name' => 'GetConferencePreference', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetConferencePreferenceRequest'], 'output' => ['shape' => 'GetConferencePreferenceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetConferenceProvider' => ['name' => 'GetConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetConferenceProviderRequest'], 'output' => ['shape' => 'GetConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetContact' => ['name' => 'GetContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetContactRequest'], 'output' => ['shape' => 'GetContactResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetDevice' => ['name' => 'GetDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetDeviceRequest'], 'output' => ['shape' => 'GetDeviceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetGateway' => ['name' => 'GetGateway', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetGatewayRequest'], 'output' => ['shape' => 'GetGatewayResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetGatewayGroup' => ['name' => 'GetGatewayGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetGatewayGroupRequest'], 'output' => ['shape' => 'GetGatewayGroupResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetInvitationConfiguration' => ['name' => 'GetInvitationConfiguration', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetInvitationConfigurationRequest'], 'output' => ['shape' => 'GetInvitationConfigurationResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetNetworkProfile' => ['name' => 'GetNetworkProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetNetworkProfileRequest'], 'output' => ['shape' => 'GetNetworkProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'InvalidSecretsManagerResourceException']]], 'GetProfile' => ['name' => 'GetProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetProfileRequest'], 'output' => ['shape' => 'GetProfileResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetRoom' => ['name' => 'GetRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetRoomRequest'], 'output' => ['shape' => 'GetRoomResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetRoomSkillParameter' => ['name' => 'GetRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetRoomSkillParameterRequest'], 'output' => ['shape' => 'GetRoomSkillParameterResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetSkillGroup' => ['name' => 'GetSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetSkillGroupRequest'], 'output' => ['shape' => 'GetSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListBusinessReportSchedules' => ['name' => 'ListBusinessReportSchedules', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListBusinessReportSchedulesRequest'], 'output' => ['shape' => 'ListBusinessReportSchedulesResponse']], 'ListConferenceProviders' => ['name' => 'ListConferenceProviders', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListConferenceProvidersRequest'], 'output' => ['shape' => 'ListConferenceProvidersResponse']], 'ListDeviceEvents' => ['name' => 'ListDeviceEvents', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListDeviceEventsRequest'], 'output' => ['shape' => 'ListDeviceEventsResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListGatewayGroups' => ['name' => 'ListGatewayGroups', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListGatewayGroupsRequest'], 'output' => ['shape' => 'ListGatewayGroupsResponse']], 'ListGateways' => ['name' => 'ListGateways', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListGatewaysRequest'], 'output' => ['shape' => 'ListGatewaysResponse']], 'ListSkills' => ['name' => 'ListSkills', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsRequest'], 'output' => ['shape' => 'ListSkillsResponse']], 'ListSkillsStoreCategories' => ['name' => 'ListSkillsStoreCategories', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsStoreCategoriesRequest'], 'output' => ['shape' => 'ListSkillsStoreCategoriesResponse']], 'ListSkillsStoreSkillsByCategory' => ['name' => 'ListSkillsStoreSkillsByCategory', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsStoreSkillsByCategoryRequest'], 'output' => ['shape' => 'ListSkillsStoreSkillsByCategoryResponse']], 'ListSmartHomeAppliances' => ['name' => 'ListSmartHomeAppliances', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSmartHomeAppliancesRequest'], 'output' => ['shape' => 'ListSmartHomeAppliancesResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListTags' => ['name' => 'ListTags', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsRequest'], 'output' => ['shape' => 'ListTagsResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'PutConferencePreference' => ['name' => 'PutConferencePreference', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutConferencePreferenceRequest'], 'output' => ['shape' => 'PutConferencePreferenceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'PutInvitationConfiguration' => ['name' => 'PutInvitationConfiguration', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutInvitationConfigurationRequest'], 'output' => ['shape' => 'PutInvitationConfigurationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'PutRoomSkillParameter' => ['name' => 'PutRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutRoomSkillParameterRequest'], 'output' => ['shape' => 'PutRoomSkillParameterResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'PutSkillAuthorization' => ['name' => 'PutSkillAuthorization', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutSkillAuthorizationRequest'], 'output' => ['shape' => 'PutSkillAuthorizationResponse'], 'errors' => [['shape' => 'UnauthorizedException'], ['shape' => 'ConcurrentModificationException']]], 'RegisterAVSDevice' => ['name' => 'RegisterAVSDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RegisterAVSDeviceRequest'], 'output' => ['shape' => 'RegisterAVSDeviceResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidDeviceException']]], 'RejectSkill' => ['name' => 'RejectSkill', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RejectSkillRequest'], 'output' => ['shape' => 'RejectSkillResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'ResolveRoom' => ['name' => 'ResolveRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ResolveRoomRequest'], 'output' => ['shape' => 'ResolveRoomResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'RevokeInvitation' => ['name' => 'RevokeInvitation', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RevokeInvitationRequest'], 'output' => ['shape' => 'RevokeInvitationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'SearchAddressBooks' => ['name' => 'SearchAddressBooks', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchAddressBooksRequest'], 'output' => ['shape' => 'SearchAddressBooksResponse']], 'SearchContacts' => ['name' => 'SearchContacts', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchContactsRequest'], 'output' => ['shape' => 'SearchContactsResponse']], 'SearchDevices' => ['name' => 'SearchDevices', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchDevicesRequest'], 'output' => ['shape' => 'SearchDevicesResponse']], 'SearchNetworkProfiles' => ['name' => 'SearchNetworkProfiles', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchNetworkProfilesRequest'], 'output' => ['shape' => 'SearchNetworkProfilesResponse']], 'SearchProfiles' => ['name' => 'SearchProfiles', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchProfilesRequest'], 'output' => ['shape' => 'SearchProfilesResponse']], 'SearchRooms' => ['name' => 'SearchRooms', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchRoomsRequest'], 'output' => ['shape' => 'SearchRoomsResponse']], 'SearchSkillGroups' => ['name' => 'SearchSkillGroups', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchSkillGroupsRequest'], 'output' => ['shape' => 'SearchSkillGroupsResponse']], 'SearchUsers' => ['name' => 'SearchUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchUsersRequest'], 'output' => ['shape' => 'SearchUsersResponse']], 'SendAnnouncement' => ['name' => 'SendAnnouncement', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SendAnnouncementRequest'], 'output' => ['shape' => 'SendAnnouncementResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'AlreadyExistsException']]], 'SendInvitation' => ['name' => 'SendInvitation', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SendInvitationRequest'], 'output' => ['shape' => 'SendInvitationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'InvalidUserStatusException'], ['shape' => 'ConcurrentModificationException']]], 'StartDeviceSync' => ['name' => 'StartDeviceSync', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'StartDeviceSyncRequest'], 'output' => ['shape' => 'StartDeviceSyncResponse'], 'errors' => [['shape' => 'DeviceNotRegisteredException']]], 'StartSmartHomeApplianceDiscovery' => ['name' => 'StartSmartHomeApplianceDiscovery', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'StartSmartHomeApplianceDiscoveryRequest'], 'output' => ['shape' => 'StartSmartHomeApplianceDiscoveryResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'TagResource' => ['name' => 'TagResource', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'TagResourceRequest'], 'output' => ['shape' => 'TagResourceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UntagResource' => ['name' => 'UntagResource', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UntagResourceRequest'], 'output' => ['shape' => 'UntagResourceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UpdateAddressBook' => ['name' => 'UpdateAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateAddressBookRequest'], 'output' => ['shape' => 'UpdateAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateBusinessReportSchedule' => ['name' => 'UpdateBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateBusinessReportScheduleRequest'], 'output' => ['shape' => 'UpdateBusinessReportScheduleResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateConferenceProvider' => ['name' => 'UpdateConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateConferenceProviderRequest'], 'output' => ['shape' => 'UpdateConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UpdateContact' => ['name' => 'UpdateContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateContactRequest'], 'output' => ['shape' => 'UpdateContactResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateDevice' => ['name' => 'UpdateDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateDeviceRequest'], 'output' => ['shape' => 'UpdateDeviceResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'UpdateGateway' => ['name' => 'UpdateGateway', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateGatewayRequest'], 'output' => ['shape' => 'UpdateGatewayResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException']]], 'UpdateGatewayGroup' => ['name' => 'UpdateGatewayGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateGatewayGroupRequest'], 'output' => ['shape' => 'UpdateGatewayGroupResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException']]], 'UpdateNetworkProfile' => ['name' => 'UpdateNetworkProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateNetworkProfileRequest'], 'output' => ['shape' => 'UpdateNetworkProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidCertificateAuthorityException'], ['shape' => 'InvalidSecretsManagerResourceException']]], 'UpdateProfile' => ['name' => 'UpdateProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateProfileRequest'], 'output' => ['shape' => 'UpdateProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateRoom' => ['name' => 'UpdateRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateRoomRequest'], 'output' => ['shape' => 'UpdateRoomResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException']]], 'UpdateSkillGroup' => ['name' => 'UpdateSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateSkillGroupRequest'], 'output' => ['shape' => 'UpdateSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]]], 'shapes' => ['Address' => ['type' => 'string', 'max' => 500, 'min' => 1], 'AddressBook' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'AddressBookData' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'AddressBookDataList' => ['type' => 'list', 'member' => ['shape' => 'AddressBookData']], 'AddressBookDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'AddressBookName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'AlreadyExistsException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'AmazonId' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,18}'], 'ApplianceDescription' => ['type' => 'string'], 'ApplianceFriendlyName' => ['type' => 'string'], 'ApplianceManufacturerName' => ['type' => 'string'], 'ApproveSkillRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'ApproveSkillResponse' => ['type' => 'structure', 'members' => []], 'Arn' => ['type' => 'string', 'pattern' => 'arn:[a-z0-9-\\.]{1,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[^/].{0,1023}'], 'AssociateContactWithAddressBookRequest' => ['type' => 'structure', 'required' => ['ContactArn', 'AddressBookArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'AddressBookArn' => ['shape' => 'Arn']]], 'AssociateContactWithAddressBookResponse' => ['type' => 'structure', 'members' => []], 'AssociateDeviceWithNetworkProfileRequest' => ['type' => 'structure', 'required' => ['DeviceArn', 'NetworkProfileArn'], 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'NetworkProfileArn' => ['shape' => 'Arn']]], 'AssociateDeviceWithNetworkProfileResponse' => ['type' => 'structure', 'members' => []], 'AssociateDeviceWithRoomRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'AssociateDeviceWithRoomResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillGroupWithRoomRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'AssociateSkillGroupWithRoomResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillWithSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'AssociateSkillWithSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillWithUsersRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'AssociateSkillWithUsersResponse' => ['type' => 'structure', 'members' => []], 'Audio' => ['type' => 'structure', 'required' => ['Locale', 'Location'], 'members' => ['Locale' => ['shape' => 'Locale'], 'Location' => ['shape' => 'AudioLocation']]], 'AudioList' => ['type' => 'list', 'member' => ['shape' => 'Audio'], 'max' => 1], 'AudioLocation' => ['type' => 'string', 'max' => 1200, 'min' => 0, 'pattern' => 'https://([A-Za-z0-9_.-]+)?(s3-[A-Za-z0-9-]+|s3\\.([A-Za-z0-9-])+|s3|s3.dualstack\\.([A-Za-z0-9-])+)+.amazonaws.com/.*'], 'AuthorizationResult' => ['type' => 'map', 'key' => ['shape' => 'Key'], 'value' => ['shape' => 'Value'], 'sensitive' => \true], 'Boolean' => ['type' => 'boolean'], 'BulletPoint' => ['type' => 'string'], 'BulletPoints' => ['type' => 'list', 'member' => ['shape' => 'BulletPoint']], 'BusinessReport' => ['type' => 'structure', 'members' => ['Status' => ['shape' => 'BusinessReportStatus'], 'FailureCode' => ['shape' => 'BusinessReportFailureCode'], 'S3Location' => ['shape' => 'BusinessReportS3Location'], 'DeliveryTime' => ['shape' => 'BusinessReportDeliveryTime'], 'DownloadUrl' => ['shape' => 'BusinessReportDownloadUrl']]], 'BusinessReportContentRange' => ['type' => 'structure', 'members' => ['Interval' => ['shape' => 'BusinessReportInterval']]], 'BusinessReportDeliveryTime' => ['type' => 'timestamp'], 'BusinessReportDownloadUrl' => ['type' => 'string'], 'BusinessReportFailureCode' => ['type' => 'string', 'enum' => ['ACCESS_DENIED', 'NO_SUCH_BUCKET', 'INTERNAL_FAILURE']], 'BusinessReportFormat' => ['type' => 'string', 'enum' => ['CSV', 'CSV_ZIP']], 'BusinessReportInterval' => ['type' => 'string', 'enum' => ['ONE_DAY', 'ONE_WEEK', 'THIRTY_DAYS']], 'BusinessReportRecurrence' => ['type' => 'structure', 'members' => ['StartDate' => ['shape' => 'Date']]], 'BusinessReportS3Location' => ['type' => 'structure', 'members' => ['Path' => ['shape' => 'BusinessReportS3Path'], 'BucketName' => ['shape' => 'CustomerS3BucketName']]], 'BusinessReportS3Path' => ['type' => 'string'], 'BusinessReportSchedule' => ['type' => 'structure', 'members' => ['ScheduleArn' => ['shape' => 'Arn'], 'ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ContentRange' => ['shape' => 'BusinessReportContentRange'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence'], 'LastBusinessReport' => ['shape' => 'BusinessReport']]], 'BusinessReportScheduleList' => ['type' => 'list', 'member' => ['shape' => 'BusinessReportSchedule']], 'BusinessReportScheduleName' => ['type' => 'string', 'max' => 64, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'BusinessReportStatus' => ['type' => 'string', 'enum' => ['RUNNING', 'SUCCEEDED', 'FAILED']], 'Category' => ['type' => 'structure', 'members' => ['CategoryId' => ['shape' => 'CategoryId'], 'CategoryName' => ['shape' => 'CategoryName']]], 'CategoryId' => ['type' => 'long', 'min' => 1], 'CategoryList' => ['type' => 'list', 'member' => ['shape' => 'Category']], 'CategoryName' => ['type' => 'string'], 'CertificateTime' => ['type' => 'timestamp'], 'ClientId' => ['type' => 'string', 'pattern' => '^\\S+{1,256}$'], 'ClientRequestToken' => ['type' => 'string', 'max' => 150, 'min' => 10, 'pattern' => '[a-zA-Z0-9][a-zA-Z0-9_-]*'], 'CommsProtocol' => ['type' => 'string', 'enum' => ['SIP', 'SIPS', 'H323']], 'ConcurrentModificationException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'ConferencePreference' => ['type' => 'structure', 'members' => ['DefaultConferenceProviderArn' => ['shape' => 'Arn']]], 'ConferenceProvider' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'ConferenceProviderName'], 'Type' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting']]], 'ConferenceProviderName' => ['type' => 'string', 'max' => 50, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'ConferenceProviderType' => ['type' => 'string', 'enum' => ['CHIME', 'BLUEJEANS', 'FUZE', 'GOOGLE_HANGOUTS', 'POLYCOM', 'RINGCENTRAL', 'SKYPE_FOR_BUSINESS', 'WEBEX', 'ZOOM', 'CUSTOM']], 'ConferenceProvidersList' => ['type' => 'list', 'member' => ['shape' => 'ConferenceProvider']], 'ConnectionStatus' => ['type' => 'string', 'enum' => ['ONLINE', 'OFFLINE']], 'ConnectionStatusUpdatedTime' => ['type' => 'timestamp'], 'Contact' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'RawPhoneNumber'], 'PhoneNumbers' => ['shape' => 'PhoneNumberList'], 'SipAddresses' => ['shape' => 'SipAddressList']]], 'ContactData' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'RawPhoneNumber'], 'PhoneNumbers' => ['shape' => 'PhoneNumberList'], 'SipAddresses' => ['shape' => 'SipAddressList']]], 'ContactDataList' => ['type' => 'list', 'member' => ['shape' => 'ContactData']], 'ContactName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'Content' => ['type' => 'structure', 'members' => ['TextList' => ['shape' => 'TextList'], 'SsmlList' => ['shape' => 'SsmlList'], 'AudioList' => ['shape' => 'AudioList']]], 'CountryCode' => ['type' => 'string', 'pattern' => '\\d{1,3}'], 'CreateAddressBookRequest' => ['type' => 'structure', 'required' => ['Name'], 'members' => ['Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateAddressBookResponse' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'CreateBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['Format', 'ContentRange'], 'members' => ['ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ContentRange' => ['shape' => 'BusinessReportContentRange'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => ['ScheduleArn' => ['shape' => 'Arn']]], 'CreateConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderName', 'ConferenceProviderType', 'MeetingSetting'], 'members' => ['ConferenceProviderName' => ['shape' => 'ConferenceProviderName'], 'ConferenceProviderType' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateConferenceProviderResponse' => ['type' => 'structure', 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'CreateContactRequest' => ['type' => 'structure', 'required' => ['FirstName'], 'members' => ['DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'RawPhoneNumber'], 'PhoneNumbers' => ['shape' => 'PhoneNumberList'], 'SipAddresses' => ['shape' => 'SipAddressList'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateContactResponse' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'CreateEndOfMeetingReminder' => ['type' => 'structure', 'required' => ['ReminderAtMinutes', 'ReminderType', 'Enabled'], 'members' => ['ReminderAtMinutes' => ['shape' => 'EndOfMeetingReminderMinutesList'], 'ReminderType' => ['shape' => 'EndOfMeetingReminderType'], 'Enabled' => ['shape' => 'Boolean']]], 'CreateGatewayGroupRequest' => ['type' => 'structure', 'required' => ['Name', 'ClientRequestToken'], 'members' => ['Name' => ['shape' => 'GatewayGroupName'], 'Description' => ['shape' => 'GatewayGroupDescription'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateGatewayGroupResponse' => ['type' => 'structure', 'members' => ['GatewayGroupArn' => ['shape' => 'Arn']]], 'CreateInstantBooking' => ['type' => 'structure', 'required' => ['DurationInMinutes', 'Enabled'], 'members' => ['DurationInMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'CreateMeetingRoomConfiguration' => ['type' => 'structure', 'members' => ['RoomUtilizationMetricsEnabled' => ['shape' => 'Boolean'], 'EndOfMeetingReminder' => ['shape' => 'CreateEndOfMeetingReminder'], 'InstantBooking' => ['shape' => 'CreateInstantBooking'], 'RequireCheckIn' => ['shape' => 'CreateRequireCheckIn']]], 'CreateNetworkProfileRequest' => ['type' => 'structure', 'required' => ['NetworkProfileName', 'Ssid', 'SecurityType', 'ClientRequestToken'], 'members' => ['NetworkProfileName' => ['shape' => 'NetworkProfileName'], 'Description' => ['shape' => 'NetworkProfileDescription'], 'Ssid' => ['shape' => 'NetworkSsid'], 'SecurityType' => ['shape' => 'NetworkSecurityType'], 'EapMethod' => ['shape' => 'NetworkEapMethod'], 'CurrentPassword' => ['shape' => 'CurrentWiFiPassword'], 'NextPassword' => ['shape' => 'NextWiFiPassword'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'TrustAnchors' => ['shape' => 'TrustAnchorList'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateNetworkProfileResponse' => ['type' => 'structure', 'members' => ['NetworkProfileArn' => ['shape' => 'Arn']]], 'CreateProfileRequest' => ['type' => 'structure', 'required' => ['ProfileName', 'Timezone', 'Address', 'DistanceUnit', 'TemperatureUnit', 'WakeWord'], 'members' => ['ProfileName' => ['shape' => 'ProfileName'], 'Timezone' => ['shape' => 'Timezone'], 'Address' => ['shape' => 'Address'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'Locale' => ['shape' => 'DeviceLocale'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean'], 'MeetingRoomConfiguration' => ['shape' => 'CreateMeetingRoomConfiguration']]], 'CreateProfileResponse' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'CreateRequireCheckIn' => ['type' => 'structure', 'required' => ['ReleaseAfterMinutes', 'Enabled'], 'members' => ['ReleaseAfterMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'CreateRoomRequest' => ['type' => 'structure', 'required' => ['RoomName'], 'members' => ['RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProfileArn' => ['shape' => 'Arn'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'Tags' => ['shape' => 'TagList']]], 'CreateRoomResponse' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'CreateSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillGroupName'], 'members' => ['SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateSkillGroupResponse' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'CreateUserRequest' => ['type' => 'structure', 'required' => ['UserId'], 'members' => ['UserId' => ['shape' => 'user_UserId'], 'FirstName' => ['shape' => 'user_FirstName'], 'LastName' => ['shape' => 'user_LastName'], 'Email' => ['shape' => 'Email'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'Tags' => ['shape' => 'TagList']]], 'CreateUserResponse' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn']]], 'CurrentWiFiPassword' => ['type' => 'string', 'max' => 128, 'min' => 5, 'pattern' => '[\\x00-\\x7F]*', 'sensitive' => \true], 'CustomerS3BucketName' => ['type' => 'string', 'pattern' => '[a-z0-9-\\.]{3,63}'], 'Date' => ['type' => 'string', 'pattern' => '^\\d{4}\\-(0?[1-9]|1[012])\\-(0?[1-9]|[12][0-9]|3[01])$'], 'DeleteAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'DeleteAddressBookResponse' => ['type' => 'structure', 'members' => []], 'DeleteBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['ScheduleArn'], 'members' => ['ScheduleArn' => ['shape' => 'Arn']]], 'DeleteBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => []], 'DeleteConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'DeleteConferenceProviderResponse' => ['type' => 'structure', 'members' => []], 'DeleteContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'DeleteContactResponse' => ['type' => 'structure', 'members' => []], 'DeleteDeviceRequest' => ['type' => 'structure', 'required' => ['DeviceArn'], 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'DeleteDeviceResponse' => ['type' => 'structure', 'members' => []], 'DeleteDeviceUsageDataRequest' => ['type' => 'structure', 'required' => ['DeviceArn', 'DeviceUsageType'], 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceUsageType' => ['shape' => 'DeviceUsageType']]], 'DeleteDeviceUsageDataResponse' => ['type' => 'structure', 'members' => []], 'DeleteGatewayGroupRequest' => ['type' => 'structure', 'required' => ['GatewayGroupArn'], 'members' => ['GatewayGroupArn' => ['shape' => 'Arn']]], 'DeleteGatewayGroupResponse' => ['type' => 'structure', 'members' => []], 'DeleteNetworkProfileRequest' => ['type' => 'structure', 'required' => ['NetworkProfileArn'], 'members' => ['NetworkProfileArn' => ['shape' => 'Arn']]], 'DeleteNetworkProfileResponse' => ['type' => 'structure', 'members' => []], 'DeleteProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'DeleteProfileResponse' => ['type' => 'structure', 'members' => []], 'DeleteRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'DeleteRoomResponse' => ['type' => 'structure', 'members' => []], 'DeleteRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'ParameterKey'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'ParameterKey' => ['shape' => 'RoomSkillParameterKey']]], 'DeleteRoomSkillParameterResponse' => ['type' => 'structure', 'members' => []], 'DeleteSkillAuthorizationRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId'], 'RoomArn' => ['shape' => 'Arn']]], 'DeleteSkillAuthorizationResponse' => ['type' => 'structure', 'members' => []], 'DeleteSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'DeleteSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'DeleteUserRequest' => ['type' => 'structure', 'required' => ['EnrollmentId'], 'members' => ['UserArn' => ['shape' => 'Arn'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'DeleteUserResponse' => ['type' => 'structure', 'members' => []], 'DeveloperInfo' => ['type' => 'structure', 'members' => ['DeveloperName' => ['shape' => 'DeveloperName'], 'PrivacyPolicy' => ['shape' => 'PrivacyPolicy'], 'Email' => ['shape' => 'Email'], 'Url' => ['shape' => 'Url']]], 'DeveloperName' => ['type' => 'string'], 'Device' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumber'], 'DeviceType' => ['shape' => 'DeviceType'], 'DeviceName' => ['shape' => 'DeviceName'], 'SoftwareVersion' => ['shape' => 'SoftwareVersion'], 'MacAddress' => ['shape' => 'MacAddress'], 'RoomArn' => ['shape' => 'Arn'], 'DeviceStatus' => ['shape' => 'DeviceStatus'], 'DeviceStatusInfo' => ['shape' => 'DeviceStatusInfo'], 'NetworkProfileInfo' => ['shape' => 'DeviceNetworkProfileInfo']]], 'DeviceData' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumber'], 'DeviceType' => ['shape' => 'DeviceType'], 'DeviceName' => ['shape' => 'DeviceName'], 'SoftwareVersion' => ['shape' => 'SoftwareVersion'], 'MacAddress' => ['shape' => 'MacAddress'], 'DeviceStatus' => ['shape' => 'DeviceStatus'], 'NetworkProfileArn' => ['shape' => 'Arn'], 'NetworkProfileName' => ['shape' => 'NetworkProfileName'], 'RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'DeviceStatusInfo' => ['shape' => 'DeviceStatusInfo'], 'CreatedTime' => ['shape' => 'DeviceDataCreatedTime']]], 'DeviceDataCreatedTime' => ['type' => 'timestamp'], 'DeviceDataList' => ['type' => 'list', 'member' => ['shape' => 'DeviceData']], 'DeviceEvent' => ['type' => 'structure', 'members' => ['Type' => ['shape' => 'DeviceEventType'], 'Value' => ['shape' => 'DeviceEventValue'], 'Timestamp' => ['shape' => 'DeviceEventTime']]], 'DeviceEventList' => ['type' => 'list', 'member' => ['shape' => 'DeviceEvent']], 'DeviceEventTime' => ['type' => 'timestamp'], 'DeviceEventType' => ['type' => 'string', 'enum' => ['CONNECTION_STATUS', 'DEVICE_STATUS']], 'DeviceEventValue' => ['type' => 'string'], 'DeviceLocale' => ['type' => 'string', 'max' => 256, 'min' => 1], 'DeviceName' => ['type' => 'string', 'max' => 100, 'min' => 2, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'DeviceNetworkProfileInfo' => ['type' => 'structure', 'members' => ['NetworkProfileArn' => ['shape' => 'Arn'], 'CertificateArn' => ['shape' => 'Arn'], 'CertificateExpirationTime' => ['shape' => 'CertificateTime']]], 'DeviceNotRegisteredException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'DeviceSerialNumber' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,200}'], 'DeviceSerialNumberForAVS' => ['type' => 'string', 'pattern' => '^[a-zA-Z0-9]{1,50}$'], 'DeviceStatus' => ['type' => 'string', 'enum' => ['READY', 'PENDING', 'WAS_OFFLINE', 'DEREGISTERED', 'FAILED']], 'DeviceStatusDetail' => ['type' => 'structure', 'members' => ['Feature' => ['shape' => 'Feature'], 'Code' => ['shape' => 'DeviceStatusDetailCode']]], 'DeviceStatusDetailCode' => ['type' => 'string', 'enum' => ['DEVICE_SOFTWARE_UPDATE_NEEDED', 'DEVICE_WAS_OFFLINE', 'CREDENTIALS_ACCESS_FAILURE', 'TLS_VERSION_MISMATCH', 'ASSOCIATION_REJECTION', 'AUTHENTICATION_FAILURE', 'DHCP_FAILURE', 'INTERNET_UNAVAILABLE', 'DNS_FAILURE', 'UNKNOWN_FAILURE', 'CERTIFICATE_ISSUING_LIMIT_EXCEEDED', 'INVALID_CERTIFICATE_AUTHORITY', 'NETWORK_PROFILE_NOT_FOUND', 'INVALID_PASSWORD_STATE', 'PASSWORD_NOT_FOUND']], 'DeviceStatusDetails' => ['type' => 'list', 'member' => ['shape' => 'DeviceStatusDetail']], 'DeviceStatusInfo' => ['type' => 'structure', 'members' => ['DeviceStatusDetails' => ['shape' => 'DeviceStatusDetails'], 'ConnectionStatus' => ['shape' => 'ConnectionStatus'], 'ConnectionStatusUpdatedTime' => ['shape' => 'ConnectionStatusUpdatedTime']]], 'DeviceType' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,200}'], 'DeviceUsageType' => ['type' => 'string', 'enum' => ['VOICE']], 'DisassociateContactFromAddressBookRequest' => ['type' => 'structure', 'required' => ['ContactArn', 'AddressBookArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'AddressBookArn' => ['shape' => 'Arn']]], 'DisassociateContactFromAddressBookResponse' => ['type' => 'structure', 'members' => []], 'DisassociateDeviceFromRoomRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'DisassociateDeviceFromRoomResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillFromSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'DisassociateSkillFromSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillFromUsersRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'DisassociateSkillFromUsersResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillGroupFromRoomRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'DisassociateSkillGroupFromRoomResponse' => ['type' => 'structure', 'members' => []], 'DistanceUnit' => ['type' => 'string', 'enum' => ['METRIC', 'IMPERIAL']], 'Email' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '([0-9a-zA-Z]([+-.\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z]([-\\w]*[0-9a-zA-Z]+)*\\.)+[a-zA-Z]{2,9})'], 'EnablementType' => ['type' => 'string', 'enum' => ['ENABLED', 'PENDING']], 'EnablementTypeFilter' => ['type' => 'string', 'enum' => ['ENABLED', 'PENDING']], 'EndOfMeetingReminder' => ['type' => 'structure', 'members' => ['ReminderAtMinutes' => ['shape' => 'EndOfMeetingReminderMinutesList'], 'ReminderType' => ['shape' => 'EndOfMeetingReminderType'], 'Enabled' => ['shape' => 'Boolean']]], 'EndOfMeetingReminderMinutesList' => ['type' => 'list', 'member' => ['shape' => 'Minutes'], 'max' => 1, 'min' => 1], 'EndOfMeetingReminderType' => ['type' => 'string', 'enum' => ['ANNOUNCEMENT_TIME_CHECK', 'ANNOUNCEMENT_VARIABLE_TIME_LEFT', 'CHIME', 'KNOCK']], 'EndUserLicenseAgreement' => ['type' => 'string'], 'Endpoint' => ['type' => 'string', 'max' => 256, 'min' => 1], 'EnrollmentId' => ['type' => 'string', 'max' => 128, 'min' => 0], 'EnrollmentStatus' => ['type' => 'string', 'enum' => ['INITIALIZED', 'PENDING', 'REGISTERED', 'DISASSOCIATING', 'DEREGISTERING']], 'ErrorMessage' => ['type' => 'string'], 'Feature' => ['type' => 'string', 'enum' => ['BLUETOOTH', 'VOLUME', 'NOTIFICATIONS', 'LISTS', 'SKILLS', 'NETWORK_PROFILE', 'SETTINGS', 'ALL']], 'Features' => ['type' => 'list', 'member' => ['shape' => 'Feature']], 'Filter' => ['type' => 'structure', 'required' => ['Key', 'Values'], 'members' => ['Key' => ['shape' => 'FilterKey'], 'Values' => ['shape' => 'FilterValueList']]], 'FilterKey' => ['type' => 'string', 'max' => 500, 'min' => 1], 'FilterList' => ['type' => 'list', 'member' => ['shape' => 'Filter'], 'max' => 25], 'FilterValue' => ['type' => 'string', 'max' => 500, 'min' => 1], 'FilterValueList' => ['type' => 'list', 'member' => ['shape' => 'FilterValue'], 'max' => 50], 'ForgetSmartHomeAppliancesRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'ForgetSmartHomeAppliancesResponse' => ['type' => 'structure', 'members' => []], 'Gateway' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayName'], 'Description' => ['shape' => 'GatewayDescription'], 'GatewayGroupArn' => ['shape' => 'Arn'], 'SoftwareVersion' => ['shape' => 'GatewayVersion']]], 'GatewayDescription' => ['type' => 'string', 'max' => 200, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'GatewayGroup' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayGroupName'], 'Description' => ['shape' => 'GatewayGroupDescription']]], 'GatewayGroupDescription' => ['type' => 'string', 'max' => 200, 'min' => 0], 'GatewayGroupName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'GatewayGroupSummaries' => ['type' => 'list', 'member' => ['shape' => 'GatewayGroupSummary']], 'GatewayGroupSummary' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayGroupName'], 'Description' => ['shape' => 'GatewayGroupDescription']]], 'GatewayName' => ['type' => 'string', 'max' => 253, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'GatewaySummaries' => ['type' => 'list', 'member' => ['shape' => 'GatewaySummary']], 'GatewaySummary' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayName'], 'Description' => ['shape' => 'GatewayDescription'], 'GatewayGroupArn' => ['shape' => 'Arn'], 'SoftwareVersion' => ['shape' => 'GatewayVersion']]], 'GatewayVersion' => ['type' => 'string', 'max' => 50, 'min' => 1], 'GenericKeyword' => ['type' => 'string'], 'GenericKeywords' => ['type' => 'list', 'member' => ['shape' => 'GenericKeyword']], 'GetAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'GetAddressBookResponse' => ['type' => 'structure', 'members' => ['AddressBook' => ['shape' => 'AddressBook']]], 'GetConferencePreferenceRequest' => ['type' => 'structure', 'members' => []], 'GetConferencePreferenceResponse' => ['type' => 'structure', 'members' => ['Preference' => ['shape' => 'ConferencePreference']]], 'GetConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'GetConferenceProviderResponse' => ['type' => 'structure', 'members' => ['ConferenceProvider' => ['shape' => 'ConferenceProvider']]], 'GetContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'GetContactResponse' => ['type' => 'structure', 'members' => ['Contact' => ['shape' => 'Contact']]], 'GetDeviceRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'GetDeviceResponse' => ['type' => 'structure', 'members' => ['Device' => ['shape' => 'Device']]], 'GetGatewayGroupRequest' => ['type' => 'structure', 'required' => ['GatewayGroupArn'], 'members' => ['GatewayGroupArn' => ['shape' => 'Arn']]], 'GetGatewayGroupResponse' => ['type' => 'structure', 'members' => ['GatewayGroup' => ['shape' => 'GatewayGroup']]], 'GetGatewayRequest' => ['type' => 'structure', 'required' => ['GatewayArn'], 'members' => ['GatewayArn' => ['shape' => 'Arn']]], 'GetGatewayResponse' => ['type' => 'structure', 'members' => ['Gateway' => ['shape' => 'Gateway']]], 'GetInvitationConfigurationRequest' => ['type' => 'structure', 'members' => []], 'GetInvitationConfigurationResponse' => ['type' => 'structure', 'members' => ['OrganizationName' => ['shape' => 'OrganizationName'], 'ContactEmail' => ['shape' => 'Email'], 'PrivateSkillIds' => ['shape' => 'ShortSkillIdList']]], 'GetNetworkProfileRequest' => ['type' => 'structure', 'required' => ['NetworkProfileArn'], 'members' => ['NetworkProfileArn' => ['shape' => 'Arn']]], 'GetNetworkProfileResponse' => ['type' => 'structure', 'members' => ['NetworkProfile' => ['shape' => 'NetworkProfile']]], 'GetProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'GetProfileResponse' => ['type' => 'structure', 'members' => ['Profile' => ['shape' => 'Profile']]], 'GetRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'GetRoomResponse' => ['type' => 'structure', 'members' => ['Room' => ['shape' => 'Room']]], 'GetRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'ParameterKey'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'ParameterKey' => ['shape' => 'RoomSkillParameterKey']]], 'GetRoomSkillParameterResponse' => ['type' => 'structure', 'members' => ['RoomSkillParameter' => ['shape' => 'RoomSkillParameter']]], 'GetSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'GetSkillGroupResponse' => ['type' => 'structure', 'members' => ['SkillGroup' => ['shape' => 'SkillGroup']]], 'IPDialIn' => ['type' => 'structure', 'required' => ['Endpoint', 'CommsProtocol'], 'members' => ['Endpoint' => ['shape' => 'Endpoint'], 'CommsProtocol' => ['shape' => 'CommsProtocol']]], 'IconUrl' => ['type' => 'string'], 'InstantBooking' => ['type' => 'structure', 'members' => ['DurationInMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'InvalidCertificateAuthorityException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidDeviceException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidSecretsManagerResourceException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidServiceLinkedRoleStateException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidUserStatusException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvocationPhrase' => ['type' => 'string'], 'Key' => ['type' => 'string', 'min' => 1], 'LimitExceededException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'ListBusinessReportSchedulesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListBusinessReportSchedulesResponse' => ['type' => 'structure', 'members' => ['BusinessReportSchedules' => ['shape' => 'BusinessReportScheduleList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListConferenceProvidersRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListConferenceProvidersResponse' => ['type' => 'structure', 'members' => ['ConferenceProviders' => ['shape' => 'ConferenceProvidersList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListDeviceEventsRequest' => ['type' => 'structure', 'required' => ['DeviceArn'], 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'EventType' => ['shape' => 'DeviceEventType'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListDeviceEventsResponse' => ['type' => 'structure', 'members' => ['DeviceEvents' => ['shape' => 'DeviceEventList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListGatewayGroupsRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListGatewayGroupsResponse' => ['type' => 'structure', 'members' => ['GatewayGroups' => ['shape' => 'GatewayGroupSummaries'], 'NextToken' => ['shape' => 'NextToken']]], 'ListGatewaysRequest' => ['type' => 'structure', 'members' => ['GatewayGroupArn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListGatewaysResponse' => ['type' => 'structure', 'members' => ['Gateways' => ['shape' => 'GatewaySummaries'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'EnablementType' => ['shape' => 'EnablementTypeFilter'], 'SkillType' => ['shape' => 'SkillTypeFilter'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'SkillListMaxResults']]], 'ListSkillsResponse' => ['type' => 'structure', 'members' => ['SkillSummaries' => ['shape' => 'SkillSummaryList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsStoreCategoriesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListSkillsStoreCategoriesResponse' => ['type' => 'structure', 'members' => ['CategoryList' => ['shape' => 'CategoryList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsStoreSkillsByCategoryRequest' => ['type' => 'structure', 'required' => ['CategoryId'], 'members' => ['CategoryId' => ['shape' => 'CategoryId'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'SkillListMaxResults']]], 'ListSkillsStoreSkillsByCategoryResponse' => ['type' => 'structure', 'members' => ['SkillsStoreSkills' => ['shape' => 'SkillsStoreSkillList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSmartHomeAppliancesRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'MaxResults' => ['shape' => 'MaxResults'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSmartHomeAppliancesResponse' => ['type' => 'structure', 'members' => ['SmartHomeAppliances' => ['shape' => 'SmartHomeApplianceList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListTagsRequest' => ['type' => 'structure', 'required' => ['Arn'], 'members' => ['Arn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListTagsResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList'], 'NextToken' => ['shape' => 'NextToken']]], 'Locale' => ['type' => 'string', 'enum' => ['en-US']], 'MacAddress' => ['type' => 'string'], 'MaxResults' => ['type' => 'integer', 'max' => 50, 'min' => 1], 'MaxVolumeLimit' => ['type' => 'integer'], 'MeetingRoomConfiguration' => ['type' => 'structure', 'members' => ['RoomUtilizationMetricsEnabled' => ['shape' => 'Boolean'], 'EndOfMeetingReminder' => ['shape' => 'EndOfMeetingReminder'], 'InstantBooking' => ['shape' => 'InstantBooking'], 'RequireCheckIn' => ['shape' => 'RequireCheckIn']]], 'MeetingSetting' => ['type' => 'structure', 'required' => ['RequirePin'], 'members' => ['RequirePin' => ['shape' => 'RequirePin']]], 'Minutes' => ['type' => 'integer'], 'NameInUseException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'NetworkEapMethod' => ['type' => 'string', 'enum' => ['EAP_TLS']], 'NetworkProfile' => ['type' => 'structure', 'members' => ['NetworkProfileArn' => ['shape' => 'Arn'], 'NetworkProfileName' => ['shape' => 'NetworkProfileName'], 'Description' => ['shape' => 'NetworkProfileDescription'], 'Ssid' => ['shape' => 'NetworkSsid'], 'SecurityType' => ['shape' => 'NetworkSecurityType'], 'EapMethod' => ['shape' => 'NetworkEapMethod'], 'CurrentPassword' => ['shape' => 'CurrentWiFiPassword'], 'NextPassword' => ['shape' => 'NextWiFiPassword'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'TrustAnchors' => ['shape' => 'TrustAnchorList']]], 'NetworkProfileData' => ['type' => 'structure', 'members' => ['NetworkProfileArn' => ['shape' => 'Arn'], 'NetworkProfileName' => ['shape' => 'NetworkProfileName'], 'Description' => ['shape' => 'NetworkProfileDescription'], 'Ssid' => ['shape' => 'NetworkSsid'], 'SecurityType' => ['shape' => 'NetworkSecurityType'], 'EapMethod' => ['shape' => 'NetworkEapMethod'], 'CertificateAuthorityArn' => ['shape' => 'Arn']]], 'NetworkProfileDataList' => ['type' => 'list', 'member' => ['shape' => 'NetworkProfileData']], 'NetworkProfileDescription' => ['type' => 'string', 'max' => 200, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'NetworkProfileName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'NetworkSecurityType' => ['type' => 'string', 'enum' => ['OPEN', 'WEP', 'WPA_PSK', 'WPA2_PSK', 'WPA2_ENTERPRISE']], 'NetworkSsid' => ['type' => 'string', 'max' => 32, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'NewInThisVersionBulletPoints' => ['type' => 'list', 'member' => ['shape' => 'BulletPoint']], 'NextToken' => ['type' => 'string', 'max' => 1100, 'min' => 1], 'NextWiFiPassword' => ['type' => 'string', 'max' => 128, 'min' => 0, 'pattern' => '(^$)|([\\x00-\\x7F]{5,})', 'sensitive' => \true], 'NotFoundException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'OneClickIdDelay' => ['type' => 'string', 'max' => 2, 'min' => 1], 'OneClickPinDelay' => ['type' => 'string', 'max' => 2, 'min' => 1], 'OrganizationName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'OutboundPhoneNumber' => ['type' => 'string', 'pattern' => '\\d{10}'], 'PSTNDialIn' => ['type' => 'structure', 'required' => ['CountryCode', 'PhoneNumber', 'OneClickIdDelay', 'OneClickPinDelay'], 'members' => ['CountryCode' => ['shape' => 'CountryCode'], 'PhoneNumber' => ['shape' => 'OutboundPhoneNumber'], 'OneClickIdDelay' => ['shape' => 'OneClickIdDelay'], 'OneClickPinDelay' => ['shape' => 'OneClickPinDelay']]], 'PhoneNumber' => ['type' => 'structure', 'required' => ['Number', 'Type'], 'members' => ['Number' => ['shape' => 'RawPhoneNumber'], 'Type' => ['shape' => 'PhoneNumberType']]], 'PhoneNumberList' => ['type' => 'list', 'member' => ['shape' => 'PhoneNumber'], 'max' => 3, 'min' => 0], 'PhoneNumberType' => ['type' => 'string', 'enum' => ['MOBILE', 'WORK', 'HOME'], 'sensitive' => \true], 'PrivacyPolicy' => ['type' => 'string'], 'ProductDescription' => ['type' => 'string'], 'ProductId' => ['type' => 'string', 'pattern' => '^[a-zA-Z0-9_]{1,256}$'], 'Profile' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Address' => ['shape' => 'Address'], 'Timezone' => ['shape' => 'Timezone'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'Locale' => ['shape' => 'DeviceLocale'], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean'], 'AddressBookArn' => ['shape' => 'Arn'], 'MeetingRoomConfiguration' => ['shape' => 'MeetingRoomConfiguration']]], 'ProfileData' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Address' => ['shape' => 'Address'], 'Timezone' => ['shape' => 'Timezone'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'Locale' => ['shape' => 'DeviceLocale']]], 'ProfileDataList' => ['type' => 'list', 'member' => ['shape' => 'ProfileData']], 'ProfileName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'ProviderCalendarId' => ['type' => 'string', 'max' => 100, 'min' => 0], 'PutConferencePreferenceRequest' => ['type' => 'structure', 'required' => ['ConferencePreference'], 'members' => ['ConferencePreference' => ['shape' => 'ConferencePreference']]], 'PutConferencePreferenceResponse' => ['type' => 'structure', 'members' => []], 'PutInvitationConfigurationRequest' => ['type' => 'structure', 'required' => ['OrganizationName'], 'members' => ['OrganizationName' => ['shape' => 'OrganizationName'], 'ContactEmail' => ['shape' => 'Email'], 'PrivateSkillIds' => ['shape' => 'ShortSkillIdList']]], 'PutInvitationConfigurationResponse' => ['type' => 'structure', 'members' => []], 'PutRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'RoomSkillParameter'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'RoomSkillParameter' => ['shape' => 'RoomSkillParameter']]], 'PutRoomSkillParameterResponse' => ['type' => 'structure', 'members' => []], 'PutSkillAuthorizationRequest' => ['type' => 'structure', 'required' => ['AuthorizationResult', 'SkillId'], 'members' => ['AuthorizationResult' => ['shape' => 'AuthorizationResult'], 'SkillId' => ['shape' => 'SkillId'], 'RoomArn' => ['shape' => 'Arn']]], 'PutSkillAuthorizationResponse' => ['type' => 'structure', 'members' => []], 'RawPhoneNumber' => ['type' => 'string', 'max' => 50, 'min' => 0, 'pattern' => '^[\\+0-9\\#\\,\\(][\\+0-9\\-\\.\\/\\(\\)\\,\\#\\s]+$', 'sensitive' => \true], 'RegisterAVSDeviceRequest' => ['type' => 'structure', 'required' => ['ClientId', 'UserCode', 'ProductId', 'DeviceSerialNumber', 'AmazonId'], 'members' => ['ClientId' => ['shape' => 'ClientId'], 'UserCode' => ['shape' => 'UserCode'], 'ProductId' => ['shape' => 'ProductId'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumberForAVS'], 'AmazonId' => ['shape' => 'AmazonId']]], 'RegisterAVSDeviceResponse' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'RejectSkillRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'RejectSkillResponse' => ['type' => 'structure', 'members' => []], 'ReleaseDate' => ['type' => 'string'], 'RequireCheckIn' => ['type' => 'structure', 'members' => ['ReleaseAfterMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'RequirePin' => ['type' => 'string', 'enum' => ['YES', 'NO', 'OPTIONAL']], 'ResolveRoomRequest' => ['type' => 'structure', 'required' => ['UserId', 'SkillId'], 'members' => ['UserId' => ['shape' => 'UserId'], 'SkillId' => ['shape' => 'SkillId']]], 'ResolveRoomResponse' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'RoomSkillParameters' => ['shape' => 'RoomSkillParameters']]], 'ResourceAssociatedException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'ResourceInUseException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken']], 'exception' => \true], 'ReviewKey' => ['type' => 'string'], 'ReviewValue' => ['type' => 'string'], 'Reviews' => ['type' => 'map', 'key' => ['shape' => 'ReviewKey'], 'value' => ['shape' => 'ReviewValue']], 'RevokeInvitationRequest' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'RevokeInvitationResponse' => ['type' => 'structure', 'members' => []], 'Room' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn']]], 'RoomData' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName']]], 'RoomDataList' => ['type' => 'list', 'member' => ['shape' => 'RoomData']], 'RoomDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'RoomName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'RoomSkillParameter' => ['type' => 'structure', 'required' => ['ParameterKey', 'ParameterValue'], 'members' => ['ParameterKey' => ['shape' => 'RoomSkillParameterKey'], 'ParameterValue' => ['shape' => 'RoomSkillParameterValue']]], 'RoomSkillParameterKey' => ['type' => 'string', 'max' => 256, 'min' => 1], 'RoomSkillParameterValue' => ['type' => 'string', 'max' => 512, 'min' => 1], 'RoomSkillParameters' => ['type' => 'list', 'member' => ['shape' => 'RoomSkillParameter']], 'S3KeyPrefix' => ['type' => 'string', 'max' => 100, 'min' => 0, 'pattern' => '[A-Za-z0-9!_\\-\\.\\*\'()/]*'], 'SampleUtterances' => ['type' => 'list', 'member' => ['shape' => 'Utterance']], 'SearchAddressBooksRequest' => ['type' => 'structure', 'members' => ['Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'SearchAddressBooksResponse' => ['type' => 'structure', 'members' => ['AddressBooks' => ['shape' => 'AddressBookDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchContactsRequest' => ['type' => 'structure', 'members' => ['Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'SearchContactsResponse' => ['type' => 'structure', 'members' => ['Contacts' => ['shape' => 'ContactDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchDevicesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchDevicesResponse' => ['type' => 'structure', 'members' => ['Devices' => ['shape' => 'DeviceDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchNetworkProfilesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchNetworkProfilesResponse' => ['type' => 'structure', 'members' => ['NetworkProfiles' => ['shape' => 'NetworkProfileDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchProfilesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchProfilesResponse' => ['type' => 'structure', 'members' => ['Profiles' => ['shape' => 'ProfileDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchRoomsRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchRoomsResponse' => ['type' => 'structure', 'members' => ['Rooms' => ['shape' => 'RoomDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchSkillGroupsRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchSkillGroupsResponse' => ['type' => 'structure', 'members' => ['SkillGroups' => ['shape' => 'SkillGroupDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchUsersRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchUsersResponse' => ['type' => 'structure', 'members' => ['Users' => ['shape' => 'UserDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SendAnnouncementRequest' => ['type' => 'structure', 'required' => ['RoomFilters', 'Content', 'ClientRequestToken'], 'members' => ['RoomFilters' => ['shape' => 'FilterList'], 'Content' => ['shape' => 'Content'], 'TimeToLiveInSeconds' => ['shape' => 'TimeToLiveInSeconds'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'SendAnnouncementResponse' => ['type' => 'structure', 'members' => ['AnnouncementArn' => ['shape' => 'Arn']]], 'SendInvitationRequest' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn']]], 'SendInvitationResponse' => ['type' => 'structure', 'members' => []], 'ShortDescription' => ['type' => 'string'], 'ShortSkillIdList' => ['type' => 'list', 'member' => ['shape' => 'SkillId'], 'max' => 3, 'min' => 0], 'SipAddress' => ['type' => 'structure', 'required' => ['Uri', 'Type'], 'members' => ['Uri' => ['shape' => 'SipUri'], 'Type' => ['shape' => 'SipType']]], 'SipAddressList' => ['type' => 'list', 'member' => ['shape' => 'SipAddress'], 'max' => 1, 'min' => 0], 'SipType' => ['type' => 'string', 'enum' => ['WORK'], 'sensitive' => \true], 'SipUri' => ['type' => 'string', 'max' => 256, 'min' => 1, 'pattern' => '^sip[s]?:([^@:]+)\\@([^@]+)$', 'sensitive' => \true], 'SkillDetails' => ['type' => 'structure', 'members' => ['ProductDescription' => ['shape' => 'ProductDescription'], 'InvocationPhrase' => ['shape' => 'InvocationPhrase'], 'ReleaseDate' => ['shape' => 'ReleaseDate'], 'EndUserLicenseAgreement' => ['shape' => 'EndUserLicenseAgreement'], 'GenericKeywords' => ['shape' => 'GenericKeywords'], 'BulletPoints' => ['shape' => 'BulletPoints'], 'NewInThisVersionBulletPoints' => ['shape' => 'NewInThisVersionBulletPoints'], 'SkillTypes' => ['shape' => 'SkillTypes'], 'Reviews' => ['shape' => 'Reviews'], 'DeveloperInfo' => ['shape' => 'DeveloperInfo']]], 'SkillGroup' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'SkillGroupData' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'SkillGroupDataList' => ['type' => 'list', 'member' => ['shape' => 'SkillGroupData']], 'SkillGroupDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillGroupName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillId' => ['type' => 'string', 'pattern' => '(^amzn1\\.ask\\.skill\\.[0-9a-f\\-]{1,200})|(^amzn1\\.echo-sdk-ams\\.app\\.[0-9a-f\\-]{1,200})'], 'SkillListMaxResults' => ['type' => 'integer', 'max' => 10, 'min' => 1], 'SkillName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillNotLinkedException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'SkillStoreType' => ['type' => 'string'], 'SkillSummary' => ['type' => 'structure', 'members' => ['SkillId' => ['shape' => 'SkillId'], 'SkillName' => ['shape' => 'SkillName'], 'SupportsLinking' => ['shape' => 'boolean'], 'EnablementType' => ['shape' => 'EnablementType'], 'SkillType' => ['shape' => 'SkillType']]], 'SkillSummaryList' => ['type' => 'list', 'member' => ['shape' => 'SkillSummary']], 'SkillType' => ['type' => 'string', 'enum' => ['PUBLIC', 'PRIVATE'], 'max' => 100, 'min' => 1, 'pattern' => '[a-zA-Z0-9][a-zA-Z0-9_-]*'], 'SkillTypeFilter' => ['type' => 'string', 'enum' => ['PUBLIC', 'PRIVATE', 'ALL']], 'SkillTypes' => ['type' => 'list', 'member' => ['shape' => 'SkillStoreType']], 'SkillsStoreSkill' => ['type' => 'structure', 'members' => ['SkillId' => ['shape' => 'SkillId'], 'SkillName' => ['shape' => 'SkillName'], 'ShortDescription' => ['shape' => 'ShortDescription'], 'IconUrl' => ['shape' => 'IconUrl'], 'SampleUtterances' => ['shape' => 'SampleUtterances'], 'SkillDetails' => ['shape' => 'SkillDetails'], 'SupportsLinking' => ['shape' => 'boolean']]], 'SkillsStoreSkillList' => ['type' => 'list', 'member' => ['shape' => 'SkillsStoreSkill']], 'SmartHomeAppliance' => ['type' => 'structure', 'members' => ['FriendlyName' => ['shape' => 'ApplianceFriendlyName'], 'Description' => ['shape' => 'ApplianceDescription'], 'ManufacturerName' => ['shape' => 'ApplianceManufacturerName']]], 'SmartHomeApplianceList' => ['type' => 'list', 'member' => ['shape' => 'SmartHomeAppliance']], 'SoftwareVersion' => ['type' => 'string'], 'Sort' => ['type' => 'structure', 'required' => ['Key', 'Value'], 'members' => ['Key' => ['shape' => 'SortKey'], 'Value' => ['shape' => 'SortValue']]], 'SortKey' => ['type' => 'string', 'max' => 500, 'min' => 1], 'SortList' => ['type' => 'list', 'member' => ['shape' => 'Sort'], 'max' => 25], 'SortValue' => ['type' => 'string', 'enum' => ['ASC', 'DESC']], 'Ssml' => ['type' => 'structure', 'required' => ['Locale', 'Value'], 'members' => ['Locale' => ['shape' => 'Locale'], 'Value' => ['shape' => 'SsmlValue']]], 'SsmlList' => ['type' => 'list', 'member' => ['shape' => 'Ssml'], 'max' => 1], 'SsmlValue' => ['type' => 'string', 'max' => 4096, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'StartDeviceSyncRequest' => ['type' => 'structure', 'required' => ['Features'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'DeviceArn' => ['shape' => 'Arn'], 'Features' => ['shape' => 'Features']]], 'StartDeviceSyncResponse' => ['type' => 'structure', 'members' => []], 'StartSmartHomeApplianceDiscoveryRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'StartSmartHomeApplianceDiscoveryResponse' => ['type' => 'structure', 'members' => []], 'Tag' => ['type' => 'structure', 'required' => ['Key', 'Value'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TagKeyList' => ['type' => 'list', 'member' => ['shape' => 'TagKey']], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag']], 'TagResourceRequest' => ['type' => 'structure', 'required' => ['Arn', 'Tags'], 'members' => ['Arn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'TagResourceResponse' => ['type' => 'structure', 'members' => []], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TemperatureUnit' => ['type' => 'string', 'enum' => ['FAHRENHEIT', 'CELSIUS']], 'Text' => ['type' => 'structure', 'required' => ['Locale', 'Value'], 'members' => ['Locale' => ['shape' => 'Locale'], 'Value' => ['shape' => 'TextValue']]], 'TextList' => ['type' => 'list', 'member' => ['shape' => 'Text'], 'max' => 1], 'TextValue' => ['type' => 'string', 'max' => 4096, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'TimeToLiveInSeconds' => ['type' => 'integer', 'max' => 3600, 'min' => 1], 'Timezone' => ['type' => 'string', 'max' => 100, 'min' => 1], 'TotalCount' => ['type' => 'integer'], 'TrustAnchor' => ['type' => 'string', 'pattern' => '-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}(\\u000D?\\u000A)?'], 'TrustAnchorList' => ['type' => 'list', 'member' => ['shape' => 'TrustAnchor'], 'max' => 5, 'min' => 1], 'UnauthorizedException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'UntagResourceRequest' => ['type' => 'structure', 'required' => ['Arn', 'TagKeys'], 'members' => ['Arn' => ['shape' => 'Arn'], 'TagKeys' => ['shape' => 'TagKeyList']]], 'UntagResourceResponse' => ['type' => 'structure', 'members' => []], 'UpdateAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'UpdateAddressBookResponse' => ['type' => 'structure', 'members' => []], 'UpdateBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['ScheduleArn'], 'members' => ['ScheduleArn' => ['shape' => 'Arn'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence']]], 'UpdateBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => []], 'UpdateConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn', 'ConferenceProviderType', 'MeetingSetting'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn'], 'ConferenceProviderType' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting']]], 'UpdateConferenceProviderResponse' => ['type' => 'structure', 'members' => []], 'UpdateContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'RawPhoneNumber'], 'PhoneNumbers' => ['shape' => 'PhoneNumberList'], 'SipAddresses' => ['shape' => 'SipAddressList']]], 'UpdateContactResponse' => ['type' => 'structure', 'members' => []], 'UpdateDeviceRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceName' => ['shape' => 'DeviceName']]], 'UpdateDeviceResponse' => ['type' => 'structure', 'members' => []], 'UpdateEndOfMeetingReminder' => ['type' => 'structure', 'members' => ['ReminderAtMinutes' => ['shape' => 'EndOfMeetingReminderMinutesList'], 'ReminderType' => ['shape' => 'EndOfMeetingReminderType'], 'Enabled' => ['shape' => 'Boolean']]], 'UpdateGatewayGroupRequest' => ['type' => 'structure', 'required' => ['GatewayGroupArn'], 'members' => ['GatewayGroupArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayGroupName'], 'Description' => ['shape' => 'GatewayGroupDescription']]], 'UpdateGatewayGroupResponse' => ['type' => 'structure', 'members' => []], 'UpdateGatewayRequest' => ['type' => 'structure', 'required' => ['GatewayArn'], 'members' => ['GatewayArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayName'], 'Description' => ['shape' => 'GatewayDescription'], 'SoftwareVersion' => ['shape' => 'GatewayVersion']]], 'UpdateGatewayResponse' => ['type' => 'structure', 'members' => []], 'UpdateInstantBooking' => ['type' => 'structure', 'members' => ['DurationInMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'UpdateMeetingRoomConfiguration' => ['type' => 'structure', 'members' => ['RoomUtilizationMetricsEnabled' => ['shape' => 'Boolean'], 'EndOfMeetingReminder' => ['shape' => 'UpdateEndOfMeetingReminder'], 'InstantBooking' => ['shape' => 'UpdateInstantBooking'], 'RequireCheckIn' => ['shape' => 'UpdateRequireCheckIn']]], 'UpdateNetworkProfileRequest' => ['type' => 'structure', 'required' => ['NetworkProfileArn'], 'members' => ['NetworkProfileArn' => ['shape' => 'Arn'], 'NetworkProfileName' => ['shape' => 'NetworkProfileName'], 'Description' => ['shape' => 'NetworkProfileDescription'], 'CurrentPassword' => ['shape' => 'CurrentWiFiPassword'], 'NextPassword' => ['shape' => 'NextWiFiPassword'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'TrustAnchors' => ['shape' => 'TrustAnchorList']]], 'UpdateNetworkProfileResponse' => ['type' => 'structure', 'members' => []], 'UpdateProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Timezone' => ['shape' => 'Timezone'], 'Address' => ['shape' => 'Address'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'Locale' => ['shape' => 'DeviceLocale'], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean'], 'MeetingRoomConfiguration' => ['shape' => 'UpdateMeetingRoomConfiguration']]], 'UpdateProfileResponse' => ['type' => 'structure', 'members' => []], 'UpdateRequireCheckIn' => ['type' => 'structure', 'members' => ['ReleaseAfterMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'UpdateRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn']]], 'UpdateRoomResponse' => ['type' => 'structure', 'members' => []], 'UpdateSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'UpdateSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'Url' => ['type' => 'string'], 'UserCode' => ['type' => 'string', 'max' => 128, 'min' => 1], 'UserData' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn'], 'FirstName' => ['shape' => 'user_FirstName'], 'LastName' => ['shape' => 'user_LastName'], 'Email' => ['shape' => 'Email'], 'EnrollmentStatus' => ['shape' => 'EnrollmentStatus'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'UserDataList' => ['type' => 'list', 'member' => ['shape' => 'UserData']], 'UserId' => ['type' => 'string', 'pattern' => 'amzn1\\.[A-Za-z0-9+-\\/=.]{1,300}'], 'Utterance' => ['type' => 'string'], 'Value' => ['type' => 'string', 'min' => 1], 'WakeWord' => ['type' => 'string', 'enum' => ['ALEXA', 'AMAZON', 'ECHO', 'COMPUTER']], 'boolean' => ['type' => 'boolean'], 'user_FirstName' => ['type' => 'string', 'max' => 30, 'min' => 0, 'pattern' => '([A-Za-z\\-\' 0-9._]|\\p{IsLetter})*'], 'user_LastName' => ['type' => 'string', 'max' => 30, 'min' => 0, 'pattern' => '([A-Za-z\\-\' 0-9._]|\\p{IsLetter})*'], 'user_UserId' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '[a-zA-Z0-9@_+.-]*']]];
vendor/Aws3/Aws/data/alexaforbusiness/2017-11-09/paginators-1.json.php CHANGED
@@ -1,4 +1,4 @@
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/alexaforbusiness/2017-11-09/paginators-1.json
4
- return ['pagination' => ['ListBusinessReportSchedules' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListConferenceProviders' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListDeviceEvents' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkills' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkillsStoreCategories' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkillsStoreSkillsByCategory' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSmartHomeAppliances' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListTags' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchAddressBooks' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchContacts' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchDevices' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchProfiles' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchRooms' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchSkillGroups' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchUsers' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults']]];
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/alexaforbusiness/2017-11-09/paginators-1.json
4
+ return ['pagination' => ['ListBusinessReportSchedules' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListConferenceProviders' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListDeviceEvents' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListGatewayGroups' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListGateways' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkills' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkillsStoreCategories' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkillsStoreSkillsByCategory' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSmartHomeAppliances' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListTags' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchAddressBooks' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchContacts' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchDevices' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchNetworkProfiles' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchProfiles' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchRooms' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchSkillGroups' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchUsers' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults']]];
vendor/Aws3/Aws/data/aliases.json.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+
3
+ // This file was auto-generated from sdk-root/src/data/aliases.json
4
+ return ['operations' => ['ApiGatewayV2' => ['2018-11-29' => ['GetApi' => 'GetApiResource']], 'CloudHSM' => ['2014-05-30' => ['GetConfig' => 'GetConfigFiles']], 'GroundStation' => ['2019-05-23' => ['GetConfig' => 'GetMissionProfileConfig']], 'Pinpoint' => ['2016-12-01' => ['GetEndpoint' => 'GetUserEndpoint', 'UpdateEndpoint' => 'UpdateUserEndpoint', 'UpdateEndpointsBatch' => 'UpdateUserEndpointsBatch']]]];
vendor/Aws3/Aws/data/amplify/2017-07-25/api-2.json.php CHANGED
@@ -1,4 +1,4 @@
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/amplify/2017-07-25/api-2.json
4
- return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-07-25', 'endpointPrefix' => 'amplify', 'jsonVersion' => '1.1', 'protocol' => 'rest-json', 'serviceAbbreviation' => 'Amplify', 'serviceFullName' => 'AWS Amplify', 'serviceId' => 'Amplify', 'signatureVersion' => 'v4', 'signingName' => 'amplify', 'uid' => 'amplify-2017-07-25'], 'operations' => ['CreateApp' => ['name' => 'CreateApp', 'http' => ['method' => 'POST', 'requestUri' => '/apps'], 'input' => ['shape' => 'CreateAppRequest'], 'output' => ['shape' => 'CreateAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'CreateBranch' => ['name' => 'CreateBranch', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches'], 'input' => ['shape' => 'CreateBranchRequest'], 'output' => ['shape' => 'CreateBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'CreateDomainAssociation' => ['name' => 'CreateDomainAssociation', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/domains'], 'input' => ['shape' => 'CreateDomainAssociationRequest'], 'output' => ['shape' => 'CreateDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteApp' => ['name' => 'DeleteApp', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'DeleteAppRequest'], 'output' => ['shape' => 'DeleteAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteBranch' => ['name' => 'DeleteBranch', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'DeleteBranchRequest'], 'output' => ['shape' => 'DeleteBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteDomainAssociation' => ['name' => 'DeleteDomainAssociation', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'DeleteDomainAssociationRequest'], 'output' => ['shape' => 'DeleteDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteJob' => ['name' => 'DeleteJob', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}'], 'input' => ['shape' => 'DeleteJobRequest'], 'output' => ['shape' => 'DeleteJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'GetApp' => ['name' => 'GetApp', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'GetAppRequest'], 'output' => ['shape' => 'GetAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'GetBranch' => ['name' => 'GetBranch', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'GetBranchRequest'], 'output' => ['shape' => 'GetBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException']]], 'GetDomainAssociation' => ['name' => 'GetDomainAssociation', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'GetDomainAssociationRequest'], 'output' => ['shape' => 'GetDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException']]], 'GetJob' => ['name' => 'GetJob', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}'], 'input' => ['shape' => 'GetJobRequest'], 'output' => ['shape' => 'GetJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'ListApps' => ['name' => 'ListApps', 'http' => ['method' => 'GET', 'requestUri' => '/apps'], 'input' => ['shape' => 'ListAppsRequest'], 'output' => ['shape' => 'ListAppsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListBranches' => ['name' => 'ListBranches', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches'], 'input' => ['shape' => 'ListBranchesRequest'], 'output' => ['shape' => 'ListBranchesResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListDomainAssociations' => ['name' => 'ListDomainAssociations', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/domains'], 'input' => ['shape' => 'ListDomainAssociationsRequest'], 'output' => ['shape' => 'ListDomainAssociationsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListJobs' => ['name' => 'ListJobs', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs'], 'input' => ['shape' => 'ListJobsRequest'], 'output' => ['shape' => 'ListJobsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'StartJob' => ['name' => 'StartJob', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs'], 'input' => ['shape' => 'StartJobRequest'], 'output' => ['shape' => 'StartJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'StopJob' => ['name' => 'StopJob', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}/stop'], 'input' => ['shape' => 'StopJobRequest'], 'output' => ['shape' => 'StopJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'UpdateApp' => ['name' => 'UpdateApp', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'UpdateAppRequest'], 'output' => ['shape' => 'UpdateAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'UpdateBranch' => ['name' => 'UpdateBranch', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'UpdateBranchRequest'], 'output' => ['shape' => 'UpdateBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'UpdateDomainAssociation' => ['name' => 'UpdateDomainAssociation', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'UpdateDomainAssociationRequest'], 'output' => ['shape' => 'UpdateDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]]], 'shapes' => ['ActiveJobId' => ['type' => 'string', 'max' => 1000], 'App' => ['type' => 'structure', 'required' => ['appId', 'appArn', 'name', 'description', 'repository', 'platform', 'createTime', 'updateTime', 'environmentVariables', 'defaultDomain', 'enableBranchAutoBuild', 'enableBasicAuth'], 'members' => ['appId' => ['shape' => 'AppId'], 'appArn' => ['shape' => 'AppArn'], 'name' => ['shape' => 'Name'], 'tags' => ['shape' => 'Tags'], 'description' => ['shape' => 'Description'], 'repository' => ['shape' => 'Repository'], 'platform' => ['shape' => 'Platform'], 'createTime' => ['shape' => 'CreateTime'], 'updateTime' => ['shape' => 'UpdateTime'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'defaultDomain' => ['shape' => 'DefaultDomain'], 'enableBranchAutoBuild' => ['shape' => 'EnableBranchAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'productionBranch' => ['shape' => 'ProductionBranch'], 'buildSpec' => ['shape' => 'BuildSpec']]], 'AppArn' => ['type' => 'string', 'max' => 1000], 'AppId' => ['type' => 'string', 'max' => 255, 'min' => 1], 'Apps' => ['type' => 'list', 'member' => ['shape' => 'App']], 'ArtifactsUrl' => ['type' => 'string', 'max' => 1000], 'BadRequestException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 400], 'exception' => \true], 'BasicAuthCredentials' => ['type' => 'string', 'max' => 2000], 'Branch' => ['type' => 'structure', 'required' => ['branchArn', 'branchName', 'description', 'stage', 'enableNotification', 'createTime', 'updateTime', 'environmentVariables', 'enableAutoBuild', 'customDomains', 'framework', 'activeJobId', 'totalNumberOfJobs', 'enableBasicAuth', 'ttl'], 'members' => ['branchArn' => ['shape' => 'BranchArn'], 'branchName' => ['shape' => 'BranchName'], 'description' => ['shape' => 'Description'], 'tags' => ['shape' => 'Tags'], 'stage' => ['shape' => 'Stage'], 'displayName' => ['shape' => 'DisplayName'], 'enableNotification' => ['shape' => 'EnableNotification'], 'createTime' => ['shape' => 'CreateTime'], 'updateTime' => ['shape' => 'UpdateTime'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'customDomains' => ['shape' => 'CustomDomains'], 'framework' => ['shape' => 'Framework'], 'activeJobId' => ['shape' => 'ActiveJobId'], 'totalNumberOfJobs' => ['shape' => 'TotalNumberOfJobs'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'thumbnailUrl' => ['shape' => 'ThumbnailUrl'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'buildSpec' => ['shape' => 'BuildSpec'], 'ttl' => ['shape' => 'TTL']]], 'BranchArn' => ['type' => 'string', 'max' => 1000], 'BranchName' => ['type' => 'string', 'max' => 255, 'min' => 1], 'Branches' => ['type' => 'list', 'member' => ['shape' => 'Branch'], 'max' => 255], 'BuildSpec' => ['type' => 'string', 'max' => 25000, 'min' => 1], 'CertificateVerificationDNSRecord' => ['type' => 'string', 'max' => 1000], 'CommitId' => ['type' => 'string', 'max' => 255], 'CommitMessage' => ['type' => 'string', 'max' => 10000], 'CommitTime' => ['type' => 'timestamp'], 'Condition' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'CreateAppRequest' => ['type' => 'structure', 'required' => ['name', 'repository', 'platform', 'oauthToken'], 'members' => ['name' => ['shape' => 'Name'], 'description' => ['shape' => 'Description'], 'repository' => ['shape' => 'Repository'], 'platform' => ['shape' => 'Platform'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'oauthToken' => ['shape' => 'OauthToken'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableBranchAutoBuild' => ['shape' => 'EnableBranchAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'tags' => ['shape' => 'Tags'], 'buildSpec' => ['shape' => 'BuildSpec']]], 'CreateAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'CreateBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName'], 'description' => ['shape' => 'Description'], 'stage' => ['shape' => 'Stage'], 'framework' => ['shape' => 'Framework'], 'enableNotification' => ['shape' => 'EnableNotification'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'tags' => ['shape' => 'Tags'], 'buildSpec' => ['shape' => 'BuildSpec'], 'ttl' => ['shape' => 'TTL']]], 'CreateBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'CreateDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName', 'subDomainSettings'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName'], 'enableAutoSubDomain' => ['shape' => 'EnableAutoSubDomain'], 'subDomainSettings' => ['shape' => 'SubDomainSettings']]], 'CreateDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'CreateTime' => ['type' => 'timestamp'], 'CustomDomain' => ['type' => 'string', 'max' => 255], 'CustomDomains' => ['type' => 'list', 'member' => ['shape' => 'CustomDomain'], 'max' => 255], 'CustomRule' => ['type' => 'structure', 'required' => ['source', 'target'], 'members' => ['source' => ['shape' => 'Source'], 'target' => ['shape' => 'Target'], 'status' => ['shape' => 'Status'], 'condition' => ['shape' => 'Condition']]], 'CustomRules' => ['type' => 'list', 'member' => ['shape' => 'CustomRule']], 'DNSRecord' => ['type' => 'string', 'max' => 1000], 'DefaultDomain' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'DeleteAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId']]], 'DeleteAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'DeleteBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName']]], 'DeleteBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'DeleteDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName', 'location' => 'uri', 'locationName' => 'domainName']]], 'DeleteDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'DeleteJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'DeleteJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'DependentServiceFailureException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 503], 'exception' => \true], 'Description' => ['type' => 'string', 'max' => 1000], 'DisplayName' => ['type' => 'string', 'max' => 255], 'DomainAssociation' => ['type' => 'structure', 'required' => ['domainAssociationArn', 'domainName', 'enableAutoSubDomain', 'domainStatus', 'statusReason', 'certificateVerificationDNSRecord', 'subDomains'], 'members' => ['domainAssociationArn' => ['shape' => 'DomainAssociationArn'], 'domainName' => ['shape' => 'DomainName'], 'enableAutoSubDomain' => ['shape' => 'EnableAutoSubDomain'], 'domainStatus' => ['shape' => 'DomainStatus'], 'statusReason' => ['shape' => 'StatusReason'], 'certificateVerificationDNSRecord' => ['shape' => 'CertificateVerificationDNSRecord'], 'subDomains' => ['shape' => 'SubDomains']]], 'DomainAssociationArn' => ['type' => 'string', 'max' => 1000], 'DomainAssociations' => ['type' => 'list', 'member' => ['shape' => 'DomainAssociation'], 'max' => 255], 'DomainName' => ['type' => 'string', 'max' => 255], 'DomainPrefix' => ['type' => 'string', 'max' => 255], 'DomainStatus' => ['type' => 'string', 'enum' => ['PENDING_VERIFICATION', 'IN_PROGRESS', 'AVAILABLE', 'PENDING_DEPLOYMENT', 'FAILED']], 'EnableAutoBuild' => ['type' => 'boolean'], 'EnableAutoSubDomain' => ['type' => 'boolean'], 'EnableBasicAuth' => ['type' => 'boolean'], 'EnableBranchAutoBuild' => ['type' => 'boolean'], 'EnableNotification' => ['type' => 'boolean'], 'EndTime' => ['type' => 'timestamp'], 'EnvKey' => ['type' => 'string', 'max' => 255], 'EnvValue' => ['type' => 'string', 'max' => 1000], 'EnvironmentVariables' => ['type' => 'map', 'key' => ['shape' => 'EnvKey'], 'value' => ['shape' => 'EnvValue']], 'ErrorMessage' => ['type' => 'string', 'max' => 255], 'Framework' => ['type' => 'string', 'max' => 255], 'GetAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId']]], 'GetAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'GetBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName']]], 'GetBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'GetDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName', 'location' => 'uri', 'locationName' => 'domainName']]], 'GetDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'GetJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'GetJobResult' => ['type' => 'structure', 'required' => ['job'], 'members' => ['job' => ['shape' => 'Job']]], 'InternalFailureException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 500], 'exception' => \true, 'fault' => \true], 'Job' => ['type' => 'structure', 'required' => ['summary', 'steps'], 'members' => ['summary' => ['shape' => 'JobSummary'], 'steps' => ['shape' => 'Steps']]], 'JobArn' => ['type' => 'string', 'max' => 1000], 'JobId' => ['type' => 'string', 'max' => 255], 'JobReason' => ['type' => 'string', 'max' => 255], 'JobStatus' => ['type' => 'string', 'enum' => ['PENDING', 'PROVISIONING', 'RUNNING', 'FAILED', 'SUCCEED', 'CANCELLING', 'CANCELLED']], 'JobSummaries' => ['type' => 'list', 'member' => ['shape' => 'JobSummary']], 'JobSummary' => ['type' => 'structure', 'required' => ['jobArn', 'jobId', 'commitId', 'commitMessage', 'commitTime', 'startTime', 'status', 'jobType'], 'members' => ['jobArn' => ['shape' => 'JobArn'], 'jobId' => ['shape' => 'JobId'], 'commitId' => ['shape' => 'CommitId'], 'commitMessage' => ['shape' => 'CommitMessage'], 'commitTime' => ['shape' => 'CommitTime'], 'startTime' => ['shape' => 'StartTime'], 'status' => ['shape' => 'JobStatus'], 'endTime' => ['shape' => 'EndTime'], 'jobType' => ['shape' => 'JobType']]], 'JobType' => ['type' => 'string', 'enum' => ['RELEASE', 'RETRY', 'WEB_HOOK'], 'max' => 10], 'LastDeployTime' => ['type' => 'timestamp'], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 429], 'exception' => \true], 'ListAppsRequest' => ['type' => 'structure', 'members' => ['nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListAppsResult' => ['type' => 'structure', 'required' => ['apps'], 'members' => ['apps' => ['shape' => 'Apps'], 'nextToken' => ['shape' => 'NextToken']]], 'ListBranchesRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListBranchesResult' => ['type' => 'structure', 'required' => ['branches'], 'members' => ['branches' => ['shape' => 'Branches'], 'nextToken' => ['shape' => 'NextToken']]], 'ListDomainAssociationsRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListDomainAssociationsResult' => ['type' => 'structure', 'required' => ['domainAssociations'], 'members' => ['domainAssociations' => ['shape' => 'DomainAssociations'], 'nextToken' => ['shape' => 'NextToken']]], 'ListJobsRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListJobsResult' => ['type' => 'structure', 'required' => ['jobSummaries'], 'members' => ['jobSummaries' => ['shape' => 'JobSummaries'], 'nextToken' => ['shape' => 'NextToken']]], 'LogUrl' => ['type' => 'string', 'max' => 1000], 'MaxResults' => ['type' => 'integer', 'max' => 100, 'min' => 1], 'Name' => ['type' => 'string', 'max' => 255, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 2000], 'NotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 404], 'exception' => \true], 'OauthToken' => ['type' => 'string', 'max' => 100], 'Platform' => ['type' => 'string', 'enum' => ['IOS', 'ANDROID', 'WEB', 'REACT_NATIVE']], 'ProductionBranch' => ['type' => 'structure', 'members' => ['lastDeployTime' => ['shape' => 'LastDeployTime'], 'status' => ['shape' => 'Status'], 'thumbnailUrl' => ['shape' => 'ThumbnailUrl'], 'branchName' => ['shape' => 'BranchName']]], 'Repository' => ['type' => 'string', 'max' => 1000], 'Screenshots' => ['type' => 'map', 'key' => ['shape' => 'ThumbnailName'], 'value' => ['shape' => 'ThumbnailUrl']], 'ServiceRoleArn' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'Source' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'Stage' => ['type' => 'string', 'enum' => ['PRODUCTION', 'BETA', 'DEVELOPMENT', 'EXPERIMENTAL']], 'StartJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobType'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId'], 'jobType' => ['shape' => 'JobType'], 'jobReason' => ['shape' => 'JobReason'], 'commitId' => ['shape' => 'CommitId'], 'commitMessage' => ['shape' => 'CommitMessage'], 'commitTime' => ['shape' => 'CommitTime']]], 'StartJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'StartTime' => ['type' => 'timestamp'], 'Status' => ['type' => 'string', 'max' => 3, 'min' => 3], 'StatusReason' => ['type' => 'string', 'max' => 1000], 'Step' => ['type' => 'structure', 'required' => ['stepName', 'startTime', 'status', 'endTime'], 'members' => ['stepName' => ['shape' => 'StepName'], 'startTime' => ['shape' => 'StartTime'], 'status' => ['shape' => 'JobStatus'], 'endTime' => ['shape' => 'EndTime'], 'logUrl' => ['shape' => 'LogUrl'], 'artifactsUrl' => ['shape' => 'ArtifactsUrl'], 'screenshots' => ['shape' => 'Screenshots']]], 'StepName' => ['type' => 'string', 'max' => 255], 'Steps' => ['type' => 'list', 'member' => ['shape' => 'Step']], 'StopJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'StopJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'SubDomain' => ['type' => 'structure', 'required' => ['subDomainSetting', 'verified', 'dnsRecord'], 'members' => ['subDomainSetting' => ['shape' => 'SubDomainSetting'], 'verified' => ['shape' => 'Verified'], 'dnsRecord' => ['shape' => 'DNSRecord']]], 'SubDomainSetting' => ['type' => 'structure', 'required' => ['prefix', 'branchName'], 'members' => ['prefix' => ['shape' => 'DomainPrefix'], 'branchName' => ['shape' => 'BranchName']]], 'SubDomainSettings' => ['type' => 'list', 'member' => ['shape' => 'SubDomainSetting'], 'max' => 255], 'SubDomains' => ['type' => 'list', 'member' => ['shape' => 'SubDomain'], 'max' => 255], 'TTL' => ['type' => 'string'], 'TagKey' => ['type' => 'string', 'max' => 1000], 'TagValue' => ['type' => 'string', 'max' => 1000], 'Tags' => ['type' => 'map', 'key' => ['shape' => 'TagKey'], 'value' => ['shape' => 'TagValue']], 'Target' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'ThumbnailName' => ['type' => 'string', 'max' => 256], 'ThumbnailUrl' => ['type' => 'string', 'max' => 2000, 'min' => 1], 'TotalNumberOfJobs' => ['type' => 'string', 'max' => 1000], 'UnauthorizedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 401], 'exception' => \true], 'UpdateAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'name' => ['shape' => 'Name'], 'description' => ['shape' => 'Description'], 'platform' => ['shape' => 'Platform'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableBranchAutoBuild' => ['shape' => 'EnableAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'buildSpec' => ['shape' => 'BuildSpec']]], 'UpdateAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'UpdateBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'description' => ['shape' => 'Description'], 'framework' => ['shape' => 'Framework'], 'stage' => ['shape' => 'Stage'], 'enableNotification' => ['shape' => 'EnableNotification'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'buildSpec' => ['shape' => 'BuildSpec'], 'ttl' => ['shape' => 'TTL']]], 'UpdateBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'UpdateDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName', 'subDomainSettings'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName', 'location' => 'uri', 'locationName' => 'domainName'], 'enableAutoSubDomain' => ['shape' => 'EnableAutoSubDomain'], 'subDomainSettings' => ['shape' => 'SubDomainSettings']]], 'UpdateDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'UpdateTime' => ['type' => 'timestamp'], 'Verified' => ['type' => 'boolean']]];
1
  <?php
2
 
3
  // This file was auto-generated from sdk-root/src/data/amplify/2017-07-25/api-2.json
4
+ return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-07-25', 'endpointPrefix' => 'amplify', 'jsonVersion' => '1.1', 'protocol' => 'rest-json', 'serviceAbbreviation' => 'Amplify', 'serviceFullName' => 'AWS Amplify', 'serviceId' => 'Amplify', 'signatureVersion' => 'v4', 'signingName' => 'amplify', 'uid' => 'amplify-2017-07-25'], 'operations' => ['CreateApp' => ['name' => 'CreateApp', 'http' => ['method' => 'POST', 'requestUri' => '/apps'], 'input' => ['shape' => 'CreateAppRequest'], 'output' => ['shape' => 'CreateAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'CreateBackendEnvironment' => ['name' => 'CreateBackendEnvironment', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/backendenvironments'], 'input' => ['shape' => 'CreateBackendEnvironmentRequest'], 'output' => ['shape' => 'CreateBackendEnvironmentResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'CreateBranch' => ['name' => 'CreateBranch', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches'], 'input' => ['shape' => 'CreateBranchRequest'], 'output' => ['shape' => 'CreateBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'CreateDeployment' => ['name' => 'CreateDeployment', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}/deployments'], 'input' => ['shape' => 'CreateDeploymentRequest'], 'output' => ['shape' => 'CreateDeploymentResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'CreateDomainAssociation' => ['name' => 'CreateDomainAssociation', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/domains'], 'input' => ['shape' => 'CreateDomainAssociationRequest'], 'output' => ['shape' => 'CreateDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'CreateWebhook' => ['name' => 'CreateWebhook', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/webhooks'], 'input' => ['shape' => 'CreateWebhookRequest'], 'output' => ['shape' => 'CreateWebhookResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteApp' => ['name' => 'DeleteApp', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'DeleteAppRequest'], 'output' => ['shape' => 'DeleteAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteBackendEnvironment' => ['name' => 'DeleteBackendEnvironment', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/backendenvironments/{environmentName}'], 'input' => ['shape' => 'DeleteBackendEnvironmentRequest'], 'output' => ['shape' => 'DeleteBackendEnvironmentResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteBranch' => ['name' => 'DeleteBranch', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'DeleteBranchRequest'], 'output' => ['shape' => 'DeleteBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteDomainAssociation' => ['name' => 'DeleteDomainAssociation', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'DeleteDomainAssociationRequest'], 'output' => ['shape' => 'DeleteDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteJob' => ['name' => 'DeleteJob', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}'], 'input' => ['shape' => 'DeleteJobRequest'], 'output' => ['shape' => 'DeleteJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'DeleteWebhook' => ['name' => 'DeleteWebhook', 'http' => ['method' => 'DELETE', 'requestUri' => '/webhooks/{webhookId}'], 'input' => ['shape' => 'DeleteWebhookRequest'], 'output' => ['shape' => 'DeleteWebhookResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'GenerateAccessLogs' => ['name' => 'GenerateAccessLogs', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/accesslogs'], 'input' => ['shape' => 'GenerateAccessLogsRequest'], 'output' => ['shape' => 'GenerateAccessLogsResult'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'GetApp' => ['name' => 'GetApp', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'GetAppRequest'], 'output' => ['shape' => 'GetAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'GetArtifactUrl' => ['name' => 'GetArtifactUrl', 'http' => ['method' => 'GET', 'requestUri' => '/artifacts/{artifactId}'], 'input' => ['shape' => 'GetArtifactUrlRequest'], 'output' => ['shape' => 'GetArtifactUrlResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'GetBackendEnvironment' => ['name' => 'GetBackendEnvironment', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/backendenvironments/{environmentName}'], 'input' => ['shape' => 'GetBackendEnvironmentRequest'], 'output' => ['shape' => 'GetBackendEnvironmentResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException']]], 'GetBranch' => ['name' => 'GetBranch', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'GetBranchRequest'], 'output' => ['shape' => 'GetBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException']]], 'GetDomainAssociation' => ['name' => 'GetDomainAssociation', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'GetDomainAssociationRequest'], 'output' => ['shape' => 'GetDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException']]], 'GetJob' => ['name' => 'GetJob', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}'], 'input' => ['shape' => 'GetJobRequest'], 'output' => ['shape' => 'GetJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'GetWebhook' => ['name' => 'GetWebhook', 'http' => ['method' => 'GET', 'requestUri' => '/webhooks/{webhookId}'], 'input' => ['shape' => 'GetWebhookRequest'], 'output' => ['shape' => 'GetWebhookResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'ListApps' => ['name' => 'ListApps', 'http' => ['method' => 'GET', 'requestUri' => '/apps'], 'input' => ['shape' => 'ListAppsRequest'], 'output' => ['shape' => 'ListAppsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListArtifacts' => ['name' => 'ListArtifacts', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}/artifacts'], 'input' => ['shape' => 'ListArtifactsRequest'], 'output' => ['shape' => 'ListArtifactsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'ListBackendEnvironments' => ['name' => 'ListBackendEnvironments', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/backendenvironments'], 'input' => ['shape' => 'ListBackendEnvironmentsRequest'], 'output' => ['shape' => 'ListBackendEnvironmentsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListBranches' => ['name' => 'ListBranches', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches'], 'input' => ['shape' => 'ListBranchesRequest'], 'output' => ['shape' => 'ListBranchesResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListDomainAssociations' => ['name' => 'ListDomainAssociations', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/domains'], 'input' => ['shape' => 'ListDomainAssociationsRequest'], 'output' => ['shape' => 'ListDomainAssociationsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListJobs' => ['name' => 'ListJobs', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs'], 'input' => ['shape' => 'ListJobsRequest'], 'output' => ['shape' => 'ListJobsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'ListTagsForResource' => ['name' => 'ListTagsForResource', 'http' => ['method' => 'GET', 'requestUri' => '/tags/{resourceArn}'], 'input' => ['shape' => 'ListTagsForResourceRequest'], 'output' => ['shape' => 'ListTagsForResourceResponse'], 'errors' => [['shape' => 'InternalFailureException'], ['shape' => 'BadRequestException'], ['shape' => 'ResourceNotFoundException']]], 'ListWebhooks' => ['name' => 'ListWebhooks', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/webhooks'], 'input' => ['shape' => 'ListWebhooksRequest'], 'output' => ['shape' => 'ListWebhooksResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'StartDeployment' => ['name' => 'StartDeployment', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}/deployments/start'], 'input' => ['shape' => 'StartDeploymentRequest'], 'output' => ['shape' => 'StartDeploymentResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'StartJob' => ['name' => 'StartJob', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs'], 'input' => ['shape' => 'StartJobRequest'], 'output' => ['shape' => 'StartJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'StopJob' => ['name' => 'StopJob', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}/stop'], 'input' => ['shape' => 'StopJobRequest'], 'output' => ['shape' => 'StopJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'TagResource' => ['name' => 'TagResource', 'http' => ['method' => 'POST', 'requestUri' => '/tags/{resourceArn}'], 'input' => ['shape' => 'TagResourceRequest'], 'output' => ['shape' => 'TagResourceResponse'], 'errors' => [['shape' => 'InternalFailureException'], ['shape' => 'BadRequestException'], ['shape' => 'ResourceNotFoundException']]], 'UntagResource' => ['name' => 'UntagResource', 'http' => ['method' => 'DELETE', 'requestUri' => '/tags/{resourceArn}'], 'input' => ['shape' => 'UntagResourceRequest'], 'output' => ['shape' => 'UntagResourceResponse'], 'errors' => [['shape' => 'InternalFailureException'], ['shape' => 'BadRequestException'], ['shape' => 'ResourceNotFoundException']]], 'UpdateApp' => ['name' => 'UpdateApp', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'UpdateAppRequest'], 'output' => ['shape' => 'UpdateAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'UpdateBranch' => ['name' => 'UpdateBranch', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'UpdateBranchRequest'], 'output' => ['shape' => 'UpdateBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'UpdateDomainAssociation' => ['name' => 'UpdateDomainAssociation', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'UpdateDomainAssociationRequest'], 'output' => ['shape' => 'UpdateDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'UpdateWebhook' => ['name' => 'UpdateWebhook', 'http' => ['method' => 'POST', 'requestUri' => '/webhooks/{webhookId}'], 'input' => ['shape' => 'UpdateWebhookRequest'], 'output' => ['shape' => 'UpdateWebhookResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]]], 'shapes' => ['AccessToken' => ['type' => 'string', 'max' => 255, 'min' => 1], 'ActiveJobId' => ['type' => 'string', 'max' => 1000], 'App' => ['type' => 'structure', 'required' => ['appId', 'appArn', 'name', 'description', 'repository', 'platform', 'createTime', 'updateTime', 'environmentVariables', 'defaultDomain', 'enableBranchAutoBuild', 'enableBasicAuth'], 'members' => ['appId' => ['shape' => 'AppId'], 'appArn' => ['shape' => 'AppArn'], 'name' => ['shape' => 'Name'], 'tags' => ['shape' => 'TagMap'], 'description' => ['shape' => 'Description'], 'repository' => ['shape' => 'Repository'], 'platform' => ['shape' => 'Platform'], 'createTime' => ['shape' => 'CreateTime'], 'updateTime' => ['shape' => 'UpdateTime'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'defaultDomain' => ['shape' => 'DefaultDomain'], 'enableBranchAutoBuild' => ['shape' => 'EnableBranchAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'productionBranch' => ['shape' => 'ProductionBranch'], 'buildSpec' => ['shape' => 'BuildSpec'], 'enableAutoBranchCreation' => ['shape' => 'EnableAutoBranchCreation'], 'autoBranchCreationPatterns' => ['shape' => 'AutoBranchCreationPatterns'], 'autoBranchCreationConfig' => ['shape' => 'AutoBranchCreationConfig']]], 'AppArn' => ['type' => 'string', 'max' => 1000], 'AppId' => ['type' => 'string', 'max' => 255, 'min' => 1], 'Apps' => ['type' => 'list', 'member' => ['shape' => 'App']], 'Artifact' => ['type' => 'structure', 'required' => ['artifactFileName', 'artifactId'], 'members' => ['artifactFileName' => ['shape' => 'ArtifactFileName'], 'artifactId' => ['shape' => 'ArtifactId']]], 'ArtifactFileName' => ['type' => 'string', 'max' => 1000], 'ArtifactId' => ['type' => 'string', 'max' => 255], 'ArtifactUrl' => ['type' => 'string', 'max' => 1000], 'Artifacts' => ['type' => 'list', 'member' => ['shape' => 'Artifact']], 'ArtifactsUrl' => ['type' => 'string', 'max' => 1000], 'AssociatedResource' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'AssociatedResources' => ['type' => 'list', 'member' => ['shape' => 'AssociatedResource']], 'AutoBranchCreationConfig' => ['type' => 'structure', 'members' => ['stage' => ['shape' => 'Stage'], 'framework' => ['shape' => 'Framework'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'buildSpec' => ['shape' => 'BuildSpec'], 'enablePullRequestPreview' => ['shape' => 'EnablePullRequestPreview'], 'pullRequestEnvironmentName' => ['shape' => 'PullRequestEnvironmentName']]], 'AutoBranchCreationPattern' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'AutoBranchCreationPatterns' => ['type' => 'list', 'member' => ['shape' => 'AutoBranchCreationPattern']], 'BackendEnvironment' => ['type' => 'structure', 'required' => ['backendEnvironmentArn', 'environmentName', 'createTime', 'updateTime'], 'members' => ['backendEnvironmentArn' => ['shape' => 'BackendEnvironmentArn'], 'environmentName' => ['shape' => 'EnvironmentName'], 'stackName' => ['shape' => 'StackName'], 'deploymentArtifacts' => ['shape' => 'DeploymentArtifacts'], 'createTime' => ['shape' => 'CreateTime'], 'updateTime' => ['shape' => 'UpdateTime']]], 'BackendEnvironmentArn' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'BackendEnvironments' => ['type' => 'list', 'member' => ['shape' => 'BackendEnvironment']], 'BadRequestException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 400], 'exception' => \true], 'BasicAuthCredentials' => ['type' => 'string', 'max' => 2000], 'Branch' => ['type' => 'structure', 'required' => ['branchArn', 'branchName', 'description', 'stage', 'displayName', 'enableNotification', 'createTime', 'updateTime', 'environmentVariables', 'enableAutoBuild', 'customDomains', 'framework', 'activeJobId', 'totalNumberOfJobs', 'enableBasicAuth', 'ttl', 'enablePullRequestPreview'], 'members' => ['branchArn' => ['shape' => 'BranchArn'], 'branchName' => ['shape' => 'BranchName'], 'description' => ['shape' => 'Description'], 'tags' => ['shape' => 'TagMap'], 'stage' => ['shape' => 'Stage'], 'displayName' => ['shape' => 'DisplayName'], 'enableNotification' => ['shape' => 'EnableNotification'], 'createTime' => ['shape' => 'CreateTime'], 'updateTime' => ['shape' => 'UpdateTime'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'customDomains' => ['shape' => 'CustomDomains'], 'framework' => ['shape' => 'Framework'], 'activeJobId' => ['shape' => 'ActiveJobId'], 'totalNumberOfJobs' => ['shape' => 'TotalNumberOfJobs'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'thumbnailUrl' => ['shape' => 'ThumbnailUrl'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'buildSpec' => ['shape' => 'BuildSpec'], 'ttl' => ['shape' => 'TTL'], 'associatedResources' => ['shape' => 'AssociatedResources'], 'enablePullRequestPreview' => ['shape' => 'EnablePullRequestPreview'], 'pullRequestEnvironmentName' => ['shape' => 'PullRequestEnvironmentName'], 'destinationBranch' => ['shape' => 'BranchName'], 'sourceBranch' => ['shape' => 'BranchName'], 'backendEnvironmentArn' => ['shape' => 'BackendEnvironmentArn']]], 'BranchArn' => ['type' => 'string', 'max' => 1000], 'BranchName' => ['type' => 'string', 'max' => 255, 'min' => 1], 'Branches' => ['type' => 'list', 'member' => ['shape' => 'Branch'], 'max' => 255], 'BuildSpec' => ['type' => 'string', 'max' => 25000, 'min' => 1], 'CertificateVerificationDNSRecord' => ['type' => 'string', 'max' => 1000], 'Code' => ['type' => 'string'], 'CommitId' => ['type' => 'string', 'max' => 255], 'CommitMessage' => ['type' => 'string', 'max' => 10000], 'CommitTime' => ['type' => 'timestamp'], 'Condition' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'Context' => ['type' => 'string'], 'CreateAppRequest' => ['type' => 'structure', 'required' => ['name'], 'members' => ['name' => ['shape' => 'Name'], 'description' => ['shape' => 'Description'], 'repository' => ['shape' => 'Repository'], 'platform' => ['shape' => 'Platform'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'oauthToken' => ['shape' => 'OauthToken'], 'accessToken' => ['shape' => 'AccessToken'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableBranchAutoBuild' => ['shape' => 'EnableBranchAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'tags' => ['shape' => 'TagMap'], 'buildSpec' => ['shape' => 'BuildSpec'], 'enableAutoBranchCreation' => ['shape' => 'EnableAutoBranchCreation'], 'autoBranchCreationPatterns' => ['shape' => 'AutoBranchCreationPatterns'], 'autoBranchCreationConfig' => ['shape' => 'AutoBranchCreationConfig']]], 'CreateAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'CreateBackendEnvironmentRequest' => ['type' => 'structure', 'required' => ['appId', 'environmentName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'environmentName' => ['shape' => 'EnvironmentName'], 'stackName' => ['shape' => 'StackName'], 'deploymentArtifacts' => ['shape' => 'DeploymentArtifacts']]], 'CreateBackendEnvironmentResult' => ['type' => 'structure', 'required' => ['backendEnvironment'], 'members' => ['backendEnvironment' => ['shape' => 'BackendEnvironment']]], 'CreateBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName'], 'description' => ['shape' => 'Description'], 'stage' => ['shape' => 'Stage'], 'framework' => ['shape' => 'Framework'], 'enableNotification' => ['shape' => 'EnableNotification'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'tags' => ['shape' => 'TagMap'], 'buildSpec' => ['shape' => 'BuildSpec'], 'ttl' => ['shape' => 'TTL'], 'displayName' => ['shape' => 'DisplayName'], 'enablePullRequestPreview' => ['shape' => 'EnablePullRequestPreview'], 'pullRequestEnvironmentName' => ['shape' => 'PullRequestEnvironmentName'], 'backendEnvironmentArn' => ['shape' => 'BackendEnvironmentArn']]], 'CreateBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'CreateDeploymentRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'fileMap' => ['shape' => 'FileMap']]], 'CreateDeploymentResult' => ['type' => 'structure', 'required' => ['fileUploadUrls', 'zipUploadUrl'], 'members' => ['jobId' => ['shape' => 'JobId'], 'fileUploadUrls' => ['shape' => 'FileUploadUrls'], 'zipUploadUrl' => ['shape' => 'UploadUrl']]], 'CreateDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName', 'subDomainSettings'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName'], 'enableAutoSubDomain' => ['shape' => 'EnableAutoSubDomain'], 'subDomainSettings' => ['shape' => 'SubDomainSettings']]], 'CreateDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'CreateTime' => ['type' => 'timestamp'], 'CreateWebhookRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName'], 'description' => ['shape' => 'Description']]], 'CreateWebhookResult' => ['type' => 'structure', 'required' => ['webhook'], 'members' => ['webhook' => ['shape' => 'Webhook']]], 'CustomDomain' => ['type' => 'string', 'max' => 255], 'CustomDomains' => ['type' => 'list', 'member' => ['shape' => 'CustomDomain'], 'max' => 255], 'CustomRule' => ['type' => 'structure', 'required' => ['source', 'target'], 'members' => ['source' => ['shape' => 'Source'], 'target' => ['shape' => 'Target'], 'status' => ['shape' => 'Status'], 'condition' => ['shape' => 'Condition']]], 'CustomRules' => ['type' => 'list', 'member' => ['shape' => 'CustomRule']], 'DNSRecord' => ['type' => 'string', 'max' => 1000], 'DefaultDomain' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'DeleteAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId']]], 'DeleteAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'DeleteBackendEnvironmentRequest' => ['type' => 'structure', 'required' => ['appId', 'environmentName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'environmentName' => ['shape' => 'EnvironmentName', 'location' => 'uri', 'locationName' => 'environmentName']]], 'DeleteBackendEnvironmentResult' => ['type' => 'structure', 'required' => ['backendEnvironment'], 'members' => ['backendEnvironment' => ['shape' => 'BackendEnvironment']]], 'DeleteBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName']]], 'DeleteBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'DeleteDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName', 'location' => 'uri', 'locationName' => 'domainName']]], 'DeleteDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'DeleteJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'DeleteJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'DeleteWebhookRequest' => ['type' => 'structure', 'required' => ['webhookId'], 'members' => ['webhookId' => ['shape' => 'WebhookId', 'location' => 'uri', 'locationName' => 'webhookId']]], 'DeleteWebhookResult' => ['type' => 'structure', 'required' => ['webhook'], 'members' => ['webhook' => ['shape' => 'Webhook']]], 'DependentServiceFailureException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 503], 'exception' => \true], 'DeploymentArtifacts' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'Description' => ['type' => 'string', 'max' => 1000], 'DisplayName' => ['type' => 'string', 'max' => 255], 'DomainAssociation' => ['type' => 'structure', 'required' => ['domainAssociationArn', 'domainName', 'enableAutoSubDomain', 'domainStatus', 'statusReason', 'subDomains'], 'members' => ['domainAssociationArn' => ['shape' => 'DomainAssociationArn'], 'domainName' => ['shape' => 'DomainName'], 'enableAutoSubDomain' => ['shape' => 'EnableAutoSubDomain'], 'domainStatus' => ['shape' => 'DomainStatus'], 'statusReason' => ['shape' => 'StatusReason'], 'certificateVerificationDNSRecord' => ['shape' => 'CertificateVerificationDNSRecord'], 'subDomains' => ['shape' => 'SubDomains']]], 'DomainAssociationArn' => ['type' => 'string', 'max' => 1000], 'DomainAssociations' => ['type' => 'list', 'member' => ['shape' => 'DomainAssociation'], 'max' => 255], 'DomainName' => ['type' => 'string', 'max' => 255], 'DomainPrefix' => ['type' => 'string', 'max' => 255], 'DomainStatus' => ['type' => 'string', 'enum' => ['PENDING_VERIFICATION', 'IN_PROGRESS', 'AVAILABLE', 'PENDING_DEPLOYMENT', 'FAILED', 'CREATING', 'REQUESTING_CERTIFICATE', 'UPDATING']], 'EnableAutoBranchCreation' => ['type' => 'boolean'], 'EnableAutoBuild' => ['type' => 'boolean'], 'EnableAutoSubDomain' => ['type' => 'boolean'], 'EnableBasicAuth' => ['type' => 'boolean'], 'EnableBranchAutoBuild' => ['type' => 'boolean'], 'EnableNotification' => ['type' => 'boolean'], 'EnablePullRequestPreview' => ['type' => 'boolean'], 'EndTime' => ['type' => 'timestamp'], 'EnvKey' => ['type' => 'string', 'max' => 255], 'EnvValue' => ['type' => 'string', 'max' => 1000], 'EnvironmentName' => ['type' => 'string', 'max' => 255, 'min' => 1], 'EnvironmentVariables' => ['type' => 'map', 'key' => ['shape' => 'EnvKey'], 'value' => ['shape' => 'EnvValue']], 'ErrorMessage' => ['type' => 'string', 'max' => 255], 'FileMap' => ['type' => 'map', 'key' => ['shape' => 'FileName'], 'value' => ['shape' => 'MD5Hash']], 'FileName' => ['type' => 'string', 'max' => 255], 'FileUploadUrls' => ['type' => 'map', 'key' => ['shape' => 'FileName'], 'value' => ['shape' => 'UploadUrl']], 'Framework' => ['type' => 'string', 'max' => 255], 'GenerateAccessLogsRequest' => ['type' => 'structure', 'required' => ['domainName', 'appId'], 'members' => ['startTime' => ['shape' => 'StartTime'], 'endTime' => ['shape' => 'EndTime'], 'domainName' => ['shape' => 'DomainName'], 'appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId']]], 'GenerateAccessLogsResult' => ['type' => 'structure', 'members' => ['logUrl' => ['shape' => 'LogUrl']]], 'GetAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId']]], 'GetAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'GetArtifactUrlRequest' => ['type' => 'structure', 'required' => ['artifactId'], 'members' => ['artifactId' => ['shape' => 'ArtifactId', 'location' => 'uri', 'locationName' => 'artifactId']]], 'GetArtifactUrlResult' => ['type' => 'structure', 'required' => ['artifactId', 'artifactUrl'], 'members' => ['artifactId' => ['shape' => 'ArtifactId'], 'artifactUrl' => ['shape' => 'ArtifactUrl']]], 'GetBackendEnvironmentRequest' => ['type' => 'structure', 'required' => ['appId', 'environmentName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'environmentName' => ['shape' => 'EnvironmentName', 'location' => 'uri', 'locationName' => 'environmentName']]], 'GetBackendEnvironmentResult' => ['type' => 'structure', 'required' => ['backendEnvironment'], 'members' => ['backendEnvironment' => ['shape' => 'BackendEnvironment']]], 'GetBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName']]], 'GetBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'GetDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName', 'location' => 'uri', 'locationName' => 'domainName']]], 'GetDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'GetJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'GetJobResult' => ['type' => 'structure', 'required' => ['job'], 'members' => ['job' => ['shape' => 'Job']]], 'GetWebhookRequest' => ['type' => 'structure', 'required' => ['webhookId'], 'members' => ['webhookId' => ['shape' => 'WebhookId', 'location' => 'uri', 'locationName' => 'webhookId']]], 'GetWebhookResult' => ['type' => 'structure', 'required' => ['webhook'], 'members' => ['webhook' => ['shape' => 'Webhook']]], 'InternalFailureException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 500], 'exception' => \true, 'fault' => \true], 'Job' => ['type' => 'structure', 'required' => ['summary', 'steps'], 'members' => ['summary' => ['shape' => 'JobSummary'], 'steps' => ['shape' => 'Steps']]], 'JobArn' => ['type' => 'string', 'max' => 1000], 'JobId' => ['type' => 'string', 'max' => 255], 'JobReason' => ['type' => 'string', 'max' => 255], 'JobStatus' => ['type' => 'string', 'enum' => ['PENDING', 'PROVISIONING', 'RUNNING', 'FAILED', 'SUCCEED', 'CANCELLING', 'CANCELLED']], 'JobSummaries' => ['type' => 'list', 'member' => ['shape' => 'JobSummary']], 'JobSummary' => ['type' => 'structure', 'required' => ['jobArn', 'jobId', 'commitId', 'commitMessage', 'commitTime', 'startTime', 'status', 'jobType'], 'members' => ['jobArn' => ['shape' => 'JobArn'], 'jobId' => ['shape' => 'JobId'], 'commitId' => ['shape' => 'CommitId'], 'commitMessage' => ['shape' => 'CommitMessage'], 'commitTime' => ['shape' => 'CommitTime'], 'startTime' => ['shape' => 'StartTime'], 'status' => ['shape' => 'JobStatus'], 'endTime' => ['shape' => 'EndTime'], 'jobType' => ['shape' => 'JobType']]], 'JobType' => ['type' => 'string', 'enum' => ['RELEASE', 'RETRY', 'MANUAL', 'WEB_HOOK'], 'max' => 10], 'LastDeployTime' => ['type' => 'timestamp'], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 429], 'exception' => \true], 'ListAppsRequest' => ['type' => 'structure', 'members' => ['nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListAppsResult' => ['type' => 'structure', 'required' => ['apps'], 'members' => ['apps' => ['shape' => 'Apps'], 'nextToken' => ['shape' => 'NextToken']]], 'ListArtifactsRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListArtifactsResult' => ['type' => 'structure', 'required' => ['artifacts'], 'members' => ['artifacts' => ['shape' => 'Artifacts'], 'nextToken' => ['shape' => 'NextToken']]], 'ListBackendEnvironmentsRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'environmentName' => ['shape' => 'EnvironmentName'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListBackendEnvironmentsResult' => ['type' => 'structure', 'required' => ['backendEnvironments'], 'members' => ['backendEnvironments' => ['shape' => 'BackendEnvironments'], 'nextToken' => ['shape' => 'NextToken']]], 'ListBranchesRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListBranchesResult' => ['type' => 'structure', 'required' => ['branches'], 'members' => ['branches' => ['shape' => 'Branches'], 'nextToken' => ['shape' => 'NextToken']]], 'ListDomainAssociationsRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListDomainAssociationsResult' => ['type' => 'structure', 'required' => ['domainAssociations'], 'members' => ['domainAssociations' => ['shape' => 'DomainAssociations'], 'nextToken' => ['shape' => 'NextToken']]], 'ListJobsRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListJobsResult' => ['type' => 'structure', 'required' => ['jobSummaries'], 'members' => ['jobSummaries' => ['shape' => 'JobSummaries'], 'nextToken' => ['shape' => 'NextToken']]], 'ListTagsForResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn'], 'members' => ['resourceArn' => ['shape' => 'ResourceArn', 'location' => 'uri', 'locationName' => 'resourceArn']]], 'ListTagsForResourceResponse' => ['type' => 'structure', 'members' => ['tags' => ['shape' => 'TagMap']]], 'ListWebhooksRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListWebhooksResult' => ['type' => 'structure', 'required' => ['webhooks'], 'members' => ['webhooks' => ['shape' => 'Webhooks'], 'nextToken' => ['shape' => 'NextToken']]], 'LogUrl' => ['type' => 'string', 'max' => 1000], 'MD5Hash' => ['type' => 'string', 'max' => 32], 'MaxResults' => ['type' => 'integer', 'max' => 100, 'min' => 1], 'Name' => ['type' => 'string', 'max' => 255, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 2000], 'NotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 404], 'exception' => \true], 'OauthToken' => ['type' => 'string', 'max' => 100], 'Platform' => ['type' => 'string', 'enum' => ['WEB']], 'ProductionBranch' => ['type' => 'structure', 'members' => ['lastDeployTime' => ['shape' => 'LastDeployTime'], 'status' => ['shape' => 'Status'], 'thumbnailUrl' => ['shape' => 'ThumbnailUrl'], 'branchName' => ['shape' => 'BranchName']]], 'PullRequestEnvironmentName' => ['type' => 'string', 'max' => 20], 'Repository' => ['type' => 'string', 'max' => 1000], 'ResourceArn' => ['type' => 'string', 'pattern' => '^arn:aws:amplify:.*'], 'ResourceNotFoundException' => ['type' => 'structure', 'required' => ['code', 'message'], 'members' => ['code' => ['shape' => 'Code'], 'message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 404], 'exception' => \true], 'Screenshots' => ['type' => 'map', 'key' => ['shape' => 'ThumbnailName'], 'value' => ['shape' => 'ThumbnailUrl']], 'ServiceRoleArn' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'Source' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'SourceUrl' => ['type' => 'string', 'max' => 1000], 'StackName' => ['type' => 'string', 'max' => 255, 'min' => 1], 'Stage' => ['type' => 'string', 'enum' => ['PRODUCTION', 'BETA', 'DEVELOPMENT', 'EXPERIMENTAL', 'PULL_REQUEST']], 'StartDeploymentRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId'], 'sourceUrl' => ['shape' => 'SourceUrl']]], 'StartDeploymentResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'StartJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobType'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId'], 'jobType' => ['shape' => 'JobType'], 'jobReason' => ['shape' => 'JobReason'], 'commitId' => ['shape' => 'CommitId'], 'commitMessage' => ['shape' => 'CommitMessage'], 'commitTime' => ['shape' => 'CommitTime']]], 'StartJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'StartTime' => ['type' => 'timestamp'], 'Status' => ['type' => 'string', 'max' => 7, 'min' => 3], 'StatusReason' => ['type' => 'string', 'max' => 1000], 'Step' => ['type' => 'structure', 'required' => ['stepName', 'startTime', 'status', 'endTime'], 'members' => ['stepName' => ['shape' => 'StepName'], 'startTime' => ['shape' => 'StartTime'], 'status' => ['shape' => 'JobStatus'], 'endTime' => ['shape' => 'EndTime'], 'logUrl' => ['shape' => 'LogUrl'], 'artifactsUrl' => ['shape' => 'ArtifactsUrl'], 'testArtifactsUrl' => ['shape' => 'TestArtifactsUrl'], 'testConfigUrl' => ['shape' => 'TestConfigUrl'], 'screenshots' => ['shape' => 'Screenshots'], 'statusReason' => ['shape' => 'StatusReason'], 'context' => ['shape' => 'Context']]], 'StepName' => ['type' => 'string', 'max' => 255], 'Steps' => ['type' => 'list', 'member' => ['shape' => 'Step']], 'StopJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'StopJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'SubDomain' => ['type' => 'structure', 'required' => ['subDomainSetting', 'verified', 'dnsRecord'], 'members' => ['subDomainSetting' => ['shape' => 'SubDomainSetting'], 'verified' => ['shape' => 'Verified'], 'dnsRecord' => ['shape' => 'DNSRecord']]], 'SubDomainSetting' => ['type' => 'structure', 'required' => ['prefix', 'branchName'], 'members' => ['prefix' => ['shape' => 'DomainPrefix'], 'branchName' => ['shape' => 'BranchName']]], 'SubDomainSettings' => ['type' => 'list', 'member' => ['shape' => 'SubDomainSetting'], 'max' => 255], 'SubDomains' => ['type' => 'list', 'member' => ['shape' => 'SubDomain'], 'max' => 255], 'TTL' => ['type' => 'string'], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '^(?!aws:)[a-zA-Z+-=._:/]+$'], 'TagKeyList' => ['type' => 'list', 'member' => ['shape' => 'TagKey'], 'max' => 50, 'min' => 1], 'TagMap' => ['type' => 'map', 'key' => ['shape' => 'TagKey'], 'value' => ['shape' => 'TagValue'], 'max' => 50, 'min' => 1], 'TagResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn', 'tags'], 'members' => ['resourceArn' => ['shape' => 'ResourceArn', 'location' => 'uri', 'locationName' => 'resourceArn'], 'tags' => ['shape' => 'TagMap']]], 'TagResourceResponse' => ['type' => 'structure', 'members' => []], 'TagValue' => ['type' => 'string', 'max' => 256], 'Target' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'TestArtifactsUrl' => ['type' => 'string', 'max' => 1000], 'TestConfigUrl' => ['type' => 'string', 'max' => 1000], 'ThumbnailName' => ['type' => 'string', 'max' => 256], 'ThumbnailUrl' => ['type' => 'string', 'max' => 2000, 'min' => 1], 'TotalNumberOfJobs' => ['type' => 'string', 'max' => 1000], 'UnauthorizedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 401], 'exception' => \true], 'UntagResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn', 'tagKeys'], 'members' => ['resourceArn' => ['shape' => 'ResourceArn', 'location' => 'uri', 'locationName' => 'resourceArn'], 'tagKeys' => ['shape' => 'TagKeyList', 'location' => 'querystring', 'locationName' => 'tagKeys']]], 'UntagResourceResponse' => ['type' => 'structure', 'members' => []], 'UpdateAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'name' => ['shape' => 'Name'], 'description' => ['shape' => 'Description'], 'platform' => ['shape' => 'Platform'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableBranchAutoBuild' => ['shape' => 'EnableAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'buildSpec' => ['shape' => 'BuildSpec'], 'enableAutoBranchCreation' => ['shape' => 'EnableAutoBranchCreation'], 'autoBranchCreationPatterns' => ['shape' => 'AutoBranchCreationPatterns'], 'autoBranchCreationConfig' => ['shape' => 'AutoBranchCreationConfig'], 'repository' => ['shape' => 'Repository'], 'oauthToken' => ['shape' => 'OauthToken'], 'accessToken' => ['shape' => 'AccessToken']]], 'UpdateAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'UpdateBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'description' => ['shape' => 'Description'], 'framework' => ['shape' => 'Framework'], 'stage' => ['shape' => 'Stage'], 'enableNotification' => ['shape' => 'EnableNotification'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'enableBasicA