1*ba677afaSXin Li// Package parser2v3 contains functions to read, load and parse 2*ba677afaSXin Li// SPDX tag-value files, version 2.3. 3*ba677afaSXin Li// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 4*ba677afaSXin Lipackage parser2v3 5*ba677afaSXin Li 6*ba677afaSXin Liimport ( 7*ba677afaSXin Li "fmt" 8*ba677afaSXin Li 9*ba677afaSXin Li "github.com/spdx/tools-golang/spdx/common" 10*ba677afaSXin Li "github.com/spdx/tools-golang/spdx/v2_3" 11*ba677afaSXin Li "github.com/spdx/tools-golang/tvloader/reader" 12*ba677afaSXin Li) 13*ba677afaSXin Li 14*ba677afaSXin Li// ParseTagValues takes a list of (tag, value) pairs, parses it and returns 15*ba677afaSXin Li// a pointer to a parsed SPDX Document. 16*ba677afaSXin Lifunc ParseTagValues(tvs []reader.TagValuePair) (*v2_3.Document, error) { 17*ba677afaSXin Li parser := tvParser2_3{} 18*ba677afaSXin Li for _, tv := range tvs { 19*ba677afaSXin Li err := parser.parsePair2_3(tv.Tag, tv.Value) 20*ba677afaSXin Li if err != nil { 21*ba677afaSXin Li return nil, err 22*ba677afaSXin Li } 23*ba677afaSXin Li } 24*ba677afaSXin Li if parser.file != nil && parser.file.FileSPDXIdentifier == nullSpdxElementId2_3 { 25*ba677afaSXin Li return nil, fmt.Errorf("file with FileName %s does not have SPDX identifier", parser.file.FileName) 26*ba677afaSXin Li } 27*ba677afaSXin Li if parser.pkg != nil && parser.pkg.PackageSPDXIdentifier == nullSpdxElementId2_3 { 28*ba677afaSXin Li return nil, fmt.Errorf("package with PackageName %s does not have SPDX identifier", parser.pkg.PackageName) 29*ba677afaSXin Li } 30*ba677afaSXin Li return parser.doc, nil 31*ba677afaSXin Li} 32*ba677afaSXin Li 33*ba677afaSXin Lifunc (parser *tvParser2_3) parsePair2_3(tag string, value string) error { 34*ba677afaSXin Li switch parser.st { 35*ba677afaSXin Li case psStart2_3: 36*ba677afaSXin Li return parser.parsePairFromStart2_3(tag, value) 37*ba677afaSXin Li case psCreationInfo2_3: 38*ba677afaSXin Li return parser.parsePairFromCreationInfo2_3(tag, value) 39*ba677afaSXin Li case psPackage2_3: 40*ba677afaSXin Li return parser.parsePairFromPackage2_3(tag, value) 41*ba677afaSXin Li case psFile2_3: 42*ba677afaSXin Li return parser.parsePairFromFile2_3(tag, value) 43*ba677afaSXin Li case psSnippet2_3: 44*ba677afaSXin Li return parser.parsePairFromSnippet2_3(tag, value) 45*ba677afaSXin Li case psOtherLicense2_3: 46*ba677afaSXin Li return parser.parsePairFromOtherLicense2_3(tag, value) 47*ba677afaSXin Li case psReview2_3: 48*ba677afaSXin Li return parser.parsePairFromReview2_3(tag, value) 49*ba677afaSXin Li default: 50*ba677afaSXin Li return fmt.Errorf("parser state %v not recognized when parsing (%s, %s)", parser.st, tag, value) 51*ba677afaSXin Li } 52*ba677afaSXin Li} 53*ba677afaSXin Li 54*ba677afaSXin Lifunc (parser *tvParser2_3) parsePairFromStart2_3(tag string, value string) error { 55*ba677afaSXin Li // fail if not in Start parser state 56*ba677afaSXin Li if parser.st != psStart2_3 { 57*ba677afaSXin Li return fmt.Errorf("got invalid state %v in parsePairFromStart2_3", parser.st) 58*ba677afaSXin Li } 59*ba677afaSXin Li 60*ba677afaSXin Li // create an SPDX Document data struct if we don't have one already 61*ba677afaSXin Li if parser.doc == nil { 62*ba677afaSXin Li parser.doc = &v2_3.Document{ExternalDocumentReferences: []v2_3.ExternalDocumentRef{}} 63*ba677afaSXin Li } 64*ba677afaSXin Li 65*ba677afaSXin Li switch tag { 66*ba677afaSXin Li case "DocumentComment": 67*ba677afaSXin Li parser.doc.DocumentComment = value 68*ba677afaSXin Li case "SPDXVersion": 69*ba677afaSXin Li parser.doc.SPDXVersion = value 70*ba677afaSXin Li case "DataLicense": 71*ba677afaSXin Li parser.doc.DataLicense = value 72*ba677afaSXin Li case "SPDXID": 73*ba677afaSXin Li eID, err := extractElementID(value) 74*ba677afaSXin Li if err != nil { 75*ba677afaSXin Li return err 76*ba677afaSXin Li } 77*ba677afaSXin Li parser.doc.SPDXIdentifier = eID 78*ba677afaSXin Li case "DocumentName": 79*ba677afaSXin Li parser.doc.DocumentName = value 80*ba677afaSXin Li case "DocumentNamespace": 81*ba677afaSXin Li parser.doc.DocumentNamespace = value 82*ba677afaSXin Li case "ExternalDocumentRef": 83*ba677afaSXin Li documentRefID, uri, alg, checksum, err := extractExternalDocumentReference(value) 84*ba677afaSXin Li if err != nil { 85*ba677afaSXin Li return err 86*ba677afaSXin Li } 87*ba677afaSXin Li edr := v2_3.ExternalDocumentRef{ 88*ba677afaSXin Li DocumentRefID: documentRefID, 89*ba677afaSXin Li URI: uri, 90*ba677afaSXin Li Checksum: common.Checksum{Algorithm: common.ChecksumAlgorithm(alg), Value: checksum}, 91*ba677afaSXin Li } 92*ba677afaSXin Li parser.doc.ExternalDocumentReferences = append(parser.doc.ExternalDocumentReferences, edr) 93*ba677afaSXin Li default: 94*ba677afaSXin Li // move to Creation Info parser state 95*ba677afaSXin Li parser.st = psCreationInfo2_3 96*ba677afaSXin Li return parser.parsePairFromCreationInfo2_3(tag, value) 97*ba677afaSXin Li } 98*ba677afaSXin Li 99*ba677afaSXin Li return nil 100*ba677afaSXin Li} 101