// MinIO Object Storage (c) 2021 MinIO, Inc. // // Copyright (c) 2015-2021 MinIO, Inc. // // This file is part of MinIO Object Storage stack // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package cmd import ( "fmt" "net/http" "strings" "github.com/minio/mc/pkg/probe" ) // validate the passed metadataString and populate the map func getMetaDataEntry(metadataString string) (map[string]string, *probe.Error) { metaDataMap := make(map[string]string) r := strings.NewReader(metadataString) type pToken int const ( KEY pToken = iota VALUE ) type pState int const ( NORMAL pState = iota QSTRING DQSTRING ) var key, value strings.Builder writeRune := func(ch rune, pt pToken) { switch pt { case KEY: key.WriteRune(ch) case VALUE: value.WriteRune(ch) default: panic("Invalid parser token type") } } ps := NORMAL pt := KEY p := 0 for ; ; p++ { ch, _, e := r.ReadRune() if e != nil { // eof if ps == QSTRING || ps == DQSTRING || pt == KEY { return nil, probe.NewError(ErrInvalidMetadata) } metaDataMap[http.CanonicalHeaderKey(key.String())] = value.String() return metaDataMap, nil } if ch == '"' { switch ps { case DQSTRING: ps = NORMAL case QSTRING: writeRune(ch, pt) case NORMAL: ps = DQSTRING default: break } continue } if ch == '\'' { switch ps { case QSTRING: ps = NORMAL case DQSTRING: writeRune(ch, pt) case NORMAL: ps = QSTRING default: break } continue } if ch == '=' { if ps == QSTRING || ps == DQSTRING { writeRune(ch, pt) } else if pt == KEY { pt = VALUE } else if pt == VALUE { writeRune(ch, pt) } else { break } continue } if ch == ';' { if ps == QSTRING || ps == DQSTRING { writeRune(ch, pt) } else if pt == KEY { return nil, probe.NewError(ErrInvalidMetadata) } else if pt == VALUE { metaDataMap[http.CanonicalHeaderKey(key.String())] = value.String() key.Reset() value.Reset() pt = KEY } else { break } continue } writeRune(ch, pt) } fatalErr := fmt.Sprintf("Invalid parser state at index: %d", p) panic(fatalErr) }