github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/cp-main_contrib.go (about) 1 // MinIO Object Storage (c) 2021 MinIO, Inc. 2 // 3 // Copyright (c) 2015-2021 MinIO, Inc. 4 // 5 // This file is part of MinIO Object Storage stack 6 // 7 // This program is free software: you can redistribute it and/or modify 8 // it under the terms of the GNU Affero General Public License as published by 9 // the Free Software Foundation, either version 3 of the License, or 10 // (at your option) any later version. 11 // 12 // This program is distributed in the hope that it will be useful 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU Affero General Public License for more details. 16 // 17 // You should have received a copy of the GNU Affero General Public License 18 // along with this program. If not, see <http://www.gnu.org/licenses/>. 19 20 package cmd 21 22 import ( 23 "fmt" 24 "net/http" 25 "strings" 26 27 "github.com/minio/mc/pkg/probe" 28 ) 29 30 // validate the passed metadataString and populate the map 31 func getMetaDataEntry(metadataString string) (map[string]string, *probe.Error) { 32 metaDataMap := make(map[string]string) 33 r := strings.NewReader(metadataString) 34 35 type pToken int 36 const ( 37 KEY pToken = iota 38 VALUE 39 ) 40 41 type pState int 42 const ( 43 NORMAL pState = iota 44 QSTRING 45 DQSTRING 46 ) 47 48 var key, value strings.Builder 49 50 writeRune := func(ch rune, pt pToken) { 51 if pt == KEY { 52 key.WriteRune(ch) 53 } else if pt == VALUE { 54 value.WriteRune(ch) 55 } else { 56 panic("Invalid parser token type") 57 } 58 } 59 60 ps := NORMAL 61 pt := KEY 62 p := 0 63 64 for ; ; p++ { 65 ch, _, e := r.ReadRune() 66 if e != nil { 67 // eof 68 if ps == QSTRING || ps == DQSTRING || pt == KEY { 69 return nil, probe.NewError(ErrInvalidMetadata) 70 } 71 metaDataMap[http.CanonicalHeaderKey(key.String())] = value.String() 72 return metaDataMap, nil 73 } 74 75 if ch == '"' { 76 if ps == DQSTRING { 77 ps = NORMAL 78 } else if ps == QSTRING { 79 writeRune(ch, pt) 80 } else if ps == NORMAL { 81 ps = DQSTRING 82 } else { 83 break 84 } 85 continue 86 } 87 88 if ch == '\'' { 89 if ps == QSTRING { 90 ps = NORMAL 91 } else if ps == DQSTRING { 92 writeRune(ch, pt) 93 } else if ps == NORMAL { 94 ps = QSTRING 95 } else { 96 break 97 } 98 continue 99 } 100 101 if ch == '=' { 102 if ps == QSTRING || ps == DQSTRING { 103 writeRune(ch, pt) 104 } else if pt == KEY { 105 pt = VALUE 106 } else if pt == VALUE { 107 writeRune(ch, pt) 108 } else { 109 break 110 } 111 continue 112 } 113 114 if ch == ';' { 115 if ps == QSTRING || ps == DQSTRING { 116 writeRune(ch, pt) 117 } else if pt == KEY { 118 return nil, probe.NewError(ErrInvalidMetadata) 119 } else if pt == VALUE { 120 metaDataMap[http.CanonicalHeaderKey(key.String())] = value.String() 121 key.Reset() 122 value.Reset() 123 pt = KEY 124 } else { 125 break 126 } 127 continue 128 } 129 130 writeRune(ch, pt) 131 } 132 133 fatalErr := fmt.Sprintf("Invalid parser state at index: %d", p) 134 panic(fatalErr) 135 }