diff --git a/S3.php b/S3.php index 60d08ae5..92ca759e 100644 --- a/S3.php +++ b/S3.php @@ -102,6 +102,19 @@ class S3 */ public static $region = ''; + /** + * Force path style for bucket endpoint + * + * Instead of using the DNS name of the bucket (e.g. BUCKET.s3.amazonaws.com) + * use the path style (e.g. s3.amazonaws.com/BUCKET/). This is useful when + * using a custom endpoint. + * + * @var bool + * @acess public + * @static + */ + public static $forcePathStyle = false; + /** * Proxy information * @@ -217,13 +230,14 @@ class S3 * @param string $endpoint Amazon URI * @return void */ - public function __construct($accessKey = null, $secretKey = null, $useSSL = false, $endpoint = 's3.amazonaws.com', $region = '') + public function __construct($accessKey = null, $secretKey = null, $useSSL = false, $endpoint = 's3.amazonaws.com', $region = '', $forcePathStyle = false) { if ($accessKey !== null && $secretKey !== null) self::setAuth($accessKey, $secretKey); self::$useSSL = $useSSL; self::$endpoint = $endpoint; self::$region = $region; + self::$forcePathStyle = $forcePathStyle; } @@ -238,7 +252,6 @@ public function setEndpoint($host) self::$endpoint = $host; } - /** * Set the service region * @@ -274,6 +287,17 @@ public static function getRegion() return empty($region) ? 'us-east-1' : $region; } + /** + * Use bucket path style + * + * @param bool $enabled Use path style + * @return void + */ + public function setForcePathStyle($enabled = 1) + { + self::$forcePathStyle = $enabled; + } + /** * Set AWS access key and secret key @@ -398,7 +422,6 @@ public static function setSigningKey($keyPairId, $signingKey, $isFile = true) } - /** * Free signing key from memory, MUST be called if you are using setSigningKey() * @@ -449,7 +472,7 @@ private static function __triggerError($message, $file, $line, $code = 0) */ public static function listBuckets($detailed = false) { - $rest = new S3Request('GET', '', '', self::$endpoint); + $rest = new S3Request('GET', '', '', self::$endpoint, self::$forcePathStyle); $rest = $rest->getResponse(); if ($rest->error === false && $rest->code !== 200) $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); @@ -495,7 +518,7 @@ public static function listBuckets($detailed = false) */ public static function getBucket($bucket, $prefix = null, $marker = null, $maxKeys = null, $delimiter = null, $returnCommonPrefixes = false) { - $rest = new S3Request('GET', $bucket, '', self::$endpoint); + $rest = new S3Request('GET', $bucket, '', self::$endpoint, self::$forcePathStyle); if ($maxKeys == 0) $maxKeys = null; if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix); if ($marker !== null && $marker !== '') $rest->setParameter('marker', $marker); @@ -541,7 +564,7 @@ public static function getBucket($bucket, $prefix = null, $marker = null, $maxKe if ($maxKeys == null && $nextMarker !== null && (string)$response->body->IsTruncated == 'true') do { - $rest = new S3Request('GET', $bucket, '', self::$endpoint); + $rest = new S3Request('GET', $bucket, '', self::$endpoint, self::$forcePathStyle); if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix); $rest->setParameter('marker', $nextMarker); if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter); @@ -583,7 +606,7 @@ public static function getBucket($bucket, $prefix = null, $marker = null, $maxKe */ public static function putBucket($bucket, $acl = self::ACL_PRIVATE, $location = false) { - $rest = new S3Request('PUT', $bucket, '', self::$endpoint); + $rest = new S3Request('PUT', $bucket, '', self::$endpoint, self::$forcePathStyle); $rest->setAmzHeader('x-amz-acl', $acl); if ($location === false) $location = self::getRegion(); @@ -621,7 +644,7 @@ public static function putBucket($bucket, $acl = self::ACL_PRIVATE, $location = */ public static function deleteBucket($bucket) { - $rest = new S3Request('DELETE', $bucket, '', self::$endpoint); + $rest = new S3Request('DELETE', $bucket, '', self::$endpoint, self::$forcePathStyle); $rest = $rest->getResponse(); if ($rest->error === false && $rest->code !== 204) $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); @@ -704,7 +727,7 @@ public static function inputResource(&$resource, $bufferSize = false, $md5sum = public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array(), $storageClass = self::STORAGE_CLASS_STANDARD, $serverSideEncryption = self::SSE_NONE) { if ($input === false) return false; - $rest = new S3Request('PUT', $bucket, $uri, self::$endpoint); + $rest = new S3Request('PUT', $bucket, $uri, self::$endpoint, self::$forcePathStyle); if (!is_array($input)) $input = array( 'data' => $input, 'size' => strlen($input), @@ -826,7 +849,7 @@ public static function putObjectString($string, $bucket, $uri, $acl = self::ACL_ */ public static function getObject($bucket, $uri, $saveTo = false) { - $rest = new S3Request('GET', $bucket, $uri, self::$endpoint); + $rest = new S3Request('GET', $bucket, $uri, self::$endpoint, self::$forcePathStyle); if ($saveTo !== false) { if (is_resource($saveTo)) @@ -861,7 +884,7 @@ public static function getObject($bucket, $uri, $saveTo = false) */ public static function getObjectInfo($bucket, $uri, $returnInfo = true) { - $rest = new S3Request('HEAD', $bucket, $uri, self::$endpoint); + $rest = new S3Request('HEAD', $bucket, $uri, self::$endpoint, self::$forcePathStyle); $rest = $rest->getResponse(); if ($rest->error === false && ($rest->code !== 200 && $rest->code !== 404)) $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); @@ -890,7 +913,7 @@ public static function getObjectInfo($bucket, $uri, $returnInfo = true) */ public static function copyObject($srcBucket, $srcUri, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array(), $storageClass = self::STORAGE_CLASS_STANDARD) { - $rest = new S3Request('PUT', $bucket, $uri, self::$endpoint); + $rest = new S3Request('PUT', $bucket, $uri, self::$endpoint, self::$forcePathStyle); $rest->setHeader('Content-Length', 0); foreach ($requestHeaders as $h => $v) strpos($h, 'x-amz-') === 0 ? $rest->setAmzHeader($h, $v) : $rest->setHeader($h, $v); @@ -927,7 +950,7 @@ public static function copyObject($srcBucket, $srcUri, $bucket, $uri, $acl = sel */ public static function setBucketRedirect($bucket = NULL, $location = NULL) { - $rest = new S3Request('PUT', $bucket, '', self::$endpoint); + $rest = new S3Request('PUT', $bucket, '', self::$endpoint, self::$forcePathStyle); if( empty($bucket) || empty($location) ) { self::__triggerError("S3::setBucketRedirect({$bucket}, {$location}): Empty parameter.", __FILE__, __LINE__); @@ -1004,7 +1027,7 @@ public static function setBucketLogging($bucket, $targetBucket, $targetPrefix = } $dom->appendChild($bucketLoggingStatus); - $rest = new S3Request('PUT', $bucket, '', self::$endpoint); + $rest = new S3Request('PUT', $bucket, '', self::$endpoint, self::$forcePathStyle); $rest->setParameter('logging', null); $rest->data = $dom->saveXML(); $rest->size = strlen($rest->data); @@ -1033,7 +1056,7 @@ public static function setBucketLogging($bucket, $targetBucket, $targetPrefix = */ public static function getBucketLogging($bucket) { - $rest = new S3Request('GET', $bucket, '', self::$endpoint); + $rest = new S3Request('GET', $bucket, '', self::$endpoint, self::$forcePathStyle); $rest->setParameter('logging', null); $rest = $rest->getResponse(); if ($rest->error === false && $rest->code !== 200) @@ -1072,7 +1095,7 @@ public static function disableBucketLogging($bucket) */ public static function getBucketLocation($bucket) { - $rest = new S3Request('GET', $bucket, '', self::$endpoint); + $rest = new S3Request('GET', $bucket, '', self::$endpoint, self::$forcePathStyle); $rest->setParameter('location', null); $rest = $rest->getResponse(); if ($rest->error === false && $rest->code !== 200) @@ -1136,7 +1159,7 @@ public static function setAccessControlPolicy($bucket, $uri = '', $acp = array() $accessControlPolicy->appendChild($accessControlList); $dom->appendChild($accessControlPolicy); - $rest = new S3Request('PUT', $bucket, $uri, self::$endpoint); + $rest = new S3Request('PUT', $bucket, $uri, self::$endpoint, self::$forcePathStyle); $rest->setParameter('acl', null); $rest->data = $dom->saveXML(); $rest->size = strlen($rest->data); @@ -1163,7 +1186,7 @@ public static function setAccessControlPolicy($bucket, $uri = '', $acp = array() */ public static function getAccessControlPolicy($bucket, $uri = '') { - $rest = new S3Request('GET', $bucket, $uri, self::$endpoint); + $rest = new S3Request('GET', $bucket, $uri, self::$endpoint, self::$forcePathStyle); $rest->setParameter('acl', null); $rest = $rest->getResponse(); if ($rest->error === false && $rest->code !== 200) @@ -1224,7 +1247,7 @@ public static function getAccessControlPolicy($bucket, $uri = '') */ public static function deleteObject($bucket, $uri) { - $rest = new S3Request('DELETE', $bucket, $uri, self::$endpoint); + $rest = new S3Request('DELETE', $bucket, $uri, self::$endpoint, self::$forcePathStyle); $rest = $rest->getResponse(); if ($rest->error === false && $rest->code !== 204) $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); @@ -2195,7 +2218,7 @@ final class S3Request * @param string $endpoint AWS endpoint URI * @return mixed */ - function __construct($verb, $bucket = '', $uri = '', $endpoint = 's3.amazonaws.com') + function __construct($verb, $bucket = '', $uri = '', $endpoint = 's3.amazonaws.com', $forcePathStyle = 0) { $this->endpoint = $endpoint; $this->verb = $verb; @@ -2204,7 +2227,7 @@ function __construct($verb, $bucket = '', $uri = '', $endpoint = 's3.amazonaws.c if ($this->bucket !== '') { - if ($this->__dnsBucketName($this->bucket)) + if ($this->__dnsBucketName($this->bucket) && !$forcePathStyle) { $this->headers['Host'] = $this->bucket.'.'.$this->endpoint; $this->resource = '/'.$this->bucket.$this->uri; @@ -2363,7 +2386,6 @@ public function getResponse() $this->uri, $this->parameters ); - } }