|
|
|
@ -21,7 +21,6 @@ import ( |
|
|
|
|
"fmt" |
|
|
|
|
"io" |
|
|
|
|
"path" |
|
|
|
|
"regexp" |
|
|
|
|
"runtime" |
|
|
|
|
"strings" |
|
|
|
|
"unicode/utf8" |
|
|
|
@ -38,12 +37,10 @@ const ( |
|
|
|
|
minioMetaMultipartBucket = minioMetaBucket + "/" + mpartMetaPrefix |
|
|
|
|
// Minio Tmp meta prefix.
|
|
|
|
|
minioMetaTmpBucket = minioMetaBucket + "/tmp" |
|
|
|
|
// DNS separator (period), used for bucket name validation.
|
|
|
|
|
dnsDelimiter = "." |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// validBucket regexp.
|
|
|
|
|
var validBucket = regexp.MustCompile(`^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$`) |
|
|
|
|
var isIPAddress = regexp.MustCompile(`^(\d+\.){3}\d+$`) |
|
|
|
|
|
|
|
|
|
// isMinioBucket returns true if given bucket is a Minio internal
|
|
|
|
|
// bucket and false otherwise.
|
|
|
|
|
func isMinioMetaBucketName(bucket string) bool { |
|
|
|
@ -52,10 +49,13 @@ func isMinioMetaBucketName(bucket string) bool { |
|
|
|
|
bucket == minioMetaTmpBucket |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// IsValidBucketName verifies a bucket name in accordance with Amazon's
|
|
|
|
|
// requirements. It must be 3-63 characters long, can contain dashes
|
|
|
|
|
// and periods, but must begin and end with a lowercase letter or a number.
|
|
|
|
|
// See: http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
|
|
|
|
|
// IsValidBucketName verifies that a bucket name is in accordance with
|
|
|
|
|
// Amazon's requirements (i.e. DNS naming conventions). It must be 3-63
|
|
|
|
|
// characters long, and it must be a sequence of one or more labels
|
|
|
|
|
// separated by periods. Each label can contain lowercase ascii
|
|
|
|
|
// letters, decimal digits and hyphens, but must not begin or end with
|
|
|
|
|
// a hyphen. See:
|
|
|
|
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
|
|
|
|
|
func IsValidBucketName(bucket string) bool { |
|
|
|
|
// Special case when bucket is equal to one of the meta buckets.
|
|
|
|
|
if isMinioMetaBucketName(bucket) { |
|
|
|
@ -64,12 +64,39 @@ func IsValidBucketName(bucket string) bool { |
|
|
|
|
if len(bucket) < 3 || len(bucket) > 63 { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
if bucket[0] == '.' || bucket[len(bucket)-1] == '.' { |
|
|
|
|
|
|
|
|
|
// Split on dot and check each piece conforms to rules.
|
|
|
|
|
allNumbers := true |
|
|
|
|
pieces := strings.Split(bucket, dnsDelimiter) |
|
|
|
|
for _, piece := range pieces { |
|
|
|
|
if len(piece) == 0 || piece[0] == '-' || |
|
|
|
|
piece[len(piece)-1] == '-' { |
|
|
|
|
// Current piece has 0-length or starts or
|
|
|
|
|
// ends with a hyphen.
|
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
// Now only need to check if each piece is a valid
|
|
|
|
|
// 'label' in AWS terminology and if the bucket looks
|
|
|
|
|
// like an IP address.
|
|
|
|
|
isNotNumber := false |
|
|
|
|
for i := 0; i < len(piece); i++ { |
|
|
|
|
switch { |
|
|
|
|
case (piece[i] >= 'a' && piece[i] <= 'z' || |
|
|
|
|
piece[i] == '-'): |
|
|
|
|
// Found a non-digit character, so
|
|
|
|
|
// this piece is not a number.
|
|
|
|
|
isNotNumber = true |
|
|
|
|
case piece[i] >= '0' && piece[i] <= '9': |
|
|
|
|
// Nothing to do.
|
|
|
|
|
default: |
|
|
|
|
// Found invalid character.
|
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
return (validBucket.MatchString(bucket) && |
|
|
|
|
!isIPAddress.MatchString(bucket) && |
|
|
|
|
!strings.Contains(bucket, "..")) |
|
|
|
|
} |
|
|
|
|
allNumbers = allNumbers && !isNotNumber |
|
|
|
|
} |
|
|
|
|
// Does the bucket name look like an IP address?
|
|
|
|
|
return !(len(pieces) == 4 && allNumbers) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// IsValidObjectName verifies an object name in accordance with Amazon's
|
|
|
|
|