1*ba677afaSXin Li// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 2*ba677afaSXin Li 3*ba677afaSXin Lipackage parser2v1 4*ba677afaSXin Li 5*ba677afaSXin Liimport ( 6*ba677afaSXin Li "fmt" 7*ba677afaSXin Li "strings" 8*ba677afaSXin Li 9*ba677afaSXin Li "github.com/spdx/tools-golang/spdx/common" 10*ba677afaSXin Li) 11*ba677afaSXin Li 12*ba677afaSXin Li// used to extract key / value from embedded substrings 13*ba677afaSXin Li// returns subkey, subvalue, nil if no error, or "", "", error otherwise 14*ba677afaSXin Lifunc extractSubs(value string) (string, string, error) { 15*ba677afaSXin Li // parse the value to see if it's a valid subvalue format 16*ba677afaSXin Li sp := strings.SplitN(value, ":", 2) 17*ba677afaSXin Li if len(sp) == 1 { 18*ba677afaSXin Li return "", "", fmt.Errorf("invalid subvalue format for %s (no colon found)", value) 19*ba677afaSXin Li } 20*ba677afaSXin Li 21*ba677afaSXin Li subkey := strings.TrimSpace(sp[0]) 22*ba677afaSXin Li subvalue := strings.TrimSpace(sp[1]) 23*ba677afaSXin Li 24*ba677afaSXin Li return subkey, subvalue, nil 25*ba677afaSXin Li} 26*ba677afaSXin Li 27*ba677afaSXin Li// used to extract DocumentRef and SPDXRef values from an SPDX Identifier 28*ba677afaSXin Li// which can point either to this document or to a different one 29*ba677afaSXin Lifunc extractDocElementID(value string) (common.DocElementID, error) { 30*ba677afaSXin Li docRefID := "" 31*ba677afaSXin Li idStr := value 32*ba677afaSXin Li 33*ba677afaSXin Li // check prefix to see if it's a DocumentRef ID 34*ba677afaSXin Li if strings.HasPrefix(idStr, "DocumentRef-") { 35*ba677afaSXin Li // extract the part that comes between "DocumentRef-" and ":" 36*ba677afaSXin Li strs := strings.Split(idStr, ":") 37*ba677afaSXin Li // should be exactly two, part before and part after 38*ba677afaSXin Li if len(strs) < 2 { 39*ba677afaSXin Li return common.DocElementID{}, fmt.Errorf("no colon found although DocumentRef- prefix present") 40*ba677afaSXin Li } 41*ba677afaSXin Li if len(strs) > 2 { 42*ba677afaSXin Li return common.DocElementID{}, fmt.Errorf("more than one colon found") 43*ba677afaSXin Li } 44*ba677afaSXin Li 45*ba677afaSXin Li // trim the prefix and confirm non-empty 46*ba677afaSXin Li docRefID = strings.TrimPrefix(strs[0], "DocumentRef-") 47*ba677afaSXin Li if docRefID == "" { 48*ba677afaSXin Li return common.DocElementID{}, fmt.Errorf("document identifier has nothing after prefix") 49*ba677afaSXin Li } 50*ba677afaSXin Li // and use remainder for element ID parsing 51*ba677afaSXin Li idStr = strs[1] 52*ba677afaSXin Li } 53*ba677afaSXin Li 54*ba677afaSXin Li // check prefix to confirm it's got the right prefix for element IDs 55*ba677afaSXin Li if !strings.HasPrefix(idStr, "SPDXRef-") { 56*ba677afaSXin Li return common.DocElementID{}, fmt.Errorf("missing SPDXRef- prefix for element identifier") 57*ba677afaSXin Li } 58*ba677afaSXin Li 59*ba677afaSXin Li // make sure no colons are present 60*ba677afaSXin Li if strings.Contains(idStr, ":") { 61*ba677afaSXin Li // we know this means there was no DocumentRef- prefix, because 62*ba677afaSXin Li // we would have handled multiple colons above if it was 63*ba677afaSXin Li return common.DocElementID{}, fmt.Errorf("invalid colon in element identifier") 64*ba677afaSXin Li } 65*ba677afaSXin Li 66*ba677afaSXin Li // trim the prefix and confirm non-empty 67*ba677afaSXin Li eltRefID := strings.TrimPrefix(idStr, "SPDXRef-") 68*ba677afaSXin Li if eltRefID == "" { 69*ba677afaSXin Li return common.DocElementID{}, fmt.Errorf("element identifier has nothing after prefix") 70*ba677afaSXin Li } 71*ba677afaSXin Li 72*ba677afaSXin Li // we're good 73*ba677afaSXin Li return common.DocElementID{DocumentRefID: docRefID, ElementRefID: common.ElementID(eltRefID)}, nil 74*ba677afaSXin Li} 75*ba677afaSXin Li 76*ba677afaSXin Li// used to extract SPDXRef values only from an SPDX Identifier which can point 77*ba677afaSXin Li// to this document only. Use extractDocElementID for parsing IDs that can 78*ba677afaSXin Li// refer either to this document or a different one. 79*ba677afaSXin Lifunc extractElementID(value string) (common.ElementID, error) { 80*ba677afaSXin Li // check prefix to confirm it's got the right prefix for element IDs 81*ba677afaSXin Li if !strings.HasPrefix(value, "SPDXRef-") { 82*ba677afaSXin Li return common.ElementID(""), fmt.Errorf("missing SPDXRef- prefix for element identifier") 83*ba677afaSXin Li } 84*ba677afaSXin Li 85*ba677afaSXin Li // make sure no colons are present 86*ba677afaSXin Li if strings.Contains(value, ":") { 87*ba677afaSXin Li return common.ElementID(""), fmt.Errorf("invalid colon in element identifier") 88*ba677afaSXin Li } 89*ba677afaSXin Li 90*ba677afaSXin Li // trim the prefix and confirm non-empty 91*ba677afaSXin Li eltRefID := strings.TrimPrefix(value, "SPDXRef-") 92*ba677afaSXin Li if eltRefID == "" { 93*ba677afaSXin Li return common.ElementID(""), fmt.Errorf("element identifier has nothing after prefix") 94*ba677afaSXin Li } 95*ba677afaSXin Li 96*ba677afaSXin Li // we're good 97*ba677afaSXin Li return common.ElementID(eltRefID), nil 98*ba677afaSXin Li} 99