storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/api-utils.go (about) 1 /* 2 * Minio Cloud Storage, (C) 2019 Minio, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package cmd 18 19 import ( 20 "strings" 21 ) 22 23 func shouldEscape(c byte) bool { 24 if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' { 25 return false 26 } 27 28 switch c { 29 case '-', '_', '.', '/', '*': 30 return false 31 } 32 return true 33 } 34 35 // s3URLEncode is based on Golang's url.QueryEscape() code, 36 // while considering some S3 exceptions: 37 // - Avoid encoding '/' and '*' 38 // - Force encoding of '~' 39 func s3URLEncode(s string) string { 40 spaceCount, hexCount := 0, 0 41 for i := 0; i < len(s); i++ { 42 c := s[i] 43 if shouldEscape(c) { 44 if c == ' ' { 45 spaceCount++ 46 } else { 47 hexCount++ 48 } 49 } 50 } 51 52 if spaceCount == 0 && hexCount == 0 { 53 return s 54 } 55 56 var buf [64]byte 57 var t []byte 58 59 required := len(s) + 2*hexCount 60 if required <= len(buf) { 61 t = buf[:required] 62 } else { 63 t = make([]byte, required) 64 } 65 66 if hexCount == 0 { 67 copy(t, s) 68 for i := 0; i < len(s); i++ { 69 if s[i] == ' ' { 70 t[i] = '+' 71 } 72 } 73 return string(t) 74 } 75 76 j := 0 77 for i := 0; i < len(s); i++ { 78 switch c := s[i]; { 79 case c == ' ': 80 t[j] = '+' 81 j++ 82 case shouldEscape(c): 83 t[j] = '%' 84 t[j+1] = "0123456789ABCDEF"[c>>4] 85 t[j+2] = "0123456789ABCDEF"[c&15] 86 j += 3 87 default: 88 t[j] = s[i] 89 j++ 90 } 91 } 92 return string(t) 93 } 94 95 // s3EncodeName encodes string in response when encodingType is specified in AWS S3 requests. 96 func s3EncodeName(name string, encodingType string) (result string) { 97 // Quick path to exit 98 if encodingType == "" { 99 return name 100 } 101 encodingType = strings.ToLower(encodingType) 102 switch encodingType { 103 case "url": 104 return s3URLEncode(name) 105 } 106 return name 107 }