xref: /aosp_15_r20/external/spdx-tools/rdfloader/parser2v3/parse_package.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
1*ba677afaSXin Li// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2*ba677afaSXin Li
3*ba677afaSXin Lipackage parser2v3
4*ba677afaSXin Li
5*ba677afaSXin Liimport (
6*ba677afaSXin Li	"fmt"
7*ba677afaSXin Li	"strings"
8*ba677afaSXin Li
9*ba677afaSXin Li	gordfParser "github.com/spdx/gordf/rdfloader/parser"
10*ba677afaSXin Li	"github.com/spdx/tools-golang/spdx/common"
11*ba677afaSXin Li	"github.com/spdx/tools-golang/spdx/v2_3"
12*ba677afaSXin Li)
13*ba677afaSXin Li
14*ba677afaSXin Lifunc (parser *rdfParser2_3) getPackageFromNode(packageNode *gordfParser.Node) (pkg *v2_3.Package, err error) {
15*ba677afaSXin Li	pkg = &v2_3.Package{} // new package which will be returned
16*ba677afaSXin Li
17*ba677afaSXin Li	currState := parser.cache[packageNode.ID]
18*ba677afaSXin Li	if currState == nil {
19*ba677afaSXin Li		// there is no entry about the state of current package node.
20*ba677afaSXin Li		// this is the first time we're seeing this node.
21*ba677afaSXin Li		parser.cache[packageNode.ID] = &nodeState{
22*ba677afaSXin Li			object: pkg,
23*ba677afaSXin Li			Color:  WHITE,
24*ba677afaSXin Li		}
25*ba677afaSXin Li	} else if currState.Color == GREY {
26*ba677afaSXin Li		// we have already started parsing this package node and we needn't parse it again.
27*ba677afaSXin Li		return currState.object.(*v2_3.Package), nil
28*ba677afaSXin Li	}
29*ba677afaSXin Li
30*ba677afaSXin Li	// setting color of the state to grey to indicate that we've started to
31*ba677afaSXin Li	// parse this node once.
32*ba677afaSXin Li	parser.cache[packageNode.ID].Color = GREY
33*ba677afaSXin Li
34*ba677afaSXin Li	// setting state color to black to indicate when we're done parsing this node.
35*ba677afaSXin Li	defer func() { parser.cache[packageNode.ID].Color = BLACK }()
36*ba677afaSXin Li
37*ba677afaSXin Li	// setting the SPDXIdentifier for the package.
38*ba677afaSXin Li	eId, err := ExtractElementID(getLastPartOfURI(packageNode.ID))
39*ba677afaSXin Li	if err != nil {
40*ba677afaSXin Li		return nil, fmt.Errorf("error extracting elementID of a package identifier: %v", err)
41*ba677afaSXin Li	}
42*ba677afaSXin Li	pkg.PackageSPDXIdentifier = eId // 3.2
43*ba677afaSXin Li
44*ba677afaSXin Li	// check if we already have a package initialized for this ID
45*ba677afaSXin Li	existingPackageIndex := -1
46*ba677afaSXin Li	for ii, existingPkg := range parser.doc.Packages {
47*ba677afaSXin Li		if existingPkg != nil && existingPkg.PackageSPDXIdentifier == eId {
48*ba677afaSXin Li			existingPackageIndex = ii
49*ba677afaSXin Li			pkg = existingPkg
50*ba677afaSXin Li			break
51*ba677afaSXin Li		}
52*ba677afaSXin Li	}
53*ba677afaSXin Li
54*ba677afaSXin Li	// iterate over all the triples associated with the provided package packageNode.
55*ba677afaSXin Li	for _, subTriple := range parser.nodeToTriples(packageNode) {
56*ba677afaSXin Li		switch subTriple.Predicate.ID {
57*ba677afaSXin Li		case RDF_TYPE:
58*ba677afaSXin Li			// cardinality: exactly 1
59*ba677afaSXin Li			continue
60*ba677afaSXin Li		case SPDX_NAME: // 7.1
61*ba677afaSXin Li			// cardinality: exactly 1
62*ba677afaSXin Li			pkg.PackageName = subTriple.Object.ID
63*ba677afaSXin Li		case SPDX_VERSION_INFO: // 7.3
64*ba677afaSXin Li			// cardinality: max 1
65*ba677afaSXin Li			pkg.PackageVersion = subTriple.Object.ID
66*ba677afaSXin Li		case SPDX_PACKAGE_FILE_NAME: // 7.4
67*ba677afaSXin Li			// cardinality: max 1
68*ba677afaSXin Li			pkg.PackageFileName = subTriple.Object.ID
69*ba677afaSXin Li		case SPDX_SUPPLIER: // 7.5
70*ba677afaSXin Li			// cardinality: max 1
71*ba677afaSXin Li			err = setPackageSupplier(pkg, subTriple.Object.ID)
72*ba677afaSXin Li		case SPDX_ORIGINATOR: // 7.6
73*ba677afaSXin Li			// cardinality: max 1
74*ba677afaSXin Li			err = setPackageOriginator(pkg, subTriple.Object.ID)
75*ba677afaSXin Li		case SPDX_DOWNLOAD_LOCATION: // 7.7
76*ba677afaSXin Li			// cardinality: exactly 1
77*ba677afaSXin Li			err = setDocumentLocationFromURI(pkg, subTriple.Object.ID)
78*ba677afaSXin Li		case SPDX_FILES_ANALYZED: // 7.8
79*ba677afaSXin Li			// cardinality: max 1
80*ba677afaSXin Li			err = setFilesAnalyzed(pkg, subTriple.Object.ID)
81*ba677afaSXin Li		case SPDX_PACKAGE_VERIFICATION_CODE: // 7.9
82*ba677afaSXin Li			// cardinality: max 1
83*ba677afaSXin Li			err = parser.setPackageVerificationCode(pkg, subTriple.Object)
84*ba677afaSXin Li		case SPDX_CHECKSUM: // 7.10
85*ba677afaSXin Li			// cardinality: min 0
86*ba677afaSXin Li			err = parser.setPackageChecksum(pkg, subTriple.Object)
87*ba677afaSXin Li		case DOAP_HOMEPAGE: // 7.11
88*ba677afaSXin Li			// cardinality: max 1
89*ba677afaSXin Li			// homepage must be a valid Uri
90*ba677afaSXin Li			if !isUriValid(subTriple.Object.ID) {
91*ba677afaSXin Li				return nil, fmt.Errorf("invalid uri %s while parsing doap_homepage in a package", subTriple.Object.ID)
92*ba677afaSXin Li			}
93*ba677afaSXin Li			pkg.PackageHomePage = subTriple.Object.ID
94*ba677afaSXin Li		case SPDX_SOURCE_INFO: // 7.12
95*ba677afaSXin Li			// cardinality: max 1
96*ba677afaSXin Li			pkg.PackageSourceInfo = subTriple.Object.ID
97*ba677afaSXin Li		case SPDX_LICENSE_CONCLUDED: // 7.13
98*ba677afaSXin Li			// cardinality: exactly 1
99*ba677afaSXin Li			anyLicenseInfo, err := parser.getAnyLicenseFromNode(subTriple.Object)
100*ba677afaSXin Li			if err != nil {
101*ba677afaSXin Li				return nil, err
102*ba677afaSXin Li			}
103*ba677afaSXin Li			pkg.PackageLicenseConcluded = anyLicenseInfo.ToLicenseString()
104*ba677afaSXin Li		case SPDX_LICENSE_INFO_FROM_FILES: // 7.14
105*ba677afaSXin Li			// cardinality: min 0
106*ba677afaSXin Li			pkg.PackageLicenseInfoFromFiles = append(pkg.PackageLicenseInfoFromFiles, getLicenseStringFromURI(subTriple.Object.ID))
107*ba677afaSXin Li		case SPDX_LICENSE_DECLARED: // 7.15
108*ba677afaSXin Li			// cardinality: exactly 1
109*ba677afaSXin Li			anyLicenseInfo, err := parser.getAnyLicenseFromNode(subTriple.Object)
110*ba677afaSXin Li			if err != nil {
111*ba677afaSXin Li				return nil, err
112*ba677afaSXin Li			}
113*ba677afaSXin Li			pkg.PackageLicenseDeclared = anyLicenseInfo.ToLicenseString()
114*ba677afaSXin Li		case SPDX_LICENSE_COMMENTS: // 7.16
115*ba677afaSXin Li			// cardinality: max 1
116*ba677afaSXin Li			pkg.PackageLicenseComments = subTriple.Object.ID
117*ba677afaSXin Li		case SPDX_COPYRIGHT_TEXT: // 7.17
118*ba677afaSXin Li			// cardinality: exactly 1
119*ba677afaSXin Li			pkg.PackageCopyrightText = subTriple.Object.ID
120*ba677afaSXin Li		case SPDX_SUMMARY: // 7.18
121*ba677afaSXin Li			// cardinality: max 1
122*ba677afaSXin Li			pkg.PackageSummary = subTriple.Object.ID
123*ba677afaSXin Li		case SPDX_DESCRIPTION: // 7.19
124*ba677afaSXin Li			// cardinality: max 1
125*ba677afaSXin Li			pkg.PackageDescription = subTriple.Object.ID
126*ba677afaSXin Li		case RDFS_COMMENT: // 7.20
127*ba677afaSXin Li			// cardinality: max 1
128*ba677afaSXin Li			pkg.PackageComment = subTriple.Object.ID
129*ba677afaSXin Li		case SPDX_EXTERNAL_REF: // 7.21
130*ba677afaSXin Li			// cardinality: min 0
131*ba677afaSXin Li			externalDocRef, err := parser.getPackageExternalRef(subTriple.Object)
132*ba677afaSXin Li			if err != nil {
133*ba677afaSXin Li				return nil, fmt.Errorf("error parsing externalRef of a package: %v", err)
134*ba677afaSXin Li			}
135*ba677afaSXin Li			pkg.PackageExternalReferences = append(pkg.PackageExternalReferences, externalDocRef)
136*ba677afaSXin Li		case SPDX_HAS_FILE: // 7.22
137*ba677afaSXin Li			// cardinality: min 0
138*ba677afaSXin Li			file, err := parser.getFileFromNode(subTriple.Object)
139*ba677afaSXin Li			if err != nil {
140*ba677afaSXin Li				return nil, fmt.Errorf("error setting file inside a package: %v", err)
141*ba677afaSXin Li			}
142*ba677afaSXin Li			parser.setFileToPackage(pkg, file)
143*ba677afaSXin Li		case SPDX_PRIMARY_PACKAGE_PURPOSE: // 7.24
144*ba677afaSXin Li			// cardinality: exactly 1
145*ba677afaSXin Li			pkg.PrimaryPackagePurpose = getPrimaryPackagePurpose(subTriple.Object.ID)
146*ba677afaSXin Li		case SPDX_RELEASE_DATE: // 7.25
147*ba677afaSXin Li			// cardinality: exactly 1
148*ba677afaSXin Li			pkg.ReleaseDate = subTriple.Object.ID
149*ba677afaSXin Li		case SPDX_BUILT_DATE: // 7.26
150*ba677afaSXin Li			// cardinality: exactly 1
151*ba677afaSXin Li			pkg.BuiltDate = subTriple.Object.ID
152*ba677afaSXin Li		case SPDX_VALID_UNTIL_DATE: // 7.27
153*ba677afaSXin Li			// cardinality: exactly 1
154*ba677afaSXin Li			pkg.ValidUntilDate = subTriple.Object.ID
155*ba677afaSXin Li		case SPDX_RELATIONSHIP:
156*ba677afaSXin Li			// cardinality: min 0
157*ba677afaSXin Li			err = parser.parseRelationship(subTriple)
158*ba677afaSXin Li		case SPDX_ATTRIBUTION_TEXT:
159*ba677afaSXin Li			// cardinality: min 0
160*ba677afaSXin Li			pkg.PackageAttributionTexts = append(pkg.PackageAttributionTexts, subTriple.Object.ID)
161*ba677afaSXin Li		case SPDX_ANNOTATION:
162*ba677afaSXin Li			// cardinality: min 0
163*ba677afaSXin Li			err = parser.parseAnnotationFromNode(subTriple.Object)
164*ba677afaSXin Li		default:
165*ba677afaSXin Li			return nil, fmt.Errorf("unknown predicate id %s while parsing a package", subTriple.Predicate.ID)
166*ba677afaSXin Li		}
167*ba677afaSXin Li		if err != nil {
168*ba677afaSXin Li			return nil, err
169*ba677afaSXin Li		}
170*ba677afaSXin Li	}
171*ba677afaSXin Li
172*ba677afaSXin Li	if existingPackageIndex != -1 {
173*ba677afaSXin Li		parser.doc.Packages[existingPackageIndex] = pkg
174*ba677afaSXin Li	} else {
175*ba677afaSXin Li		parser.doc.Packages = append(parser.doc.Packages, pkg)
176*ba677afaSXin Li	}
177*ba677afaSXin Li
178*ba677afaSXin Li	return pkg, nil
179*ba677afaSXin Li}
180*ba677afaSXin Li
181*ba677afaSXin Li// parses externalReference found in the package by the associated triple.
182*ba677afaSXin Lifunc (parser *rdfParser2_3) getPackageExternalRef(node *gordfParser.Node) (externalDocRef *v2_3.PackageExternalReference, err error) {
183*ba677afaSXin Li	externalDocRef = &v2_3.PackageExternalReference{}
184*ba677afaSXin Li	for _, triple := range parser.nodeToTriples(node) {
185*ba677afaSXin Li		switch triple.Predicate.ID {
186*ba677afaSXin Li		case SPDX_REFERENCE_CATEGORY:
187*ba677afaSXin Li			// cardinality: exactly 1
188*ba677afaSXin Li			switch triple.Object.ID {
189*ba677afaSXin Li			case SPDX_REFERENCE_CATEGORY_SECURITY:
190*ba677afaSXin Li				externalDocRef.Category = "SECURITY"
191*ba677afaSXin Li			case SPDX_REFERENCE_CATEGORY_PACKAGE_MANAGER:
192*ba677afaSXin Li				externalDocRef.Category = "PACKAGE-MANAGER"
193*ba677afaSXin Li			case SPDX_REFERENCE_CATEGORY_OTHER:
194*ba677afaSXin Li				externalDocRef.Category = "OTHER"
195*ba677afaSXin Li			default:
196*ba677afaSXin Li				return nil, fmt.Errorf("unknown packageManager uri %s", triple.Predicate.ID)
197*ba677afaSXin Li			}
198*ba677afaSXin Li		case RDF_TYPE:
199*ba677afaSXin Li			continue
200*ba677afaSXin Li		case SPDX_REFERENCE_TYPE:
201*ba677afaSXin Li			// assumes: the reference type is associated with just the uri and
202*ba677afaSXin Li			// 			other associated fields are ignored.
203*ba677afaSXin Li			// other fields include:
204*ba677afaSXin Li			//		1. contextualExample,
205*ba677afaSXin Li			//		2. documentation and,
206*ba677afaSXin Li			//		3. externalReferenceSite
207*ba677afaSXin Li			externalDocRef.RefType = triple.Object.ID
208*ba677afaSXin Li		case SPDX_REFERENCE_LOCATOR:
209*ba677afaSXin Li			// cardinality: exactly 1
210*ba677afaSXin Li			externalDocRef.Locator = triple.Object.ID
211*ba677afaSXin Li		case RDFS_COMMENT:
212*ba677afaSXin Li			// cardinality: max 1
213*ba677afaSXin Li			externalDocRef.ExternalRefComment = triple.Object.ID
214*ba677afaSXin Li		default:
215*ba677afaSXin Li			return nil, fmt.Errorf("unknown package external reference predicate id %s", triple.Predicate.ID)
216*ba677afaSXin Li		}
217*ba677afaSXin Li	}
218*ba677afaSXin Li	return
219*ba677afaSXin Li}
220*ba677afaSXin Li
221*ba677afaSXin Lifunc getPrimaryPackagePurpose(purpose string) string {
222*ba677afaSXin Li	value := strings.ReplaceAll(purpose, "packagePurpose_", "")
223*ba677afaSXin Li	value = strings.ReplaceAll(value, "_", "-")
224*ba677afaSXin Li	value = strings.ToUpper(value)
225*ba677afaSXin Li	switch value {
226*ba677afaSXin Li	case "APPLICATION", "FRAMEWORK", "LIBRARY", "CONTAINER", "OPERATING-SYSTEM", "DEVICE", "FIRMWARE", "SOURCE", "ARCHIVE", "FILE", "INSTALL", "OTHER":
227*ba677afaSXin Li		return value
228*ba677afaSXin Li	}
229*ba677afaSXin Li	// invalid value
230*ba677afaSXin Li	return ""
231*ba677afaSXin Li}
232*ba677afaSXin Li
233*ba677afaSXin Lifunc (parser *rdfParser2_3) setPackageVerificationCode(pkg *v2_3.Package, node *gordfParser.Node) error {
234*ba677afaSXin Li	if pkg.PackageVerificationCode == nil {
235*ba677afaSXin Li		pkg.PackageVerificationCode = &common.PackageVerificationCode{}
236*ba677afaSXin Li	}
237*ba677afaSXin Li	for _, subTriple := range parser.nodeToTriples(node) {
238*ba677afaSXin Li		switch subTriple.Predicate.ID {
239*ba677afaSXin Li		case SPDX_PACKAGE_VERIFICATION_CODE_VALUE:
240*ba677afaSXin Li			// cardinality: exactly 1
241*ba677afaSXin Li			pkg.PackageVerificationCode.Value = subTriple.Object.ID
242*ba677afaSXin Li		case SPDX_PACKAGE_VERIFICATION_CODE_EXCLUDED_FILE:
243*ba677afaSXin Li			// cardinality: min 0
244*ba677afaSXin Li			pkg.PackageVerificationCode.ExcludedFiles = append(pkg.PackageVerificationCode.ExcludedFiles, subTriple.Object.ID)
245*ba677afaSXin Li		case RDF_TYPE:
246*ba677afaSXin Li			// cardinality: exactly 1
247*ba677afaSXin Li			continue
248*ba677afaSXin Li		default:
249*ba677afaSXin Li			return fmt.Errorf("unparsed predicate %s", subTriple.Predicate.ID)
250*ba677afaSXin Li		}
251*ba677afaSXin Li	}
252*ba677afaSXin Li	return nil
253*ba677afaSXin Li}
254*ba677afaSXin Li
255*ba677afaSXin Li// appends the file to the package and also sets the assocWithPackage for the
256*ba677afaSXin Li// file to indicate the file is associated with a package
257*ba677afaSXin Lifunc (parser *rdfParser2_3) setFileToPackage(pkg *v2_3.Package, file *v2_3.File) {
258*ba677afaSXin Li	if pkg.Files == nil {
259*ba677afaSXin Li		pkg.Files = []*v2_3.File{}
260*ba677afaSXin Li	}
261*ba677afaSXin Li	pkg.Files = append(pkg.Files, file)
262*ba677afaSXin Li	parser.assocWithPackage[file.FileSPDXIdentifier] = true
263*ba677afaSXin Li}
264*ba677afaSXin Li
265*ba677afaSXin Li// given a supplierObject, sets the PackageSupplier attribute of the pkg.
266*ba677afaSXin Li// Args:
267*ba677afaSXin Li//
268*ba677afaSXin Li//	value: [NOASSERTION | [Person | Organization]: string]
269*ba677afaSXin Lifunc setPackageSupplier(pkg *v2_3.Package, value string) error {
270*ba677afaSXin Li	value = strings.TrimSpace(value)
271*ba677afaSXin Li	supplier := &common.Supplier{}
272*ba677afaSXin Li	if strings.ToUpper(value) == "NOASSERTION" {
273*ba677afaSXin Li		supplier.Supplier = "NOASSERTION"
274*ba677afaSXin Li		pkg.PackageSupplier = supplier
275*ba677afaSXin Li		return nil
276*ba677afaSXin Li	}
277*ba677afaSXin Li
278*ba677afaSXin Li	subKey, subValue, err := ExtractSubs(value, ":")
279*ba677afaSXin Li	if err != nil {
280*ba677afaSXin Li		return fmt.Errorf("package supplier must be of the form NOASSERTION or [Person|Organization]: string. found: %s", value)
281*ba677afaSXin Li	}
282*ba677afaSXin Li	switch subKey {
283*ba677afaSXin Li	case "Person", "Organization":
284*ba677afaSXin Li		supplier.Supplier = subValue
285*ba677afaSXin Li		supplier.SupplierType = subKey
286*ba677afaSXin Li	default:
287*ba677afaSXin Li		return fmt.Errorf("unknown supplier %s", subKey)
288*ba677afaSXin Li	}
289*ba677afaSXin Li
290*ba677afaSXin Li	pkg.PackageSupplier = supplier
291*ba677afaSXin Li
292*ba677afaSXin Li	return nil
293*ba677afaSXin Li}
294*ba677afaSXin Li
295*ba677afaSXin Li// given a OriginatorObject, sets the PackageOriginator attribute of the pkg.
296*ba677afaSXin Li// Args:
297*ba677afaSXin Li//
298*ba677afaSXin Li//	value: [NOASSERTION | [Person | Organization]: string]
299*ba677afaSXin Lifunc setPackageOriginator(pkg *v2_3.Package, value string) error {
300*ba677afaSXin Li	value = strings.TrimSpace(value)
301*ba677afaSXin Li	originator := &common.Originator{}
302*ba677afaSXin Li	if strings.ToUpper(value) == "NOASSERTION" {
303*ba677afaSXin Li		originator.Originator = "NOASSERTION"
304*ba677afaSXin Li		pkg.PackageOriginator = originator
305*ba677afaSXin Li		return nil
306*ba677afaSXin Li	}
307*ba677afaSXin Li
308*ba677afaSXin Li	subKey, subValue, err := ExtractSubs(value, ":")
309*ba677afaSXin Li	if err != nil {
310*ba677afaSXin Li		return fmt.Errorf("package Originator must be of the form NOASSERTION or [Person|Organization]: string. found: %s", value)
311*ba677afaSXin Li	}
312*ba677afaSXin Li	switch subKey {
313*ba677afaSXin Li	case "Person", "Organization":
314*ba677afaSXin Li		originator.Originator = subValue
315*ba677afaSXin Li		originator.OriginatorType = subKey
316*ba677afaSXin Li	default:
317*ba677afaSXin Li		return fmt.Errorf("unknown Originator %s", subKey)
318*ba677afaSXin Li	}
319*ba677afaSXin Li
320*ba677afaSXin Li	pkg.PackageOriginator = originator
321*ba677afaSXin Li
322*ba677afaSXin Li	return nil
323*ba677afaSXin Li}
324*ba677afaSXin Li
325*ba677afaSXin Li// validates the uri and sets the location if it is valid
326*ba677afaSXin Lifunc setDocumentLocationFromURI(pkg *v2_3.Package, locationURI string) error {
327*ba677afaSXin Li	switch locationURI {
328*ba677afaSXin Li	case SPDX_NOASSERTION_CAPS, SPDX_NOASSERTION_SMALL:
329*ba677afaSXin Li		pkg.PackageDownloadLocation = "NOASSERTION"
330*ba677afaSXin Li	case SPDX_NONE_CAPS, SPDX_NONE_SMALL:
331*ba677afaSXin Li		pkg.PackageDownloadLocation = "NONE"
332*ba677afaSXin Li	default:
333*ba677afaSXin Li		if !isUriValid(locationURI) {
334*ba677afaSXin Li			return fmt.Errorf("%s is not a valid uri", locationURI)
335*ba677afaSXin Li		}
336*ba677afaSXin Li		pkg.PackageDownloadLocation = locationURI
337*ba677afaSXin Li	}
338*ba677afaSXin Li	return nil
339*ba677afaSXin Li}
340*ba677afaSXin Li
341*ba677afaSXin Li// sets the FilesAnalyzed attribute to the given package
342*ba677afaSXin Li// boolValue is a string of type "true" or "false"
343*ba677afaSXin Lifunc setFilesAnalyzed(pkg *v2_3.Package, boolValue string) (err error) {
344*ba677afaSXin Li	pkg.IsFilesAnalyzedTagPresent = true
345*ba677afaSXin Li	pkg.FilesAnalyzed, err = boolFromString(boolValue)
346*ba677afaSXin Li	return err
347*ba677afaSXin Li}
348*ba677afaSXin Li
349*ba677afaSXin Lifunc (parser *rdfParser2_3) setPackageChecksum(pkg *v2_3.Package, node *gordfParser.Node) error {
350*ba677afaSXin Li	checksumAlgorithm, checksumValue, err := parser.getChecksumFromNode(node)
351*ba677afaSXin Li	if err != nil {
352*ba677afaSXin Li		return fmt.Errorf("error getting checksum algorithm and value from %v", node)
353*ba677afaSXin Li	}
354*ba677afaSXin Li	if pkg.PackageChecksums == nil {
355*ba677afaSXin Li		pkg.PackageChecksums = make([]common.Checksum, 0, 1)
356*ba677afaSXin Li	}
357*ba677afaSXin Li	switch checksumAlgorithm {
358*ba677afaSXin Li	case common.SHA1,
359*ba677afaSXin Li		common.SHA224,
360*ba677afaSXin Li		common.SHA256,
361*ba677afaSXin Li		common.SHA384,
362*ba677afaSXin Li		common.SHA512,
363*ba677afaSXin Li		common.MD2,
364*ba677afaSXin Li		common.MD4,
365*ba677afaSXin Li		common.MD5,
366*ba677afaSXin Li		common.MD6,
367*ba677afaSXin Li		common.SHA3_256,
368*ba677afaSXin Li		common.SHA3_384,
369*ba677afaSXin Li		common.SHA3_512,
370*ba677afaSXin Li		common.BLAKE2b_256,
371*ba677afaSXin Li		common.BLAKE2b_384,
372*ba677afaSXin Li		common.BLAKE2b_512,
373*ba677afaSXin Li		common.BLAKE3,
374*ba677afaSXin Li		common.ADLER32:
375*ba677afaSXin Li		pkg.PackageChecksums = append(pkg.PackageChecksums, common.Checksum{Algorithm: checksumAlgorithm, Value: checksumValue})
376*ba677afaSXin Li	default:
377*ba677afaSXin Li		return fmt.Errorf("unknown checksumAlgorithm %s while parsing a package", checksumAlgorithm)
378*ba677afaSXin Li	}
379*ba677afaSXin Li	return nil
380*ba677afaSXin Li}
381