aboutsummaryrefslogtreecommitdiff
path: root/tvloader/parser2v2/parse_creation_info.go
diff options
context:
space:
mode:
Diffstat (limited to 'tvloader/parser2v2/parse_creation_info.go')
-rw-r--r--tvloader/parser2v2/parse_creation_info.go156
1 files changed, 156 insertions, 0 deletions
diff --git a/tvloader/parser2v2/parse_creation_info.go b/tvloader/parser2v2/parse_creation_info.go
new file mode 100644
index 0000000..da258bd
--- /dev/null
+++ b/tvloader/parser2v2/parse_creation_info.go
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+package parser2v2
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/spdx/tools-golang/spdx/common"
+ "github.com/spdx/tools-golang/spdx/v2_2"
+)
+
+func (parser *tvParser2_2) parsePairFromCreationInfo2_2(tag string, value string) error {
+ // fail if not in Creation Info parser state
+ if parser.st != psCreationInfo2_2 {
+ return fmt.Errorf("got invalid state %v in parsePairFromCreationInfo2_2", parser.st)
+ }
+
+ // create an SPDX Creation Info data struct if we don't have one already
+ if parser.doc.CreationInfo == nil {
+ parser.doc.CreationInfo = &v2_2.CreationInfo{}
+ }
+
+ ci := parser.doc.CreationInfo
+ switch tag {
+ case "LicenseListVersion":
+ ci.LicenseListVersion = value
+ case "Creator":
+ subkey, subvalue, err := extractSubs(value)
+ if err != nil {
+ return err
+ }
+
+ creator := common.Creator{Creator: subvalue}
+ switch subkey {
+ case "Person", "Organization", "Tool":
+ creator.CreatorType = subkey
+ default:
+ return fmt.Errorf("unrecognized Creator type %v", subkey)
+ }
+
+ ci.Creators = append(ci.Creators, creator)
+ case "Created":
+ ci.Created = value
+ case "CreatorComment":
+ ci.CreatorComment = value
+
+ // tag for going on to package section
+ case "PackageName":
+ // error if last file does not have an identifier
+ // this may be a null case: can we ever have a "last file" in
+ // the "creation info" state? should go on to "file" state
+ // even when parsing unpackaged files.
+ if parser.file != nil && parser.file.FileSPDXIdentifier == nullSpdxElementId2_2 {
+ return fmt.Errorf("file with FileName %s does not have SPDX identifier", parser.file.FileName)
+ }
+ parser.st = psPackage2_2
+ parser.pkg = &v2_2.Package{
+ FilesAnalyzed: true,
+ IsFilesAnalyzedTagPresent: false,
+ }
+ return parser.parsePairFromPackage2_2(tag, value)
+ // tag for going on to _unpackaged_ file section
+ case "FileName":
+ // leave pkg as nil, so that packages will be placed in Files
+ parser.st = psFile2_2
+ parser.pkg = nil
+ return parser.parsePairFromFile2_2(tag, value)
+ // tag for going on to other license section
+ case "LicenseID":
+ parser.st = psOtherLicense2_2
+ return parser.parsePairFromOtherLicense2_2(tag, value)
+ // tag for going on to review section (DEPRECATED)
+ case "Reviewer":
+ parser.st = psReview2_2
+ return parser.parsePairFromReview2_2(tag, value)
+ // for relationship tags, pass along but don't change state
+ case "Relationship":
+ parser.rln = &v2_2.Relationship{}
+ parser.doc.Relationships = append(parser.doc.Relationships, parser.rln)
+ return parser.parsePairForRelationship2_2(tag, value)
+ case "RelationshipComment":
+ return parser.parsePairForRelationship2_2(tag, value)
+ // for annotation tags, pass along but don't change state
+ case "Annotator":
+ parser.ann = &v2_2.Annotation{}
+ parser.doc.Annotations = append(parser.doc.Annotations, parser.ann)
+ return parser.parsePairForAnnotation2_2(tag, value)
+ case "AnnotationDate":
+ return parser.parsePairForAnnotation2_2(tag, value)
+ case "AnnotationType":
+ return parser.parsePairForAnnotation2_2(tag, value)
+ case "SPDXREF":
+ return parser.parsePairForAnnotation2_2(tag, value)
+ case "AnnotationComment":
+ return parser.parsePairForAnnotation2_2(tag, value)
+ default:
+ return fmt.Errorf("received unknown tag %v in CreationInfo section", tag)
+ }
+
+ return nil
+}
+
+// ===== Helper functions =====
+
+func extractExternalDocumentReference(value string) (string, string, string, string, error) {
+ sp := strings.Split(value, " ")
+ // remove any that are just whitespace
+ keepSp := []string{}
+ for _, s := range sp {
+ ss := strings.TrimSpace(s)
+ if ss != "" {
+ keepSp = append(keepSp, ss)
+ }
+ }
+
+ var documentRefID, uri, alg, checksum string
+
+ // now, should have 4 items (or 3, if Alg and Checksum were joined)
+ // and should be able to map them
+ if len(keepSp) == 4 {
+ documentRefID = keepSp[0]
+ uri = keepSp[1]
+ alg = keepSp[2]
+ // check that colon is present for alg, and remove it
+ if !strings.HasSuffix(alg, ":") {
+ return "", "", "", "", fmt.Errorf("algorithm does not end with colon")
+ }
+ alg = strings.TrimSuffix(alg, ":")
+ checksum = keepSp[3]
+ } else if len(keepSp) == 3 {
+ documentRefID = keepSp[0]
+ uri = keepSp[1]
+ // split on colon into alg and checksum
+ parts := strings.SplitN(keepSp[2], ":", 2)
+ if len(parts) != 2 {
+ return "", "", "", "", fmt.Errorf("missing colon separator between algorithm and checksum")
+ }
+ alg = parts[0]
+ checksum = parts[1]
+ } else {
+ return "", "", "", "", fmt.Errorf("expected 4 elements, got %d", len(keepSp))
+ }
+
+ // additionally, we should be able to parse the first element as a
+ // DocumentRef- ID string, and we should remove that prefix
+ if !strings.HasPrefix(documentRefID, "DocumentRef-") {
+ return "", "", "", "", fmt.Errorf("expected first element to have DocumentRef- prefix")
+ }
+ documentRefID = strings.TrimPrefix(documentRefID, "DocumentRef-")
+ if documentRefID == "" {
+ return "", "", "", "", fmt.Errorf("document identifier has nothing after prefix")
+ }
+
+ return documentRefID, uri, alg, checksum, nil
+}