mirror of
https://git.friendi.ca/friendica/friendica-addons.git
synced 2025-07-11 10:58:48 +00:00
[s3_storage] Bump version of akeeba/s3 to version 2.3.1
- Address https://github.com/friendica/friendica/issues/12011#issuecomment-1854681792
This commit is contained in:
parent
9daa11eb10
commit
3e74af9775
61 changed files with 1472 additions and 708 deletions
18
s3_storage/vendor/akeeba/s3/src/Acl.php
vendored
18
s3_storage/vendor/akeeba/s3/src/Acl.php
vendored
|
@ -3,29 +3,29 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4;
|
||||
namespace Akeeba\S3;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
/**
|
||||
* Shortcuts to often used access control privileges
|
||||
*/
|
||||
class Acl
|
||||
{
|
||||
const ACL_PRIVATE = 'private';
|
||||
public const ACL_PRIVATE = 'private';
|
||||
|
||||
const ACL_PUBLIC_READ = 'public-read';
|
||||
public const ACL_PUBLIC_READ = 'public-read';
|
||||
|
||||
const ACL_PUBLIC_READ_WRITE = 'public-read-write';
|
||||
public const ACL_PUBLIC_READ_WRITE = 'public-read-write';
|
||||
|
||||
const ACL_AUTHENTICATED_READ = 'authenticated-read';
|
||||
public const ACL_AUTHENTICATED_READ = 'authenticated-read';
|
||||
|
||||
const ACL_BUCKET_OWNER_READ = 'bucket-owner-read';
|
||||
public const ACL_BUCKET_OWNER_READ = 'bucket-owner-read';
|
||||
|
||||
const ACL_BUCKET_OWNER_FULL_CONTROL = 'bucket-owner-full-control';
|
||||
public const ACL_BUCKET_OWNER_FULL_CONTROL = 'bucket-owner-full-control';
|
||||
}
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4;
|
||||
namespace Akeeba\S3;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
/**
|
||||
* Holds the Amazon S3 confiugration credentials
|
||||
|
@ -199,6 +199,8 @@ class Configuration
|
|||
throw new Exception\InvalidSignatureMethod;
|
||||
}
|
||||
|
||||
$this->signatureMethod = $signatureMethod;
|
||||
|
||||
// If you switch to v2 signatures we unset the region.
|
||||
if ($signatureMethod == 'v2')
|
||||
{
|
||||
|
@ -214,13 +216,7 @@ class Configuration
|
|||
$this->setUseLegacyPathStyle(false);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (empty($this->getRegion())) {
|
||||
$this->setRegion('us-east-1');
|
||||
}
|
||||
}
|
||||
|
||||
$this->signatureMethod = $signatureMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
367
s3_storage/vendor/akeeba/s3/src/Connector.php
vendored
367
s3_storage/vendor/akeeba/s3/src/Connector.php
vendored
|
@ -3,22 +3,22 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4;
|
||||
namespace Akeeba\S3;
|
||||
|
||||
// Protection against direct access
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotDeleteFile;
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotGetBucket;
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotGetFile;
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotListBuckets;
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotOpenFileForWrite;
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotPutFile;
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Response\Error;
|
||||
use Akeeba\S3\Exception\CannotDeleteFile;
|
||||
use Akeeba\S3\Exception\CannotGetBucket;
|
||||
use Akeeba\S3\Exception\CannotGetFile;
|
||||
use Akeeba\S3\Exception\CannotListBuckets;
|
||||
use Akeeba\S3\Exception\CannotOpenFileForWrite;
|
||||
use Akeeba\S3\Exception\CannotPutFile;
|
||||
use Akeeba\S3\Response\Error;
|
||||
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
class Connector
|
||||
{
|
||||
|
@ -81,7 +81,10 @@ class Connector
|
|||
|
||||
if (($input->getSize() <= 0) || (($input->getInputType() == Input::INPUT_DATA) && (!strlen($input->getDataReference()))))
|
||||
{
|
||||
throw new CannotPutFile('Missing input parameters', 0);
|
||||
if (substr($uri, -1) !== '/')
|
||||
{
|
||||
throw new CannotPutFile('Missing input parameters', 0);
|
||||
}
|
||||
}
|
||||
|
||||
// We need to post with Content-Length and Content-Type, MD5 is optional
|
||||
|
@ -169,7 +172,7 @@ class Connector
|
|||
|
||||
if (!is_resource($saveTo) && is_string($saveTo))
|
||||
{
|
||||
$fp = @fopen($saveTo, 'wb');
|
||||
$fp = @fopen($saveTo, 'w');
|
||||
|
||||
if ($fp === false)
|
||||
{
|
||||
|
@ -193,6 +196,53 @@ class Connector
|
|||
$request->setHeader('Range', "bytes=$from-$to");
|
||||
}
|
||||
|
||||
$response = $request->getResponse(true);
|
||||
|
||||
if (!$response->error->isError() && (($response->code !== 200) && ($response->code !== 206)))
|
||||
{
|
||||
$response->error = new Error(
|
||||
$response->code,
|
||||
"Unexpected HTTP status {$response->code}"
|
||||
);
|
||||
}
|
||||
|
||||
if ($response->error->isError())
|
||||
{
|
||||
throw new CannotGetFile(
|
||||
sprintf(
|
||||
__METHOD__ . "({%s}, {%s}): [%s] %s\n\nDebug info:\n%s",
|
||||
$bucket,
|
||||
$uri,
|
||||
$response->error->getCode(),
|
||||
$response->error->getMessage(),
|
||||
print_r($response->body, true)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!is_resource($fp))
|
||||
{
|
||||
return $response->body;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about an object.
|
||||
*
|
||||
* @param string $bucket Bucket name
|
||||
* @param string $uri Object URI
|
||||
*
|
||||
* @return array The headers returned by Amazon S3
|
||||
*
|
||||
* @throws CannotGetFile If the file does not exist
|
||||
* @see https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html
|
||||
*/
|
||||
public function headObject(string $bucket, string $uri): array
|
||||
{
|
||||
$request = new Request('HEAD', $bucket, $uri, $this->configuration);
|
||||
|
||||
$response = $request->getResponse();
|
||||
|
||||
if (!$response->error->isError() && (($response->code !== 200) && ($response->code !== 206)))
|
||||
|
@ -206,20 +256,21 @@ class Connector
|
|||
if ($response->error->isError())
|
||||
{
|
||||
throw new CannotGetFile(
|
||||
sprintf(__METHOD__ . "({$bucket}, {$uri}): [%s] %s\n\nDebug info:\n%s",
|
||||
$response->error->getCode(), $response->error->getMessage(), print_r($response->body, true)),
|
||||
$response->error->getCode()
|
||||
sprintf(
|
||||
__METHOD__ . "({%s}, {%s}): [%s] %s\n\nDebug info:\n%s",
|
||||
$bucket,
|
||||
$uri,
|
||||
$response->error->getCode(),
|
||||
$response->error->getMessage(),
|
||||
print_r($response->body, true)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!is_resource($fp))
|
||||
{
|
||||
return $response->body;
|
||||
}
|
||||
|
||||
return null;
|
||||
return $response->getHeaders();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete an object
|
||||
*
|
||||
|
@ -244,9 +295,13 @@ class Connector
|
|||
if ($response->error->isError())
|
||||
{
|
||||
throw new CannotDeleteFile(
|
||||
sprintf(__METHOD__ . "({$bucket}, {$uri}): [%s] %s",
|
||||
$response->error->getCode(), $response->error->getMessage()),
|
||||
$response->error->getCode()
|
||||
sprintf(
|
||||
__METHOD__ . "({%s}, {%s}): [%s] %s",
|
||||
$bucket,
|
||||
$uri,
|
||||
$response->error->getCode(),
|
||||
$response->error->getMessage()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -358,8 +413,7 @@ class Connector
|
|||
if ($response->error->isError())
|
||||
{
|
||||
throw new CannotGetBucket(
|
||||
sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()),
|
||||
$response->error->getCode()
|
||||
sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage())
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -403,168 +457,47 @@ class Connector
|
|||
*/
|
||||
public function getBucket(string $bucket, ?string $prefix = null, ?string $marker = null, ?int $maxKeys = null, string $delimiter = '/', bool $returnCommonPrefixes = false): array
|
||||
{
|
||||
$request = new Request('GET', $bucket, '', $this->configuration);
|
||||
$internalResult = $this->internalGetBucket($bucket, $prefix, $marker, $maxKeys, $delimiter, $returnCommonPrefixes);
|
||||
|
||||
if (!empty($prefix))
|
||||
{
|
||||
$request->setParameter('prefix', $prefix);
|
||||
}
|
||||
/**
|
||||
* @var array $objects
|
||||
* @var ?string $nextMarker
|
||||
*/
|
||||
extract($internalResult);
|
||||
unset($internalResult);
|
||||
|
||||
if (!empty($marker))
|
||||
{
|
||||
$request->setParameter('marker', $marker);
|
||||
}
|
||||
|
||||
if (!empty($maxKeys))
|
||||
{
|
||||
$request->setParameter('max-keys', $maxKeys);
|
||||
}
|
||||
|
||||
if (!empty($delimiter))
|
||||
{
|
||||
$request->setParameter('delimiter', $delimiter);
|
||||
}
|
||||
|
||||
$response = $request->getResponse();
|
||||
|
||||
if (!$response->error->isError() && $response->code !== 200)
|
||||
{
|
||||
$response->error = new Error(
|
||||
$response->code,
|
||||
"Unexpected HTTP status {$response->code}"
|
||||
);
|
||||
}
|
||||
|
||||
if ($response->error->isError())
|
||||
{
|
||||
throw new CannotGetBucket(
|
||||
sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()),
|
||||
$response->error->getCode()
|
||||
);
|
||||
}
|
||||
|
||||
$results = [];
|
||||
|
||||
$nextMarker = null;
|
||||
|
||||
if ($response->hasBody() && isset($response->body->Contents))
|
||||
{
|
||||
foreach ($response->body->Contents as $c)
|
||||
{
|
||||
$results[(string) $c->Key] = [
|
||||
'name' => (string) $c->Key,
|
||||
'time' => strtotime((string) $c->LastModified),
|
||||
'size' => (int) $c->Size,
|
||||
'hash' => substr((string) $c->ETag, 1, -1),
|
||||
];
|
||||
|
||||
$nextMarker = (string) $c->Key;
|
||||
}
|
||||
}
|
||||
|
||||
if ($returnCommonPrefixes && $response->hasBody() && isset($response->body->CommonPrefixes))
|
||||
{
|
||||
foreach ($response->body->CommonPrefixes as $c)
|
||||
{
|
||||
$results[(string) $c->Prefix] = ['prefix' => (string) $c->Prefix];
|
||||
}
|
||||
}
|
||||
|
||||
if ($response->hasBody() && isset($response->body->IsTruncated) &&
|
||||
((string) $response->body->IsTruncated == 'false')
|
||||
)
|
||||
{
|
||||
return $results;
|
||||
}
|
||||
|
||||
if ($response->hasBody() && isset($response->body->NextMarker))
|
||||
{
|
||||
$nextMarker = (string) $response->body->NextMarker;
|
||||
}
|
||||
|
||||
// Is it a truncated result?
|
||||
$isTruncated = ($nextMarker !== null) && ((string) $response->body->IsTruncated == 'true');
|
||||
// Is this a truncated result and no maxKeys specified?
|
||||
$isTruncatedAndNoMaxKeys = ($maxKeys == null) && $isTruncated;
|
||||
// Is this a truncated result with less keys than the specified maxKeys; and common prefixes found but not returned to the caller?
|
||||
$isTruncatedAndNeedsContinue = ($maxKeys != null) && $isTruncated && (count($results) < $maxKeys);
|
||||
|
||||
// Loop through truncated results if maxKeys isn't specified
|
||||
if ($isTruncatedAndNoMaxKeys || $isTruncatedAndNeedsContinue)
|
||||
// Loop through truncated results if maxKeys isn't specified or we don't have enough object records yet.
|
||||
if ($nextMarker !== null && ($maxKeys === null || count($objects) < $maxKeys))
|
||||
{
|
||||
do
|
||||
{
|
||||
$request = new Request('GET', $bucket, '', $this->configuration);
|
||||
$internalResult = $this->internalGetBucket($bucket, $prefix, $nextMarker, $maxKeys, $delimiter, $returnCommonPrefixes);
|
||||
|
||||
if (!empty($prefix))
|
||||
{
|
||||
$request->setParameter('prefix', $prefix);
|
||||
}
|
||||
$nextMarker = $internalResult['nextMarker'];
|
||||
$objects = array_merge($objects, $internalResult['objects']);
|
||||
|
||||
$request->setParameter('marker', $nextMarker);
|
||||
unset($internalResult);
|
||||
|
||||
if (!empty($delimiter))
|
||||
{
|
||||
$request->setParameter('delimiter', $delimiter);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$response = $request->getResponse();
|
||||
}
|
||||
catch (\Exception $e)
|
||||
// If the last call did not return a nextMarker I am done iterating.
|
||||
if ($nextMarker === null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ($response->hasBody() && isset($response->body->Contents))
|
||||
// If we have maxKeys AND the number of objects is at least this many I am done iterating.
|
||||
if ($maxKeys !== null && count($objects) >= $maxKeys)
|
||||
{
|
||||
foreach ($response->body->Contents as $c)
|
||||
{
|
||||
$results[(string) $c->Key] = [
|
||||
'name' => (string) $c->Key,
|
||||
'time' => strtotime((string) $c->LastModified),
|
||||
'size' => (int) $c->Size,
|
||||
'hash' => substr((string) $c->ETag, 1, -1),
|
||||
];
|
||||
|
||||
$nextMarker = (string) $c->Key;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ($returnCommonPrefixes && $response->hasBody() && isset($response->body->CommonPrefixes))
|
||||
{
|
||||
foreach ($response->body->CommonPrefixes as $c)
|
||||
{
|
||||
$results[(string) $c->Prefix] = ['prefix' => (string) $c->Prefix];
|
||||
}
|
||||
}
|
||||
|
||||
if ($response->hasBody() && isset($response->body->NextMarker))
|
||||
{
|
||||
$nextMarker = (string) $response->body->NextMarker;
|
||||
}
|
||||
|
||||
$continueCondition = false;
|
||||
|
||||
if ($isTruncatedAndNoMaxKeys)
|
||||
{
|
||||
$continueCondition = !$response->error->isError() && $isTruncated;
|
||||
}
|
||||
|
||||
if ($isTruncatedAndNeedsContinue)
|
||||
{
|
||||
$continueCondition = !$response->error->isError() && $isTruncated && (count($results) < $maxKeys);
|
||||
}
|
||||
} while ($continueCondition);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
if (!is_null($maxKeys))
|
||||
if ($maxKeys !== null)
|
||||
{
|
||||
$results = array_splice($results, 0, $maxKeys);
|
||||
return array_splice($objects, 0, $maxKeys);
|
||||
}
|
||||
|
||||
return $results;
|
||||
return $objects;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -594,8 +527,7 @@ class Connector
|
|||
if ($response->error->isError())
|
||||
{
|
||||
throw new CannotListBuckets(
|
||||
sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()),
|
||||
$response->error->getCode()
|
||||
sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage())
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -691,7 +623,12 @@ class Connector
|
|||
if ($response->error->isError())
|
||||
{
|
||||
throw new CannotPutFile(
|
||||
sprintf(__METHOD__ . "(): [%s] %s\n\nDebug info:\n%s", $response->error->getCode(), $response->error->getMessage(), print_r($response->body, true))
|
||||
sprintf(
|
||||
__METHOD__ . "(): [%s] %s\n\nDebug info:\n%s",
|
||||
$response->error->getCode(),
|
||||
$response->error->getMessage(),
|
||||
print_r($response->body, true)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -958,4 +895,90 @@ class Connector
|
|||
{
|
||||
return $this->configuration;
|
||||
}
|
||||
|
||||
private function internalGetBucket(string $bucket, ?string $prefix = null, ?string $marker = null, ?int $maxKeys = null, string $delimiter = '/', bool $returnCommonPrefixes = false): array
|
||||
{
|
||||
$request = new Request('GET', $bucket, '', $this->configuration);
|
||||
|
||||
if (!empty($prefix))
|
||||
{
|
||||
$request->setParameter('prefix', $prefix);
|
||||
}
|
||||
|
||||
if (!empty($marker))
|
||||
{
|
||||
$request->setParameter('marker', $marker);
|
||||
}
|
||||
|
||||
if (!empty($maxKeys))
|
||||
{
|
||||
$request->setParameter('max-keys', $maxKeys);
|
||||
}
|
||||
|
||||
if (!empty($delimiter))
|
||||
{
|
||||
$request->setParameter('delimiter', $delimiter);
|
||||
}
|
||||
|
||||
$response = $request->getResponse();
|
||||
|
||||
if (!$response->error->isError() && $response->code !== 200)
|
||||
{
|
||||
$response->error = new Error(
|
||||
$response->code,
|
||||
"Unexpected HTTP status {$response->code}"
|
||||
);
|
||||
}
|
||||
|
||||
if ($response->error->isError())
|
||||
{
|
||||
throw new CannotGetBucket(
|
||||
sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage())
|
||||
);
|
||||
}
|
||||
|
||||
$results = [
|
||||
'objects' => [],
|
||||
'nextMarker' => null,
|
||||
];
|
||||
|
||||
if ($response->hasBody() && isset($response->body->Contents))
|
||||
{
|
||||
foreach ($response->body->Contents as $c)
|
||||
{
|
||||
$results['objects'][(string) $c->Key] = [
|
||||
'name' => (string) $c->Key,
|
||||
'time' => strtotime((string) $c->LastModified),
|
||||
'size' => (int) $c->Size,
|
||||
'hash' => substr((string) $c->ETag, 1, -1),
|
||||
];
|
||||
|
||||
$results['nextMarker'] = (string) $c->Key;
|
||||
}
|
||||
}
|
||||
|
||||
if ($returnCommonPrefixes && $response->hasBody() && isset($response->body->CommonPrefixes))
|
||||
{
|
||||
foreach ($response->body->CommonPrefixes as $c)
|
||||
{
|
||||
$results['objects'][(string) $c->Prefix] = ['prefix' => (string) $c->Prefix];
|
||||
}
|
||||
}
|
||||
|
||||
if ($response->hasBody() && isset($response->body->IsTruncated) &&
|
||||
((string) $response->body->IsTruncated == 'false')
|
||||
)
|
||||
{
|
||||
$results['nextMarker'] = null;
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
if ($response->hasBody() && isset($response->body->NextMarker))
|
||||
{
|
||||
$results['nextMarker'] = (string) $response->body->NextMarker;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Exception;
|
||||
use RuntimeException;
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Exception;
|
||||
use RuntimeException;
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Exception;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Exception;
|
||||
use RuntimeException;
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Exception;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Exception;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Exception;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Exception;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception;
|
||||
namespace Akeeba\S3\Exception;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use LogicException;
|
||||
|
||||
|
|
52
s3_storage/vendor/akeeba/s3/src/Input.php
vendored
52
s3_storage/vendor/akeeba/s3/src/Input.php
vendored
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4;
|
||||
namespace Akeeba\S3;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
/**
|
||||
* Defines an input source for PUT/POST requests to Amazon S3
|
||||
|
@ -20,17 +20,17 @@ class Input
|
|||
/**
|
||||
* Input type: resource
|
||||
*/
|
||||
const INPUT_RESOURCE = 1;
|
||||
public const INPUT_RESOURCE = 1;
|
||||
|
||||
/**
|
||||
* Input type: file
|
||||
*/
|
||||
const INPUT_FILE = 2;
|
||||
public const INPUT_FILE = 2;
|
||||
|
||||
/**
|
||||
* Input type: raw data
|
||||
*/
|
||||
const INPUT_DATA = 3;
|
||||
public const INPUT_DATA = 3;
|
||||
|
||||
/**
|
||||
* File pointer, in case we have a resource
|
||||
|
@ -177,7 +177,13 @@ class Input
|
|||
{
|
||||
if (is_resource($this->fp))
|
||||
{
|
||||
@fclose($this->fp);
|
||||
try
|
||||
{
|
||||
@fclose($this->fp);
|
||||
}
|
||||
catch (\Throwable $e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,10 +264,16 @@ class Input
|
|||
|
||||
if (is_resource($this->fp))
|
||||
{
|
||||
@fclose($this->fp);
|
||||
try
|
||||
{
|
||||
@fclose($this->fp);
|
||||
}
|
||||
catch (\Throwable $e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
$this->fp = @fopen($file, 'rb');
|
||||
$this->fp = @fopen($file, 'r');
|
||||
|
||||
if ($this->fp === false)
|
||||
{
|
||||
|
@ -295,7 +307,13 @@ class Input
|
|||
|
||||
if (is_resource($this->fp))
|
||||
{
|
||||
@fclose($this->fp);
|
||||
try
|
||||
{
|
||||
@fclose($this->fp);
|
||||
}
|
||||
catch (\Throwable $e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
$this->file = null;
|
||||
|
@ -329,7 +347,13 @@ class Input
|
|||
|
||||
if (is_resource($this->fp))
|
||||
{
|
||||
@fclose($this->fp);
|
||||
try
|
||||
{
|
||||
@fclose($this->fp);
|
||||
}
|
||||
catch (\Throwable $e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
$this->file = null;
|
||||
|
@ -450,7 +474,7 @@ class Input
|
|||
*/
|
||||
public function setSha256(?string $sha256): void
|
||||
{
|
||||
$this->sha256 = strtolower($sha256);
|
||||
$this->sha256 = is_null($sha256) ? null : strtolower($sha256);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -532,7 +556,7 @@ class Input
|
|||
switch ($this->getInputType())
|
||||
{
|
||||
case self::INPUT_DATA:
|
||||
return function_exists('mb_strlen') ? mb_strlen($this->data, '8bit') : strlen($this->data);
|
||||
return function_exists('mb_strlen') ? mb_strlen($this->data ?? '', '8bit') : strlen($this->data ?? '');
|
||||
break;
|
||||
|
||||
case self::INPUT_FILE:
|
||||
|
@ -635,7 +659,7 @@ class Input
|
|||
|
||||
$ext = strtolower(pathInfo($file, PATHINFO_EXTENSION));
|
||||
|
||||
return isset($exts[$ext]) ? $exts[$ext] : 'application/octet-stream';
|
||||
return $exts[$ext] ?? 'application/octet-stream';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
124
s3_storage/vendor/akeeba/s3/src/Request.php
vendored
124
s3_storage/vendor/akeeba/s3/src/Request.php
vendored
|
@ -3,16 +3,16 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4;
|
||||
namespace Akeeba\S3;
|
||||
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Response\Error;
|
||||
use Akeeba\S3\Response\Error;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
|
||||
class Request
|
||||
|
@ -142,6 +142,12 @@ class Request
|
|||
// The date must always be added as a header
|
||||
$this->headers['Date'] = gmdate('D, d M Y H:i:s O');
|
||||
|
||||
// S3-"compatible" services use a different date format. Because why not?
|
||||
if (strpos($this->headers['Host'], '.amazonaws.com') === false)
|
||||
{
|
||||
$this->headers['Date'] = gmdate('D, d M Y H:i:s T');
|
||||
}
|
||||
|
||||
// If there is a security token we need to set up the X-Amz-Security-Token header
|
||||
$token = $this->configuration->getToken();
|
||||
|
||||
|
@ -367,7 +373,7 @@ class Request
|
|||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getResponse(): Response
|
||||
public function getResponse(bool $rawResponse = false): Response
|
||||
{
|
||||
$this->processParametersIntoResource();
|
||||
|
||||
|
@ -417,8 +423,10 @@ class Request
|
|||
* Caveat: if your bucket contains dots in the name we have to turn off host verification due to the way the
|
||||
* S3 SSL certificates are set up.
|
||||
*/
|
||||
$isAmazonS3 = (substr($this->headers['Host'], -14) == '.amazonaws.com') ||
|
||||
substr($this->headers['Host'], -16) == 'amazonaws.com.cn';
|
||||
$isAmazonS3 = (substr($this->headers['Host'], -14) == '.amazonaws.com')
|
||||
|| substr(
|
||||
$this->headers['Host'], -16
|
||||
) == 'amazonaws.com.cn';
|
||||
$tooManyDots = substr_count($this->headers['Host'], '.') > 4;
|
||||
|
||||
$verifyHost = ($isAmazonS3 && $tooManyDots) ? 0 : 2;
|
||||
|
@ -429,6 +437,27 @@ class Request
|
|||
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
|
||||
/**
|
||||
* Set the optional x-amz-date header for third party services.
|
||||
*
|
||||
* Amazon S3 proper expects to get the date from the Date header. Third party services typically implement the
|
||||
* (wrongly) documented behaviour of using the x-amz-date header but, if it's missing, fall back to the Date
|
||||
* header. Wasabi does not fall back; it only uses the x-amz-date header which is why we have to set it here if
|
||||
* the request iss not made to Amazon S3 proper.
|
||||
*/
|
||||
$this->headers['x-amz-date'] = strpos($this->headers['Host'], '.amazonaws.com') !== false
|
||||
? ''
|
||||
: (new \DateTime($this->headers['Date']))->format('Ymd\THis\Z');
|
||||
|
||||
/**
|
||||
* Remove empty headers.
|
||||
*
|
||||
* While Amazon S3 proper and most third party implementations have no problem with that, there a few of them
|
||||
* (such as Synology C2) which choke on empty headers.
|
||||
*/
|
||||
$this->headers = array_filter($this->headers);
|
||||
|
||||
// Get the request signature
|
||||
$signer = Signature::getSignatureObject($this, $this->configuration->getSignatureMethod());
|
||||
$signer->preProcessHeaders($this->headers, $this->amzHeaders);
|
||||
|
||||
|
@ -482,7 +511,7 @@ class Request
|
|||
|
||||
$data = $this->input->getDataReference();
|
||||
|
||||
if (strlen($data))
|
||||
if (strlen($data ?? ''))
|
||||
{
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
|
@ -538,12 +567,18 @@ class Request
|
|||
@curl_close($curl);
|
||||
|
||||
// Set the body data
|
||||
$this->response->finaliseBody();
|
||||
$this->response->finaliseBody($rawResponse);
|
||||
|
||||
// Clean up file resources
|
||||
if (!is_null($this->fp) && is_resource($this->fp))
|
||||
{
|
||||
fclose($this->fp);
|
||||
try
|
||||
{
|
||||
@fclose($this->fp);
|
||||
}
|
||||
catch (\Throwable $e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return $this->response;
|
||||
|
@ -560,7 +595,7 @@ class Request
|
|||
*/
|
||||
protected function __responseWriteCallback($curl, string $data): int
|
||||
{
|
||||
if (in_array($this->response->code, [200, 206]) && !is_null($this->fp) && is_resource($this->fp))
|
||||
if (in_array($this->response->code, [0, 200, 206]) && !is_null($this->fp) && is_resource($this->fp))
|
||||
{
|
||||
return fwrite($this->fp, $data);
|
||||
}
|
||||
|
@ -573,7 +608,7 @@ class Request
|
|||
/**
|
||||
* cURL header callback
|
||||
*
|
||||
* @param resource $curl cURL resource
|
||||
* @param resource $curl cURL resource
|
||||
* @param string &$data Data
|
||||
*
|
||||
* @return int Length in bytes
|
||||
|
@ -592,7 +627,15 @@ class Request
|
|||
return $strlen;
|
||||
}
|
||||
|
||||
[$header, $value] = explode(': ', trim($data), 2);
|
||||
// Ignore malformed headers without a value.
|
||||
if (strpos($data, ':') === false)
|
||||
{
|
||||
return $strlen;
|
||||
}
|
||||
|
||||
[$header, $value] = explode(':', trim($data), 2);
|
||||
$header = trim($header ?? '');
|
||||
$value = trim($value ?? '');
|
||||
|
||||
switch (strtolower($header))
|
||||
{
|
||||
|
@ -609,10 +652,12 @@ class Request
|
|||
break;
|
||||
|
||||
case 'etag':
|
||||
$this->response->setHeader('hash', $value[0] == '"' ? substr($value, 1, -1) : $value);
|
||||
$this->response->setHeader('hash', trim($value, '"'));
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->response->setHeader(strtolower($header), is_numeric($value) ? (int) $value : $value);
|
||||
|
||||
if (preg_match('/^x-amz-meta-.*$/', $header))
|
||||
{
|
||||
$this->setHeader($header, is_numeric($value) ? (int) $value : $value);
|
||||
|
@ -652,13 +697,12 @@ class Request
|
|||
$query = substr($query, 0, -1);
|
||||
$this->uri .= $query;
|
||||
|
||||
if (array_key_exists('acl', $this->parameters) ||
|
||||
array_key_exists('location', $this->parameters) ||
|
||||
array_key_exists('torrent', $this->parameters) ||
|
||||
array_key_exists('logging', $this->parameters) ||
|
||||
array_key_exists('uploads', $this->parameters) ||
|
||||
array_key_exists('uploadId', $this->parameters) ||
|
||||
array_key_exists('partNumber', $this->parameters)
|
||||
if (array_key_exists('acl', $this->parameters) || array_key_exists('location', $this->parameters)
|
||||
|| array_key_exists('torrent', $this->parameters)
|
||||
|| array_key_exists('logging', $this->parameters)
|
||||
|| array_key_exists('uploads', $this->parameters)
|
||||
|| array_key_exists('uploadId', $this->parameters)
|
||||
|| array_key_exists('partNumber', $this->parameters)
|
||||
)
|
||||
{
|
||||
$this->resource .= $query;
|
||||
|
@ -720,6 +764,8 @@ class Request
|
|||
}
|
||||
|
||||
/**
|
||||
* Only applies to Amazon S3 proper.
|
||||
*
|
||||
* When using the Amazon S3 with the v4 signature API we have to use a different hostname per region. The
|
||||
* mapping can be found in https://docs.aws.amazon.com/general/latest/gr/s3.html#s3_region
|
||||
*
|
||||
|
@ -728,25 +774,27 @@ class Request
|
|||
*
|
||||
* v4 signing does NOT support non-Amazon endpoints.
|
||||
*/
|
||||
|
||||
// Most endpoints: s3-REGION.amazonaws.com
|
||||
$regionalEndpoint = $region . '.amazonaws.com';
|
||||
|
||||
// Exception: China
|
||||
if (substr($region, 0, 3) == 'cn-')
|
||||
if (in_array($endpoint, ['s3.amazonaws.com', 'amazonaws.com.cn']))
|
||||
{
|
||||
// Chinese endpoint, e.g.: s3.cn-north-1.amazonaws.com.cn
|
||||
$regionalEndpoint = $regionalEndpoint . '.cn';
|
||||
}
|
||||
// Most endpoints: s3-REGION.amazonaws.com
|
||||
$regionalEndpoint = $region . '.amazonaws.com';
|
||||
|
||||
// If dual-stack URLs are enabled then prepend the endpoint
|
||||
if ($configuration->getDualstackUrl())
|
||||
{
|
||||
$endpoint = 's3.dualstack.' . $regionalEndpoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
$endpoint = 's3.' . $regionalEndpoint;
|
||||
// Exception: China
|
||||
if (substr($region, 0, 3) == 'cn-')
|
||||
{
|
||||
// Chinese endpoint, e.g.: s3.cn-north-1.amazonaws.com.cn
|
||||
$regionalEndpoint = $regionalEndpoint . '.cn';
|
||||
}
|
||||
|
||||
// If dual-stack URLs are enabled then prepend the endpoint
|
||||
if ($configuration->getDualstackUrl())
|
||||
{
|
||||
$endpoint = 's3.dualstack.' . $regionalEndpoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
$endpoint = 's3.' . $regionalEndpoint;
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy path style access: return just the endpoint
|
||||
|
|
30
s3_storage/vendor/akeeba/s3/src/Response.php
vendored
30
s3_storage/vendor/akeeba/s3/src/Response.php
vendored
|
@ -3,18 +3,18 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4;
|
||||
namespace Akeeba\S3;
|
||||
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Exception\PropertyNotFound;
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Response\Error;
|
||||
use Akeeba\S3\Exception\PropertyNotFound;
|
||||
use Akeeba\S3\Response\Error;
|
||||
use SimpleXMLElement;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
/**
|
||||
* Amazon S3 API response object
|
||||
|
@ -124,7 +124,7 @@ class Response
|
|||
*
|
||||
* @param string|SimpleXMLElement|null $body
|
||||
*/
|
||||
public function setBody($body): void
|
||||
public function setBody($body, bool $rawResponse = false): void
|
||||
{
|
||||
$this->body = null;
|
||||
|
||||
|
@ -135,7 +135,7 @@ class Response
|
|||
|
||||
$this->body = $body;
|
||||
|
||||
$this->finaliseBody();
|
||||
$this->finaliseBody($rawResponse);
|
||||
}
|
||||
|
||||
public function resetBody(): void
|
||||
|
@ -153,7 +153,7 @@ class Response
|
|||
$this->body .= $data;
|
||||
}
|
||||
|
||||
public function finaliseBody(): void
|
||||
public function finaliseBody(bool $rawResponse = false): void
|
||||
{
|
||||
if (!$this->hasBody())
|
||||
{
|
||||
|
@ -165,8 +165,14 @@ class Response
|
|||
$this->headers['type'] = 'text/plain';
|
||||
}
|
||||
|
||||
if (is_string($this->body) &&
|
||||
(($this->headers['type'] == 'application/xml') || (substr($this->body, 0, 5) == '<?xml'))
|
||||
if (
|
||||
!$rawResponse
|
||||
&& is_string($this->body)
|
||||
&&
|
||||
(
|
||||
($this->headers['type'] == 'application/xml')
|
||||
|| (substr($this->body, 0, 5) == '<?xml')
|
||||
)
|
||||
)
|
||||
{
|
||||
$this->body = simplexml_load_string($this->body);
|
||||
|
@ -332,8 +338,8 @@ class Response
|
|||
)
|
||||
{
|
||||
$this->error = new Error(
|
||||
$this->code,
|
||||
(string) $this->body->Message
|
||||
500,
|
||||
(string) $this->body->Code . ':' . (string) $this->body->Message
|
||||
);
|
||||
|
||||
if (isset($this->body->Resource))
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Response;
|
||||
namespace Akeeba\S3\Response;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
/**
|
||||
* S3 response error object
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4;
|
||||
namespace Akeeba\S3;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
/**
|
||||
* Base class for request signing objects.
|
||||
|
@ -44,7 +44,7 @@ abstract class Signature
|
|||
*/
|
||||
public static function getSignatureObject(Request $request, string $method = 'v2'): self
|
||||
{
|
||||
$className = '\\Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Signature\\' . ucfirst($method);
|
||||
$className = __NAMESPACE__ . '\\Signature\\' . ucfirst($method);
|
||||
|
||||
return new $className($request);
|
||||
}
|
||||
|
|
14
s3_storage/vendor/akeeba/s3/src/Signature/V2.php
vendored
14
s3_storage/vendor/akeeba/s3/src/Signature/V2.php
vendored
|
@ -3,16 +3,16 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Signature;
|
||||
namespace Akeeba\S3\Signature;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Signature;
|
||||
use Akeeba\S3\Signature;
|
||||
|
||||
/**
|
||||
* Implements the Amazon AWS v2 signatures
|
||||
|
@ -123,7 +123,7 @@ class V2 extends Signature
|
|||
}
|
||||
|
||||
// AMZ headers must be sorted and sent as separate lines
|
||||
if (sizeof($amz) > 0)
|
||||
if (count($amz) > 0)
|
||||
{
|
||||
sort($amz);
|
||||
$amzString = "\n" . implode("\n", $amz);
|
||||
|
@ -150,8 +150,8 @@ class V2 extends Signature
|
|||
}
|
||||
|
||||
$stringToSign = $verb . "\n" .
|
||||
(isset($headers['Content-MD5']) ? $headers['Content-MD5'] : '') . "\n" .
|
||||
(isset($headers['Content-Type']) ? $headers['Content-Type'] : '') . "\n" .
|
||||
($headers['Content-MD5'] ?? '') . "\n" .
|
||||
($headers['Content-Type'] ?? '') . "\n" .
|
||||
$headers['Date'] .
|
||||
$amzString . "\n" .
|
||||
$resourcePath;
|
||||
|
|
170
s3_storage/vendor/akeeba/s3/src/Signature/V4.php
vendored
170
s3_storage/vendor/akeeba/s3/src/Signature/V4.php
vendored
|
@ -3,16 +3,16 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4\Signature;
|
||||
namespace Akeeba\S3\Signature;
|
||||
|
||||
// Protection against direct access
|
||||
defined('AKEEBAENGINE') or die();
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Akeeba\Engine\Postproc\Connector\S3v4\Signature;
|
||||
use Akeeba\S3\Signature;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
|
@ -77,14 +77,20 @@ class V4 extends Signature
|
|||
* http://s3-eu-west-1.amazonaws.com/example instead of http://example.amazonaws.com/ for all authenticated URLs
|
||||
*/
|
||||
$region = $this->request->getConfiguration()->getRegion();
|
||||
$bucket = $this->request->getBucket();
|
||||
$hostname = $this->getPresignedHostnameForRegion($region);
|
||||
|
||||
if ($this->isValidBucketName($bucket))
|
||||
{
|
||||
$hostname = $bucket . '.' . $hostname;
|
||||
}
|
||||
|
||||
$this->request->setHeader('Host', $hostname);
|
||||
|
||||
// Set the expiration time in seconds
|
||||
$this->request->setHeader('Expires', (int) $lifetime);
|
||||
|
||||
// Get the query parameters, including the calculated signature
|
||||
$bucket = $this->request->getBucket();
|
||||
$uri = $this->request->getResource();
|
||||
$headers = $this->request->getHeaders();
|
||||
$protocol = $https ? 'https' : 'http';
|
||||
|
@ -93,6 +99,11 @@ class V4 extends Signature
|
|||
// The query parameters are returned serialized; unserialize them, then build and return the URL.
|
||||
$queryParameters = unserialize($serialisedParams);
|
||||
|
||||
if ($this->isValidBucketName($bucket) && strpos($uri, '/' . $bucket) === 0)
|
||||
{
|
||||
$uri = substr($uri, strlen($bucket) + 1);
|
||||
}
|
||||
|
||||
$query = http_build_query($queryParameters);
|
||||
|
||||
$url = $protocol . '://' . $headers['Host'] . $uri;
|
||||
|
@ -129,8 +140,8 @@ class V4 extends Signature
|
|||
$signatureDate = new DateTime($headers['Date']);
|
||||
|
||||
$credentialScope = $signatureDate->format('Ymd') . '/' .
|
||||
$this->request->getConfiguration()->getRegion() . '/' .
|
||||
's3/aws4_request';
|
||||
$this->request->getConfiguration()->getRegion() . '/' .
|
||||
's3/aws4_request';
|
||||
|
||||
/**
|
||||
* If the Expires header is set up we're pre-signing a download URL. The string to sign is a bit
|
||||
|
@ -208,12 +219,14 @@ class V4 extends Signature
|
|||
// The canonical URI is the resource path
|
||||
$canonicalURI = $resourcePath;
|
||||
$bucketResource = '/' . $bucket;
|
||||
$regionalHostname = ($headers['Host'] != 's3.amazonaws.com') && ($headers['Host'] != $bucket . '.s3.amazonaws.com');
|
||||
$regionalHostname = ($headers['Host'] != 's3.amazonaws.com')
|
||||
&& ($headers['Host'] != $bucket . '.s3.amazonaws.com');
|
||||
|
||||
// Special case: if the canonical URI ends in /?location the bucket name DOES count as part of the canonical URL
|
||||
// even though the Host is s3.amazonaws.com (in which case it normally shouldn't count). Yeah, I know, it makes
|
||||
// no sense!!!
|
||||
if (!$regionalHostname && ($headers['Host'] == 's3.amazonaws.com') && (substr($canonicalURI, -10) == '/?location'))
|
||||
if (!$regionalHostname && ($headers['Host'] == 's3.amazonaws.com')
|
||||
&& (substr($canonicalURI, -10) == '/?location'))
|
||||
{
|
||||
$regionalHostname = true;
|
||||
}
|
||||
|
@ -274,11 +287,11 @@ class V4 extends Signature
|
|||
|
||||
// Calculate the canonical request
|
||||
$canonicalRequest = $verb . "\n" .
|
||||
$canonicalURI . "\n" .
|
||||
$canonicalQueryString . "\n" .
|
||||
$canonicalHeaders . "\n" .
|
||||
$signedHeaders . "\n" .
|
||||
$requestPayloadHash;
|
||||
$canonicalURI . "\n" .
|
||||
$canonicalQueryString . "\n" .
|
||||
$canonicalHeaders . "\n" .
|
||||
$signedHeaders . "\n" .
|
||||
$requestPayloadHash;
|
||||
|
||||
$hashedCanonicalRequest = hash('sha256', $canonicalRequest);
|
||||
|
||||
|
@ -290,17 +303,40 @@ class V4 extends Signature
|
|||
$headers['Date'] = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* The Date in the String-to-Sign is a messy situation.
|
||||
*
|
||||
* Amazon's documentation says it must be in ISO 8601 format: `Ymd\THis\Z`. Unfortunately, Amazon's
|
||||
* documentation is actually wrong :troll_face: The actual Amazon S3 service expects the date to be formatted as
|
||||
* per RFC1123.
|
||||
*
|
||||
* Most third party implementations have caught up to the fact that Amazon has documented the v4 signatures
|
||||
* wrongly (naughty AWS!) and accept either format.
|
||||
*
|
||||
* Some other third party implementations, which never bothered to validate their implementations against Amazon
|
||||
* S3 proper, only expect what Amazon has documented as "ISO 8601". Therefore, we detect third party services
|
||||
* and switch to the as-documented date format.
|
||||
*
|
||||
* Some other third party services, like Wasabi, are broken in yet a different way. They will only use the date
|
||||
* from the x-amz-date header, WITHOUT falling back to the Date header if the former is not present. This is
|
||||
* the opposite of Amazon S3 proper which does expect the Date header. That's why the Request class sets both
|
||||
* headers if the request is made to a service _other_ than Amazon S3 proper.
|
||||
*/
|
||||
$dateToSignFor = strpos($headers['Host'], '.amazonaws.com') !== false
|
||||
? $headers['Date']
|
||||
: $signatureDate->format('Ymd\THis\Z');
|
||||
|
||||
$stringToSign = "AWS4-HMAC-SHA256\n" .
|
||||
$headers['Date'] . "\n" .
|
||||
$credentialScope . "\n" .
|
||||
$hashedCanonicalRequest;
|
||||
$dateToSignFor . "\n" .
|
||||
$credentialScope . "\n" .
|
||||
$hashedCanonicalRequest;
|
||||
|
||||
if ($isPresignedURL)
|
||||
{
|
||||
$stringToSign = "AWS4-HMAC-SHA256\n" .
|
||||
$parameters['X-Amz-Date'] . "\n" .
|
||||
$credentialScope . "\n" .
|
||||
$hashedCanonicalRequest;
|
||||
$parameters['X-Amz-Date'] . "\n" .
|
||||
$credentialScope . "\n" .
|
||||
$hashedCanonicalRequest;
|
||||
}
|
||||
|
||||
// ========== Step 3: Calculate the signature ==========
|
||||
|
@ -313,9 +349,9 @@ class V4 extends Signature
|
|||
// See http://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html
|
||||
|
||||
$authorization = 'AWS4-HMAC-SHA256 Credential=' .
|
||||
$this->request->getConfiguration()->getAccess() . '/' . $credentialScope . ', ' .
|
||||
'SignedHeaders=' . $signedHeaders . ', ' .
|
||||
'Signature=' . $signature;
|
||||
$this->request->getConfiguration()->getAccess() . '/' . $credentialScope . ', ' .
|
||||
'SignedHeaders=' . $signedHeaders . ', ' .
|
||||
'Signature=' . $signature;
|
||||
|
||||
// For presigned URLs we only return the Base64-encoded signature without the AWS format specifier and the
|
||||
// public access key.
|
||||
|
@ -366,7 +402,14 @@ class V4 extends Signature
|
|||
*/
|
||||
private function getPresignedHostnameForRegion(string $region): string
|
||||
{
|
||||
$endpoint = 's3.' . $region . '.amazonaws.com';
|
||||
$config = $this->request->getConfiguration();
|
||||
$endpoint = $config->getEndpoint();
|
||||
|
||||
if (empty($endpoint))
|
||||
{
|
||||
$endpoint = 's3.' . $region . '.amazonaws.com';
|
||||
}
|
||||
|
||||
$dualstackEnabled = $this->request->getConfiguration()->getDualstackUrl();
|
||||
|
||||
// If dual-stack URLs are enabled then prepend the endpoint
|
||||
|
@ -382,4 +425,83 @@ class V4 extends Signature
|
|||
|
||||
return $endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a valid bucket name?
|
||||
*
|
||||
* @param string $bucketName The bucket name to check
|
||||
* @param bool $asSubdomain Should I put additional restrictions for use as a subdomain?
|
||||
*
|
||||
* @return bool
|
||||
* @since 2.3.1
|
||||
*
|
||||
* @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html
|
||||
*/
|
||||
private function isValidBucketName(string $bucketName, bool $asSubdomain = true): bool
|
||||
{
|
||||
/**
|
||||
* If there are dots in the bucket name I can't use it as a subdomain.
|
||||
*
|
||||
* "If you include dots in a bucket's name, you can't use virtual-host-style addressing over HTTPS, unless you
|
||||
* perform your own certificate validation. This is because the security certificates used for virtual hosting
|
||||
* of buckets don't work for buckets with dots in their names."
|
||||
*/
|
||||
if ($asSubdomain && strpos($bucketName, '.') !== false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* - Bucket names must be between 3 (min) and 63 (max) characters long.
|
||||
* - Bucket names can consist only of lowercase letters, numbers, dots (.), and hyphens (-).
|
||||
*/
|
||||
if (!preg_match('/^[a-z0-9\-.]{3,63}$/', $bucketName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bucket names must begin and end with a letter or number.
|
||||
if (!preg_match('/^[a-z0-9].*[a-z0-9]$/', $bucketName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bucket names must not contain two adjacent periods.
|
||||
if (preg_match('/\.\./', $bucketName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bucket names must not be formatted as an IP address (for example, 192.168.5.4).
|
||||
if (preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $bucketName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bucket names must not start with the prefix xn--.
|
||||
if (strpos($bucketName, 'xn--') === 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bucket names must not start with the prefix sthree- and the prefix sthree-configurator.
|
||||
if (strpos($bucketName, 'sthree-') === 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bucket names must not end with the suffix -s3alias.
|
||||
if (substr($bucketName, -8) === '-s3alias')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bucket names must not end with the suffix --ol-s3.
|
||||
if (substr($bucketName, -7) === '--ol-s3')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
18
s3_storage/vendor/akeeba/s3/src/StorageClass.php
vendored
18
s3_storage/vendor/akeeba/s3/src/StorageClass.php
vendored
|
@ -3,11 +3,11 @@
|
|||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Connector\S3v4;
|
||||
namespace Akeeba\S3;
|
||||
|
||||
/**
|
||||
* Amazon S3 Storage Classes
|
||||
|
@ -28,39 +28,39 @@ class StorageClass
|
|||
/**
|
||||
* Amazon S3 Standard (S3 Standard)
|
||||
*/
|
||||
const STANDARD = 'STANDARD';
|
||||
public const STANDARD = 'STANDARD';
|
||||
|
||||
/**
|
||||
* Reduced redundancy storage
|
||||
*
|
||||
* Not recommended anymore. Use INTELLIGENT_TIERING instead.
|
||||
*/
|
||||
const REDUCED_REDUNDANCY = 'REDUCED_REDUNDANCY';
|
||||
public const REDUCED_REDUNDANCY = 'REDUCED_REDUNDANCY';
|
||||
|
||||
/**
|
||||
* Amazon S3 Intelligent-Tiering (S3 Intelligent-Tiering)
|
||||
*/
|
||||
const INTELLIGENT_TIERING = 'INTELLIGENT_TIERING';
|
||||
public const INTELLIGENT_TIERING = 'INTELLIGENT_TIERING';
|
||||
|
||||
/**
|
||||
* Amazon S3 Standard-Infrequent Access (S3 Standard-IA)
|
||||
*/
|
||||
const STANDARD_IA = 'STANDARD_IA';
|
||||
public const STANDARD_IA = 'STANDARD_IA';
|
||||
|
||||
/**
|
||||
* Amazon S3 One Zone-Infrequent Access (S3 One Zone-IA)
|
||||
*/
|
||||
const ONEZONE_IA = 'ONEZONE_IA';
|
||||
public const ONEZONE_IA = 'ONEZONE_IA';
|
||||
|
||||
/**
|
||||
* Amazon S3 Glacier (S3 Glacier)
|
||||
*/
|
||||
const GLACIER = 'GLACIER';
|
||||
public const GLACIER = 'GLACIER';
|
||||
|
||||
/**
|
||||
* Amazon S3 Glacier Deep Archive (S3 Glacier Deep Archive)
|
||||
*/
|
||||
const DEEP_ARCHIVE = 'DEEP_ARCHIVE';
|
||||
public const DEEP_ARCHIVE = 'DEEP_ARCHIVE';
|
||||
|
||||
/**
|
||||
* Manipulate the $headers array, setting the X-Amz-Storage-Class header for the requested storage class.
|
||||
|
|
35
s3_storage/vendor/akeeba/s3/src/aliasing.php
vendored
Normal file
35
s3_storage/vendor/akeeba/s3/src/aliasing.php
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Automatic aliasing of the old namespace to the new, as you use each old class.
|
||||
*/
|
||||
spl_autoload_register(
|
||||
static function (string $className)
|
||||
{
|
||||
$oldNS = 'Akeeba\Engine\Postproc\Connector\S3v4';
|
||||
$newNS = 'Akeeba\S3';
|
||||
|
||||
$className = trim($className, '\\');
|
||||
|
||||
if (strpos($className, $oldNS) !== 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$newClassName = $newNS . '\\' . trim(substr($className, strlen($oldNS)), '\\');
|
||||
|
||||
if (class_exists($newClassName, true))
|
||||
{
|
||||
class_alias($newClassName, $className, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
Loading…
Add table
Add a link
Reference in a new issue