xref: /aosp_15_r20/external/spdx-tools/tvloader/parser2v3/parse_file.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
1// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2
3package parser2v3
4
5import (
6	"fmt"
7
8	"github.com/spdx/tools-golang/spdx/common"
9	"github.com/spdx/tools-golang/spdx/v2_3"
10)
11
12func (parser *tvParser2_3) parsePairFromFile2_3(tag string, value string) error {
13	// expire fileAOP for anything other than an AOPHomePage or AOPURI
14	// (we'll actually handle the HomePage and URI further below)
15	if tag != "ArtifactOfProjectHomePage" && tag != "ArtifactOfProjectURI" {
16		parser.fileAOP = nil
17	}
18
19	switch tag {
20	// tag for creating new file section
21	case "FileName":
22		// check if the previous file contained an spdx Id or not
23		if parser.file != nil && parser.file.FileSPDXIdentifier == nullSpdxElementId2_3 {
24			return fmt.Errorf("file with FileName %s does not have SPDX identifier", parser.file.FileName)
25		}
26		parser.file = &v2_3.File{}
27		parser.file.FileName = value
28	// tag for creating new package section and going back to parsing Package
29	case "PackageName":
30		parser.st = psPackage2_3
31		// check if the previous file contained an spdx Id or not
32		if parser.file != nil && parser.file.FileSPDXIdentifier == nullSpdxElementId2_3 {
33			return fmt.Errorf("file with FileName %s does not have SPDX identifier", parser.file.FileName)
34		}
35		parser.file = nil
36		return parser.parsePairFromPackage2_3(tag, value)
37	// tag for going on to snippet section
38	case "SnippetSPDXID":
39		parser.st = psSnippet2_3
40		return parser.parsePairFromSnippet2_3(tag, value)
41	// tag for going on to other license section
42	case "LicenseID":
43		parser.st = psOtherLicense2_3
44		return parser.parsePairFromOtherLicense2_3(tag, value)
45	// tags for file data
46	case "SPDXID":
47		eID, err := extractElementID(value)
48		if err != nil {
49			return err
50		}
51		parser.file.FileSPDXIdentifier = eID
52		if parser.pkg == nil {
53			if parser.doc.Files == nil {
54				parser.doc.Files = []*v2_3.File{}
55			}
56			parser.doc.Files = append(parser.doc.Files, parser.file)
57		} else {
58			if parser.pkg.Files == nil {
59				parser.pkg.Files = []*v2_3.File{}
60			}
61			parser.pkg.Files = append(parser.pkg.Files, parser.file)
62		}
63	case "FileType":
64		parser.file.FileTypes = append(parser.file.FileTypes, value)
65	case "FileChecksum":
66		subkey, subvalue, err := extractSubs(value)
67		if err != nil {
68			return err
69		}
70		if parser.file.Checksums == nil {
71			parser.file.Checksums = []common.Checksum{}
72		}
73		switch common.ChecksumAlgorithm(subkey) {
74		case common.SHA1,
75			common.SHA224,
76			common.SHA256,
77			common.SHA384,
78			common.SHA512,
79			common.MD2,
80			common.MD4,
81			common.MD5,
82			common.MD6,
83			common.SHA3_256,
84			common.SHA3_384,
85			common.SHA3_512,
86			common.BLAKE2b_256,
87			common.BLAKE2b_384,
88			common.BLAKE2b_512,
89			common.BLAKE3,
90			common.ADLER32:
91			algorithm := common.ChecksumAlgorithm(subkey)
92			parser.file.Checksums = append(parser.file.Checksums, common.Checksum{Algorithm: algorithm, Value: subvalue})
93		default:
94			return fmt.Errorf("got unknown checksum type %s", subkey)
95		}
96	case "LicenseConcluded":
97		parser.file.LicenseConcluded = value
98	case "LicenseInfoInFile":
99		parser.file.LicenseInfoInFiles = append(parser.file.LicenseInfoInFiles, value)
100	case "LicenseComments":
101		parser.file.LicenseComments = value
102	case "FileCopyrightText":
103		parser.file.FileCopyrightText = value
104	case "ArtifactOfProjectName":
105		parser.fileAOP = &v2_3.ArtifactOfProject{}
106		parser.file.ArtifactOfProjects = append(parser.file.ArtifactOfProjects, parser.fileAOP)
107		parser.fileAOP.Name = value
108	case "ArtifactOfProjectHomePage":
109		if parser.fileAOP == nil {
110			return fmt.Errorf("no current ArtifactOfProject found")
111		}
112		parser.fileAOP.HomePage = value
113	case "ArtifactOfProjectURI":
114		if parser.fileAOP == nil {
115			return fmt.Errorf("no current ArtifactOfProject found")
116		}
117		parser.fileAOP.URI = value
118	case "FileComment":
119		parser.file.FileComment = value
120	case "FileNotice":
121		parser.file.FileNotice = value
122	case "FileContributor":
123		parser.file.FileContributors = append(parser.file.FileContributors, value)
124	case "FileDependency":
125		parser.file.FileDependencies = append(parser.file.FileDependencies, value)
126	case "FileAttributionText":
127		parser.file.FileAttributionTexts = append(parser.file.FileAttributionTexts, value)
128	// for relationship tags, pass along but don't change state
129	case "Relationship":
130		parser.rln = &v2_3.Relationship{}
131		parser.doc.Relationships = append(parser.doc.Relationships, parser.rln)
132		return parser.parsePairForRelationship2_3(tag, value)
133	case "RelationshipComment":
134		return parser.parsePairForRelationship2_3(tag, value)
135	// for annotation tags, pass along but don't change state
136	case "Annotator":
137		parser.ann = &v2_3.Annotation{}
138		parser.doc.Annotations = append(parser.doc.Annotations, parser.ann)
139		return parser.parsePairForAnnotation2_3(tag, value)
140	case "AnnotationDate":
141		return parser.parsePairForAnnotation2_3(tag, value)
142	case "AnnotationType":
143		return parser.parsePairForAnnotation2_3(tag, value)
144	case "SPDXREF":
145		return parser.parsePairForAnnotation2_3(tag, value)
146	case "AnnotationComment":
147		return parser.parsePairForAnnotation2_3(tag, value)
148	// tag for going on to review section (DEPRECATED)
149	case "Reviewer":
150		parser.st = psReview2_3
151		return parser.parsePairFromReview2_3(tag, value)
152	default:
153		return fmt.Errorf("received unknown tag %v in File section", tag)
154	}
155
156	return nil
157}
158