diff options
author | Rutger Broekhoff | 2024-01-02 18:56:31 +0100 |
---|---|---|
committer | Rutger Broekhoff | 2024-01-02 18:56:31 +0100 |
commit | 8db41da676ac8368ef7c2549d56239a5ff5eedde (patch) | |
tree | 09c427fd66de2ec1ebffc8342f5fdbb84b0701b5 /vendor/github.com/minio/minio-go/v7/pkg/s3utils/utils.go | |
parent | d4f75fb6db22e57577867445a022227e70958931 (diff) | |
download | gitolfs3-8db41da676ac8368ef7c2549d56239a5ff5eedde.tar.gz gitolfs3-8db41da676ac8368ef7c2549d56239a5ff5eedde.zip |
Delete vendor directory
Diffstat (limited to 'vendor/github.com/minio/minio-go/v7/pkg/s3utils/utils.go')
-rw-r--r-- | vendor/github.com/minio/minio-go/v7/pkg/s3utils/utils.go | 411 |
1 files changed, 0 insertions, 411 deletions
diff --git a/vendor/github.com/minio/minio-go/v7/pkg/s3utils/utils.go b/vendor/github.com/minio/minio-go/v7/pkg/s3utils/utils.go deleted file mode 100644 index 056e78a..0000000 --- a/vendor/github.com/minio/minio-go/v7/pkg/s3utils/utils.go +++ /dev/null | |||
@@ -1,411 +0,0 @@ | |||
1 | /* | ||
2 | * MinIO Go Library for Amazon S3 Compatible Cloud Storage | ||
3 | * Copyright 2015-2020 MinIO, Inc. | ||
4 | * | ||
5 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | * you may not use this file except in compliance with the License. | ||
7 | * You may obtain a copy of the License at | ||
8 | * | ||
9 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | * | ||
11 | * Unless required by applicable law or agreed to in writing, software | ||
12 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | * See the License for the specific language governing permissions and | ||
15 | * limitations under the License. | ||
16 | */ | ||
17 | |||
18 | package s3utils | ||
19 | |||
20 | import ( | ||
21 | "bytes" | ||
22 | "encoding/hex" | ||
23 | "errors" | ||
24 | "net" | ||
25 | "net/url" | ||
26 | "regexp" | ||
27 | "sort" | ||
28 | "strings" | ||
29 | "unicode/utf8" | ||
30 | ) | ||
31 | |||
32 | // Sentinel URL is the default url value which is invalid. | ||
33 | var sentinelURL = url.URL{} | ||
34 | |||
35 | // IsValidDomain validates if input string is a valid domain name. | ||
36 | func IsValidDomain(host string) bool { | ||
37 | // See RFC 1035, RFC 3696. | ||
38 | host = strings.TrimSpace(host) | ||
39 | if len(host) == 0 || len(host) > 255 { | ||
40 | return false | ||
41 | } | ||
42 | // host cannot start or end with "-" | ||
43 | if host[len(host)-1:] == "-" || host[:1] == "-" { | ||
44 | return false | ||
45 | } | ||
46 | // host cannot start or end with "_" | ||
47 | if host[len(host)-1:] == "_" || host[:1] == "_" { | ||
48 | return false | ||
49 | } | ||
50 | // host cannot start with a "." | ||
51 | if host[:1] == "." { | ||
52 | return false | ||
53 | } | ||
54 | // All non alphanumeric characters are invalid. | ||
55 | if strings.ContainsAny(host, "`~!@#$%^&*()+={}[]|\\\"';:><?/") { | ||
56 | return false | ||
57 | } | ||
58 | // No need to regexp match, since the list is non-exhaustive. | ||
59 | // We let it valid and fail later. | ||
60 | return true | ||
61 | } | ||
62 | |||
63 | // IsValidIP parses input string for ip address validity. | ||
64 | func IsValidIP(ip string) bool { | ||
65 | return net.ParseIP(ip) != nil | ||
66 | } | ||
67 | |||
68 | // IsVirtualHostSupported - verifies if bucketName can be part of | ||
69 | // virtual host. Currently only Amazon S3 and Google Cloud Storage | ||
70 | // would support this. | ||
71 | func IsVirtualHostSupported(endpointURL url.URL, bucketName string) bool { | ||
72 | if endpointURL == sentinelURL { | ||
73 | return false | ||
74 | } | ||
75 | // bucketName can be valid but '.' in the hostname will fail SSL | ||
76 | // certificate validation. So do not use host-style for such buckets. | ||
77 | if endpointURL.Scheme == "https" && strings.Contains(bucketName, ".") { | ||
78 | return false | ||
79 | } | ||
80 | // Return true for all other cases | ||
81 | return IsAmazonEndpoint(endpointURL) || IsGoogleEndpoint(endpointURL) || IsAliyunOSSEndpoint(endpointURL) | ||
82 | } | ||
83 | |||
84 | // Refer for region styles - https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region | ||
85 | |||
86 | // amazonS3HostHyphen - regular expression used to determine if an arg is s3 host in hyphenated style. | ||
87 | var amazonS3HostHyphen = regexp.MustCompile(`^s3-(.*?).amazonaws.com$`) | ||
88 | |||
89 | // amazonS3HostDualStack - regular expression used to determine if an arg is s3 host dualstack. | ||
90 | var amazonS3HostDualStack = regexp.MustCompile(`^s3.dualstack.(.*?).amazonaws.com$`) | ||
91 | |||
92 | // amazonS3HostFIPS - regular expression used to determine if an arg is s3 FIPS host. | ||
93 | var amazonS3HostFIPS = regexp.MustCompile(`^s3-fips.(.*?).amazonaws.com$`) | ||
94 | |||
95 | // amazonS3HostFIPSDualStack - regular expression used to determine if an arg is s3 FIPS host dualstack. | ||
96 | var amazonS3HostFIPSDualStack = regexp.MustCompile(`^s3-fips.dualstack.(.*?).amazonaws.com$`) | ||
97 | |||
98 | // amazonS3HostDot - regular expression used to determine if an arg is s3 host in . style. | ||
99 | var amazonS3HostDot = regexp.MustCompile(`^s3.(.*?).amazonaws.com$`) | ||
100 | |||
101 | // amazonS3ChinaHost - regular expression used to determine if the arg is s3 china host. | ||
102 | var amazonS3ChinaHost = regexp.MustCompile(`^s3.(cn.*?).amazonaws.com.cn$`) | ||
103 | |||
104 | // amazonS3ChinaHostDualStack - regular expression used to determine if the arg is s3 china host dualstack. | ||
105 | var amazonS3ChinaHostDualStack = regexp.MustCompile(`^s3.dualstack.(cn.*?).amazonaws.com.cn$`) | ||
106 | |||
107 | // Regular expression used to determine if the arg is elb host. | ||
108 | var elbAmazonRegex = regexp.MustCompile(`elb(.*?).amazonaws.com$`) | ||
109 | |||
110 | // Regular expression used to determine if the arg is elb host in china. | ||
111 | var elbAmazonCnRegex = regexp.MustCompile(`elb(.*?).amazonaws.com.cn$`) | ||
112 | |||
113 | // amazonS3HostPrivateLink - regular expression used to determine if an arg is s3 host in AWS PrivateLink interface endpoints style | ||
114 | var amazonS3HostPrivateLink = regexp.MustCompile(`^(?:bucket|accesspoint).vpce-.*?.s3.(.*?).vpce.amazonaws.com$`) | ||
115 | |||
116 | // GetRegionFromURL - returns a region from url host. | ||
117 | func GetRegionFromURL(endpointURL url.URL) string { | ||
118 | if endpointURL == sentinelURL { | ||
119 | return "" | ||
120 | } | ||
121 | if endpointURL.Host == "s3-external-1.amazonaws.com" { | ||
122 | return "" | ||
123 | } | ||
124 | |||
125 | // if elb's are used we cannot calculate which region it may be, just return empty. | ||
126 | if elbAmazonRegex.MatchString(endpointURL.Host) || elbAmazonCnRegex.MatchString(endpointURL.Host) { | ||
127 | return "" | ||
128 | } | ||
129 | |||
130 | // We check for FIPS dualstack matching first to avoid the non-greedy | ||
131 | // regex for FIPS non-dualstack matching a dualstack URL | ||
132 | parts := amazonS3HostFIPSDualStack.FindStringSubmatch(endpointURL.Host) | ||
133 | if len(parts) > 1 { | ||
134 | return parts[1] | ||
135 | } | ||
136 | |||
137 | parts = amazonS3HostFIPS.FindStringSubmatch(endpointURL.Host) | ||
138 | if len(parts) > 1 { | ||
139 | return parts[1] | ||
140 | } | ||
141 | |||
142 | parts = amazonS3HostDualStack.FindStringSubmatch(endpointURL.Host) | ||
143 | if len(parts) > 1 { | ||
144 | return parts[1] | ||
145 | } | ||
146 | |||
147 | parts = amazonS3HostHyphen.FindStringSubmatch(endpointURL.Host) | ||
148 | if len(parts) > 1 { | ||
149 | return parts[1] | ||
150 | } | ||
151 | |||
152 | parts = amazonS3ChinaHost.FindStringSubmatch(endpointURL.Host) | ||
153 | if len(parts) > 1 { | ||
154 | return parts[1] | ||
155 | } | ||
156 | |||
157 | parts = amazonS3ChinaHostDualStack.FindStringSubmatch(endpointURL.Host) | ||
158 | if len(parts) > 1 { | ||
159 | return parts[1] | ||
160 | } | ||
161 | |||
162 | parts = amazonS3HostDot.FindStringSubmatch(endpointURL.Host) | ||
163 | if len(parts) > 1 { | ||
164 | return parts[1] | ||
165 | } | ||
166 | |||
167 | parts = amazonS3HostPrivateLink.FindStringSubmatch(endpointURL.Host) | ||
168 | if len(parts) > 1 { | ||
169 | return parts[1] | ||
170 | } | ||
171 | |||
172 | return "" | ||
173 | } | ||
174 | |||
175 | // IsAliyunOSSEndpoint - Match if it is exactly Aliyun OSS endpoint. | ||
176 | func IsAliyunOSSEndpoint(endpointURL url.URL) bool { | ||
177 | return strings.HasSuffix(endpointURL.Host, "aliyuncs.com") | ||
178 | } | ||
179 | |||
180 | // IsAmazonEndpoint - Match if it is exactly Amazon S3 endpoint. | ||
181 | func IsAmazonEndpoint(endpointURL url.URL) bool { | ||
182 | if endpointURL.Host == "s3-external-1.amazonaws.com" || endpointURL.Host == "s3.amazonaws.com" { | ||
183 | return true | ||
184 | } | ||
185 | return GetRegionFromURL(endpointURL) != "" | ||
186 | } | ||
187 | |||
188 | // IsAmazonGovCloudEndpoint - Match if it is exactly Amazon S3 GovCloud endpoint. | ||
189 | func IsAmazonGovCloudEndpoint(endpointURL url.URL) bool { | ||
190 | if endpointURL == sentinelURL { | ||
191 | return false | ||
192 | } | ||
193 | return (endpointURL.Host == "s3-us-gov-west-1.amazonaws.com" || | ||
194 | endpointURL.Host == "s3-us-gov-east-1.amazonaws.com" || | ||
195 | IsAmazonFIPSGovCloudEndpoint(endpointURL)) | ||
196 | } | ||
197 | |||
198 | // IsAmazonFIPSGovCloudEndpoint - match if the endpoint is FIPS and GovCloud. | ||
199 | func IsAmazonFIPSGovCloudEndpoint(endpointURL url.URL) bool { | ||
200 | if endpointURL == sentinelURL { | ||
201 | return false | ||
202 | } | ||
203 | return IsAmazonFIPSEndpoint(endpointURL) && strings.Contains(endpointURL.Host, "us-gov-") | ||
204 | } | ||
205 | |||
206 | // IsAmazonFIPSEndpoint - Match if it is exactly Amazon S3 FIPS endpoint. | ||
207 | // See https://aws.amazon.com/compliance/fips. | ||
208 | func IsAmazonFIPSEndpoint(endpointURL url.URL) bool { | ||
209 | if endpointURL == sentinelURL { | ||
210 | return false | ||
211 | } | ||
212 | return strings.HasPrefix(endpointURL.Host, "s3-fips") && strings.HasSuffix(endpointURL.Host, ".amazonaws.com") | ||
213 | } | ||
214 | |||
215 | // IsAmazonPrivateLinkEndpoint - Match if it is exactly Amazon S3 PrivateLink interface endpoint | ||
216 | // See https://docs.aws.amazon.com/AmazonS3/latest/userguide/privatelink-interface-endpoints.html. | ||
217 | func IsAmazonPrivateLinkEndpoint(endpointURL url.URL) bool { | ||
218 | if endpointURL == sentinelURL { | ||
219 | return false | ||
220 | } | ||
221 | return amazonS3HostPrivateLink.MatchString(endpointURL.Host) | ||
222 | } | ||
223 | |||
224 | // IsGoogleEndpoint - Match if it is exactly Google cloud storage endpoint. | ||
225 | func IsGoogleEndpoint(endpointURL url.URL) bool { | ||
226 | if endpointURL == sentinelURL { | ||
227 | return false | ||
228 | } | ||
229 | return endpointURL.Host == "storage.googleapis.com" | ||
230 | } | ||
231 | |||
232 | // Expects ascii encoded strings - from output of urlEncodePath | ||
233 | func percentEncodeSlash(s string) string { | ||
234 | return strings.ReplaceAll(s, "/", "%2F") | ||
235 | } | ||
236 | |||
237 | // QueryEncode - encodes query values in their URL encoded form. In | ||
238 | // addition to the percent encoding performed by urlEncodePath() used | ||
239 | // here, it also percent encodes '/' (forward slash) | ||
240 | func QueryEncode(v url.Values) string { | ||
241 | if v == nil { | ||
242 | return "" | ||
243 | } | ||
244 | var buf bytes.Buffer | ||
245 | keys := make([]string, 0, len(v)) | ||
246 | for k := range v { | ||
247 | keys = append(keys, k) | ||
248 | } | ||
249 | sort.Strings(keys) | ||
250 | for _, k := range keys { | ||
251 | vs := v[k] | ||
252 | prefix := percentEncodeSlash(EncodePath(k)) + "=" | ||
253 | for _, v := range vs { | ||
254 | if buf.Len() > 0 { | ||
255 | buf.WriteByte('&') | ||
256 | } | ||
257 | buf.WriteString(prefix) | ||
258 | buf.WriteString(percentEncodeSlash(EncodePath(v))) | ||
259 | } | ||
260 | } | ||
261 | return buf.String() | ||
262 | } | ||
263 | |||
264 | // TagDecode - decodes canonical tag into map of key and value. | ||
265 | func TagDecode(ctag string) map[string]string { | ||
266 | if ctag == "" { | ||
267 | return map[string]string{} | ||
268 | } | ||
269 | tags := strings.Split(ctag, "&") | ||
270 | tagMap := make(map[string]string, len(tags)) | ||
271 | var err error | ||
272 | for _, tag := range tags { | ||
273 | kvs := strings.SplitN(tag, "=", 2) | ||
274 | if len(kvs) == 0 { | ||
275 | return map[string]string{} | ||
276 | } | ||
277 | if len(kvs) == 1 { | ||
278 | return map[string]string{} | ||
279 | } | ||
280 | tagMap[kvs[0]], err = url.PathUnescape(kvs[1]) | ||
281 | if err != nil { | ||
282 | continue | ||
283 | } | ||
284 | } | ||
285 | return tagMap | ||
286 | } | ||
287 | |||
288 | // TagEncode - encodes tag values in their URL encoded form. In | ||
289 | // addition to the percent encoding performed by urlEncodePath() used | ||
290 | // here, it also percent encodes '/' (forward slash) | ||
291 | func TagEncode(tags map[string]string) string { | ||
292 | if tags == nil { | ||
293 | return "" | ||
294 | } | ||
295 | values := url.Values{} | ||
296 | for k, v := range tags { | ||
297 | values[k] = []string{v} | ||
298 | } | ||
299 | return QueryEncode(values) | ||
300 | } | ||
301 | |||
302 | // if object matches reserved string, no need to encode them | ||
303 | var reservedObjectNames = regexp.MustCompile("^[a-zA-Z0-9-_.~/]+$") | ||
304 | |||
305 | // EncodePath encode the strings from UTF-8 byte representations to HTML hex escape sequences | ||
306 | // | ||
307 | // This is necessary since regular url.Parse() and url.Encode() functions do not support UTF-8 | ||
308 | // non english characters cannot be parsed due to the nature in which url.Encode() is written | ||
309 | // | ||
310 | // This function on the other hand is a direct replacement for url.Encode() technique to support | ||
311 | // pretty much every UTF-8 character. | ||
312 | func EncodePath(pathName string) string { | ||
313 | if reservedObjectNames.MatchString(pathName) { | ||
314 | return pathName | ||
315 | } | ||
316 | var encodedPathname strings.Builder | ||
317 | for _, s := range pathName { | ||
318 | if 'A' <= s && s <= 'Z' || 'a' <= s && s <= 'z' || '0' <= s && s <= '9' { // §2.3 Unreserved characters (mark) | ||
319 | encodedPathname.WriteRune(s) | ||
320 | continue | ||
321 | } | ||
322 | switch s { | ||
323 | case '-', '_', '.', '~', '/': // §2.3 Unreserved characters (mark) | ||
324 | encodedPathname.WriteRune(s) | ||
325 | continue | ||
326 | default: | ||
327 | l := utf8.RuneLen(s) | ||
328 | if l < 0 { | ||
329 | // if utf8 cannot convert return the same string as is | ||
330 | return pathName | ||
331 | } | ||
332 | u := make([]byte, l) | ||
333 | utf8.EncodeRune(u, s) | ||
334 | for _, r := range u { | ||
335 | hex := hex.EncodeToString([]byte{r}) | ||
336 | encodedPathname.WriteString("%" + strings.ToUpper(hex)) | ||
337 | } | ||
338 | } | ||
339 | } | ||
340 | return encodedPathname.String() | ||
341 | } | ||
342 | |||
343 | // We support '.' with bucket names but we fallback to using path | ||
344 | // style requests instead for such buckets. | ||
345 | var ( | ||
346 | validBucketName = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9\.\-\_\:]{1,61}[A-Za-z0-9]$`) | ||
347 | validBucketNameStrict = regexp.MustCompile(`^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$`) | ||
348 | ipAddress = regexp.MustCompile(`^(\d+\.){3}\d+$`) | ||
349 | ) | ||
350 | |||
351 | // Common checker for both stricter and basic validation. | ||
352 | func checkBucketNameCommon(bucketName string, strict bool) (err error) { | ||
353 | if strings.TrimSpace(bucketName) == "" { | ||
354 | return errors.New("Bucket name cannot be empty") | ||
355 | } | ||
356 | if len(bucketName) < 3 { | ||
357 | return errors.New("Bucket name cannot be shorter than 3 characters") | ||
358 | } | ||
359 | if len(bucketName) > 63 { | ||
360 | return errors.New("Bucket name cannot be longer than 63 characters") | ||
361 | } | ||
362 | if ipAddress.MatchString(bucketName) { | ||
363 | return errors.New("Bucket name cannot be an ip address") | ||
364 | } | ||
365 | if strings.Contains(bucketName, "..") || strings.Contains(bucketName, ".-") || strings.Contains(bucketName, "-.") { | ||
366 | return errors.New("Bucket name contains invalid characters") | ||
367 | } | ||
368 | if strict { | ||
369 | if !validBucketNameStrict.MatchString(bucketName) { | ||
370 | err = errors.New("Bucket name contains invalid characters") | ||
371 | } | ||
372 | return err | ||
373 | } | ||
374 | if !validBucketName.MatchString(bucketName) { | ||
375 | err = errors.New("Bucket name contains invalid characters") | ||
376 | } | ||
377 | return err | ||
378 | } | ||
379 | |||
380 | // CheckValidBucketName - checks if we have a valid input bucket name. | ||
381 | func CheckValidBucketName(bucketName string) (err error) { | ||
382 | return checkBucketNameCommon(bucketName, false) | ||
383 | } | ||
384 | |||
385 | // CheckValidBucketNameStrict - checks if we have a valid input bucket name. | ||
386 | // This is a stricter version. | ||
387 | // - http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html | ||
388 | func CheckValidBucketNameStrict(bucketName string) (err error) { | ||
389 | return checkBucketNameCommon(bucketName, true) | ||
390 | } | ||
391 | |||
392 | // CheckValidObjectNamePrefix - checks if we have a valid input object name prefix. | ||
393 | // - http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html | ||
394 | func CheckValidObjectNamePrefix(objectName string) error { | ||
395 | if len(objectName) > 1024 { | ||
396 | return errors.New("Object name cannot be longer than 1024 characters") | ||
397 | } | ||
398 | if !utf8.ValidString(objectName) { | ||
399 | return errors.New("Object name with non UTF-8 strings are not supported") | ||
400 | } | ||
401 | return nil | ||
402 | } | ||
403 | |||
404 | // CheckValidObjectName - checks if we have a valid input object name. | ||
405 | // - http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html | ||
406 | func CheckValidObjectName(objectName string) error { | ||
407 | if strings.TrimSpace(objectName) == "" { | ||
408 | return errors.New("Object name cannot be empty") | ||
409 | } | ||
410 | return CheckValidObjectNamePrefix(objectName) | ||
411 | } | ||