From 357c07bbbc20fa1340993c6ad4af44f025176f39 Mon Sep 17 00:00:00 2001
From: "Ian M. Jones"
"+a.data.message+"
").show(),a.success&&as3cf.reloadUpdated()}.bind(this)).always(function(){this.$spinner.removeClass("is-active")}.bind(this))},a(document).ready(function(){j(),window.onhashchange=function(a){"function"==typeof history.replaceState&&"#"===location.href.slice(-1)&&history.replaceState({},"",location.href.slice(0,-1)),j()};var m=a(".as3cf-main .nav-tab-wrapper");a(".as3cf-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(m),p.length&&p.each(function(a,b){l[b.id]=c(b.id)}),a(window).on("beforeunload.as3cf-settings",function(){if(!a.isEmptyObject(l)){var b=k.attr("id");return c(b)!==l[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){g()}),h(),a("#as3cf-serve-from-s3,#as3cf-remove-local-file").on("change",function(a){h()}),i(),a("#as3cf-remove-local-file").on("change",function(a){i()}),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("#"+k.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"),o.on("click",".bucket-action-manual",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual").show().siblings().hide()}),o.on("click",".bucket-action-browse",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").show().siblings().hide(),as3cf.buckets.loadList(n),n=!1}),o.on("click",".bucket-action-create",function(c){c.preventDefault(),a(".as3cf-bucket-name").val(""),a(".as3cf-invalid-bucket-name").html(""),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create").show().siblings().hide()}),o.on("click",".bucket-action-cancel",function(a){a.preventDefault(),as3cf.buckets.resetModal()}),o.on("click",".bucket-action-save",function(a){a.preventDefault(),as3cf.buckets.saveManual()}),o.on("click",'.as3cf-create-bucket-form button[type="submit"]',function(a){a.preventDefault(),as3cf.buckets.create()}),o.on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),o.on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.saveSelected(a(this))}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),o.on("as3cf-modal-open",function(c,d){if(".as3cf-bucket-container."+b.prefix===d){as3cf.buckets.resetModal();var e=a(".as3cf-bucket-manual h3").data("modal-title");a(".as3cf-bucket-manual h3").text(e),as3cf.buckets.disabledButtons()}}),as3cf.buckets.disabledButtons(),o.on("input keyup",".as3cf-create-bucket-form .as3cf-bucket-name",function(c){var d=a(this).val(),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form");as3cf.buckets.isValidName(d)?e.find("button[type=submit]").prop("disabled",!1):e.find("button[type=submit]").prop("disabled",!0),as3cf.buckets.updateNameNotice(d)}),o.on("input keyup",".as3cf-manual-save-bucket-form .as3cf-bucket-name",function(c){var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");d.find(".as3cf-bucket-name").val().length"+a.data.message+"
").show(),a.success&&as3cf.reloadUpdated()}.bind(this)).always(function(){this.$spinner.removeClass("is-active")}.bind(this))},a(document).ready(function(){j(),window.onhashchange=function(a){"function"==typeof history.replaceState&&"#"===location.href.slice(-1)&&history.replaceState({},"",location.href.slice(0,-1)),j()};var m=a(".as3cf-main .nav-tab-wrapper");a(".as3cf-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(m),p.length&&p.each(function(a,b){l[b.id]=c(b.id)}),a(window).on("beforeunload.as3cf-settings",function(){if(!a.isEmptyObject(l)){var b=k.attr("id");return c(b)!==l[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){g()}),h(),a("#as3cf-serve-from-s3,#as3cf-remove-local-file").on("change",function(a){h()}),i(),a("#as3cf-remove-local-file").on("change",function(a){i()}),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("#"+k.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"),o.on("click",".bucket-action-manual",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual").show().siblings().hide()}),o.on("click",".bucket-action-browse",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").show().siblings().hide(),as3cf.buckets.loadList(n),n=!1}),o.on("click",".bucket-action-create",function(c){c.preventDefault(),a(".as3cf-bucket-name").val(""),a(".as3cf-invalid-bucket-name").html(""),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create").show().siblings().hide()}),o.on("click",".bucket-action-cancel",function(a){a.preventDefault(),as3cf.buckets.resetModal()}),o.on("click",".bucket-action-save",function(a){a.preventDefault(),as3cf.buckets.saveManual()}),o.on("click",'.as3cf-create-bucket-form button[type="submit"]',function(a){a.preventDefault(),as3cf.buckets.create()}),o.on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),o.on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.saveSelected(a(this))}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),o.on("as3cf-modal-open",function(c,d){if(".as3cf-bucket-container."+b.prefix===d){as3cf.buckets.resetModal();var e=a(".as3cf-bucket-manual h3").data("modal-title");a(".as3cf-bucket-manual h3").text(e),as3cf.buckets.disabledButtons()}}),as3cf.buckets.disabledButtons(),o.on("input keyup",".as3cf-create-bucket-form .as3cf-bucket-name",function(c){var d=a(this).val(),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form");as3cf.buckets.isValidName(d)?e.find("button[type=submit]").prop("disabled",!1):e.find("button[type=submit]").prop("disabled",!0),as3cf.buckets.updateNameNotice(d)}),o.on("input keyup",".as3cf-manual-save-bucket-form .as3cf-bucket-name",function(c){var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");d.find(".as3cf-bucket-name").val().length
- * var_export($response->getLinks());
- * array(
- * array(
- * 'url' => 'http:/.../front.jpeg',
- * 'rel' => 'back',
- * 'type' => 'image/jpeg',
- * )
- * )
- *
- *
- * @return array
- */
- public function getLinks()
- {
- $links = $this->parseParams();
- foreach ($links as &$link) {
- $key = key($link);
- unset($link[$key]);
- $link['url'] = trim($key, '<> ');
- }
- return $links;
- }
-}
diff --git a/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/MessageInterface.php b/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/MessageInterface.php
deleted file mode 100644
index f253e6a4..00000000
--- a/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/MessageInterface.php
+++ /dev/null
@@ -1,92 +0,0 @@
-fieldName = $fieldName;
- $this->setFilename($filename);
- $this->postname = $postname ? $postname : basename($filename);
- $this->contentType = $contentType ?: $this->guessContentType();
- }
- public function setFieldName($name)
- {
- $this->fieldName = $name;
- return $this;
- }
- public function getFieldName()
- {
- return $this->fieldName;
- }
- public function setFilename($filename)
- {
- // Remove leading @ symbol
- if (strpos($filename, '@') === 0) {
- $filename = substr($filename, 1);
- }
- if (!is_readable($filename)) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\InvalidArgumentException("Unable to open {$filename} for reading");
- }
- $this->filename = $filename;
- return $this;
- }
- public function setPostname($postname)
- {
- $this->postname = $postname;
- return $this;
- }
- public function getFilename()
- {
- return $this->filename;
- }
- public function getPostname()
- {
- return $this->postname;
- }
- public function setContentType($type)
- {
- $this->contentType = $type;
- return $this;
- }
- public function getContentType()
- {
- return $this->contentType;
- }
- public function getCurlValue()
- {
- // PHP 5.5 introduced a CurlFile object that deprecates the old @filename syntax
- // See: https://wiki.php.net/rfc/curl-file-upload
- if (function_exists('curl_file_create')) {
- return curl_file_create($this->filename, $this->contentType, $this->postname);
- }
- // Use the old style if using an older version of PHP
- $value = "@{$this->filename};filename=" . $this->postname;
- if ($this->contentType) {
- $value .= ';type=' . $this->contentType;
- }
- return $value;
- }
- /**
- * @deprecated
- * @codeCoverageIgnore
- */
- public function getCurlString()
- {
- \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Version::warn(__METHOD__ . ' is deprecated. Use getCurlValue()');
- return $this->getCurlValue();
- }
- /**
- * Determine the Content-Type of the file
- */
- protected function guessContentType()
- {
- return \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Mimetypes::getInstance()->fromFilename($this->filename) ?: 'application/octet-stream';
- }
-}
diff --git a/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/PostFileInterface.php b/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/PostFileInterface.php
deleted file mode 100644
index f054929e..00000000
--- a/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/PostFileInterface.php
+++ /dev/null
@@ -1,74 +0,0 @@
-method = strtoupper($method);
- $this->curlOptions = new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Collection();
- $this->setUrl($url);
- if ($headers) {
- // Special handling for multi-value headers
- foreach ($headers as $key => $value) {
- // Deal with collisions with Host and Authorization
- if ($key == 'host' || $key == 'Host') {
- $this->setHeader($key, $value);
- } elseif ($value instanceof HeaderInterface) {
- $this->addHeader($key, $value);
- } else {
- foreach ((array) $value as $v) {
- $this->addHeader($key, $v);
- }
- }
- }
- }
- $this->setState(self::STATE_NEW);
- }
- public function __clone()
- {
- if ($this->eventDispatcher) {
- $this->eventDispatcher = clone $this->eventDispatcher;
- }
- $this->curlOptions = clone $this->curlOptions;
- $this->params = clone $this->params;
- $this->url = clone $this->url;
- $this->response = $this->responseBody = null;
- $this->headers = clone $this->headers;
- $this->setState(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface::STATE_NEW);
- $this->dispatch('request.clone', array('request' => $this));
- }
- /**
- * Get the HTTP request as a string
- *
- * @return string
- */
- public function __toString()
- {
- return $this->getRawHeaders() . "\r\n\r\n";
- }
- /**
- * Default method that will throw exceptions if an unsuccessful response is received.
- *
- * @param Event $event Received
- * @throws BadResponseException if the response is not successful
- */
- public static function onRequestError(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Event $event)
- {
- $e = \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Exception\BadResponseException::factory($event['request'], $event['response']);
- $event['request']->setState(self::STATE_ERROR, array('exception' => $e) + $event->toArray());
- throw $e;
- }
- public function setClient(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\ClientInterface $client)
- {
- $this->client = $client;
- return $this;
- }
- public function getClient()
- {
- return $this->client;
- }
- public function getRawHeaders()
- {
- $protocolVersion = $this->protocolVersion ?: '1.1';
- return trim($this->method . ' ' . $this->getResource()) . ' ' . strtoupper(str_replace('https', 'http', $this->url->getScheme())) . '/' . $protocolVersion . "\r\n" . implode("\r\n", $this->getHeaderLines());
- }
- public function setUrl($url)
- {
- if ($url instanceof Url) {
- $this->url = $url;
- } else {
- $this->url = \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Url::factory($url);
- }
- // Update the port and host header
- $this->setPort($this->url->getPort());
- if ($this->url->getUsername() || $this->url->getPassword()) {
- $this->setAuth($this->url->getUsername(), $this->url->getPassword());
- // Remove the auth info from the URL
- $this->url->setUsername(null);
- $this->url->setPassword(null);
- }
- return $this;
- }
- public function send()
- {
- if (!$this->client) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\RuntimeException('A client must be set on the request');
- }
- return $this->client->send($this);
- }
- public function getResponse()
- {
- return $this->response;
- }
- public function getQuery($asString = false)
- {
- return $asString ? (string) $this->url->getQuery() : $this->url->getQuery();
- }
- public function getMethod()
- {
- return $this->method;
- }
- public function getScheme()
- {
- return $this->url->getScheme();
- }
- public function setScheme($scheme)
- {
- $this->url->setScheme($scheme);
- return $this;
- }
- public function getHost()
- {
- return $this->url->getHost();
- }
- public function setHost($host)
- {
- $this->url->setHost($host);
- $this->setPort($this->url->getPort());
- return $this;
- }
- public function getProtocolVersion()
- {
- return $this->protocolVersion;
- }
- public function setProtocolVersion($protocol)
- {
- $this->protocolVersion = $protocol;
- return $this;
- }
- public function getPath()
- {
- return '/' . ltrim($this->url->getPath(), '/');
- }
- public function setPath($path)
- {
- $this->url->setPath($path);
- return $this;
- }
- public function getPort()
- {
- return $this->url->getPort();
- }
- public function setPort($port)
- {
- $this->url->setPort($port);
- // Include the port in the Host header if it is not the default port for the scheme of the URL
- $scheme = $this->url->getScheme();
- if ($port && ($scheme == 'http' && $port != 80 || $scheme == 'https' && $port != 443)) {
- $this->headers['host'] = $this->headerFactory->createHeader('Host', $this->url->getHost() . ':' . $port);
- } else {
- $this->headers['host'] = $this->headerFactory->createHeader('Host', $this->url->getHost());
- }
- return $this;
- }
- public function getUsername()
- {
- return $this->username;
- }
- public function getPassword()
- {
- return $this->password;
- }
- public function setAuth($user, $password = '', $scheme = CURLAUTH_BASIC)
- {
- static $authMap = array('basic' => CURLAUTH_BASIC, 'digest' => CURLAUTH_DIGEST, 'ntlm' => CURLAUTH_NTLM, 'any' => CURLAUTH_ANY);
- // If we got false or null, disable authentication
- if (!$user) {
- $this->password = $this->username = null;
- $this->removeHeader('Authorization');
- $this->getCurlOptions()->remove(CURLOPT_HTTPAUTH);
- return $this;
- }
- if (!is_numeric($scheme)) {
- $scheme = strtolower($scheme);
- if (!isset($authMap[$scheme])) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\InvalidArgumentException($scheme . ' is not a valid authentication type');
- }
- $scheme = $authMap[$scheme];
- }
- $this->username = $user;
- $this->password = $password;
- // Bypass CURL when using basic auth to promote connection reuse
- if ($scheme == CURLAUTH_BASIC) {
- $this->getCurlOptions()->remove(CURLOPT_HTTPAUTH);
- $this->setHeader('Authorization', 'Basic ' . base64_encode($this->username . ':' . $this->password));
- } else {
- $this->getCurlOptions()->set(CURLOPT_HTTPAUTH, $scheme)->set(CURLOPT_USERPWD, $this->username . ':' . $this->password);
- }
- return $this;
- }
- public function getResource()
- {
- $resource = $this->getPath();
- if ($query = (string) $this->url->getQuery()) {
- $resource .= '?' . $query;
- }
- return $resource;
- }
- public function getUrl($asObject = false)
- {
- return $asObject ? clone $this->url : (string) $this->url;
- }
- public function getState()
- {
- return $this->state;
- }
- public function setState($state, array $context = array())
- {
- $oldState = $this->state;
- $this->state = $state;
- switch ($state) {
- case self::STATE_NEW:
- $this->response = null;
- break;
- case self::STATE_TRANSFER:
- if ($oldState !== $state) {
- // Fix Content-Length and Transfer-Encoding collisions
- if ($this->hasHeader('Transfer-Encoding') && $this->hasHeader('Content-Length')) {
- $this->removeHeader('Transfer-Encoding');
- }
- $this->dispatch('request.before_send', array('request' => $this));
- }
- break;
- case self::STATE_COMPLETE:
- if ($oldState !== $state) {
- $this->processResponse($context);
- $this->responseBody = null;
- }
- break;
- case self::STATE_ERROR:
- if (isset($context['exception'])) {
- $this->dispatch('request.exception', array('request' => $this, 'response' => isset($context['response']) ? $context['response'] : $this->response, 'exception' => isset($context['exception']) ? $context['exception'] : null));
- }
- }
- return $this->state;
- }
- public function getCurlOptions()
- {
- return $this->curlOptions;
- }
- public function startResponse(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\Response $response)
- {
- $this->state = self::STATE_TRANSFER;
- $response->setEffectiveUrl((string) $this->getUrl());
- $this->response = $response;
- return $this;
- }
- public function setResponse(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\Response $response, $queued = false)
- {
- $response->setEffectiveUrl((string) $this->url);
- if ($queued) {
- $ed = $this->getEventDispatcher();
- $ed->addListener('request.before_send', $f = function ($e) use($response, &$f, $ed) {
- $e['request']->setResponse($response);
- $ed->removeListener('request.before_send', $f);
- }, -9999);
- } else {
- $this->response = $response;
- // If a specific response body is specified, then use it instead of the response's body
- if ($this->responseBody && !$this->responseBody->getCustomData('default') && !$response->isRedirect()) {
- $this->getResponseBody()->write((string) $this->response->getBody());
- } else {
- $this->responseBody = $this->response->getBody();
- }
- $this->setState(self::STATE_COMPLETE);
- }
- return $this;
- }
- public function setResponseBody($body)
- {
- // Attempt to open a file for writing if a string was passed
- if (is_string($body)) {
- // @codeCoverageIgnoreStart
- if (!($body = fopen($body, 'w+'))) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\InvalidArgumentException('Could not open ' . $body . ' for writing');
- }
- // @codeCoverageIgnoreEnd
- }
- $this->responseBody = \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\EntityBody::factory($body);
- return $this;
- }
- public function getResponseBody()
- {
- if ($this->responseBody === null) {
- $this->responseBody = \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\EntityBody::factory()->setCustomData('default', true);
- }
- return $this->responseBody;
- }
- /**
- * Determine if the response body is repeatable (readable + seekable)
- *
- * @return bool
- * @deprecated Use getResponseBody()->isSeekable()
- * @codeCoverageIgnore
- */
- public function isResponseBodyRepeatable()
- {
- \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Version::warn(__METHOD__ . ' is deprecated. Use $request->getResponseBody()->isRepeatable()');
- return !$this->responseBody ? true : $this->responseBody->isRepeatable();
- }
- public function getCookies()
- {
- if ($cookie = $this->getHeader('Cookie')) {
- $data = \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Parser\ParserRegistry::getInstance()->getParser('cookie')->parseCookie($cookie);
- return $data['cookies'];
- }
- return array();
- }
- public function getCookie($name)
- {
- $cookies = $this->getCookies();
- return isset($cookies[$name]) ? $cookies[$name] : null;
- }
- public function addCookie($name, $value)
- {
- if (!$this->hasHeader('Cookie')) {
- $this->setHeader('Cookie', "{$name}={$value}");
- } else {
- $this->getHeader('Cookie')->add("{$name}={$value}");
- }
- // Always use semicolons to separate multiple cookie headers
- $this->getHeader('Cookie')->setGlue(';');
- return $this;
- }
- public function removeCookie($name)
- {
- if ($cookie = $this->getHeader('Cookie')) {
- foreach ($cookie as $cookieValue) {
- if (strpos($cookieValue, $name . '=') === 0) {
- $cookie->removeValue($cookieValue);
- }
- }
- }
- return $this;
- }
- public function setEventDispatcher(\DeliciousBrains\WP_Offload_S3\Aws2\Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher)
- {
- $this->eventDispatcher = $eventDispatcher;
- $this->eventDispatcher->addListener('request.error', array(__CLASS__, 'onRequestError'), -255);
- return $this;
- }
- public function getEventDispatcher()
- {
- if (!$this->eventDispatcher) {
- $this->setEventDispatcher(new \DeliciousBrains\WP_Offload_S3\Aws2\Symfony\Component\EventDispatcher\EventDispatcher());
- }
- return $this->eventDispatcher;
- }
- public function dispatch($eventName, array $context = array())
- {
- $context['request'] = $this;
- return $this->getEventDispatcher()->dispatch($eventName, new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Event($context));
- }
- public function addSubscriber(\DeliciousBrains\WP_Offload_S3\Aws2\Symfony\Component\EventDispatcher\EventSubscriberInterface $subscriber)
- {
- $this->getEventDispatcher()->addSubscriber($subscriber);
- return $this;
- }
- /**
- * Get an array containing the request and response for event notifications
- *
- * @return array
- */
- protected function getEventArray()
- {
- return array('request' => $this, 'response' => $this->response);
- }
- /**
- * Process a received response
- *
- * @param array $context Contextual information
- * @throws RequestException|BadResponseException on unsuccessful responses
- */
- protected function processResponse(array $context = array())
- {
- if (!$this->response) {
- // If no response, then processResponse shouldn't have been called
- $e = new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Exception\RequestException('Error completing request');
- $e->setRequest($this);
- throw $e;
- }
- $this->state = self::STATE_COMPLETE;
- // A request was sent, but we don't know if we'll send more or if the final response will be successful
- $this->dispatch('request.sent', $this->getEventArray() + $context);
- // Some response processors will remove the response or reset the state (example: ExponentialBackoffPlugin)
- if ($this->state == \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface::STATE_COMPLETE) {
- // The request completed, so the HTTP transaction is complete
- $this->dispatch('request.complete', $this->getEventArray());
- // If the response is bad, allow listeners to modify it or throw exceptions. You can change the response by
- // modifying the Event object in your listeners or calling setResponse() on the request
- if ($this->response->isError()) {
- $event = new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Event($this->getEventArray());
- $this->getEventDispatcher()->dispatch('request.error', $event);
- // Allow events of request.error to quietly change the response
- if ($event['response'] !== $this->response) {
- $this->response = $event['response'];
- }
- }
- // If a successful response was received, dispatch an event
- if ($this->response->isSuccessful()) {
- $this->dispatch('request.success', $this->getEventArray());
- }
- }
- }
- /**
- * @deprecated Use Guzzle\Plugin\Cache\DefaultCanCacheStrategy
- * @codeCoverageIgnore
- */
- public function canCache()
- {
- \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Version::warn(__METHOD__ . ' is deprecated. Use Guzzle\\Plugin\\Cache\\DefaultCanCacheStrategy.');
- if (class_exists('DeliciousBrains\\WP_Offload_S3\\Aws2\\Guzzle\\Plugin\\Cache\\DefaultCanCacheStrategy')) {
- $canCache = new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Plugin\Cache\DefaultCanCacheStrategy();
- return $canCache->canCacheRequest($this);
- } else {
- return false;
- }
- }
- /**
- * @deprecated Use the history plugin (not emitting a warning as this is built-into the RedirectPlugin for now)
- * @codeCoverageIgnore
- */
- public function setIsRedirect($isRedirect)
- {
- $this->isRedirect = $isRedirect;
- return $this;
- }
- /**
- * @deprecated Use the history plugin
- * @codeCoverageIgnore
- */
- public function isRedirect()
- {
- \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Version::warn(__METHOD__ . ' is deprecated. Use the HistoryPlugin to track this.');
- return $this->isRedirect;
- }
-}
diff --git a/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/RequestFactory.php b/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/RequestFactory.php
deleted file mode 100644
index e2ba5d44..00000000
--- a/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/RequestFactory.php
+++ /dev/null
@@ -1,304 +0,0 @@
-methods = array_flip(get_class_methods(__CLASS__));
- }
- public function fromMessage($message)
- {
- $parsed = \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Parser\ParserRegistry::getInstance()->getParser('message')->parseRequest($message);
- if (!$parsed) {
- return false;
- }
- $request = $this->fromParts($parsed['method'], $parsed['request_url'], $parsed['headers'], $parsed['body'], $parsed['protocol'], $parsed['version']);
- // EntityEnclosingRequest adds an "Expect: 100-Continue" header when using a raw request body for PUT or POST
- // requests. This factory method should accurately reflect the message, so here we are removing the Expect
- // header if one was not supplied in the message.
- if (!isset($parsed['headers']['Expect']) && !isset($parsed['headers']['expect'])) {
- $request->removeHeader('Expect');
- }
- return $request;
- }
- public function fromParts($method, array $urlParts, $headers = null, $body = null, $protocol = 'HTTP', $protocolVersion = '1.1')
- {
- return $this->create($method, \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Url::buildUrl($urlParts), $headers, $body)->setProtocolVersion($protocolVersion);
- }
- public function create($method, $url, $headers = null, $body = null, array $options = array())
- {
- $method = strtoupper($method);
- if ($method == 'GET' || $method == 'HEAD' || $method == 'TRACE') {
- // Handle non-entity-enclosing request methods
- $request = new $this->requestClass($method, $url, $headers);
- if ($body) {
- // The body is where the response body will be stored
- $type = gettype($body);
- if ($type == 'string' || $type == 'resource' || $type == 'object') {
- $request->setResponseBody($body);
- }
- }
- } else {
- // Create an entity enclosing request by default
- $request = new $this->entityEnclosingRequestClass($method, $url, $headers);
- if ($body || $body === '0') {
- // Add POST fields and files to an entity enclosing request if an array is used
- if (is_array($body) || $body instanceof Collection) {
- // Normalize PHP style cURL uploads with a leading '@' symbol
- foreach ($body as $key => $value) {
- if (is_string($value) && substr($value, 0, 1) == '@') {
- $request->addPostFile($key, $value);
- unset($body[$key]);
- }
- }
- // Add the fields if they are still present and not all files
- $request->addPostFields($body);
- } else {
- // Add a raw entity body body to the request
- $request->setBody($body, (string) $request->getHeader('Content-Type'));
- if ((string) $request->getHeader('Transfer-Encoding') == 'chunked') {
- $request->removeHeader('Content-Length');
- }
- }
- }
- }
- if ($options) {
- $this->applyOptions($request, $options);
- }
- return $request;
- }
- /**
- * Clone a request while changing the method. Emulates the behavior of
- * {@see Guzzle\Http\Message\Request::clone}, but can change the HTTP method.
- *
- * @param RequestInterface $request Request to clone
- * @param string $method Method to set
- *
- * @return RequestInterface
- */
- public function cloneRequestWithMethod(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $method)
- {
- // Create the request with the same client if possible
- if ($request->getClient()) {
- $cloned = $request->getClient()->createRequest($method, $request->getUrl(), $request->getHeaders());
- } else {
- $cloned = $this->create($method, $request->getUrl(), $request->getHeaders());
- }
- $cloned->getCurlOptions()->replace($request->getCurlOptions()->toArray());
- $cloned->setEventDispatcher(clone $request->getEventDispatcher());
- // Ensure that that the Content-Length header is not copied if changing to GET or HEAD
- if (!$cloned instanceof EntityEnclosingRequestInterface) {
- $cloned->removeHeader('Content-Length');
- } elseif ($request instanceof EntityEnclosingRequestInterface) {
- $cloned->setBody($request->getBody());
- }
- $cloned->getParams()->replace($request->getParams()->toArray());
- $cloned->dispatch('request.clone', array('request' => $cloned));
- return $cloned;
- }
- public function applyOptions(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, array $options = array(), $flags = self::OPTIONS_NONE)
- {
- // Iterate over each key value pair and attempt to apply a config using function visitors
- foreach ($options as $key => $value) {
- $method = "visit_{$key}";
- if (isset($this->methods[$method])) {
- $this->{$method}($request, $value, $flags);
- }
- }
- }
- protected function visit_headers(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if (!is_array($value)) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\InvalidArgumentException('headers value must be an array');
- }
- if ($flags & self::OPTIONS_AS_DEFAULTS) {
- // Merge headers in but do not overwrite existing values
- foreach ($value as $key => $header) {
- if (!$request->hasHeader($key)) {
- $request->setHeader($key, $header);
- }
- }
- } else {
- $request->addHeaders($value);
- }
- }
- protected function visit_body(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if ($request instanceof EntityEnclosingRequestInterface) {
- $request->setBody($value);
- } else {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\InvalidArgumentException('Attempting to set a body on a non-entity-enclosing request');
- }
- }
- protected function visit_allow_redirects(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if ($value === false) {
- $request->getParams()->set(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\RedirectPlugin::DISABLE, true);
- }
- }
- protected function visit_auth(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if (!is_array($value)) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\InvalidArgumentException('auth value must be an array');
- }
- $request->setAuth($value[0], isset($value[1]) ? $value[1] : null, isset($value[2]) ? $value[2] : 'basic');
- }
- protected function visit_query(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if (!is_array($value)) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\InvalidArgumentException('query value must be an array');
- }
- if ($flags & self::OPTIONS_AS_DEFAULTS) {
- // Merge query string values in but do not overwrite existing values
- $query = $request->getQuery();
- $query->overwriteWith(array_diff_key($value, $query->toArray()));
- } else {
- $request->getQuery()->overwriteWith($value);
- }
- }
- protected function visit_cookies(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if (!is_array($value)) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\InvalidArgumentException('cookies value must be an array');
- }
- foreach ($value as $name => $v) {
- $request->addCookie($name, $v);
- }
- }
- protected function visit_events(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if (!is_array($value)) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\InvalidArgumentException('events value must be an array');
- }
- foreach ($value as $name => $method) {
- if (is_array($method)) {
- $request->getEventDispatcher()->addListener($name, $method[0], $method[1]);
- } else {
- $request->getEventDispatcher()->addListener($name, $method);
- }
- }
- }
- protected function visit_plugins(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if (!is_array($value)) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\InvalidArgumentException('plugins value must be an array');
- }
- foreach ($value as $plugin) {
- $request->addSubscriber($plugin);
- }
- }
- protected function visit_exceptions(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if ($value === false || $value === 0) {
- $dispatcher = $request->getEventDispatcher();
- foreach ($dispatcher->getListeners('request.error') as $listener) {
- if (is_array($listener) && $listener[0] == 'DeliciousBrains\\WP_Offload_S3\\Aws2\\Guzzle\\Http\\Message\\Request' && ($listener[1] = 'onRequestError')) {
- $dispatcher->removeListener('request.error', $listener);
- break;
- }
- }
- }
- }
- protected function visit_save_to(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- $request->setResponseBody($value);
- }
- protected function visit_params(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if (!is_array($value)) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\InvalidArgumentException('params value must be an array');
- }
- $request->getParams()->overwriteWith($value);
- }
- protected function visit_timeout(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if (defined('CURLOPT_TIMEOUT_MS')) {
- $request->getCurlOptions()->set(CURLOPT_TIMEOUT_MS, $value * 1000);
- } else {
- $request->getCurlOptions()->set(CURLOPT_TIMEOUT, $value);
- }
- }
- protected function visit_connect_timeout(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if (defined('CURLOPT_CONNECTTIMEOUT_MS')) {
- $request->getCurlOptions()->set(CURLOPT_CONNECTTIMEOUT_MS, $value * 1000);
- } else {
- $request->getCurlOptions()->set(CURLOPT_CONNECTTIMEOUT, $value);
- }
- }
- protected function visit_debug(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if ($value) {
- $request->getCurlOptions()->set(CURLOPT_VERBOSE, true);
- }
- }
- protected function visit_verify(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- $curl = $request->getCurlOptions();
- if ($value === true || is_string($value)) {
- $curl[CURLOPT_SSL_VERIFYHOST] = 2;
- $curl[CURLOPT_SSL_VERIFYPEER] = true;
- if ($value !== true) {
- $curl[CURLOPT_CAINFO] = $value;
- }
- } elseif ($value === false) {
- unset($curl[CURLOPT_CAINFO]);
- $curl[CURLOPT_SSL_VERIFYHOST] = 0;
- $curl[CURLOPT_SSL_VERIFYPEER] = false;
- }
- }
- protected function visit_proxy(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- $request->getCurlOptions()->set(CURLOPT_PROXY, $value, $flags);
- }
- protected function visit_cert(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if (is_array($value)) {
- $request->getCurlOptions()->set(CURLOPT_SSLCERT, $value[0]);
- $request->getCurlOptions()->set(CURLOPT_SSLCERTPASSWD, $value[1]);
- } else {
- $request->getCurlOptions()->set(CURLOPT_SSLCERT, $value);
- }
- }
- protected function visit_ssl_key(\DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Message\RequestInterface $request, $value, $flags)
- {
- if (is_array($value)) {
- $request->getCurlOptions()->set(CURLOPT_SSLKEY, $value[0]);
- $request->getCurlOptions()->set(CURLOPT_SSLKEYPASSWD, $value[1]);
- } else {
- $request->getCurlOptions()->set(CURLOPT_SSLKEY, $value);
- }
- }
-}
diff --git a/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/RequestFactoryInterface.php b/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/RequestFactoryInterface.php
deleted file mode 100644
index ece01cbc..00000000
--- a/vendor/Aws2/guzzle/guzzle/src/Guzzle/Http/Message/RequestFactoryInterface.php
+++ /dev/null
@@ -1,93 +0,0 @@
- 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', 208 => 'Already Reported', 226 => 'IM Used', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Reserved for WebDAV advanced collections expired proposal', 426 => 'Upgrade required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates (Experimental)', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 510 => 'Not Extended', 511 => 'Network Authentication Required');
- /** @var EntityBodyInterface The response body */
- protected $body;
- /** @var string The reason phrase of the response (human readable code) */
- protected $reasonPhrase;
- /** @var string The status code of the response */
- protected $statusCode;
- /** @var array Information about the request */
- protected $info = array();
- /** @var string The effective URL that returned this response */
- protected $effectiveUrl;
- /** @var array Cacheable response codes (see RFC 2616:13.4) */
- protected static $cacheResponseCodes = array(200, 203, 206, 300, 301, 410);
- /**
- * Create a new Response based on a raw response message
- *
- * @param string $message Response message
- *
- * @return self|bool Returns false on error
- */
- public static function fromMessage($message)
- {
- $data = \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Parser\ParserRegistry::getInstance()->getParser('message')->parseResponse($message);
- if (!$data) {
- return false;
- }
- $response = new static($data['code'], $data['headers'], $data['body']);
- $response->setProtocol($data['protocol'], $data['version'])->setStatus($data['code'], $data['reason_phrase']);
- // Set the appropriate Content-Length if the one set is inaccurate (e.g. setting to X)
- $contentLength = (string) $response->getHeader('Content-Length');
- $actualLength = strlen($data['body']);
- if (strlen($data['body']) > 0 && $contentLength != $actualLength) {
- $response->setHeader('Content-Length', $actualLength);
- }
- return $response;
- }
- /**
- * Construct the response
- *
- * @param string $statusCode The response status code (e.g. 200, 404, etc)
- * @param ToArrayInterface|array $headers The response headers
- * @param string|resource|EntityBodyInterface $body The body of the response
- *
- * @throws BadResponseException if an invalid response code is given
- */
- public function __construct($statusCode, $headers = null, $body = null)
- {
- parent::__construct();
- $this->setStatus($statusCode);
- $this->body = \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\EntityBody::factory($body !== null ? $body : '');
- if ($headers) {
- if (is_array($headers)) {
- $this->setHeaders($headers);
- } elseif ($headers instanceof ToArrayInterface) {
- $this->setHeaders($headers->toArray());
- } else {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\Exception\BadResponseException('Invalid headers argument received');
- }
- }
- }
- /**
- * @return string
- */
- public function __toString()
- {
- return $this->getMessage();
- }
- public function serialize()
- {
- return json_encode(array('status' => $this->statusCode, 'body' => (string) $this->body, 'headers' => $this->headers->toArray()));
- }
- public function unserialize($serialize)
- {
- $data = json_decode($serialize, true);
- $this->__construct($data['status'], $data['headers'], $data['body']);
- }
- /**
- * Get the response entity body
- *
- * @param bool $asString Set to TRUE to return a string of the body rather than a full body object
- *
- * @return EntityBodyInterface|string
- */
- public function getBody($asString = false)
- {
- return $asString ? (string) $this->body : $this->body;
- }
- /**
- * Set the response entity body
- *
- * @param EntityBodyInterface|string $body Body to set
- *
- * @return self
- */
- public function setBody($body)
- {
- $this->body = \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Http\EntityBody::factory($body);
- return $this;
- }
- /**
- * Set the protocol and protocol version of the response
- *
- * @param string $protocol Response protocol
- * @param string $version Protocol version
- *
- * @return self
- */
- public function setProtocol($protocol, $version)
- {
- $this->protocol = $protocol;
- $this->protocolVersion = $version;
- return $this;
- }
- /**
- * Get the protocol used for the response (e.g. HTTP)
- *
- * @return string
- */
- public function getProtocol()
- {
- return $this->protocol;
- }
- /**
- * Get the HTTP protocol version
- *
- * @return string
- */
- public function getProtocolVersion()
- {
- return $this->protocolVersion;
- }
- /**
- * Get a cURL transfer information
- *
- * @param string $key A single statistic to check
- *
- * @return array|string|null Returns all stats if no key is set, a single stat if a key is set, or null if a key
- * is set and not found
- * @link http://www.php.net/manual/en/function.curl-getinfo.php
- */
- public function getInfo($key = null)
- {
- if ($key === null) {
- return $this->info;
- } elseif (array_key_exists($key, $this->info)) {
- return $this->info[$key];
- } else {
- return null;
- }
- }
- /**
- * Set the transfer information
- *
- * @param array $info Array of cURL transfer stats
- *
- * @return self
- */
- public function setInfo(array $info)
- {
- $this->info = $info;
- return $this;
- }
- /**
- * Set the response status
- *
- * @param int $statusCode Response status code to set
- * @param string $reasonPhrase Response reason phrase
- *
- * @return self
- * @throws BadResponseException when an invalid response code is received
- */
- public function setStatus($statusCode, $reasonPhrase = '')
- {
- $this->statusCode = (int) $statusCode;
- if (!$reasonPhrase && isset(self::$statusTexts[$this->statusCode])) {
- $this->reasonPhrase = self::$statusTexts[$this->statusCode];
- } else {
- $this->reasonPhrase = $reasonPhrase;
- }
- return $this;
- }
- /**
- * Get the response status code
- *
- * @return integer
- */
- public function getStatusCode()
- {
- return $this->statusCode;
- }
- /**
- * Get the entire response as a string
- *
- * @return string
- */
- public function getMessage()
- {
- $message = $this->getRawHeaders();
- // Only include the body in the message if the size is < 2MB
- $size = $this->body->getSize();
- if ($size < 2097152) {
- $message .= (string) $this->body;
- }
- return $message;
- }
- /**
- * Get the the raw message headers as a string
- *
- * @return string
- */
- public function getRawHeaders()
- {
- $headers = 'HTTP/1.1 ' . $this->statusCode . ' ' . $this->reasonPhrase . "\r\n";
- $lines = $this->getHeaderLines();
- if (!empty($lines)) {
- $headers .= implode("\r\n", $lines) . "\r\n";
- }
- return $headers . "\r\n";
- }
- /**
- * Get the response reason phrase- a human readable version of the numeric
- * status code
- *
- * @return string
- */
- public function getReasonPhrase()
- {
- return $this->reasonPhrase;
- }
- /**
- * Get the Accept-Ranges HTTP header
- *
- * @return string Returns what partial content range types this server supports.
- */
- public function getAcceptRanges()
- {
- return (string) $this->getHeader('Accept-Ranges');
- }
- /**
- * Calculate the age of the response
- *
- * @return integer
- */
- public function calculateAge()
- {
- $age = $this->getHeader('Age');
- if ($age === null && $this->getDate()) {
- $age = time() - strtotime($this->getDate());
- }
- return $age === null ? null : (int) (string) $age;
- }
- /**
- * Get the Age HTTP header
- *
- * @return integer|null Returns the age the object has been in a proxy cache in seconds.
- */
- public function getAge()
- {
- return (string) $this->getHeader('Age');
- }
- /**
- * Get the Allow HTTP header
- *
- * @return string|null Returns valid actions for a specified resource. To be used for a 405 Method not allowed.
- */
- public function getAllow()
- {
- return (string) $this->getHeader('Allow');
- }
- /**
- * Check if an HTTP method is allowed by checking the Allow response header
- *
- * @param string $method Method to check
- *
- * @return bool
- */
- public function isMethodAllowed($method)
- {
- $allow = $this->getHeader('Allow');
- if ($allow) {
- foreach (explode(',', $allow) as $allowable) {
- if (!strcasecmp(trim($allowable), $method)) {
- return true;
- }
- }
- }
- return false;
- }
- /**
- * Get the Cache-Control HTTP header
- *
- * @return string
- */
- public function getCacheControl()
- {
- return (string) $this->getHeader('Cache-Control');
- }
- /**
- * Get the Connection HTTP header
- *
- * @return string
- */
- public function getConnection()
- {
- return (string) $this->getHeader('Connection');
- }
- /**
- * Get the Content-Encoding HTTP header
- *
- * @return string|null
- */
- public function getContentEncoding()
- {
- return (string) $this->getHeader('Content-Encoding');
- }
- /**
- * Get the Content-Language HTTP header
- *
- * @return string|null Returns the language the content is in.
- */
- public function getContentLanguage()
- {
- return (string) $this->getHeader('Content-Language');
- }
- /**
- * Get the Content-Length HTTP header
- *
- * @return integer Returns the length of the response body in bytes
- */
- public function getContentLength()
- {
- return (int) (string) $this->getHeader('Content-Length');
- }
- /**
- * Get the Content-Location HTTP header
- *
- * @return string|null Returns an alternate location for the returned data (e.g /index.htm)
- */
- public function getContentLocation()
- {
- return (string) $this->getHeader('Content-Location');
- }
- /**
- * Get the Content-Disposition HTTP header
- *
- * @return string|null Returns the Content-Disposition header
- */
- public function getContentDisposition()
- {
- return (string) $this->getHeader('Content-Disposition');
- }
- /**
- * Get the Content-MD5 HTTP header
- *
- * @return string|null Returns a Base64-encoded binary MD5 sum of the content of the response.
- */
- public function getContentMd5()
- {
- return (string) $this->getHeader('Content-MD5');
- }
- /**
- * Get the Content-Range HTTP header
- *
- * @return string Returns where in a full body message this partial message belongs (e.g. bytes 21010-47021/47022).
- */
- public function getContentRange()
- {
- return (string) $this->getHeader('Content-Range');
- }
- /**
- * Get the Content-Type HTTP header
- *
- * @return string Returns the mime type of this content.
- */
- public function getContentType()
- {
- return (string) $this->getHeader('Content-Type');
- }
- /**
- * Checks if the Content-Type is of a certain type. This is useful if the
- * Content-Type header contains charset information and you need to know if
- * the Content-Type matches a particular type.
- *
- * @param string $type Content type to check against
- *
- * @return bool
- */
- public function isContentType($type)
- {
- return stripos($this->getHeader('Content-Type'), $type) !== false;
- }
- /**
- * Get the Date HTTP header
- *
- * @return string|null Returns the date and time that the message was sent.
- */
- public function getDate()
- {
- return (string) $this->getHeader('Date');
- }
- /**
- * Get the ETag HTTP header
- *
- * @return string|null Returns an identifier for a specific version of a resource, often a Message digest.
- */
- public function getEtag()
- {
- return (string) $this->getHeader('ETag');
- }
- /**
- * Get the Expires HTTP header
- *
- * @return string|null Returns the date/time after which the response is considered stale.
- */
- public function getExpires()
- {
- return (string) $this->getHeader('Expires');
- }
- /**
- * Get the Last-Modified HTTP header
- *
- * @return string|null Returns the last modified date for the requested object, in RFC 2822 format
- * (e.g. Tue, 15 Nov 1994 12:45:26 GMT)
- */
- public function getLastModified()
- {
- return (string) $this->getHeader('Last-Modified');
- }
- /**
- * Get the Location HTTP header
- *
- * @return string|null Used in redirection, or when a new resource has been created.
- */
- public function getLocation()
- {
- return (string) $this->getHeader('Location');
- }
- /**
- * Get the Pragma HTTP header
- *
- * @return Header|null Returns the implementation-specific headers that may have various effects anywhere along
- * the request-response chain.
- */
- public function getPragma()
- {
- return (string) $this->getHeader('Pragma');
- }
- /**
- * Get the Proxy-Authenticate HTTP header
- *
- * @return string|null Authentication to access the proxy (e.g. Basic)
- */
- public function getProxyAuthenticate()
- {
- return (string) $this->getHeader('Proxy-Authenticate');
- }
- /**
- * Get the Retry-After HTTP header
- *
- * @return int|null If an entity is temporarily unavailable, this instructs the client to try again after a
- * specified period of time.
- */
- public function getRetryAfter()
- {
- return (string) $this->getHeader('Retry-After');
- }
- /**
- * Get the Server HTTP header
- *
- * @return string|null A name for the server
- */
- public function getServer()
- {
- return (string) $this->getHeader('Server');
- }
- /**
- * Get the Set-Cookie HTTP header
- *
- * @return string|null An HTTP cookie.
- */
- public function getSetCookie()
- {
- return (string) $this->getHeader('Set-Cookie');
- }
- /**
- * Get the Trailer HTTP header
- *
- * @return string|null The Trailer general field value indicates that the given set of header fields is present in
- * the trailer of a message encoded with chunked transfer-coding.
- */
- public function getTrailer()
- {
- return (string) $this->getHeader('Trailer');
- }
- /**
- * Get the Transfer-Encoding HTTP header
- *
- * @return string|null The form of encoding used to safely transfer the entity to the user
- */
- public function getTransferEncoding()
- {
- return (string) $this->getHeader('Transfer-Encoding');
- }
- /**
- * Get the Vary HTTP header
- *
- * @return string|null Tells downstream proxies how to match future request headers to decide whether the cached
- * response can be used rather than requesting a fresh one from the origin server.
- */
- public function getVary()
- {
- return (string) $this->getHeader('Vary');
- }
- /**
- * Get the Via HTTP header
- *
- * @return string|null Informs the client of proxies through which the response was sent.
- */
- public function getVia()
- {
- return (string) $this->getHeader('Via');
- }
- /**
- * Get the Warning HTTP header
- *
- * @return string|null A general warning about possible problems with the entity body
- */
- public function getWarning()
- {
- return (string) $this->getHeader('Warning');
- }
- /**
- * Get the WWW-Authenticate HTTP header
- *
- * @return string|null Indicates the authentication scheme that should be used to access the requested entity
- */
- public function getWwwAuthenticate()
- {
- return (string) $this->getHeader('WWW-Authenticate');
- }
- /**
- * Checks if HTTP Status code is a Client Error (4xx)
- *
- * @return bool
- */
- public function isClientError()
- {
- return $this->statusCode >= 400 && $this->statusCode < 500;
- }
- /**
- * Checks if HTTP Status code is Server OR Client Error (4xx or 5xx)
- *
- * @return boolean
- */
- public function isError()
- {
- return $this->isClientError() || $this->isServerError();
- }
- /**
- * Checks if HTTP Status code is Information (1xx)
- *
- * @return bool
- */
- public function isInformational()
- {
- return $this->statusCode < 200;
- }
- /**
- * Checks if HTTP Status code is a Redirect (3xx)
- *
- * @return bool
- */
- public function isRedirect()
- {
- return $this->statusCode >= 300 && $this->statusCode < 400;
- }
- /**
- * Checks if HTTP Status code is Server Error (5xx)
- *
- * @return bool
- */
- public function isServerError()
- {
- return $this->statusCode >= 500 && $this->statusCode < 600;
- }
- /**
- * Checks if HTTP Status code is Successful (2xx | 304)
- *
- * @return bool
- */
- public function isSuccessful()
- {
- return $this->statusCode >= 200 && $this->statusCode < 300 || $this->statusCode == 304;
- }
- /**
- * Check if the response can be cached based on the response headers
- *
- * @return bool Returns TRUE if the response can be cached or false if not
- */
- public function canCache()
- {
- // Check if the response is cacheable based on the code
- if (!in_array((int) $this->getStatusCode(), self::$cacheResponseCodes)) {
- return false;
- }
- // Make sure a valid body was returned and can be cached
- if ((!$this->getBody()->isReadable() || !$this->getBody()->isSeekable()) && ($this->getContentLength() > 0 || $this->getTransferEncoding() == 'chunked')) {
- return false;
- }
- // Never cache no-store resources (this is a private cache, so private
- // can be cached)
- if ($this->getHeader('Cache-Control') && $this->getHeader('Cache-Control')->hasDirective('no-store')) {
- return false;
- }
- return $this->isFresh() || $this->getFreshness() === null || $this->canValidate();
- }
- /**
- * Gets the number of seconds from the current time in which this response is still considered fresh
- *
- * @return int|null Returns the number of seconds
- */
- public function getMaxAge()
- {
- if ($header = $this->getHeader('Cache-Control')) {
- // s-max-age, then max-age, then Expires
- if ($age = $header->getDirective('s-maxage')) {
- return $age;
- }
- if ($age = $header->getDirective('max-age')) {
- return $age;
- }
- }
- if ($this->getHeader('Expires')) {
- return strtotime($this->getExpires()) - time();
- }
- return null;
- }
- /**
- * Check if the response is considered fresh.
- *
- * A response is considered fresh when its age is less than or equal to the freshness lifetime (maximum age) of the
- * response.
- *
- * @return bool|null
- */
- public function isFresh()
- {
- $fresh = $this->getFreshness();
- return $fresh === null ? null : $fresh >= 0;
- }
- /**
- * Check if the response can be validated against the origin server using a conditional GET request.
- *
- * @return bool
- */
- public function canValidate()
- {
- return $this->getEtag() || $this->getLastModified();
- }
- /**
- * Get the freshness of the response by returning the difference of the maximum lifetime of the response and the
- * age of the response (max-age - age).
- *
- * Freshness values less than 0 mean that the response is no longer fresh and is ABS(freshness) seconds expired.
- * Freshness values of greater than zero is the number of seconds until the response is no longer fresh. A NULL
- * result means that no freshness information is available.
- *
- * @return int
- */
- public function getFreshness()
- {
- $maxAge = $this->getMaxAge();
- $age = $this->calculateAge();
- return $maxAge && $age ? $maxAge - $age : null;
- }
- /**
- * Parse the JSON response body and return an array
- *
- * @return array|string|int|bool|float
- * @throws RuntimeException if the response body is not in JSON format
- */
- public function json()
- {
- $data = json_decode((string) $this->body, true);
- if (JSON_ERROR_NONE !== json_last_error()) {
- throw new \DeliciousBrains\WP_Offload_S3\Aws2\Guzzle\Common\Exception\RuntimeException('Unable to parse response body into JSON: ' . json_last_error());
- }
- return $data === null ? array() : $data;
- }
- /**
- * Parse the XML response body and return a \SimpleXMLElement.
- *
- * In order to prevent XXE attacks, this method disables loading external
- * entities. If you rely on external entities, then you must parse the
- * XML response manually by accessing the response body directly.
- *
- * @return \SimpleXMLElement
- * @throws RuntimeException if the response body is not in XML format
- * @link http://websec.io/2012/08/27/Preventing-XXE-in-PHP.html
- */
- public function xml()
- {
- $errorMessage = null;
- $internalErrors = libxml_use_internal_errors(true);
- $disableEntities = libxml_disable_entity_loader(true);
- libxml_clear_errors();
- try {
- $xml = new \SimpleXMLElement((string) $this->body ?: '
+ * // First try an INI file at this location.
+ * $a = CredentialProvider::ini(null, '/path/to/file.ini');
+ * // Then try an INI file at this location.
+ * $b = CredentialProvider::ini(null, '/path/to/other-file.ini');
+ * // Then try loading from environment variables.
+ * $c = CredentialProvider::env();
+ * // Combine the three providers together.
+ * $composed = CredentialProvider::chain($a, $b, $c);
+ * // Returns a promise that is fulfilled with credentials or throws.
+ * $promise = $composed();
+ * // Wait on the credentials to resolve.
+ * $creds = $promise->wait();
+ *
+ */
+class CredentialProvider
+{
+ const ENV_KEY = 'AWS_ACCESS_KEY_ID';
+ const ENV_SECRET = 'AWS_SECRET_ACCESS_KEY';
+ const ENV_SESSION = 'AWS_SESSION_TOKEN';
+ const ENV_PROFILE = 'AWS_PROFILE';
+ /**
+ * Create a default credential provider that first checks for environment
+ * variables, then checks for the "default" profile in ~/.aws/credentials,
+ * then checks for "profile default" profile in ~/.aws/config (which is
+ * the default profile of AWS CLI), then tries to make a GET Request to
+ * fetch credentials if Ecs environment variable is presented, and finally
+ * checks for EC2 instance profile credentials.
+ *
+ * This provider is automatically wrapped in a memoize function that caches
+ * previously provided credentials.
+ *
+ * @param array $config Optional array of ecs/instance profile credentials
+ * provider options.
+ *
+ * @return callable
+ */
+ public static function defaultProvider(array $config = [])
+ {
+ $localCredentialProviders = self::localCredentialProviders();
+ $remoteCredentialProviders = self::remoteCredentialProviders($config);
+ return self::memoize(call_user_func_array('self::chain', array_merge($localCredentialProviders, $remoteCredentialProviders)));
+ }
+ /**
+ * Create a credential provider function from a set of static credentials.
+ *
+ * @param CredentialsInterface $creds
+ *
+ * @return callable
+ */
+ public static function fromCredentials(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\CredentialsInterface $creds)
+ {
+ $promise = \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\promise_for($creds);
+ return function () use($promise) {
+ return $promise;
+ };
+ }
+ /**
+ * Creates an aggregate credentials provider that invokes the provided
+ * variadic providers one after the other until a provider returns
+ * credentials.
+ *
+ * @return callable
+ */
+ public static function chain()
+ {
+ $links = func_get_args();
+ if (empty($links)) {
+ throw new \InvalidArgumentException('No providers in chain');
+ }
+ return function () use($links) {
+ /** @var callable $parent */
+ $parent = array_shift($links);
+ $promise = $parent();
+ while ($next = array_shift($links)) {
+ $promise = $promise->otherwise($next);
+ }
+ return $promise;
+ };
+ }
+ /**
+ * Wraps a credential provider and caches previously provided credentials.
+ *
+ * Ensures that cached credentials are refreshed when they expire.
+ *
+ * @param callable $provider Credentials provider function to wrap.
+ *
+ * @return callable
+ */
+ public static function memoize(callable $provider)
+ {
+ return function () use($provider) {
+ static $result;
+ static $isConstant;
+ // Constant credentials will be returned constantly.
+ if ($isConstant) {
+ return $result;
+ }
+ // Create the initial promise that will be used as the cached value
+ // until it expires.
+ if (null === $result) {
+ $result = $provider();
+ }
+ // Return credentials that could expire and refresh when needed.
+ return $result->then(function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\CredentialsInterface $creds) use($provider, &$isConstant, &$result) {
+ // Determine if these are constant credentials.
+ if (!$creds->getExpiration()) {
+ $isConstant = true;
+ return $creds;
+ }
+ // Refresh expired credentials.
+ if (!$creds->isExpired()) {
+ return $creds;
+ }
+ // Refresh the result and forward the promise.
+ return $result = $provider();
+ });
+ };
+ }
+ /**
+ * Wraps a credential provider and saves provided credentials in an
+ * instance of Aws\CacheInterface. Forwards calls when no credentials found
+ * in cache and updates cache with the results.
+ *
+ * Defaults to using a simple file-based cache when none provided.
+ *
+ * @param callable $provider Credentials provider function to wrap
+ * @param CacheInterface $cache Cache to store credentials
+ * @param string|null $cacheKey (optional) Cache key to use
+ *
+ * @return callable
+ */
+ public static function cache(callable $provider, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\CacheInterface $cache, $cacheKey = null)
+ {
+ $cacheKey = $cacheKey ?: 'aws_cached_credentials';
+ return function () use($provider, $cache, $cacheKey) {
+ $found = $cache->get($cacheKey);
+ if ($found instanceof CredentialsInterface && !$found->isExpired()) {
+ return \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\promise_for($found);
+ }
+ return $provider()->then(function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\CredentialsInterface $creds) use($cache, $cacheKey) {
+ $cache->set($cacheKey, $creds, null === $creds->getExpiration() ? 0 : $creds->getExpiration() - time());
+ return $creds;
+ });
+ };
+ }
+ /**
+ * Provider that creates credentials from environment variables
+ * AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN.
+ *
+ * @return callable
+ */
+ public static function env()
+ {
+ return function () {
+ // Use credentials from environment variables, if available
+ $key = getenv(self::ENV_KEY);
+ $secret = getenv(self::ENV_SECRET);
+ if ($key && $secret) {
+ return \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\Credentials($key, $secret, getenv(self::ENV_SESSION) ?: NULL));
+ }
+ return self::reject('Could not find environment variable ' . 'credentials in ' . self::ENV_KEY . '/' . self::ENV_SECRET);
+ };
+ }
+ /**
+ * Credential provider that creates credentials using instance profile
+ * credentials.
+ *
+ * @param array $config Array of configuration data.
+ *
+ * @return InstanceProfileProvider
+ * @see Aws\Credentials\InstanceProfileProvider for $config details.
+ */
+ public static function instanceProfile(array $config = [])
+ {
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\InstanceProfileProvider($config);
+ }
+ /**
+ * Credential provider that creates credentials using
+ * ecs credentials by a GET request, whose uri is specified
+ * by environment variable
+ *
+ * @param array $config Array of configuration data.
+ *
+ * @return EcsCredentialProvider
+ * @see Aws\Credentials\EcsCredentialProvider for $config details.
+ */
+ public static function ecsCredentials(array $config = [])
+ {
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\EcsCredentialProvider($config);
+ }
+ /**
+ * Credential provider that creates credentials using assume role
+ *
+ * @param array $config Array of configuration data
+ * @return callable
+ * @see Aws\Credentials\AssumeRoleCredentialProvider for $config details.
+ */
+ public static function assumeRole(array $config = [])
+ {
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\AssumeRoleCredentialProvider($config);
+ }
+ /**
+ * Credentials provider that creates credentials using an ini file stored
+ * in the current user's home directory.
+ *
+ * @param string|null $profile Profile to use. If not specified will use
+ * the "default" profile in "~/.aws/credentials".
+ * @param string|null $filename If provided, uses a custom filename rather
+ * than looking in the home directory.
+ *
+ * @return callable
+ */
+ public static function ini($profile = null, $filename = null)
+ {
+ $filename = $filename ?: self::getHomeDir() . '/.aws/credentials';
+ $profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
+ return function () use($profile, $filename) {
+ if (!is_readable($filename)) {
+ return self::reject("Cannot read credentials from {$filename}");
+ }
+ $data = parse_ini_file($filename, true);
+ if ($data === false) {
+ return self::reject("Invalid credentials file: {$filename}");
+ }
+ if (!isset($data[$profile])) {
+ return self::reject("'{$profile}' not found in credentials file");
+ }
+ if (!isset($data[$profile]['aws_access_key_id']) || !isset($data[$profile]['aws_secret_access_key'])) {
+ return self::reject("No credentials present in INI profile " . "'{$profile}' ({$filename})");
+ }
+ if (empty($data[$profile]['aws_session_token'])) {
+ $data[$profile]['aws_session_token'] = isset($data[$profile]['aws_security_token']) ? $data[$profile]['aws_security_token'] : null;
+ }
+ return \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\Credentials($data[$profile]['aws_access_key_id'], $data[$profile]['aws_secret_access_key'], $data[$profile]['aws_session_token']));
+ };
+ }
+ /**
+ * Local credential providers returns a list of local credential providers
+ * in following order:
+ * - credentials from environment variables
+ * - 'default' profile in '.aws/credentials' file
+ * - 'profile default' profile in '.aws/config' file
+ *
+ * @return array
+ */
+ private static function localCredentialProviders()
+ {
+ return [self::env(), self::ini(), self::ini('profile default', self::getHomeDir() . '/.aws/config')];
+ }
+ /**
+ * Remote credential providers returns a list of credentials providers
+ * for the remote endpoints such as EC2 or ECS Roles.
+ *
+ * @param array $config Array of configuration data.
+ *
+ * @return array
+ * @see Aws\Credentials\InstanceProfileProvider for $config details.
+ * @see Aws\Credentials\EcsCredentialProvider for $config details.
+ */
+ private static function remoteCredentialProviders(array $config = [])
+ {
+ if (!empty(getenv(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\EcsCredentialProvider::ENV_URI))) {
+ $providers['ecs'] = self::ecsCredentials($config);
+ }
+ $providers['instance'] = self::instanceProfile($config);
+ if (isset($config['credentials']) && $config['credentials'] instanceof CacheInterface) {
+ foreach ($providers as $key => $provider) {
+ $providers[$key] = self::cache($provider, $config['credentials'], 'aws_cached_' . $key . '_credentials');
+ }
+ }
+ return $providers;
+ }
+ /**
+ * Gets the environment's HOME directory if available.
+ *
+ * @return null|string
+ */
+ private static function getHomeDir()
+ {
+ // On Linux/Unix-like systems, use the HOME environment variable
+ if ($homeDir = getenv('HOME')) {
+ return $homeDir;
+ }
+ // Get the HOMEDRIVE and HOMEPATH values for Windows hosts
+ $homeDrive = getenv('HOMEDRIVE');
+ $homePath = getenv('HOMEPATH');
+ return $homeDrive && $homePath ? $homeDrive . $homePath : null;
+ }
+ private static function reject($msg)
+ {
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\RejectedPromise(new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\CredentialsException($msg));
+ }
+}
diff --git a/vendor/Aws3/Aws/Credentials/Credentials.php b/vendor/Aws3/Aws/Credentials/Credentials.php
new file mode 100644
index 00000000..703cbf6f
--- /dev/null
+++ b/vendor/Aws3/Aws/Credentials/Credentials.php
@@ -0,0 +1,71 @@
+key = trim($key);
+ $this->secret = trim($secret);
+ $this->token = $token;
+ $this->expires = $expires;
+ }
+ public static function __set_state(array $state)
+ {
+ return new self($state['key'], $state['secret'], $state['token'], $state['expires']);
+ }
+ public function getAccessKeyId()
+ {
+ return $this->key;
+ }
+ public function getSecretKey()
+ {
+ return $this->secret;
+ }
+ public function getSecurityToken()
+ {
+ return $this->token;
+ }
+ public function getExpiration()
+ {
+ return $this->expires;
+ }
+ public function isExpired()
+ {
+ return $this->expires !== null && time() >= $this->expires;
+ }
+ public function toArray()
+ {
+ return ['key' => $this->key, 'secret' => $this->secret, 'token' => $this->token, 'expires' => $this->expires];
+ }
+ public function serialize()
+ {
+ return json_encode($this->toArray());
+ }
+ public function unserialize($serialized)
+ {
+ $data = json_decode($serialized, true);
+ $this->key = $data['key'];
+ $this->secret = $data['secret'];
+ $this->token = $data['token'];
+ $this->expires = $data['expires'];
+ }
+}
diff --git a/vendor/Aws3/Aws/Credentials/CredentialsInterface.php b/vendor/Aws3/Aws/Credentials/CredentialsInterface.php
new file mode 100644
index 00000000..6514ceeb
--- /dev/null
+++ b/vendor/Aws3/Aws/Credentials/CredentialsInterface.php
@@ -0,0 +1,48 @@
+timeout = isset($config['timeout']) ? $config['timeout'] : 1.0;
+ $this->client = isset($config['client']) ? $config['client'] : \DeliciousBrains\WP_Offload_S3\Aws3\Aws\default_http_handler();
+ }
+ /**
+ * Load ECS credentials
+ *
+ * @return PromiseInterface
+ */
+ public function __invoke()
+ {
+ $client = $this->client;
+ $request = new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Request('GET', self::getEcsUri());
+ return $client($request, ['timeout' => $this->timeout])->then(function (\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response) {
+ $result = $this->decodeResult((string) $response->getBody());
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\Credentials($result['AccessKeyId'], $result['SecretAccessKey'], $result['Token'], strtotime($result['Expiration']));
+ })->otherwise(function ($reason) {
+ $reason = is_array($reason) ? $reason['exception'] : $reason;
+ $msg = $reason->getMessage();
+ throw new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\CredentialsException("Error retrieving credential from ECS ({$msg})");
+ });
+ }
+ /**
+ * Fetch credential URI from ECS environment variable
+ *
+ * @return string Returns ECS URI
+ */
+ private function getEcsUri()
+ {
+ $creds_uri = getenv(self::ENV_URI);
+ return self::SERVER_URI . $creds_uri;
+ }
+ private function decodeResult($response)
+ {
+ $result = json_decode($response, true);
+ if (!isset($result['AccessKeyId'])) {
+ throw new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\CredentialsException('Unexpected ECS credential value');
+ }
+ return $result;
+ }
+}
diff --git a/vendor/Aws3/Aws/Credentials/InstanceProfileProvider.php b/vendor/Aws3/Aws/Credentials/InstanceProfileProvider.php
new file mode 100644
index 00000000..70db616f
--- /dev/null
+++ b/vendor/Aws3/Aws/Credentials/InstanceProfileProvider.php
@@ -0,0 +1,85 @@
+timeout = isset($config['timeout']) ? $config['timeout'] : 1.0;
+ $this->profile = isset($config['profile']) ? $config['profile'] : null;
+ $this->client = isset($config['client']) ? $config['client'] : \DeliciousBrains\WP_Offload_S3\Aws3\Aws\default_http_handler();
+ }
+ /**
+ * Loads instance profile credentials.
+ *
+ * @return PromiseInterface
+ */
+ public function __invoke()
+ {
+ return \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\coroutine(function () {
+ if (!$this->profile) {
+ $this->profile = (yield $this->request(self::CRED_PATH));
+ }
+ $json = (yield $this->request(self::CRED_PATH . $this->profile));
+ $result = $this->decodeResult($json);
+ (yield new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\Credentials($result['AccessKeyId'], $result['SecretAccessKey'], $result['Token'], strtotime($result['Expiration'])));
+ });
+ }
+ /**
+ * @param string $url
+ * @return PromiseInterface Returns a promise that is fulfilled with the
+ * body of the response as a string.
+ */
+ private function request($url)
+ {
+ $disabled = getenv(self::ENV_DISABLE) ?: false;
+ if (strcasecmp($disabled, 'true') === 0) {
+ throw new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\CredentialsException($this->createErrorMessage('EC2 metadata server access disabled'));
+ }
+ $fn = $this->client;
+ $request = new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Request('GET', self::SERVER_URI . $url);
+ return $fn($request, ['timeout' => $this->timeout])->then(function (\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response) {
+ return (string) $response->getBody();
+ })->otherwise(function (array $reason) {
+ $reason = $reason['exception'];
+ $msg = $reason->getMessage();
+ throw new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\CredentialsException($this->createErrorMessage($msg));
+ });
+ }
+ private function createErrorMessage($previous)
+ {
+ return "Error retrieving credentials from the instance profile " . "metadata server. ({$previous})";
+ }
+ private function decodeResult($response)
+ {
+ $result = json_decode($response, true);
+ if ($result['Code'] !== 'Success') {
+ throw new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\CredentialsException('Unexpected instance profile ' . 'response code: ' . $result['Code']);
+ }
+ return $result;
+ }
+}
diff --git a/vendor/Aws3/Aws/Crypto/AbstractCryptoClient.php b/vendor/Aws3/Aws/Crypto/AbstractCryptoClient.php
new file mode 100644
index 00000000..7a7a6351
--- /dev/null
+++ b/vendor/Aws3/Aws/Crypto/AbstractCryptoClient.php
@@ -0,0 +1,97 @@
+stream = $cipherText;
+ $this->key = $key;
+ $this->cipherMethod = clone $cipherMethod;
+ }
+ public function getOpenSslName()
+ {
+ return $this->cipherMethod->getOpenSslName();
+ }
+ public function getAesName()
+ {
+ return $this->cipherMethod->getAesName();
+ }
+ public function getCurrentIv()
+ {
+ return $this->cipherMethod->getCurrentIv();
+ }
+ public function getSize()
+ {
+ $plainTextSize = $this->stream->getSize();
+ if ($this->cipherMethod->requiresPadding()) {
+ // PKCS7 padding requires that between 1 and self::BLOCK_SIZE be
+ // added to the plaintext to make it an even number of blocks. The
+ // plaintext is between strlen($cipherText) - self::BLOCK_SIZE and
+ // strlen($cipherText) - 1
+ return null;
+ }
+ return $plainTextSize;
+ }
+ public function isWritable()
+ {
+ return false;
+ }
+ public function read($length)
+ {
+ if ($length > strlen($this->buffer)) {
+ $this->buffer .= $this->decryptBlock(self::BLOCK_SIZE * ceil(($length - strlen($this->buffer)) / self::BLOCK_SIZE));
+ }
+ $data = substr($this->buffer, 0, $length);
+ $this->buffer = substr($this->buffer, $length);
+ return $data ? $data : '';
+ }
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if ($offset === 0 && $whence === SEEK_SET) {
+ $this->buffer = '';
+ $this->cipherMethod->seek(0, SEEK_SET);
+ $this->stream->seek(0, SEEK_SET);
+ } else {
+ throw new \LogicException('AES encryption streams only support being' . ' rewound, not arbitrary seeking.');
+ }
+ }
+ private function decryptBlock($length)
+ {
+ if ($this->stream->eof()) {
+ return '';
+ }
+ $cipherText = '';
+ do {
+ $cipherText .= $this->stream->read($length - strlen($cipherText));
+ } while (strlen($cipherText) < $length && !$this->stream->eof());
+ $options = OPENSSL_RAW_DATA;
+ if (!$this->stream->eof() && $this->stream->getSize() !== $this->stream->tell()) {
+ $options |= OPENSSL_ZERO_PADDING;
+ }
+ $plaintext = openssl_decrypt($cipherText, $this->cipherMethod->getOpenSslName(), $this->key, $options, $this->cipherMethod->getCurrentIv());
+ $this->cipherMethod->update($cipherText);
+ return $plaintext;
+ }
+}
diff --git a/vendor/Aws3/Aws/Crypto/AesEncryptingStream.php b/vendor/Aws3/Aws/Crypto/AesEncryptingStream.php
new file mode 100644
index 00000000..9812f749
--- /dev/null
+++ b/vendor/Aws3/Aws/Crypto/AesEncryptingStream.php
@@ -0,0 +1,113 @@
+stream = $plainText;
+ $this->key = $key;
+ $this->cipherMethod = clone $cipherMethod;
+ }
+ public function getOpenSslName()
+ {
+ return $this->cipherMethod->getOpenSslName();
+ }
+ public function getAesName()
+ {
+ return $this->cipherMethod->getAesName();
+ }
+ public function getCurrentIv()
+ {
+ return $this->cipherMethod->getCurrentIv();
+ }
+ public function getSize()
+ {
+ $plainTextSize = $this->stream->getSize();
+ if ($this->cipherMethod->requiresPadding() && $plainTextSize !== null) {
+ // PKCS7 padding requires that between 1 and self::BLOCK_SIZE be
+ // added to the plaintext to make it an even number of blocks.
+ $padding = self::BLOCK_SIZE - $plainTextSize % self::BLOCK_SIZE;
+ return $plainTextSize + $padding;
+ }
+ return $plainTextSize;
+ }
+ public function isWritable()
+ {
+ return false;
+ }
+ public function read($length)
+ {
+ if ($length > strlen($this->buffer)) {
+ $this->buffer .= $this->encryptBlock(self::BLOCK_SIZE * ceil(($length - strlen($this->buffer)) / self::BLOCK_SIZE));
+ }
+ $data = substr($this->buffer, 0, $length);
+ $this->buffer = substr($this->buffer, $length);
+ return $data ? $data : '';
+ }
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if ($whence === SEEK_CUR) {
+ $offset = $this->tell() + $offset;
+ $whence = SEEK_SET;
+ }
+ if ($whence === SEEK_SET) {
+ $this->buffer = '';
+ $wholeBlockOffset = (int) ($offset / self::BLOCK_SIZE) * self::BLOCK_SIZE;
+ $this->stream->seek($wholeBlockOffset);
+ $this->cipherMethod->seek($wholeBlockOffset);
+ $this->read($offset - $wholeBlockOffset);
+ } else {
+ throw new \LogicException('Unrecognized whence.');
+ }
+ }
+ private function encryptBlock($length)
+ {
+ if ($this->stream->eof()) {
+ return '';
+ }
+ $plainText = '';
+ do {
+ $plainText .= $this->stream->read($length - strlen($plainText));
+ } while (strlen($plainText) < $length && !$this->stream->eof());
+ $options = OPENSSL_RAW_DATA;
+ if (!$this->stream->eof() || $this->stream->getSize() !== $this->stream->tell()) {
+ $options |= OPENSSL_ZERO_PADDING;
+ }
+ $cipherText = openssl_encrypt($plainText, $this->cipherMethod->getOpenSslName(), $this->key, $options, $this->cipherMethod->getCurrentIv());
+ $this->cipherMethod->update($cipherText);
+ return $cipherText;
+ }
+}
diff --git a/vendor/Aws3/Aws/Crypto/AesGcmDecryptingStream.php b/vendor/Aws3/Aws/Crypto/AesGcmDecryptingStream.php
new file mode 100644
index 00000000..8caf6179
--- /dev/null
+++ b/vendor/Aws3/Aws/Crypto/AesGcmDecryptingStream.php
@@ -0,0 +1,64 @@
+cipherText = $cipherText;
+ $this->key = $key;
+ $this->initializationVector = $initializationVector;
+ $this->tag = $tag;
+ $this->aad = $aad;
+ $this->tagLength = $tagLength;
+ $this->keySize = $keySize;
+ }
+ public function getOpenSslName()
+ {
+ return "aes-{$this->keySize}-gcm";
+ }
+ public function getAesName()
+ {
+ return 'AES/GCM/NoPadding';
+ }
+ public function getCurrentIv()
+ {
+ return $this->initializationVector;
+ }
+ public function createStream()
+ {
+ return \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\stream_for(openssl_decrypt((string) $this->cipherText, $this->getOpenSslName(), $this->key, OPENSSL_RAW_DATA, $this->initializationVector, $this->tag, $this->aad));
+ }
+ public function isWritable()
+ {
+ return false;
+ }
+}
diff --git a/vendor/Aws3/Aws/Crypto/AesGcmEncryptingStream.php b/vendor/Aws3/Aws/Crypto/AesGcmEncryptingStream.php
new file mode 100644
index 00000000..ad187eb8
--- /dev/null
+++ b/vendor/Aws3/Aws/Crypto/AesGcmEncryptingStream.php
@@ -0,0 +1,69 @@
+plaintext = $plaintext;
+ $this->key = $key;
+ $this->initializationVector = $initializationVector;
+ $this->aad = $aad;
+ $this->tagLength = $tagLength;
+ $this->keySize = $keySize;
+ }
+ public function getOpenSslName()
+ {
+ return "aes-{$this->keySize}-gcm";
+ }
+ public function getAesName()
+ {
+ return 'AES/GCM/NoPadding';
+ }
+ public function getCurrentIv()
+ {
+ return $this->initializationVector;
+ }
+ public function createStream()
+ {
+ return \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\stream_for(openssl_encrypt((string) $this->plaintext, $this->getOpenSslName(), $this->key, OPENSSL_RAW_DATA, $this->initializationVector, $this->tag, $this->aad, $this->tagLength));
+ }
+ /**
+ * @return string
+ */
+ public function getTag()
+ {
+ return $this->tag;
+ }
+ public function isWritable()
+ {
+ return false;
+ }
+}
diff --git a/vendor/Aws3/Aws/Crypto/AesStreamInterface.php b/vendor/Aws3/Aws/Crypto/AesStreamInterface.php
new file mode 100644
index 00000000..ae22c735
--- /dev/null
+++ b/vendor/Aws3/Aws/Crypto/AesStreamInterface.php
@@ -0,0 +1,28 @@
+baseIv = $this->iv = $iv;
+ $this->keySize = $keySize;
+ if (strlen($iv) !== openssl_cipher_iv_length($this->getOpenSslName())) {
+ throw new \InvalidArgumentException('Invalid initialization vector');
+ }
+ }
+ public function getOpenSslName()
+ {
+ return "aes-{$this->keySize}-cbc";
+ }
+ public function getAesName()
+ {
+ return 'AES/CBC/PKCS5Padding';
+ }
+ public function getCurrentIv()
+ {
+ return $this->iv;
+ }
+ public function requiresPadding()
+ {
+ return true;
+ }
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if ($offset === 0 && $whence === SEEK_SET) {
+ $this->iv = $this->baseIv;
+ } else {
+ throw new \LogicException('CBC initialization only support being' . ' rewound, not arbitrary seeking.');
+ }
+ }
+ public function update($cipherTextBlock)
+ {
+ $this->iv = substr($cipherTextBlock, self::BLOCK_SIZE * -1);
+ }
+}
diff --git a/vendor/Aws3/Aws/Crypto/Cipher/CipherBuilderTrait.php b/vendor/Aws3/Aws/Crypto/Cipher/CipherBuilderTrait.php
new file mode 100644
index 00000000..f15741cb
--- /dev/null
+++ b/vendor/Aws3/Aws/Crypto/Cipher/CipherBuilderTrait.php
@@ -0,0 +1,65 @@
+decryptCek(base64_decode($envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::CONTENT_KEY_V2_HEADER]), json_decode($envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER], true));
+ $cipherOptions['KeySize'] = strlen($cek) * 8;
+ $cipherOptions['Cipher'] = $this->getCipherFromAesName($envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER]);
+ $decryptionSteam = $this->getDecryptingStream($cipherText, $cek, $cipherOptions);
+ unset($cek);
+ return $decryptionSteam;
+ }
+ private function getTagFromCiphertextStream(\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Stream $cipherText, $tagLength)
+ {
+ $cipherTextSize = $cipherText->getSize();
+ if ($cipherTextSize == null || $cipherTextSize <= 0) {
+ throw new \RuntimeException('Cannot decrypt a stream of unknown' . ' size.');
+ }
+ return (string) new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\LimitStream($cipherText, $tagLength, $cipherTextSize - $tagLength);
+ }
+ private function getStrippedCiphertextStream(\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Stream $cipherText, $tagLength)
+ {
+ $cipherTextSize = $cipherText->getSize();
+ if ($cipherTextSize == null || $cipherTextSize <= 0) {
+ throw new \RuntimeException('Cannot decrypt a stream of unknown' . ' size.');
+ }
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\LimitStream($cipherText, $cipherTextSize - $tagLength, 0);
+ }
+ /**
+ * Generates a stream that wraps the cipher text with the proper cipher and
+ * uses the content encryption key (CEK) to decrypt the data when read.
+ *
+ * @param string $cipherText Plain-text data to be encrypted using the
+ * materials, algorithm, and data provided.
+ * @param string $cek A content encryption key for use by the stream for
+ * encrypting the plaintext data.
+ * @param array $cipherOptions Options for use in determining the cipher to
+ * be used for encrypting data.
+ *
+ * @return AesStreamInterface
+ *
+ * @internal
+ */
+ protected function getDecryptingStream($cipherText, $cek, $cipherOptions)
+ {
+ $cipherTextStream = \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\stream_for($cipherText);
+ switch ($cipherOptions['Cipher']) {
+ case 'gcm':
+ $cipherOptions['Tag'] = $this->getTagFromCiphertextStream($cipherTextStream, $cipherOptions['TagLength']);
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\AesGcmDecryptingStream($this->getStrippedCiphertextStream($cipherTextStream, $cipherOptions['TagLength']), $cek, $cipherOptions['Iv'], $cipherOptions['Tag'], $cipherOptions['Aad'] = isset($cipherOptions['Aad']) ? $cipherOptions['Aad'] : null, $cipherOptions['TagLength'] ?: null, $cipherOptions['KeySize']);
+ default:
+ $cipherMethod = $this->buildCipherMethod($cipherOptions['Cipher'], $cipherOptions['Iv'], $cipherOptions['KeySize']);
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\AesDecryptingStream($cipherTextStream, $cek, $cipherMethod);
+ }
+ }
+}
diff --git a/vendor/Aws3/Aws/Crypto/EncryptionTrait.php b/vendor/Aws3/Aws/Crypto/EncryptionTrait.php
new file mode 100644
index 00000000..e4de6631
--- /dev/null
+++ b/vendor/Aws3/Aws/Crypto/EncryptionTrait.php
@@ -0,0 +1,112 @@
+ true, 'KeySize' => true, 'Aad' => true];
+ /**
+ * Dependency to generate a CipherMethod from a set of inputs for loading
+ * in to an AesEncryptingStream.
+ *
+ * @param string $cipherName Name of the cipher to generate for encrypting.
+ * @param string $iv Base Initialization Vector for the cipher.
+ * @param int $keySize Size of the encryption key, in bits, that will be
+ * used.
+ *
+ * @return Cipher\CipherMethod
+ *
+ * @internal
+ */
+ protected abstract function buildCipherMethod($cipherName, $iv, $keySize);
+ /**
+ * Builds an AesStreamInterface and populates encryption metadata into the
+ * supplied envelope.
+ *
+ * @param Stream $plaintext Plain-text data to be encrypted using the
+ * materials, algorithm, and data provided.
+ * @param array $cipherOptions Options for use in determining the cipher to
+ * be used for encrypting data.
+ * @param MaterialsProvider $provider A provider to supply and encrypt
+ * materials used in encryption.
+ * @param MetadataEnvelope $envelope A storage envelope for encryption
+ * metadata to be added to.
+ *
+ * @return AesStreamInterface
+ *
+ * @throws \InvalidArgumentException Thrown when a value in $cipherOptions
+ * is not valid.
+ *
+ * @internal
+ */
+ protected function encrypt(\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Stream $plaintext, array $cipherOptions, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MaterialsProvider $provider, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope $envelope)
+ {
+ $materialsDescription = $provider->getMaterialsDescription();
+ $cipherOptions = array_intersect_key($cipherOptions, self::$allowedOptions);
+ if (empty($cipherOptions['Cipher'])) {
+ throw new \InvalidArgumentException('An encryption cipher must be' . ' specified in the "cipher_options".');
+ }
+ if (!self::isSupportedCipher($cipherOptions['Cipher'])) {
+ throw new \InvalidArgumentException('The cipher requested is not' . ' supported by the SDK.');
+ }
+ if (empty($cipherOptions['KeySize'])) {
+ $cipherOptions['KeySize'] = 256;
+ }
+ if (!is_int($cipherOptions['KeySize'])) {
+ throw new \InvalidArgumentException('The cipher "KeySize" must be' . ' an integer.');
+ }
+ if (!\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MaterialsProvider::isSupportedKeySize($cipherOptions['KeySize'])) {
+ throw new \InvalidArgumentException('The cipher "KeySize" requested' . ' is not supported by AES (128, 192, or 256).');
+ }
+ $cipherOptions['Iv'] = $provider->generateIv($this->getCipherOpenSslName($cipherOptions['Cipher'], $cipherOptions['KeySize']));
+ $cek = $provider->generateCek($cipherOptions['KeySize']);
+ list($encryptingStream, $aesName) = $this->getEncryptingStream($plaintext, $cek, $cipherOptions);
+ // Populate envelope data
+ $envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::CONTENT_KEY_V2_HEADER] = $provider->encryptCek($cek, $materialsDescription);
+ unset($cek);
+ $envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::IV_HEADER] = base64_encode($cipherOptions['Iv']);
+ $envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER] = $provider->getWrapAlgorithmName();
+ $envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER] = $aesName;
+ $envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::UNENCRYPTED_CONTENT_LENGTH_HEADER] = strlen($plaintext);
+ $envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::UNENCRYPTED_CONTENT_MD5_HEADER] = base64_encode(md5($plaintext));
+ $envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER] = json_encode($materialsDescription);
+ if (!empty($cipherOptions['Tag'])) {
+ $envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] = strlen($cipherOptions['Tag']) * 8;
+ }
+ return $encryptingStream;
+ }
+ /**
+ * Generates a stream that wraps the plaintext with the proper cipher and
+ * uses the content encryption key (CEK) to encrypt the data when read.
+ *
+ * @param Stream $plaintext Plain-text data to be encrypted using the
+ * materials, algorithm, and data provided.
+ * @param string $cek A content encryption key for use by the stream for
+ * encrypting the plaintext data.
+ * @param array $cipherOptions Options for use in determining the cipher to
+ * be used for encrypting data.
+ *
+ * @return [AesStreamInterface, string]
+ *
+ * @internal
+ */
+ protected function getEncryptingStream(\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Stream $plaintext, $cek, &$cipherOptions)
+ {
+ switch ($cipherOptions['Cipher']) {
+ case 'gcm':
+ $cipherOptions['TagLength'] = 16;
+ $cipherTextStream = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\AesGcmEncryptingStream($plaintext, $cek, $cipherOptions['Iv'], $cipherOptions['Aad'] = isset($cipherOptions['Aad']) ? $cipherOptions['Aad'] : null, $cipherOptions['TagLength'], $cipherOptions['KeySize']);
+ $appendStream = new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\AppendStream([$cipherTextStream->createStream()]);
+ $cipherOptions['Tag'] = $cipherTextStream->getTag();
+ $appendStream->addStream(\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\stream_for($cipherOptions['Tag']));
+ return [$appendStream, $cipherTextStream->getAesName()];
+ default:
+ $cipherMethod = $this->buildCipherMethod($cipherOptions['Cipher'], $cipherOptions['Iv'], $cipherOptions['KeySize']);
+ $cipherTextStream = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\AesEncryptingStream($plaintext, $cek, $cipherMethod);
+ return [$cipherTextStream, $cipherTextStream->getAesName()];
+ }
+ }
+}
diff --git a/vendor/Aws3/Aws/Crypto/KmsMaterialsProvider.php b/vendor/Aws3/Aws/Crypto/KmsMaterialsProvider.php
new file mode 100644
index 00000000..45edba3d
--- /dev/null
+++ b/vendor/Aws3/Aws/Crypto/KmsMaterialsProvider.php
@@ -0,0 +1,82 @@
+kmsClient = $kmsClient;
+ $this->kmsKeyId = $kmsKeyId;
+ }
+ public function fromDecryptionEnvelope(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope $envelope)
+ {
+ if (empty($envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER])) {
+ throw new \RuntimeException('Not able to detect kms_cmk_id from an' . ' empty materials description.');
+ }
+ $materialsDescription = json_decode($envelope[\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER], true);
+ if (empty($materialsDescription['kms_cmk_id'])) {
+ throw new \RuntimeException('Not able to detect kms_cmk_id from kms' . ' materials description.');
+ }
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\KmsMaterialsProvider($this->kmsClient, $materialsDescription['kms_cmk_id']);
+ }
+ /**
+ * The KMS key id for use in matching this Provider to its keys,
+ * consistently with other SDKs as 'kms_cmk_id'.
+ *
+ * @return array
+ */
+ public function getMaterialsDescription()
+ {
+ return ['kms_cmk_id' => $this->kmsKeyId];
+ }
+ public function getWrapAlgorithmName()
+ {
+ return 'kms';
+ }
+ /**
+ * Takes a content encryption key (CEK) and description to return an encrypted
+ * key by using KMS' Encrypt API.
+ *
+ * @param string $unencryptedCek Key for use in encrypting other data
+ * that itself needs to be encrypted by the
+ * Provider.
+ * @param string $materialDescription Material Description for use in
+ * encrypting the $cek.
+ *
+ * @return string
+ */
+ public function encryptCek($unencryptedCek, $materialDescription)
+ {
+ $encryptedDataKey = $this->kmsClient->encrypt(['Plaintext' => $unencryptedCek, 'KeyId' => $this->kmsKeyId, 'EncryptionContext' => $materialDescription]);
+ return base64_encode($encryptedDataKey['CiphertextBlob']);
+ }
+ /**
+ * Takes an encrypted content encryption key (CEK) and material description
+ * for use decrypting the key by using KMS' Decrypt API.
+ *
+ * @param string $encryptedCek Encrypted key to be decrypted by the Provider
+ * for use decrypting other data.
+ * @param string $materialDescription Material Description for use in
+ * encrypting the $cek.
+ *
+ * @return string
+ */
+ public function decryptCek($encryptedCek, $materialDescription)
+ {
+ $result = $this->kmsClient->decrypt(['CiphertextBlob' => $encryptedCek, 'EncryptionContext' => $materialDescription]);
+ return $result['Plaintext'];
+ }
+}
diff --git a/vendor/Aws3/Aws/Crypto/MaterialsProvider.php b/vendor/Aws3/Aws/Crypto/MaterialsProvider.php
new file mode 100644
index 00000000..828077e3
--- /dev/null
+++ b/vendor/Aws3/Aws/Crypto/MaterialsProvider.php
@@ -0,0 +1,92 @@
+ true, 192 => true, 256 => true];
+ /**
+ * Returns if the requested size is supported by AES.
+ *
+ * @param int $keySize Size of the requested key in bits.
+ *
+ * @return bool
+ */
+ public static function isSupportedKeySize($keySize)
+ {
+ return isset(self::$supportedKeySizes[$keySize]);
+ }
+ /**
+ * Performs further initialization of the MaterialsProvider based on the
+ * data inside the MetadataEnvelope.
+ *
+ * @param MetadataEnvelope $envelope A storage envelope for encryption
+ * metadata to be read from.
+ *
+ * @return MaterialsProvider
+ *
+ * @throws \RuntimeException Thrown when there is an empty or improperly
+ * formed materials description in the envelope.
+ *
+ * @internal
+ */
+ public abstract function fromDecryptionEnvelope(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Crypto\MetadataEnvelope $envelope);
+ /**
+ * Returns the material description for this Provider so it can be verified
+ * by encryption mechanisms.
+ *
+ * @return string
+ */
+ public abstract function getMaterialsDescription();
+ /**
+ * Returns the wrap algorithm name for this Provider.
+ *
+ * @return string
+ */
+ public abstract function getWrapAlgorithmName();
+ /**
+ * Takes a content encryption key (CEK) and description to return an
+ * encrypted key according to the Provider's specifications.
+ *
+ * @param string $unencryptedCek Key for use in encrypting other data
+ * that itself needs to be encrypted by the
+ * Provider.
+ * @param string $materialDescription Material Description for use in
+ * encrypting the $cek.
+ *
+ * @return string
+ */
+ public abstract function encryptCek($unencryptedCek, $materialDescription);
+ /**
+ * Takes an encrypted content encryption key (CEK) and material description
+ * for use decrypting the key according to the Provider's specifications.
+ *
+ * @param string $encryptedCek Encrypted key to be decrypted by the Provider
+ * for use decrypting other data.
+ * @param string $materialDescription Material Description for use in
+ * encrypting the $cek.
+ *
+ * @return string
+ */
+ public abstract function decryptCek($encryptedCek, $materialDescription);
+ /**
+ * @param string $keySize Length of a cipher key in bits for generating a
+ * random content encryption key (CEK).
+ *
+ * @return string
+ */
+ public function generateCek($keySize)
+ {
+ return openssl_random_pseudo_bytes($keySize / 8);
+ }
+ /**
+ * @param string $openSslName Cipher OpenSSL name to use for generating
+ * an initialization vector.
+ *
+ * @return string
+ */
+ public function generateIv($openSslName)
+ {
+ return openssl_random_pseudo_bytes(openssl_cipher_iv_length($openSslName));
+ }
+}
diff --git a/vendor/Aws3/Aws/Crypto/MetadataEnvelope.php b/vendor/Aws3/Aws/Crypto/MetadataEnvelope.php
new file mode 100644
index 00000000..a418780e
--- /dev/null
+++ b/vendor/Aws3/Aws/Crypto/MetadataEnvelope.php
@@ -0,0 +1,49 @@
+getConstants()) as $constant) {
+ self::$constants[$constant] = true;
+ }
+ }
+ return array_keys(self::$constants);
+ }
+ public function offsetSet($name, $value)
+ {
+ $constants = self::getConstantValues();
+ if (is_null($name) || !in_array($name, $constants)) {
+ throw new \InvalidArgumentException('MetadataEnvelope fields must' . ' must match a predefined offset; use the header constants.');
+ }
+ $this->data[$name] = $value;
+ }
+ public function jsonSerialize()
+ {
+ return $this->data;
+ }
+}
diff --git a/vendor/Aws3/Aws/Crypto/MetadataStrategyInterface.php b/vendor/Aws3/Aws/Crypto/MetadataStrategyInterface.php
new file mode 100644
index 00000000..90c121b2
--- /dev/null
+++ b/vendor/Aws3/Aws/Crypto/MetadataStrategyInterface.php
@@ -0,0 +1,30 @@
+cache = $cache;
+ }
+ public function get($key)
+ {
+ return $this->cache->fetch($key);
+ }
+ public function fetch($key)
+ {
+ return $this->get($key);
+ }
+ public function set($key, $value, $ttl = 0)
+ {
+ return $this->cache->save($key, $value, $ttl);
+ }
+ public function save($key, $value, $ttl = 0)
+ {
+ return $this->set($key, $value, $ttl);
+ }
+ public function remove($key)
+ {
+ return $this->cache->delete($key);
+ }
+ public function delete($key)
+ {
+ return $this->remove($key);
+ }
+ public function contains($key)
+ {
+ return $this->cache->contains($key);
+ }
+ public function getStats()
+ {
+ return $this->cache->getStats();
+ }
+}
diff --git a/vendor/Aws3/Aws/Endpoint/EndpointProvider.php b/vendor/Aws3/Aws/Endpoint/EndpointProvider.php
new file mode 100644
index 00000000..ed0429a2
--- /dev/null
+++ b/vendor/Aws3/Aws/Endpoint/EndpointProvider.php
@@ -0,0 +1,89 @@
+ 'ec2', 'region' => 'us-west-2']);
+ * // Returns an endpoint array or throws.
+ * $endpoint = EndpointProvider::resolve($provider, [
+ * 'service' => 'ec2',
+ * 'region' => 'us-west-2'
+ * ]);
+ *
+ * You can compose multiple providers into a single provider using
+ * {@see Aws\or_chain}. This function accepts providers as arguments and
+ * returns a new function that will invoke each provider until a non-null value
+ * is returned.
+ *
+ * $a = function (array $args) {
+ * if ($args['region'] === 'my-test-region') {
+ * return ['endpoint' => 'http://localhost:123/api'];
+ * }
+ * };
+ * $b = EndpointProvider::defaultProvider();
+ * $c = \Aws\or_chain($a, $b);
+ * $config = ['service' => 'ec2', 'region' => 'my-test-region'];
+ * $res = $c($config); // $a handles this.
+ * $config['region'] = 'us-west-2';
+ * $res = $c($config); // $b handles this.
+ */
+class EndpointProvider
+{
+ /**
+ * Resolves and endpoint provider and ensures a non-null return value.
+ *
+ * @param callable $provider Provider function to invoke.
+ * @param array $args Endpoint arguments to pass to the provider.
+ *
+ * @return array
+ * @throws UnresolvedEndpointException
+ */
+ public static function resolve(callable $provider, array $args = [])
+ {
+ $result = $provider($args);
+ if (is_array($result)) {
+ return $result;
+ }
+ throw new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\UnresolvedEndpointException('Unable to resolve an endpoint using the provider arguments: ' . json_encode($args) . '. Note: you can provide an "endpoint" ' . 'option to a client constructor to bypass invoking an endpoint ' . 'provider.');
+ }
+ /**
+ * Creates and returns the default SDK endpoint provider.
+ *
+ * @deprecated Use an instance of \Aws\Endpoint\Partition instead.
+ *
+ * @return callable
+ */
+ public static function defaultProvider()
+ {
+ return \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Endpoint\PartitionEndpointProvider::defaultProvider();
+ }
+ /**
+ * Creates and returns an endpoint provider that uses patterns from an
+ * array.
+ *
+ * @param array $patterns Endpoint patterns
+ *
+ * @return callable
+ */
+ public static function patterns(array $patterns)
+ {
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Endpoint\PatternEndpointProvider($patterns);
+ }
+}
diff --git a/vendor/Aws3/Aws/Endpoint/Partition.php b/vendor/Aws3/Aws/Endpoint/Partition.php
new file mode 100644
index 00000000..d6610ce5
--- /dev/null
+++ b/vendor/Aws3/Aws/Endpoint/Partition.php
@@ -0,0 +1,113 @@
+data = $definition;
+ }
+ public function getName()
+ {
+ return $this->data['partition'];
+ }
+ public function isRegionMatch($region, $service)
+ {
+ if (isset($this->data['regions'][$region]) || isset($this->data['services'][$service]['endpoints'][$region])) {
+ return true;
+ }
+ if (isset($this->data['regionRegex'])) {
+ return (bool) preg_match("@{$this->data['regionRegex']}@", $region);
+ }
+ return false;
+ }
+ public function getAvailableEndpoints($service, $allowNonRegionalEndpoints = false)
+ {
+ if ($this->isServicePartitionGlobal($service)) {
+ return [$this->getPartitionEndpoint($service)];
+ }
+ if (isset($this->data['services'][$service]['endpoints'])) {
+ $serviceRegions = array_keys($this->data['services'][$service]['endpoints']);
+ return $allowNonRegionalEndpoints ? $serviceRegions : array_intersect($serviceRegions, array_keys($this->data['regions']));
+ }
+ return [];
+ }
+ public function __invoke(array $args = [])
+ {
+ $service = isset($args['service']) ? $args['service'] : '';
+ $region = isset($args['region']) ? $args['region'] : '';
+ $scheme = isset($args['scheme']) ? $args['scheme'] : 'https';
+ $data = $this->getEndpointData($service, $region);
+ 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];
+ }
+ private function getEndpointData($service, $region)
+ {
+ $resolved = $this->resolveRegion($service, $region);
+ $data = isset($this->data['services'][$service]['endpoints'][$resolved]) ? $this->data['services'][$service]['endpoints'][$resolved] : [];
+ $data += isset($this->data['services'][$service]['defaults']) ? $this->data['services'][$service]['defaults'] : [];
+ $data += isset($this->data['defaults']) ? $this->data['defaults'] : [];
+ return $data;
+ }
+ private function getSignatureVersion(array $data)
+ {
+ static $supportedBySdk = ['s3v4', 'v4', 'anonymous'];
+ $possibilities = array_intersect($supportedBySdk, isset($data['signatureVersions']) ? $data['signatureVersions'] : ['v4']);
+ return array_shift($possibilities);
+ }
+ private function resolveRegion($service, $region)
+ {
+ if ($this->isServicePartitionGlobal($service)) {
+ return $this->getPartitionEndpoint($service);
+ }
+ return $region;
+ }
+ private function isServicePartitionGlobal($service)
+ {
+ return isset($this->data['services'][$service]['isRegionalized']) && false === $this->data['services'][$service]['isRegionalized'] && isset($this->data['services'][$service]['partitionEndpoint']);
+ }
+ private function getPartitionEndpoint($service)
+ {
+ return $this->data['services'][$service]['partitionEndpoint'];
+ }
+ private function formatEndpoint($template, $service, $region)
+ {
+ return strtr($template, ['{service}' => $service, '{region}' => $region, '{dnsSuffix}' => $this->data['dnsSuffix']]);
+ }
+}
diff --git a/vendor/Aws3/Aws/Endpoint/PartitionEndpointProvider.php b/vendor/Aws3/Aws/Endpoint/PartitionEndpointProvider.php
new file mode 100644
index 00000000..2953cc19
--- /dev/null
+++ b/vendor/Aws3/Aws/Endpoint/PartitionEndpointProvider.php
@@ -0,0 +1,67 @@
+partitions = array_map(function (array $definition) {
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Endpoint\Partition($definition);
+ }, array_values($partitions));
+ $this->defaultPartition = $defaultPartition;
+ }
+ public function __invoke(array $args = [])
+ {
+ $partition = $this->getPartition(isset($args['region']) ? $args['region'] : '', isset($args['service']) ? $args['service'] : '');
+ return $partition($args);
+ }
+ /**
+ * Returns the partition containing the provided region or the default
+ * partition if no match is found.
+ *
+ * @param string $region
+ * @param string $service
+ *
+ * @return Partition
+ */
+ public function getPartition($region, $service)
+ {
+ foreach ($this->partitions as $partition) {
+ if ($partition->isRegionMatch($region, $service)) {
+ return $partition;
+ }
+ }
+ return $this->getPartitionByName($this->defaultPartition);
+ }
+ /**
+ * Returns the partition with the provided name or null if no partition with
+ * the provided name can be found.
+ *
+ * @param string $name
+ *
+ * @return Partition|null
+ */
+ public function getPartitionByName($name)
+ {
+ foreach ($this->partitions as $partition) {
+ if ($name === $partition->getName()) {
+ return $partition;
+ }
+ }
+ }
+ /**
+ * Creates and returns the default SDK partition provider.
+ *
+ * @return PartitionEndpointProvider
+ */
+ public static function defaultProvider()
+ {
+ $data = \DeliciousBrains\WP_Offload_S3\Aws3\Aws\load_compiled_json(__DIR__ . '/../data/endpoints.json');
+ return new self($data['partitions']);
+ }
+}
diff --git a/vendor/Aws3/Aws/Endpoint/PartitionInterface.php b/vendor/Aws3/Aws/Endpoint/PartitionInterface.php
new file mode 100644
index 00000000..f8d7f8ec
--- /dev/null
+++ b/vendor/Aws3/Aws/Endpoint/PartitionInterface.php
@@ -0,0 +1,51 @@
+patterns = $patterns;
+ }
+ public function __invoke(array $args = [])
+ {
+ $service = isset($args['service']) ? $args['service'] : '';
+ $region = isset($args['region']) ? $args['region'] : '';
+ $keys = ["{$region}/{$service}", "{$region}/*", "*/{$service}", "*/*"];
+ foreach ($keys as $key) {
+ if (isset($this->patterns[$key])) {
+ return $this->expand($this->patterns[$key], isset($args['scheme']) ? $args['scheme'] : 'https', $service, $region);
+ }
+ }
+ return null;
+ }
+ private function expand(array $config, $scheme, $service, $region)
+ {
+ $config['endpoint'] = $scheme . '://' . strtr($config['endpoint'], ['{service}' => $service, '{region}' => $region]);
+ return $config;
+ }
+}
diff --git a/vendor/Aws3/Aws/Exception/AwsException.php b/vendor/Aws3/Aws/Exception/AwsException.php
new file mode 100644
index 00000000..b0a83cd0
--- /dev/null
+++ b/vendor/Aws3/Aws/Exception/AwsException.php
@@ -0,0 +1,175 @@
+command = $command;
+ $this->response = isset($context['response']) ? $context['response'] : null;
+ $this->request = isset($context['request']) ? $context['request'] : null;
+ $this->requestId = isset($context['request_id']) ? $context['request_id'] : null;
+ $this->errorType = isset($context['type']) ? $context['type'] : null;
+ $this->errorCode = isset($context['code']) ? $context['code'] : null;
+ $this->connectionError = !empty($context['connection_error']);
+ $this->result = isset($context['result']) ? $context['result'] : null;
+ $this->transferInfo = isset($context['transfer_stats']) ? $context['transfer_stats'] : [];
+ $this->errorMessage = isset($context['message']) ? $context['message'] : null;
+ parent::__construct($message, 0, $previous);
+ }
+ public function __toString()
+ {
+ if (!$this->getPrevious()) {
+ return parent::__toString();
+ }
+ // PHP strangely shows the innermost exception first before the outer
+ // exception message. It also has a default character limit for
+ // exception message strings such that the "next" exception (this one)
+ // might not even get shown, causing developers to attempt to catch
+ // the inner exception instead of the actual exception because they
+ // can't see the outer exception's __toString output.
+ return sprintf("exception '%s' with message '%s'\n\n%s", get_class($this), $this->getMessage(), parent::__toString());
+ }
+ /**
+ * Get the command that was executed.
+ *
+ * @return CommandInterface
+ */
+ public function getCommand()
+ {
+ return $this->command;
+ }
+ /**
+ * Get the concise error message if any.
+ *
+ * @return string|null
+ */
+ public function getAwsErrorMessage()
+ {
+ return $this->errorMessage;
+ }
+ /**
+ * Get the sent HTTP request if any.
+ *
+ * @return RequestInterface|null
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+ /**
+ * Get the received HTTP response if any.
+ *
+ * @return ResponseInterface|null
+ */
+ public function getResponse()
+ {
+ return $this->response;
+ }
+ /**
+ * Get the result of the exception if available
+ *
+ * @return ResultInterface|null
+ */
+ public function getResult()
+ {
+ return $this->result;
+ }
+ /**
+ * Returns true if this is a connection error.
+ *
+ * @return bool
+ */
+ public function isConnectionError()
+ {
+ return $this->connectionError;
+ }
+ /**
+ * If available, gets the HTTP status code of the corresponding response
+ *
+ * @return int|null
+ */
+ public function getStatusCode()
+ {
+ return $this->response ? $this->response->getStatusCode() : null;
+ }
+ /**
+ * Get the request ID of the error. This value is only present if a
+ * response was received and is not present in the event of a networking
+ * error.
+ *
+ * @return string|null Returns null if no response was received
+ */
+ public function getAwsRequestId()
+ {
+ return $this->requestId;
+ }
+ /**
+ * Get the AWS error type.
+ *
+ * @return string|null Returns null if no response was received
+ */
+ public function getAwsErrorType()
+ {
+ return $this->errorType;
+ }
+ /**
+ * Get the AWS error code.
+ *
+ * @return string|null Returns null if no response was received
+ */
+ public function getAwsErrorCode()
+ {
+ return $this->errorCode;
+ }
+ /**
+ * Get all transfer information as an associative array if no $name
+ * argument is supplied, or gets a specific transfer statistic if
+ * a $name attribute is supplied (e.g., 'retries_attempted').
+ *
+ * @param string $name Name of the transfer stat to retrieve
+ *
+ * @return mixed|null|array
+ */
+ public function getTransferInfo($name = null)
+ {
+ if (!$name) {
+ return $this->transferInfo;
+ }
+ return isset($this->transferInfo[$name]) ? $this->transferInfo[$name] : null;
+ }
+ /**
+ * Replace the transfer information associated with an exception.
+ *
+ * @param array $info
+ */
+ public function setTransferInfo(array $info)
+ {
+ $this->transferInfo = $info;
+ }
+}
diff --git a/vendor/Aws3/Aws/Exception/CouldNotCreateChecksumException.php b/vendor/Aws3/Aws/Exception/CouldNotCreateChecksumException.php
new file mode 100644
index 00000000..666e32d2
--- /dev/null
+++ b/vendor/Aws3/Aws/Exception/CouldNotCreateChecksumException.php
@@ -0,0 +1,12 @@
+ 'uploading parts to']);
+ $msg .= ". The following parts had errors:\n";
+ /** @var $error AwsException */
+ foreach ($prev as $part => $error) {
+ $msg .= "- Part {$part}: " . $error->getMessage() . "\n";
+ }
+ } elseif ($prev instanceof AwsException) {
+ switch ($prev->getCommand()->getName()) {
+ case 'CreateMultipartUpload':
+ case 'InitiateMultipartUpload':
+ $action = 'initiating';
+ break;
+ case 'CompleteMultipartUpload':
+ $action = 'completing';
+ break;
+ }
+ if (isset($action)) {
+ $msg = strtr($msg, ['performing' => $action]);
+ }
+ $msg .= ": {$prev->getMessage()}";
+ }
+ if (!$prev instanceof \Exception) {
+ $prev = null;
+ }
+ parent::__construct($msg, 0, $prev);
+ $this->state = $state;
+ }
+ /**
+ * Get the state of the transfer
+ *
+ * @return UploadState
+ */
+ public function getState()
+ {
+ return $this->state;
+ }
+}
diff --git a/vendor/Aws3/Aws/Exception/UnresolvedApiException.php b/vendor/Aws3/Aws/Exception/UnresolvedApiException.php
new file mode 100644
index 00000000..d33a6e3a
--- /dev/null
+++ b/vendor/Aws3/Aws/Exception/UnresolvedApiException.php
@@ -0,0 +1,7 @@
+ true, 'verify' => true, 'timeout' => true, 'debug' => true, 'connect_timeout' => true, 'stream' => true, 'delay' => true, 'sink' => true];
+ /** @var ClientInterface */
+ private $client;
+ /**
+ * @param ClientInterface $client
+ */
+ public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\ClientInterface $client = null)
+ {
+ $this->client = $client ?: new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Client();
+ }
+ /**
+ * @param Psr7Request $request
+ * @param array $options
+ *
+ * @return Promise\Promise
+ */
+ public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request, array $options = [])
+ {
+ // Create and send a Guzzle 5 request
+ $guzzlePromise = $this->client->send($this->createGuzzleRequest($request, $options));
+ $promise = new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\Promise(function () use($guzzlePromise) {
+ try {
+ $guzzlePromise->wait();
+ } catch (\Exception $e) {
+ // The promise is already delivered when the exception is
+ // thrown, so don't rethrow it.
+ }
+ }, [$guzzlePromise, 'cancel']);
+ $guzzlePromise->then([$promise, 'resolve'], [$promise, 'reject']);
+ return $promise->then(function (\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Message\ResponseInterface $response) {
+ // Adapt the Guzzle 5 Future to a Guzzle 6 ResponsePromise.
+ return $this->createPsr7Response($response);
+ }, function (\Exception $exception) use($options) {
+ // If we got a 'sink' that's a path, set the response body to
+ // the contents of the file. This will build the resulting
+ // exception with more information.
+ if ($exception instanceof RequestException) {
+ if (isset($options['sink'])) {
+ if (!$options['sink'] instanceof Psr7StreamInterface) {
+ $exception->getResponse()->setBody(\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Stream\Stream::factory(file_get_contents($options['sink'])));
+ }
+ }
+ }
+ // Reject with information about the error.
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\RejectedPromise($this->prepareErrorData($exception));
+ });
+ }
+ private function createGuzzleRequest(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $psrRequest, array $options)
+ {
+ $ringConfig = [];
+ $statsCallback = isset($options['http_stats_receiver']) ? $options['http_stats_receiver'] : null;
+ unset($options['http_stats_receiver']);
+ // Remove unsupported options.
+ foreach (array_keys($options) as $key) {
+ if (!isset(self::$validOptions[$key])) {
+ unset($options[$key]);
+ }
+ }
+ // Handle delay option.
+ if (isset($options['delay'])) {
+ $ringConfig['delay'] = $options['delay'];
+ unset($options['delay']);
+ }
+ // Prepare sink option.
+ if (isset($options['sink'])) {
+ $ringConfig['save_to'] = $options['sink'] instanceof Psr7StreamInterface ? new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Handler\GuzzleV5\GuzzleStream($options['sink']) : $options['sink'];
+ unset($options['sink']);
+ }
+ // Ensure that all requests are async and lazy like Guzzle 6.
+ $options['future'] = 'lazy';
+ // Create the Guzzle 5 request from the provided PSR7 request.
+ $request = $this->client->createRequest($psrRequest->getMethod(), $psrRequest->getUri(), $options);
+ if (is_callable($statsCallback)) {
+ $request->getEmitter()->on('end', function (\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Event\EndEvent $event) use($statsCallback) {
+ $statsCallback($event->getTransferInfo());
+ });
+ }
+ // For the request body, adapt the PSR stream to a Guzzle stream.
+ $body = $psrRequest->getBody();
+ if ($body->getSize() === 0) {
+ $request->setBody(null);
+ } else {
+ $request->setBody(new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Handler\GuzzleV5\GuzzleStream($body));
+ }
+ $request->setHeaders($psrRequest->getHeaders());
+ $request->setHeader('User-Agent', $request->getHeader('User-Agent') . ' ' . \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Client::getDefaultUserAgent());
+ // Make sure the delay is configured, if provided.
+ if ($ringConfig) {
+ foreach ($ringConfig as $k => $v) {
+ $request->getConfig()->set($k, $v);
+ }
+ }
+ return $request;
+ }
+ private function createPsr7Response(\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Message\ResponseInterface $response)
+ {
+ if ($body = $response->getBody()) {
+ $body = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Handler\GuzzleV5\PsrStream($body);
+ }
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Response($response->getStatusCode(), $response->getHeaders(), $body, $response->getReasonPhrase());
+ }
+ private function prepareErrorData(\Exception $e)
+ {
+ $error = ['exception' => $e, 'connection_error' => false, 'response' => null];
+ if ($e instanceof ConnectException) {
+ $error['connection_error'] = true;
+ }
+ if ($e instanceof RequestException && $e->getResponse()) {
+ $error['response'] = $this->createPsr7Response($e->getResponse());
+ }
+ return $error;
+ }
+}
diff --git a/vendor/Aws3/Aws/Handler/GuzzleV5/GuzzleStream.php b/vendor/Aws3/Aws/Handler/GuzzleV5/GuzzleStream.php
new file mode 100644
index 00000000..cb513732
--- /dev/null
+++ b/vendor/Aws3/Aws/Handler/GuzzleV5/GuzzleStream.php
@@ -0,0 +1,22 @@
+stream = $stream;
+ }
+}
diff --git a/vendor/Aws3/Aws/Handler/GuzzleV5/PsrStream.php b/vendor/Aws3/Aws/Handler/GuzzleV5/PsrStream.php
new file mode 100644
index 00000000..007be8a1
--- /dev/null
+++ b/vendor/Aws3/Aws/Handler/GuzzleV5/PsrStream.php
@@ -0,0 +1,30 @@
+stream = $stream;
+ }
+ public function rewind()
+ {
+ $this->stream->seek(0);
+ }
+ public function getContents()
+ {
+ return $this->stream->getContents();
+ }
+}
diff --git a/vendor/Aws3/Aws/Handler/GuzzleV6/GuzzleHandler.php b/vendor/Aws3/Aws/Handler/GuzzleV6/GuzzleHandler.php
new file mode 100644
index 00000000..69fd8d50
--- /dev/null
+++ b/vendor/Aws3/Aws/Handler/GuzzleV6/GuzzleHandler.php
@@ -0,0 +1,61 @@
+client = $client ?: new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Client();
+ }
+ /**
+ * @param Psr7Request $request
+ * @param array $options
+ *
+ * @return Promise\Promise
+ */
+ public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request, array $options = [])
+ {
+ $request = $request->withHeader('User-Agent', $request->getHeaderLine('User-Agent') . ' ' . \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\default_user_agent());
+ return $this->client->sendAsync($request, $this->parseOptions($options))->otherwise(static function (\Exception $e) {
+ $error = ['exception' => $e, 'connection_error' => $e instanceof ConnectException, 'response' => null];
+ if ($e instanceof RequestException && $e->getResponse()) {
+ $error['response'] = $e->getResponse();
+ }
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\RejectedPromise($error);
+ });
+ }
+ private function parseOptions(array $options)
+ {
+ if (isset($options['http_stats_receiver'])) {
+ $fn = $options['http_stats_receiver'];
+ unset($options['http_stats_receiver']);
+ $prev = isset($options['on_stats']) ? $options['on_stats'] : null;
+ $options['on_stats'] = static function (\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\TransferStats $stats) use($fn, $prev) {
+ if (is_callable($prev)) {
+ $prev($stats);
+ }
+ $transferStats = ['total_time' => $stats->getTransferTime()];
+ $transferStats += $stats->getHandlerStats();
+ $fn($transferStats);
+ };
+ }
+ return $options;
+ }
+}
diff --git a/vendor/Aws3/Aws/HandlerList.php b/vendor/Aws3/Aws/HandlerList.php
new file mode 100644
index 00000000..f31f13be
--- /dev/null
+++ b/vendor/Aws3/Aws/HandlerList.php
@@ -0,0 +1,366 @@
+ [], self::BUILD => [], self::VALIDATE => [], self::INIT => []];
+ /**
+ * @param callable $handler HTTP handler.
+ */
+ public function __construct(callable $handler = null)
+ {
+ $this->handler = $handler;
+ }
+ /**
+ * Dumps a string representation of the list.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $str = '';
+ $i = 0;
+ foreach (array_reverse($this->steps) as $k => $step) {
+ foreach (array_reverse($step) as $j => $tuple) {
+ $str .= "{$i}) Step: {$k}, ";
+ if ($tuple[1]) {
+ $str .= "Name: {$tuple[1]}, ";
+ }
+ $str .= "Function: " . $this->debugCallable($tuple[0]) . "\n";
+ $i++;
+ }
+ }
+ if ($this->handler) {
+ $str .= "{$i}) Handler: " . $this->debugCallable($this->handler) . "\n";
+ }
+ return $str;
+ }
+ /**
+ * Set the HTTP handler that actually returns a response.
+ *
+ * @param callable $handler Function that accepts a request and array of
+ * options and returns a Promise.
+ */
+ public function setHandler(callable $handler)
+ {
+ $this->handler = $handler;
+ }
+ /**
+ * Returns true if the builder has a handler.
+ *
+ * @return bool
+ */
+ public function hasHandler()
+ {
+ return (bool) $this->handler;
+ }
+ /**
+ * Append a middleware to the init step.
+ *
+ * @param callable $middleware Middleware function to add.
+ * @param string $name Name of the middleware.
+ */
+ public function appendInit(callable $middleware, $name = null)
+ {
+ $this->add(self::INIT, $name, $middleware);
+ }
+ /**
+ * Prepend a middleware to the init step.
+ *
+ * @param callable $middleware Middleware function to add.
+ * @param string $name Name of the middleware.
+ */
+ public function prependInit(callable $middleware, $name = null)
+ {
+ $this->add(self::INIT, $name, $middleware, true);
+ }
+ /**
+ * Append a middleware to the validate step.
+ *
+ * @param callable $middleware Middleware function to add.
+ * @param string $name Name of the middleware.
+ */
+ public function appendValidate(callable $middleware, $name = null)
+ {
+ $this->add(self::VALIDATE, $name, $middleware);
+ }
+ /**
+ * Prepend a middleware to the validate step.
+ *
+ * @param callable $middleware Middleware function to add.
+ * @param string $name Name of the middleware.
+ */
+ public function prependValidate(callable $middleware, $name = null)
+ {
+ $this->add(self::VALIDATE, $name, $middleware, true);
+ }
+ /**
+ * Append a middleware to the build step.
+ *
+ * @param callable $middleware Middleware function to add.
+ * @param string $name Name of the middleware.
+ */
+ public function appendBuild(callable $middleware, $name = null)
+ {
+ $this->add(self::BUILD, $name, $middleware);
+ }
+ /**
+ * Prepend a middleware to the build step.
+ *
+ * @param callable $middleware Middleware function to add.
+ * @param string $name Name of the middleware.
+ */
+ public function prependBuild(callable $middleware, $name = null)
+ {
+ $this->add(self::BUILD, $name, $middleware, true);
+ }
+ /**
+ * Append a middleware to the sign step.
+ *
+ * @param callable $middleware Middleware function to add.
+ * @param string $name Name of the middleware.
+ */
+ public function appendSign(callable $middleware, $name = null)
+ {
+ $this->add(self::SIGN, $name, $middleware);
+ }
+ /**
+ * Prepend a middleware to the sign step.
+ *
+ * @param callable $middleware Middleware function to add.
+ * @param string $name Name of the middleware.
+ */
+ public function prependSign(callable $middleware, $name = null)
+ {
+ $this->add(self::SIGN, $name, $middleware, true);
+ }
+ /**
+ * Add a middleware before the given middleware by name.
+ *
+ * @param string|callable $findName Add before this
+ * @param string $withName Optional name to give the middleware
+ * @param callable $middleware Middleware to add.
+ */
+ public function before($findName, $withName, callable $middleware)
+ {
+ $this->splice($findName, $withName, $middleware, true);
+ }
+ /**
+ * Add a middleware after the given middleware by name.
+ *
+ * @param string|callable $findName Add after this
+ * @param string $withName Optional name to give the middleware
+ * @param callable $middleware Middleware to add.
+ */
+ public function after($findName, $withName, callable $middleware)
+ {
+ $this->splice($findName, $withName, $middleware, false);
+ }
+ /**
+ * Remove a middleware by name or by instance from the list.
+ *
+ * @param string|callable $nameOrInstance Middleware to remove.
+ */
+ public function remove($nameOrInstance)
+ {
+ if (is_callable($nameOrInstance)) {
+ $this->removeByInstance($nameOrInstance);
+ } elseif (is_string($nameOrInstance)) {
+ $this->removeByName($nameOrInstance);
+ }
+ }
+ /**
+ * Interpose a function between each middleware (e.g., allowing for a trace
+ * through the middleware layers).
+ *
+ * The interpose function is a function that accepts a "step" argument as a
+ * string and a "name" argument string. This function must then return a
+ * function that accepts the next handler in the list. This function must
+ * then return a function that accepts a CommandInterface and optional
+ * RequestInterface and returns a promise that is fulfilled with an
+ * Aws\ResultInterface or rejected with an Aws\Exception\AwsException
+ * object.
+ *
+ * @param callable|null $fn Pass null to remove any previously set function
+ */
+ public function interpose(callable $fn = null)
+ {
+ $this->sorted = null;
+ $this->interposeFn = $fn;
+ }
+ /**
+ * Compose the middleware and handler into a single callable function.
+ *
+ * @return callable
+ */
+ public function resolve()
+ {
+ if (!($prev = $this->handler)) {
+ throw new \LogicException('No handler has been specified');
+ }
+ if ($this->sorted === null) {
+ $this->sortMiddleware();
+ }
+ foreach ($this->sorted as $fn) {
+ $prev = $fn($prev);
+ }
+ return $prev;
+ }
+ public function count()
+ {
+ return count($this->steps[self::INIT]) + count($this->steps[self::VALIDATE]) + count($this->steps[self::BUILD]) + count($this->steps[self::SIGN]);
+ }
+ /**
+ * Splices a function into the middleware list at a specific position.
+ *
+ * @param $findName
+ * @param $withName
+ * @param callable $middleware
+ * @param $before
+ */
+ private function splice($findName, $withName, callable $middleware, $before)
+ {
+ if (!isset($this->named[$findName])) {
+ throw new \InvalidArgumentException("{$findName} not found");
+ }
+ $idx = $this->sorted = null;
+ $step = $this->named[$findName];
+ if ($withName) {
+ $this->named[$withName] = $step;
+ }
+ foreach ($this->steps[$step] as $i => $tuple) {
+ if ($tuple[1] === $findName) {
+ $idx = $i;
+ break;
+ }
+ }
+ $replacement = $before ? [$this->steps[$step][$idx], [$middleware, $withName]] : [[$middleware, $withName], $this->steps[$step][$idx]];
+ array_splice($this->steps[$step], $idx, 1, $replacement);
+ }
+ /**
+ * Provides a debug string for a given callable.
+ *
+ * @param array|callable $fn Function to write as a string.
+ *
+ * @return string
+ */
+ private function debugCallable($fn)
+ {
+ if (is_string($fn)) {
+ return "callable({$fn})";
+ }
+ if (is_array($fn)) {
+ $ele = is_string($fn[0]) ? $fn[0] : get_class($fn[0]);
+ return "callable(['{$ele}', '{$fn[1]}'])";
+ }
+ return 'callable(' . spl_object_hash($fn) . ')';
+ }
+ /**
+ * Sort the middleware, and interpose if needed in the sorted list.
+ */
+ private function sortMiddleware()
+ {
+ $this->sorted = [];
+ if (!$this->interposeFn) {
+ foreach ($this->steps as $step) {
+ foreach ($step as $fn) {
+ $this->sorted[] = $fn[0];
+ }
+ }
+ return;
+ }
+ $ifn = $this->interposeFn;
+ // Interpose the interposeFn into the handler stack.
+ foreach ($this->steps as $stepName => $step) {
+ foreach ($step as $fn) {
+ $this->sorted[] = $ifn($stepName, $fn[1]);
+ $this->sorted[] = $fn[0];
+ }
+ }
+ }
+ private function removeByName($name)
+ {
+ if (!isset($this->named[$name])) {
+ return;
+ }
+ $this->sorted = null;
+ $step = $this->named[$name];
+ $this->steps[$step] = array_values(array_filter($this->steps[$step], function ($tuple) use($name) {
+ return $tuple[1] !== $name;
+ }));
+ }
+ private function removeByInstance(callable $fn)
+ {
+ foreach ($this->steps as $k => $step) {
+ foreach ($step as $j => $tuple) {
+ if ($tuple[0] === $fn) {
+ $this->sorted = null;
+ unset($this->named[$this->steps[$k][$j][1]]);
+ unset($this->steps[$k][$j]);
+ }
+ }
+ }
+ }
+ /**
+ * Add a middleware to a step.
+ *
+ * @param string $step Middleware step.
+ * @param string $name Middleware name.
+ * @param callable $middleware Middleware function to add.
+ * @param bool $prepend Prepend instead of append.
+ */
+ private function add($step, $name, callable $middleware, $prepend = false)
+ {
+ $this->sorted = null;
+ if ($prepend) {
+ $this->steps[$step][] = [$middleware, $name];
+ } else {
+ array_unshift($this->steps[$step], [$middleware, $name]);
+ }
+ if ($name) {
+ $this->named[$name] = $step;
+ }
+ }
+}
diff --git a/vendor/Aws3/Aws/HasDataTrait.php b/vendor/Aws3/Aws/HasDataTrait.php
new file mode 100644
index 00000000..88c42342
--- /dev/null
+++ b/vendor/Aws3/Aws/HasDataTrait.php
@@ -0,0 +1,53 @@
+data);
+ }
+ /**
+ * This method returns a reference to the variable to allow for indirect
+ * array modification (e.g., $foo['bar']['baz'] = 'qux').
+ *
+ * @param $offset
+ *
+ * @return mixed|null
+ */
+ public function &offsetGet($offset)
+ {
+ if (isset($this->data[$offset])) {
+ return $this->data[$offset];
+ }
+ $value = null;
+ return $value;
+ }
+ public function offsetSet($offset, $value)
+ {
+ $this->data[$offset] = $value;
+ }
+ public function offsetExists($offset)
+ {
+ return isset($this->data[$offset]);
+ }
+ public function offsetUnset($offset)
+ {
+ unset($this->data[$offset]);
+ }
+ public function toArray()
+ {
+ return $this->data;
+ }
+ public function count()
+ {
+ return count($this->data);
+ }
+}
diff --git a/vendor/Aws3/Aws/HashInterface.php b/vendor/Aws3/Aws/HashInterface.php
new file mode 100644
index 00000000..0b412067
--- /dev/null
+++ b/vendor/Aws3/Aws/HashInterface.php
@@ -0,0 +1,26 @@
+stream = $stream;
+ $this->hash = $hash;
+ $this->callback = $onComplete;
+ }
+ public function read($length)
+ {
+ $data = $this->stream->read($length);
+ $this->hash->update($data);
+ if ($this->eof()) {
+ $result = $this->hash->complete();
+ if ($this->callback) {
+ call_user_func($this->callback, $result);
+ }
+ }
+ return $data;
+ }
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if ($offset === 0) {
+ $this->hash->reset();
+ return $this->stream->seek($offset);
+ }
+ // Seeking arbitrarily is not supported.
+ return false;
+ }
+}
diff --git a/vendor/Aws3/Aws/History.php b/vendor/Aws3/Aws/History.php
new file mode 100644
index 00000000..ee8a0e0f
--- /dev/null
+++ b/vendor/Aws3/Aws/History.php
@@ -0,0 +1,129 @@
+maxEntries = $maxEntries;
+ }
+ public function count()
+ {
+ return count($this->entries);
+ }
+ public function getIterator()
+ {
+ return new \ArrayIterator(array_values($this->entries));
+ }
+ /**
+ * Get the last finished command seen by the history container.
+ *
+ * @return CommandInterface
+ * @throws \LogicException if no commands have been seen.
+ */
+ public function getLastCommand()
+ {
+ if (!$this->entries) {
+ throw new \LogicException('No commands received');
+ }
+ return end($this->entries)['command'];
+ }
+ /**
+ * Get the last finished request seen by the history container.
+ *
+ * @return RequestInterface
+ * @throws \LogicException if no requests have been seen.
+ */
+ public function getLastRequest()
+ {
+ if (!$this->entries) {
+ throw new \LogicException('No requests received');
+ }
+ return end($this->entries)['request'];
+ }
+ /**
+ * Get the last received result or exception.
+ *
+ * @return ResultInterface|AwsException
+ * @throws \LogicException if no return values have been received.
+ */
+ public function getLastReturn()
+ {
+ if (!$this->entries) {
+ throw new \LogicException('No entries');
+ }
+ $last = end($this->entries);
+ if (isset($last['result'])) {
+ return $last['result'];
+ }
+ if (isset($last['exception'])) {
+ return $last['exception'];
+ }
+ throw new \LogicException('No return value for last entry.');
+ }
+ /**
+ * Initiate an entry being added to the history.
+ *
+ * @param CommandInterface $cmd Command be executed.
+ * @param RequestInterface $req Request being sent.
+ *
+ * @return string Returns the ticket used to finish the entry.
+ */
+ public function start(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $cmd, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $req)
+ {
+ $ticket = uniqid();
+ $this->entries[$ticket] = ['command' => $cmd, 'request' => $req, 'result' => null, 'exception' => null];
+ return $ticket;
+ }
+ /**
+ * Finish adding an entry to the history container.
+ *
+ * @param string $ticket Ticket returned from the start call.
+ * @param mixed $result The result (an exception or AwsResult).
+ */
+ public function finish($ticket, $result)
+ {
+ if (!isset($this->entries[$ticket])) {
+ throw new \InvalidArgumentException('Invalid history ticket');
+ }
+ if (isset($this->entries[$ticket]['result']) || isset($this->entries[$ticket]['exception'])) {
+ throw new \LogicException('History entry is already finished');
+ }
+ if ($result instanceof \Exception) {
+ $this->entries[$ticket]['exception'] = $result;
+ } else {
+ $this->entries[$ticket]['result'] = $result;
+ }
+ if (count($this->entries) >= $this->maxEntries) {
+ $this->entries = array_slice($this->entries, -$this->maxEntries, null, true);
+ }
+ }
+ /**
+ * Flush the history
+ */
+ public function clear()
+ {
+ $this->entries = [];
+ }
+ /**
+ * Converts the history to an array.
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ return array_values($this->entries);
+ }
+}
diff --git a/vendor/Aws3/Aws/IdempotencyTokenMiddleware.php b/vendor/Aws3/Aws/IdempotencyTokenMiddleware.php
new file mode 100644
index 00000000..822ef871
--- /dev/null
+++ b/vendor/Aws3/Aws/IdempotencyTokenMiddleware.php
@@ -0,0 +1,102 @@
+bytesGenerator = $bytesGenerator ?: $this->findCompatibleRandomSource();
+ $this->service = $service;
+ $this->nextHandler = $nextHandler;
+ }
+ public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request = null)
+ {
+ $handler = $this->nextHandler;
+ if ($this->bytesGenerator) {
+ $operation = $this->service->getOperation($command->getName());
+ $members = $operation->getInput()->getMembers();
+ foreach ($members as $member => $value) {
+ if ($value['idempotencyToken']) {
+ $bytes = call_user_func($this->bytesGenerator, 16);
+ // populating UUIDv4 only when the parameter is not set
+ $command[$member] = $command[$member] ?: $this->getUuidV4($bytes);
+ // only one member could have the trait enabled
+ break;
+ }
+ }
+ }
+ return $handler($command, $request);
+ }
+ /**
+ * This function generates a random UUID v4 string,
+ * which is used as auto filled token value.
+ *
+ * @param string $bytes 16 bytes of pseudo-random bytes
+ * @return string
+ * More information about UUID v4, see:
+ * https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29
+ * https://tools.ietf.org/html/rfc4122#page-14
+ */
+ private static function getUuidV4($bytes)
+ {
+ // set version to 0100
+ $bytes[6] = chr(ord($bytes[6]) & 0xf | 0x40);
+ // set bits 6-7 to 10
+ $bytes[8] = chr(ord($bytes[8]) & 0x3f | 0x80);
+ return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($bytes), 4));
+ }
+ /**
+ * This function decides the PHP function used in generating random bytes.
+ *
+ * @return callable|null
+ */
+ private function findCompatibleRandomSource()
+ {
+ if (function_exists('random_bytes')) {
+ return 'random_bytes';
+ }
+ if (function_exists('openssl_random_pseudo_bytes')) {
+ return 'openssl_random_pseudo_bytes';
+ }
+ if (function_exists('mcrypt_create_iv')) {
+ return 'mcrypt_create_iv';
+ }
+ }
+}
diff --git a/vendor/Aws3/Aws/JsonCompiler.php b/vendor/Aws3/Aws/JsonCompiler.php
new file mode 100644
index 00000000..4fb8ce27
--- /dev/null
+++ b/vendor/Aws3/Aws/JsonCompiler.php
@@ -0,0 +1,25 @@
+maxItems = $maxItems;
+ }
+ public function get($key)
+ {
+ if (!isset($this->items[$key])) {
+ return null;
+ }
+ $entry = $this->items[$key];
+ // Ensure the item is not expired.
+ if (!$entry[1] || time() < $entry[1]) {
+ // LRU: remove the item and push it to the end of the array.
+ unset($this->items[$key]);
+ $this->items[$key] = $entry;
+ return $entry[0];
+ }
+ unset($this->items[$key]);
+ return null;
+ }
+ public function set($key, $value, $ttl = 0)
+ {
+ // Only call time() if the TTL is not 0/false/null
+ $ttl = $ttl ? time() + $ttl : 0;
+ $this->items[$key] = [$value, $ttl];
+ // Determine if there are more items in the cache than allowed.
+ $diff = count($this->items) - $this->maxItems;
+ // Clear out least recently used items.
+ if ($diff > 0) {
+ // Reset to the beginning of the array and begin unsetting.
+ reset($this->items);
+ for ($i = 0; $i < $diff; $i++) {
+ unset($this->items[key($this->items)]);
+ next($this->items);
+ }
+ }
+ }
+ public function remove($key)
+ {
+ unset($this->items[$key]);
+ }
+ public function count()
+ {
+ return count($this->items);
+ }
+}
diff --git a/vendor/Aws3/Aws/Middleware.php b/vendor/Aws3/Aws/Middleware.php
new file mode 100644
index 00000000..7416288e
--- /dev/null
+++ b/vendor/Aws3/Aws/Middleware.php
@@ -0,0 +1,276 @@
+getOperation($command->getName());
+ $source = $command[$sourceParameter];
+ if ($source !== null && $operation->getInput()->hasMember($bodyParameter)) {
+ $command[$bodyParameter] = new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\LazyOpenStream($source, 'r');
+ unset($command[$sourceParameter]);
+ }
+ return $handler($command, $request);
+ };
+ };
+ }
+ /**
+ * Adds a middleware that uses client-side validation.
+ *
+ * @param Service $api API being accessed.
+ *
+ * @return callable
+ */
+ public static function validation(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Validator $validator = null)
+ {
+ $validator = $validator ?: new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Validator();
+ return function (callable $handler) use($api, $validator) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request = null) use($api, $validator, $handler) {
+ $operation = $api->getOperation($command->getName());
+ $validator->validate($command->getName(), $operation->getInput(), $command->toArray());
+ return $handler($command, $request);
+ };
+ };
+ }
+ /**
+ * Builds an HTTP request for a command.
+ *
+ * @param callable $serializer Function used to serialize a request for a
+ * command.
+ * @return callable
+ */
+ public static function requestBuilder(callable $serializer)
+ {
+ return function (callable $handler) use($serializer) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command) use($serializer, $handler) {
+ return $handler($command, $serializer($command));
+ };
+ };
+ }
+ /**
+ * Creates a middleware that signs requests for a command.
+ *
+ * @param callable $credProvider Credentials provider function that
+ * returns a promise that is resolved
+ * with a CredentialsInterface object.
+ * @param callable $signatureFunction Function that accepts a Command
+ * object and returns a
+ * SignatureInterface.
+ *
+ * @return callable
+ */
+ public static function signer(callable $credProvider, callable $signatureFunction)
+ {
+ return function (callable $handler) use($signatureFunction, $credProvider) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request) use($handler, $signatureFunction, $credProvider) {
+ $signer = $signatureFunction($command);
+ return $credProvider()->then(function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Credentials\CredentialsInterface $creds) use($handler, $command, $signer, $request) {
+ return $handler($command, $signer->signRequest($request, $creds));
+ });
+ };
+ };
+ }
+ /**
+ * Creates a middleware that invokes a callback at a given step.
+ *
+ * The tap callback accepts a CommandInterface and RequestInterface as
+ * arguments but is not expected to return a new value or proxy to
+ * downstream middleware. It's simply a way to "tap" into the handler chain
+ * to debug or get an intermediate value.
+ *
+ * @param callable $fn Tap function
+ *
+ * @return callable
+ */
+ public static function tap(callable $fn)
+ {
+ return function (callable $handler) use($fn) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request = null) use($handler, $fn) {
+ $fn($command, $request);
+ return $handler($command, $request);
+ };
+ };
+ }
+ /**
+ * Middleware wrapper function that retries requests based on the boolean
+ * result of invoking the provided "decider" function.
+ *
+ * If no delay function is provided, a simple implementation of exponential
+ * backoff will be utilized.
+ *
+ * @param callable $decider Function that accepts the number of retries,
+ * a request, [result], and [exception] and
+ * returns true if the command is to be retried.
+ * @param callable $delay Function that accepts the number of retries and
+ * returns the number of milliseconds to delay.
+ * @param bool $stats Whether to collect statistics on retries and the
+ * associated delay.
+ *
+ * @return callable
+ */
+ public static function retry(callable $decider = null, callable $delay = null, $stats = false)
+ {
+ $decider = $decider ?: \DeliciousBrains\WP_Offload_S3\Aws3\Aws\RetryMiddleware::createDefaultDecider();
+ $delay = $delay ?: [\DeliciousBrains\WP_Offload_S3\Aws3\Aws\RetryMiddleware::class, 'exponentialDelay'];
+ return function (callable $handler) use($decider, $delay, $stats) {
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\RetryMiddleware($decider, $delay, $handler, $stats);
+ };
+ }
+ /**
+ * Middleware wrapper function that adds an invocation id header to
+ * requests, which is only applied after the build step.
+ *
+ * This is a uniquely generated UUID to identify initial and subsequent
+ * retries as part of a complete request lifecycle.
+ *
+ * @return callable
+ */
+ public static function invocationId()
+ {
+ return function (callable $handler) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request) use($handler) {
+ return $handler($command, $request->withHeader('aws-sdk-invocation-id', md5(uniqid(gethostname(), true))));
+ };
+ };
+ }
+ /**
+ * Middleware wrapper function that adds a Content-Type header to requests.
+ * This is only done when the Content-Type has not already been set, and the
+ * request body's URI is available. It then checks the file extension of the
+ * URI to determine the mime-type.
+ *
+ * @param array $operations Operations that Content-Type should be added to.
+ *
+ * @return callable
+ */
+ public static function contentType(array $operations)
+ {
+ return function (callable $handler) use($operations) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request = null) use($handler, $operations) {
+ if (!$request->hasHeader('Content-Type') && in_array($command->getName(), $operations, true) && ($uri = $request->getBody()->getMetadata('uri'))) {
+ $request = $request->withHeader('Content-Type', \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\mimetype_from_filename($uri) ?: 'application/octet-stream');
+ }
+ return $handler($command, $request);
+ };
+ };
+ }
+ /**
+ * Tracks command and request history using a history container.
+ *
+ * This is useful for testing.
+ *
+ * @param History $history History container to store entries.
+ *
+ * @return callable
+ */
+ public static function history(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\History $history)
+ {
+ return function (callable $handler) use($history) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request = null) use($handler, $history) {
+ $ticket = $history->start($command, $request);
+ return $handler($command, $request)->then(function ($result) use($history, $ticket) {
+ $history->finish($ticket, $result);
+ return $result;
+ }, function ($reason) use($history, $ticket) {
+ $history->finish($ticket, $reason);
+ return \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\rejection_for($reason);
+ });
+ };
+ };
+ }
+ /**
+ * Creates a middleware that applies a map function to requests as they
+ * pass through the middleware.
+ *
+ * @param callable $f Map function that accepts a RequestInterface and
+ * returns a RequestInterface.
+ *
+ * @return callable
+ */
+ public static function mapRequest(callable $f)
+ {
+ return function (callable $handler) use($f) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request = null) use($handler, $f) {
+ return $handler($command, $f($request));
+ };
+ };
+ }
+ /**
+ * Creates a middleware that applies a map function to commands as they
+ * pass through the middleware.
+ *
+ * @param callable $f Map function that accepts a command and returns a
+ * command.
+ *
+ * @return callable
+ */
+ public static function mapCommand(callable $f)
+ {
+ return function (callable $handler) use($f) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request = null) use($handler, $f) {
+ return $handler($f($command), $request);
+ };
+ };
+ }
+ /**
+ * Creates a middleware that applies a map function to results.
+ *
+ * @param callable $f Map function that accepts an Aws\ResultInterface and
+ * returns an Aws\ResultInterface.
+ *
+ * @return callable
+ */
+ public static function mapResult(callable $f)
+ {
+ return function (callable $handler) use($f) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request = null) use($handler, $f) {
+ return $handler($command, $request)->then($f);
+ };
+ };
+ }
+ public static function timer()
+ {
+ return function (callable $handler) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request = null) use($handler) {
+ $start = microtime(true);
+ return $handler($command, $request)->then(function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\ResultInterface $res) use($start) {
+ if (!isset($res['@metadata'])) {
+ $res['@metadata'] = [];
+ }
+ if (!isset($res['@metadata']['transferStats'])) {
+ $res['@metadata']['transferStats'] = [];
+ }
+ $res['@metadata']['transferStats']['total_time'] = microtime(true) - $start;
+ return $res;
+ }, function ($err) use($start) {
+ if ($err instanceof AwsException) {
+ $err->setTransferInfo(['total_time' => microtime(true) - $start] + $err->getTransferInfo());
+ }
+ return \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\rejection_for($err);
+ });
+ };
+ };
+ }
+}
diff --git a/vendor/Aws3/Aws/MockHandler.php b/vendor/Aws3/Aws/MockHandler.php
new file mode 100644
index 00000000..f94e9077
--- /dev/null
+++ b/vendor/Aws3/Aws/MockHandler.php
@@ -0,0 +1,107 @@
+onFulfilled = $onFulfilled;
+ $this->onRejected = $onRejected;
+ if ($resultOrQueue) {
+ call_user_func_array([$this, 'append'], $resultOrQueue);
+ }
+ }
+ /**
+ * Adds one or more variadic ResultInterface or AwsException objects to the
+ * queue.
+ */
+ public function append()
+ {
+ foreach (func_get_args() as $value) {
+ if ($value instanceof ResultInterface || $value instanceof AwsException || is_callable($value)) {
+ $this->queue[] = $value;
+ } else {
+ throw new \InvalidArgumentException('Expected an Aws\\ResultInterface or Aws\\Exception\\AwsException.');
+ }
+ }
+ }
+ public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request)
+ {
+ if (!$this->queue) {
+ $last = $this->lastCommand ? ' The last command sent was ' . $this->lastCommand->getName() . '.' : '';
+ throw new \RuntimeException('Mock queue is empty. Trying to send a ' . $command->getName() . ' command failed.' . $last);
+ }
+ $this->lastCommand = $command;
+ $this->lastRequest = $request;
+ $result = array_shift($this->queue);
+ if (is_callable($result)) {
+ $result = $result($command, $request);
+ }
+ if ($result instanceof \Exception) {
+ $result = new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\RejectedPromise($result);
+ } else {
+ // Add an effective URI and statusCode if not present.
+ $meta = $result['@metadata'];
+ if (!isset($meta['effectiveUri'])) {
+ $meta['effectiveUri'] = (string) $request->getUri();
+ }
+ if (!isset($meta['statusCode'])) {
+ $meta['statusCode'] = 200;
+ }
+ $result['@metadata'] = $meta;
+ $result = \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\promise_for($result);
+ }
+ $result->then($this->onFulfilled, $this->onRejected);
+ return $result;
+ }
+ /**
+ * Get the last received request.
+ *
+ * @return RequestInterface
+ */
+ public function getLastRequest()
+ {
+ return $this->lastRequest;
+ }
+ /**
+ * Get the last received command.
+ *
+ * @return CommandInterface
+ */
+ public function getLastCommand()
+ {
+ return $this->lastCommand;
+ }
+ /**
+ * Returns the number of remaining items in the queue.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->queue);
+ }
+}
diff --git a/vendor/Aws3/Aws/MultiRegionClient.php b/vendor/Aws3/Aws/MultiRegionClient.php
new file mode 100644
index 00000000..d371e680
--- /dev/null
+++ b/vendor/Aws3/Aws/MultiRegionClient.php
@@ -0,0 +1,174 @@
+ true, 'region' => true]);
+ $args['region']['required'] = false;
+ return $args + ['client_factory' => ['type' => 'config', 'valid' => ['callable'], 'doc' => 'A callable that takes an array of client' . ' configuration arguments and returns a regionalized' . ' client.', 'required' => true, 'internal' => true, 'default' => function (array $args) {
+ $namespace = manifest($args['service'])['namespace'];
+ $klass = "DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\{$namespace}\\{$namespace}Client";
+ $region = isset($args['region']) ? $args['region'] : null;
+ return function (array $args) use($klass, $region) {
+ if ($region && empty($args['region'])) {
+ $args['region'] = $region;
+ }
+ return new $klass($args);
+ };
+ }], 'partition' => ['type' => 'config', 'valid' => ['string', \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Endpoint\PartitionInterface::class], 'doc' => 'AWS partition to connect to. Valid partitions' . ' include "aws," "aws-cn," and "aws-us-gov." Used to' . ' restrict the scope of the mapRegions method.', 'default' => function (array $args) {
+ $region = isset($args['region']) ? $args['region'] : '';
+ return \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Endpoint\PartitionEndpointProvider::defaultProvider()->getPartition($region, $args['service']);
+ }, 'fn' => function ($value, array &$args) {
+ if (is_string($value)) {
+ $value = \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Endpoint\PartitionEndpointProvider::defaultProvider()->getPartitionByName($value);
+ }
+ if (!$value instanceof PartitionInterface) {
+ throw new \InvalidArgumentException('No valid partition' . ' was provided. Provide a concrete partition or' . ' the name of a partition (e.g., "aws," "aws-cn,"' . ' or "aws-us-gov").');
+ }
+ $args['partition'] = $value;
+ $args['endpoint_provider'] = $value;
+ }]];
+ }
+ /**
+ * The multi-region client constructor accepts the following options:
+ *
+ * - client_factory: (callable) An optional callable that takes an array of
+ * client configuration arguments and returns a regionalized client.
+ * - partition: (Aws\Endpoint\Partition|string) AWS partition to connect to.
+ * Valid partitions include "aws," "aws-cn," and "aws-us-gov." Used to
+ * restrict the scope of the mapRegions method.
+ * - region: (string) Region to connect to when no override is provided.
+ * Used to create the default client factory and determine the appropriate
+ * AWS partition when present.
+ *
+ * @param array $args Client configuration arguments.
+ */
+ public function __construct(array $args = [])
+ {
+ if (!isset($args['service'])) {
+ $args['service'] = $this->parseClass();
+ }
+ $this->handlerList = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\HandlerList(function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command) {
+ list($region, $args) = $this->getRegionFromArgs($command->toArray());
+ $command = $this->getClientFromPool($region)->getCommand($command->getName(), $args);
+ return $this->executeAsync($command);
+ });
+ $argDefinitions = static::getArguments();
+ $resolver = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\ClientResolver($argDefinitions);
+ $args = $resolver->resolve($args, $this->handlerList);
+ $this->config = $args['config'];
+ $this->factory = $args['client_factory'];
+ $this->partition = $args['partition'];
+ $this->args = array_diff_key($args, $args['config']);
+ }
+ /**
+ * Get the region to which the client is configured to send requests by
+ * default.
+ *
+ * @return string
+ */
+ public function getRegion()
+ {
+ return $this->getClientFromPool()->getRegion();
+ }
+ /**
+ * Create a command for an operation name.
+ *
+ * Special keys may be set on the command to control how it behaves,
+ * including:
+ *
+ * - @http: Associative array of transfer specific options to apply to the
+ * request that is serialized for this command. Available keys include
+ * "proxy", "verify", "timeout", "connect_timeout", "debug", "delay", and
+ * "headers".
+ * - @region: The region to which the command should be sent.
+ *
+ * @param string $name Name of the operation to use in the command
+ * @param array $args Arguments to pass to the command
+ *
+ * @return CommandInterface
+ * @throws \InvalidArgumentException if no command can be found by name
+ */
+ public function getCommand($name, array $args = [])
+ {
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Command($name, $args, clone $this->getHandlerList());
+ }
+ public function getConfig($option = null)
+ {
+ if (null === $option) {
+ return $this->config;
+ }
+ if (isset($this->config[$option])) {
+ return $this->config[$option];
+ }
+ return $this->getClientFromPool()->getConfig($option);
+ }
+ public function getCredentials()
+ {
+ return $this->getClientFromPool()->getCredentials();
+ }
+ public function getHandlerList()
+ {
+ return $this->handlerList;
+ }
+ public function getApi()
+ {
+ return $this->getClientFromPool()->getApi();
+ }
+ public function getEndpoint()
+ {
+ return $this->getClientFromPool()->getEndpoint();
+ }
+ /**
+ * @param string $region Omit this argument or pass in an empty string to
+ * allow the configured client factory to apply the
+ * region.
+ *
+ * @return AwsClientInterface
+ */
+ protected function getClientFromPool($region = '')
+ {
+ if (empty($this->clientPool[$region])) {
+ $factory = $this->factory;
+ $this->clientPool[$region] = $factory(array_replace($this->args, array_filter(['region' => $region])));
+ }
+ return $this->clientPool[$region];
+ }
+ /**
+ * Parse the class name and return the "service" name of the client.
+ *
+ * @return string
+ */
+ private function parseClass()
+ {
+ $klass = get_class($this);
+ if ($klass === __CLASS__) {
+ return '';
+ }
+ return strtolower(substr($klass, strrpos($klass, '\\') + 1, -17));
+ }
+ private function getRegionFromArgs(array $args)
+ {
+ $region = isset($args['@region']) ? $args['@region'] : $this->getRegion();
+ unset($args['@region']);
+ return [$region, $args];
+ }
+}
diff --git a/vendor/Aws3/Aws/Multipart/AbstractUploadManager.php b/vendor/Aws3/Aws/Multipart/AbstractUploadManager.php
new file mode 100644
index 00000000..b5b8377a
--- /dev/null
+++ b/vendor/Aws3/Aws/Multipart/AbstractUploadManager.php
@@ -0,0 +1,240 @@
+ null, 'state' => null, 'concurrency' => self::DEFAULT_CONCURRENCY, 'prepare_data_source' => null, 'before_initiate' => null, 'before_upload' => null, 'before_complete' => null, 'exception_class' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Exception\\MultipartUploadException'];
+ /** @var Client Client used for the upload. */
+ protected $client;
+ /** @var array Configuration used to perform the upload. */
+ protected $config;
+ /** @var array Service-specific information about the upload workflow. */
+ protected $info;
+ /** @var PromiseInterface Promise that represents the multipart upload. */
+ protected $promise;
+ /** @var UploadState State used to manage the upload. */
+ protected $state;
+ /**
+ * @param Client $client
+ * @param array $config
+ */
+ public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\AwsClientInterface $client, array $config = [])
+ {
+ $this->client = $client;
+ $this->info = $this->loadUploadWorkflowInfo();
+ $this->config = $config + self::$defaultConfig;
+ $this->state = $this->determineState();
+ }
+ /**
+ * Returns the current state of the upload
+ *
+ * @return UploadState
+ */
+ public function getState()
+ {
+ return $this->state;
+ }
+ /**
+ * Upload the source using multipart upload operations.
+ *
+ * @return Result The result of the CompleteMultipartUpload operation.
+ * @throws \LogicException if the upload is already complete or aborted.
+ * @throws MultipartUploadException if an upload operation fails.
+ */
+ public function upload()
+ {
+ return $this->promise()->wait();
+ }
+ /**
+ * Upload the source asynchronously using multipart upload operations.
+ *
+ * @return PromiseInterface
+ */
+ public function promise()
+ {
+ if ($this->promise) {
+ return $this->promise;
+ }
+ return $this->promise = \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Promise\coroutine(function () {
+ // Initiate the upload.
+ if ($this->state->isCompleted()) {
+ throw new \LogicException('This multipart upload has already ' . 'been completed or aborted.');
+ }
+ if (!$this->state->isInitiated()) {
+ // Execute the prepare callback.
+ if (is_callable($this->config["prepare_data_source"])) {
+ $this->config["prepare_data_source"]();
+ }
+ $result = (yield $this->execCommand('initiate', $this->getInitiateParams()));
+ $this->state->setUploadId($this->info['id']['upload_id'], $result[$this->info['id']['upload_id']]);
+ $this->state->setStatus(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Multipart\UploadState::INITIATED);
+ }
+ // Create a command pool from a generator that yields UploadPart
+ // commands for each upload part.
+ $resultHandler = $this->getResultHandler($errors);
+ $commands = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandPool($this->client, $this->getUploadCommands($resultHandler), ['concurrency' => $this->config['concurrency'], 'before' => $this->config['before_upload']]);
+ // Execute the pool of commands concurrently, and process errors.
+ (yield $commands->promise());
+ if ($errors) {
+ throw new $this->config['exception_class']($this->state, $errors);
+ }
+ // Complete the multipart upload.
+ (yield $this->execCommand('complete', $this->getCompleteParams()));
+ $this->state->setStatus(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Multipart\UploadState::COMPLETED);
+ })->otherwise(function (\Exception $e) {
+ // Throw errors from the operations as a specific Multipart error.
+ if ($e instanceof AwsException) {
+ $e = new $this->config['exception_class']($this->state, $e);
+ }
+ throw $e;
+ });
+ }
+ protected function getConfig()
+ {
+ return $this->config;
+ }
+ /**
+ * Provides service-specific information about the multipart upload
+ * workflow.
+ *
+ * This array of data should include the keys: 'command', 'id', and 'part_num'.
+ *
+ * @return array
+ */
+ protected abstract function loadUploadWorkflowInfo();
+ /**
+ * Determines the part size to use for upload parts.
+ *
+ * Examines the provided partSize value and the source to determine the
+ * best possible part size.
+ *
+ * @throws \InvalidArgumentException if the part size is invalid.
+ *
+ * @return int
+ */
+ protected abstract function determinePartSize();
+ /**
+ * Uses information from the Command and Result to determine which part was
+ * uploaded and mark it as uploaded in the upload's state.
+ *
+ * @param CommandInterface $command
+ * @param ResultInterface $result
+ */
+ protected abstract function handleResult(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\ResultInterface $result);
+ /**
+ * Gets the service-specific parameters used to initiate the upload.
+ *
+ * @return array
+ */
+ protected abstract function getInitiateParams();
+ /**
+ * Gets the service-specific parameters used to complete the upload.
+ *
+ * @return array
+ */
+ protected abstract function getCompleteParams();
+ /**
+ * Based on the config and service-specific workflow info, creates a
+ * `Promise` for an `UploadState` object.
+ *
+ * @return PromiseInterface A `Promise` that resolves to an `UploadState`.
+ */
+ private function determineState()
+ {
+ // If the state was provided via config, then just use it.
+ if ($this->config['state'] instanceof UploadState) {
+ return $this->config['state'];
+ }
+ // Otherwise, construct a new state from the provided identifiers.
+ $required = $this->info['id'];
+ $id = [$required['upload_id'] => null];
+ unset($required['upload_id']);
+ foreach ($required as $key => $param) {
+ if (!$this->config[$key]) {
+ throw new \InvalidArgumentException('You must provide a value for "' . $key . '" in ' . 'your config for the MultipartUploader for ' . $this->client->getApi()->getServiceFullName() . '.');
+ }
+ $id[$param] = $this->config[$key];
+ }
+ $state = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Multipart\UploadState($id);
+ $state->setPartSize($this->determinePartSize());
+ return $state;
+ }
+ /**
+ * Executes a MUP command with all of the parameters for the operation.
+ *
+ * @param string $operation Name of the operation.
+ * @param array $params Service-specific params for the operation.
+ *
+ * @return PromiseInterface
+ */
+ protected function execCommand($operation, array $params)
+ {
+ // Create the command.
+ $command = $this->client->getCommand($this->info['command'][$operation], $params + $this->state->getId());
+ // Execute the before callback.
+ if (is_callable($this->config["before_{$operation}"])) {
+ $this->config["before_{$operation}"]($command);
+ }
+ // Execute the command asynchronously and return the promise.
+ return $this->client->executeAsync($command);
+ }
+ /**
+ * Returns a middleware for processing responses of part upload operations.
+ *
+ * - Adds an onFulfilled callback that calls the service-specific
+ * handleResult method on the Result of the operation.
+ * - Adds an onRejected callback that adds the error to an array of errors.
+ * - Has a passedByRef $errors arg that the exceptions get added to. The
+ * caller should use that &$errors array to do error handling.
+ *
+ * @param array $errors Errors from upload operations are added to this.
+ *
+ * @return callable
+ */
+ protected function getResultHandler(&$errors = [])
+ {
+ return function (callable $handler) use(&$errors) {
+ return function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request = null) use($handler, &$errors) {
+ return $handler($command, $request)->then(function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\ResultInterface $result) use($command) {
+ $this->handleResult($command, $result);
+ return $result;
+ }, function (\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\AwsException $e) use(&$errors) {
+ $errors[$e->getCommand()[$this->info['part_num']]] = $e;
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Result();
+ });
+ };
+ };
+ }
+ /**
+ * Creates a generator that yields part data for the upload's source.
+ *
+ * Yields associative arrays of parameters that are ultimately merged in
+ * with others to form the complete parameters of a command. This can
+ * include the Body parameter, which is a limited stream (i.e., a Stream
+ * object, decorated with a LimitStream).
+ *
+ * @param callable $resultHandler
+ *
+ * @return \Generator
+ */
+ protected abstract function getUploadCommands(callable $resultHandler);
+}
diff --git a/vendor/Aws3/Aws/Multipart/AbstractUploader.php b/vendor/Aws3/Aws/Multipart/AbstractUploader.php
new file mode 100644
index 00000000..13958826
--- /dev/null
+++ b/vendor/Aws3/Aws/Multipart/AbstractUploader.php
@@ -0,0 +1,106 @@
+source = $this->determineSource($source);
+ parent::__construct($client, $config);
+ }
+ /**
+ * Create a stream for a part that starts at the current position and
+ * has a length of the upload part size (or less with the final part).
+ *
+ * @param Stream $stream
+ *
+ * @return Psr7\LimitStream
+ */
+ protected function limitPartStream(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\StreamInterface $stream)
+ {
+ // Limit what is read from the stream to the part size.
+ return new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\LimitStream($stream, $this->state->getPartSize(), $this->source->tell());
+ }
+ protected function getUploadCommands(callable $resultHandler)
+ {
+ // Determine if the source can be seeked.
+ $seekable = $this->source->isSeekable() && $this->source->getMetadata('wrapper_type') === 'plainfile';
+ for ($partNumber = 1; $this->isEof($seekable); $partNumber++) {
+ // If we haven't already uploaded this part, yield a new part.
+ if (!$this->state->hasPartBeenUploaded($partNumber)) {
+ $partStartPos = $this->source->tell();
+ if (!($data = $this->createPart($seekable, $partNumber))) {
+ break;
+ }
+ $command = $this->client->getCommand($this->info['command']['upload'], $data + $this->state->getId());
+ $command->getHandlerList()->appendSign($resultHandler, 'mup');
+ (yield $command);
+ if ($this->source->tell() > $partStartPos) {
+ continue;
+ }
+ }
+ // Advance the source's offset if not already advanced.
+ if ($seekable) {
+ $this->source->seek(min($this->source->tell() + $this->state->getPartSize(), $this->source->getSize()));
+ } else {
+ $this->source->read($this->state->getPartSize());
+ }
+ }
+ }
+ /**
+ * Generates the parameters for an upload part by analyzing a range of the
+ * source starting from the current offset up to the part size.
+ *
+ * @param bool $seekable
+ * @param int $number
+ *
+ * @return array|null
+ */
+ protected abstract function createPart($seekable, $number);
+ /**
+ * Checks if the source is at EOF.
+ *
+ * @param bool $seekable
+ *
+ * @return bool
+ */
+ private function isEof($seekable)
+ {
+ return $seekable ? $this->source->tell() < $this->source->getSize() : !$this->source->eof();
+ }
+ /**
+ * Turns the provided source into a stream and stores it.
+ *
+ * If a string is provided, it is assumed to be a filename, otherwise, it
+ * passes the value directly to `Psr7\stream_for()`.
+ *
+ * @param mixed $source
+ *
+ * @return Stream
+ */
+ private function determineSource($source)
+ {
+ // Use the contents of a file as the data source.
+ if (is_string($source)) {
+ $source = \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\try_fopen($source, 'r');
+ }
+ // Create a source stream.
+ $stream = \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\stream_for($source);
+ if (!$stream->isReadable()) {
+ throw new \InvalidArgumentException('Source stream must be readable.');
+ }
+ return $stream;
+ }
+}
diff --git a/vendor/Aws3/Aws/Multipart/UploadState.php b/vendor/Aws3/Aws/Multipart/UploadState.php
new file mode 100644
index 00000000..8ed47dc2
--- /dev/null
+++ b/vendor/Aws3/Aws/Multipart/UploadState.php
@@ -0,0 +1,130 @@
+id = $id;
+ }
+ /**
+ * Get the upload's ID, which is a tuple of parameters that can uniquely
+ * identify the upload.
+ *
+ * @return array
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+ /**
+ * Set's the "upload_id", or 3rd part of the upload's ID. This typically
+ * only needs to be done after initiating an upload.
+ *
+ * @param string $key The param key of the upload_id.
+ * @param string $value The param value of the upload_id.
+ */
+ public function setUploadId($key, $value)
+ {
+ $this->id[$key] = $value;
+ }
+ /**
+ * Get the part size.
+ *
+ * @return int
+ */
+ public function getPartSize()
+ {
+ return $this->partSize;
+ }
+ /**
+ * Set the part size.
+ *
+ * @param $partSize int Size of upload parts.
+ */
+ public function setPartSize($partSize)
+ {
+ $this->partSize = $partSize;
+ }
+ /**
+ * Marks a part as being uploaded.
+ *
+ * @param int $partNumber The part number.
+ * @param array $partData Data from the upload operation that needs to be
+ * recalled during the complete operation.
+ */
+ public function markPartAsUploaded($partNumber, array $partData = [])
+ {
+ $this->uploadedParts[$partNumber] = $partData;
+ }
+ /**
+ * Returns whether a part has been uploaded.
+ *
+ * @param int $partNumber The part number.
+ *
+ * @return bool
+ */
+ public function hasPartBeenUploaded($partNumber)
+ {
+ return isset($this->uploadedParts[$partNumber]);
+ }
+ /**
+ * Returns a sorted list of all the uploaded parts.
+ *
+ * @return array
+ */
+ public function getUploadedParts()
+ {
+ ksort($this->uploadedParts);
+ return $this->uploadedParts;
+ }
+ /**
+ * Set the status of the upload.
+ *
+ * @param int $status Status is an integer code defined by the constants
+ * CREATED, INITIATED, and COMPLETED on this class.
+ */
+ public function setStatus($status)
+ {
+ $this->status = $status;
+ }
+ /**
+ * Determines whether the upload state is in the INITIATED status.
+ *
+ * @return bool
+ */
+ public function isInitiated()
+ {
+ return $this->status === self::INITIATED;
+ }
+ /**
+ * Determines whether the upload state is in the COMPLETED status.
+ *
+ * @return bool
+ */
+ public function isCompleted()
+ {
+ return $this->status === self::COMPLETED;
+ }
+}
diff --git a/vendor/Aws3/Aws/PhpHash.php b/vendor/Aws3/Aws/PhpHash.php
new file mode 100644
index 00000000..ebe9867c
--- /dev/null
+++ b/vendor/Aws3/Aws/PhpHash.php
@@ -0,0 +1,65 @@
+algo = $algo;
+ $this->options = $options;
+ }
+ public function update($data)
+ {
+ if ($this->hash !== null) {
+ $this->reset();
+ }
+ hash_update($this->getContext(), $data);
+ }
+ public function complete()
+ {
+ if ($this->hash) {
+ return $this->hash;
+ }
+ $this->hash = hash_final($this->getContext(), true);
+ if (isset($this->options['base64']) && $this->options['base64']) {
+ $this->hash = base64_encode($this->hash);
+ }
+ return $this->hash;
+ }
+ public function reset()
+ {
+ $this->context = $this->hash = null;
+ }
+ /**
+ * Get a hash context or create one if needed
+ *
+ * @return resource|\HashContext
+ */
+ private function getContext()
+ {
+ if (!$this->context) {
+ $key = isset($this->options['key']) ? $this->options['key'] : null;
+ $this->context = hash_init($this->algo, $key ? HASH_HMAC : 0, $key);
+ }
+ return $this->context;
+ }
+}
diff --git a/vendor/Aws3/Aws/PresignUrlMiddleware.php b/vendor/Aws3/Aws/PresignUrlMiddleware.php
new file mode 100644
index 00000000..0085c85c
--- /dev/null
+++ b/vendor/Aws3/Aws/PresignUrlMiddleware.php
@@ -0,0 +1,70 @@
+endpointProvider = $endpointProvider;
+ $this->client = $client;
+ $this->nextHandler = $nextHandler;
+ $this->commandPool = $options['operations'];
+ $this->serviceName = $options['service'];
+ $this->presignParam = $options['presign_param'];
+ $this->requireDifferentRegion = !empty($options['require_different_region']);
+ }
+ public static function wrap(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\AwsClientInterface $client, callable $endpointProvider, array $options = [])
+ {
+ return function (callable $handler) use($endpointProvider, $client, $options) {
+ $f = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\PresignUrlMiddleware($options, $endpointProvider, $client, $handler);
+ return $f;
+ };
+ }
+ public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $cmd, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface $request = null)
+ {
+ if (in_array($cmd->getName(), $this->commandPool) && !isset($cmd->{'__skip' . $cmd->getName()})) {
+ $cmd['DestinationRegion'] = $this->client->getRegion();
+ if (!$this->requireDifferentRegion || !empty($cmd['SourceRegion']) && $cmd['SourceRegion'] !== $cmd['DestinationRegion']) {
+ $cmd[$this->presignParam] = $this->createPresignedUrl($this->client, $cmd);
+ }
+ }
+ $f = $this->nextHandler;
+ return $f($cmd, $request);
+ }
+ private function createPresignedUrl(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\AwsClientInterface $client, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $cmd)
+ {
+ $cmdName = $cmd->getName();
+ $newCmd = $client->getCommand($cmdName, $cmd->toArray());
+ // Avoid infinite recursion by flagging the new command.
+ $newCmd->{'__skip' . $cmdName} = true;
+ // Serialize a request for the operation.
+ $request = \DeliciousBrains\WP_Offload_S3\Aws3\Aws\serialize($newCmd);
+ // Create the new endpoint for the target endpoint.
+ $endpoint = \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Endpoint\EndpointProvider::resolve($this->endpointProvider, ['region' => $cmd['SourceRegion'], 'service' => $this->serviceName])['endpoint'];
+ // Set the request to hit the target endpoint.
+ $uri = $request->getUri()->withHost((new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Uri($endpoint))->getHost());
+ $request = $request->withUri($uri);
+ // Create a presigned URL for our generated request.
+ $signer = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Signature\SignatureV4($this->serviceName, $cmd['SourceRegion']);
+ return (string) $signer->presign(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Signature\SignatureV4::convertPostToGet($request), $client->getCredentials()->wait(), '+1 hour')->getUri();
+ }
+}
diff --git a/vendor/Aws3/Aws/PsrCacheAdapter.php b/vendor/Aws3/Aws/PsrCacheAdapter.php
new file mode 100644
index 00000000..d5df976d
--- /dev/null
+++ b/vendor/Aws3/Aws/PsrCacheAdapter.php
@@ -0,0 +1,32 @@
+pool = $pool;
+ }
+ public function get($key)
+ {
+ $item = $this->pool->getItem($key);
+ return $item->isHit() ? $item->get() : null;
+ }
+ public function set($key, $value, $ttl = 0)
+ {
+ $item = $this->pool->getItem($key);
+ $item->set($value);
+ if ($ttl > 0) {
+ $item->expiresAfter($ttl);
+ }
+ $this->pool->save($item);
+ }
+ public function remove($key)
+ {
+ $this->pool->deleteItem($key);
+ }
+}
diff --git a/vendor/Aws3/Aws/Result.php b/vendor/Aws3/Aws/Result.php
new file mode 100644
index 00000000..fd02428d
--- /dev/null
+++ b/vendor/Aws3/Aws/Result.php
@@ -0,0 +1,50 @@
+data = $data;
+ }
+ public function hasKey($name)
+ {
+ return isset($this->data[$name]);
+ }
+ public function get($key)
+ {
+ return $this[$key];
+ }
+ public function search($expression)
+ {
+ return \DeliciousBrains\WP_Offload_S3\Aws3\JmesPath\Env::search($expression, $this->toArray());
+ }
+ public function __toString()
+ {
+ $jsonData = json_encode($this->toArray(), JSON_PRETTY_PRINT);
+ return <<