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