aboutsummaryrefslogtreecommitdiff
path: root/spdx/common
diff options
context:
space:
mode:
authorBrandon Lum <lumjjb@gmail.com>2022-06-06 10:42:27 -0400
committerBrandon Lum <lumjjb@gmail.com>2022-06-06 10:42:27 -0400
commit41d2272711255f5a25e16e3507ec3318bc550189 (patch)
treeace557ed0ffe3fab18f721744448de5936f23976 /spdx/common
parenta532726dbb7a38d0f714075e9a1f1df4cae60230 (diff)
downloadspdx-tools-41d2272711255f5a25e16e3507ec3318bc550189.tar.gz
convert spdx structs to versioned pkgs
Signed-off-by: Brandon Lum <lumjjb@gmail.com>
Diffstat (limited to 'spdx/common')
-rw-r--r--spdx/common/annotation.go44
-rw-r--r--spdx/common/checksum.go26
-rw-r--r--spdx/common/creation_info.go44
-rw-r--r--spdx/common/identifier.go133
-rw-r--r--spdx/common/package.go105
-rw-r--r--spdx/common/snippet.go20
6 files changed, 372 insertions, 0 deletions
diff --git a/spdx/common/annotation.go b/spdx/common/annotation.go
new file mode 100644
index 0000000..e77d7b7
--- /dev/null
+++ b/spdx/common/annotation.go
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+package common
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+)
+
+type Annotator struct {
+ Annotator string
+ // including AnnotatorType: one of "Person", "Organization" or "Tool"
+ AnnotatorType string
+}
+
+// UnmarshalJSON takes an annotator in the typical one-line format and parses it into an Annotator struct.
+// This function is also used when unmarshalling YAML
+func (a *Annotator) UnmarshalJSON(data []byte) error {
+ // annotator will simply be a string
+ annotatorStr := string(data)
+ annotatorStr = strings.Trim(annotatorStr, "\"")
+
+ annotatorFields := strings.SplitN(annotatorStr, ": ", 2)
+
+ if len(annotatorFields) != 2 {
+ return fmt.Errorf("failed to parse Annotator '%s'", annotatorStr)
+ }
+
+ a.AnnotatorType = annotatorFields[0]
+ a.Annotator = annotatorFields[1]
+
+ return nil
+}
+
+// MarshalJSON converts the receiver into a slice of bytes representing an Annotator in string form.
+// This function is also used when marshalling to YAML
+func (a Annotator) MarshalJSON() ([]byte, error) {
+ if a.Annotator != "" {
+ return json.Marshal(fmt.Sprintf("%s: %s", a.AnnotatorType, a.Annotator))
+ }
+
+ return []byte{}, nil
+}
diff --git a/spdx/common/checksum.go b/spdx/common/checksum.go
new file mode 100644
index 0000000..02a57ff
--- /dev/null
+++ b/spdx/common/checksum.go
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+package common
+
+// ChecksumAlgorithm represents the algorithm used to generate the file checksum in the Checksum struct.
+type ChecksumAlgorithm string
+
+// The checksum algorithms mentioned in the spdxv2.2.0 https://spdx.github.io/spdx-spec/4-file-information/#44-file-checksum
+const (
+ SHA224 ChecksumAlgorithm = "SHA224"
+ SHA1 ChecksumAlgorithm = "SHA1"
+ SHA256 ChecksumAlgorithm = "SHA256"
+ SHA384 ChecksumAlgorithm = "SHA384"
+ SHA512 ChecksumAlgorithm = "SHA512"
+ MD2 ChecksumAlgorithm = "MD2"
+ MD4 ChecksumAlgorithm = "MD4"
+ MD5 ChecksumAlgorithm = "MD5"
+ MD6 ChecksumAlgorithm = "MD6"
+)
+
+// Checksum provides a unique identifier to match analysis information on each specific file in a package.
+// The Algorithm field describes the ChecksumAlgorithm used and the Value represents the file checksum
+type Checksum struct {
+ Algorithm ChecksumAlgorithm `json:"algorithm"`
+ Value string `json:"checksumValue"`
+}
diff --git a/spdx/common/creation_info.go b/spdx/common/creation_info.go
new file mode 100644
index 0000000..c87ae7b
--- /dev/null
+++ b/spdx/common/creation_info.go
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+package common
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+)
+
+// Creator is a wrapper around the Creator SPDX field. The SPDX field contains two values, which requires special
+// handling in order to marshal/unmarshal it to/from Go data types.
+type Creator struct {
+ Creator string
+ // CreatorType should be one of "Person", "Organization", or "Tool"
+ CreatorType string
+}
+
+// UnmarshalJSON takes an annotator in the typical one-line format and parses it into a Creator struct.
+// This function is also used when unmarshalling YAML
+func (c *Creator) UnmarshalJSON(data []byte) error {
+ str := string(data)
+ str = strings.Trim(str, "\"")
+ fields := strings.SplitN(str, ": ", 2)
+
+ if len(fields) != 2 {
+ return fmt.Errorf("failed to parse Creator '%s'", str)
+ }
+
+ c.CreatorType = fields[0]
+ c.Creator = fields[1]
+
+ return nil
+}
+
+// MarshalJSON converts the receiver into a slice of bytes representing a Creator in string form.
+// This function is also used with marshalling to YAML
+func (c Creator) MarshalJSON() ([]byte, error) {
+ if c.Creator != "" {
+ return json.Marshal(fmt.Sprintf("%s: %s", c.CreatorType, c.Creator))
+ }
+
+ return []byte{}, nil
+}
diff --git a/spdx/common/identifier.go b/spdx/common/identifier.go
new file mode 100644
index 0000000..d656867
--- /dev/null
+++ b/spdx/common/identifier.go
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+package common
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+)
+
+// ElementID represents the identifier string portion of an SPDX element
+// identifier. DocElementID should be used for any attributes which can
+// contain identifiers defined in a different SPDX document.
+// ElementIDs should NOT contain the mandatory 'SPDXRef-' portion.
+type ElementID string
+
+// DocElementID represents an SPDX element identifier that could be defined
+// in a different SPDX document, and therefore could have a "DocumentRef-"
+// portion, such as Relationships and Annotations.
+// ElementID is used for attributes in which a "DocumentRef-" portion cannot
+// appear, such as a Package or File definition (since it is necessarily
+// being defined in the present document).
+// DocumentRefID will be the empty string for elements defined in the
+// present document.
+// DocElementIDs should NOT contain the mandatory 'DocumentRef-' or
+// 'SPDXRef-' portions.
+// SpecialID is used ONLY if the DocElementID matches a defined set of
+// permitted special values for a particular field, e.g. "NONE" or
+// "NOASSERTION" for the right-hand side of Relationships. If SpecialID
+// is set, DocumentRefID and ElementRefID should be empty (and vice versa).
+type DocElementID struct {
+ DocumentRefID string
+ ElementRefID ElementID
+ SpecialID string
+}
+
+// UnmarshalJSON takes a SPDX Identifier string parses it into a DocElementID struct.
+// This function is also used when unmarshalling YAML
+func (d *DocElementID) UnmarshalJSON(data []byte) error {
+ // SPDX identifier will simply be a string
+ idStr := string(data)
+ idStr = strings.Trim(idStr, "\"")
+
+ // handle special cases
+ if idStr == "NONE" || idStr == "NOASSERTION" {
+ d.SpecialID = idStr
+ return nil
+ }
+
+ var idFields []string
+ // handle DocumentRef- if present
+ if strings.HasPrefix(idStr, "DocumentRef-") {
+ // strip out the "DocumentRef-" so we can get the value
+ idFields = strings.SplitN(idStr, "DocumentRef-", 2)
+ idStr = idFields[1]
+
+ // an SPDXRef can appear after a DocumentRef, separated by a colon
+ idFields = strings.SplitN(idStr, ":", 2)
+ d.DocumentRefID = idFields[0]
+
+ if len(idFields) == 2 {
+ idStr = idFields[1]
+ } else {
+ return nil
+ }
+ }
+
+ // handle SPDXRef-
+ idFields = strings.SplitN(idStr, "SPDXRef-", 2)
+ if len(idFields) != 2 {
+ return fmt.Errorf("failed to parse SPDX Identifier '%s'", idStr)
+ }
+
+ d.ElementRefID = ElementID(idFields[1])
+
+ return nil
+}
+
+// MarshalJSON converts the receiver into a slice of bytes representing a DocElementID in string form.
+// This function is also used when marshalling to YAML
+func (d DocElementID) MarshalJSON() ([]byte, error) {
+ if d.DocumentRefID != "" && d.ElementRefID != "" {
+ return json.Marshal(fmt.Sprintf("DocumentRef-%s:SPDXRef-%s", d.DocumentRefID, d.ElementRefID))
+ } else if d.ElementRefID != "" {
+ return json.Marshal(fmt.Sprintf("SPDXRef-%s", d.ElementRefID))
+ } else if d.SpecialID != "" {
+ return json.Marshal(d.SpecialID)
+ }
+
+ return []byte{}, fmt.Errorf("failed to marshal empty DocElementID")
+}
+
+// TODO: add equivalents for LicenseRef- identifiers
+
+// MakeDocElementID takes strings (without prefixes) for the DocumentRef-
+// and SPDXRef- identifiers, and returns a DocElementID. An empty string
+// should be used for the DocumentRef- portion if it is referring to the
+// present document.
+func MakeDocElementID(docRef string, eltRef string) DocElementID {
+ return DocElementID{
+ DocumentRefID: docRef,
+ ElementRefID: ElementID(eltRef),
+ }
+}
+
+// MakeDocElementSpecial takes a "special" string (e.g. "NONE" or
+// "NOASSERTION" for the right side of a Relationship), nd returns
+// a DocElementID with it in the SpecialID field. Other fields will
+// be empty.
+func MakeDocElementSpecial(specialID string) DocElementID {
+ return DocElementID{SpecialID: specialID}
+}
+
+// RenderElementID takes an ElementID and returns the string equivalent,
+// with the SPDXRef- prefix reinserted.
+func RenderElementID(eID ElementID) string {
+ return "SPDXRef-" + string(eID)
+}
+
+// RenderDocElementID takes a DocElementID and returns the string equivalent,
+// with the SPDXRef- prefix (and, if applicable, the DocumentRef- prefix)
+// reinserted. If a SpecialID is present, it will be rendered verbatim and
+// DocumentRefID and ElementRefID will be ignored.
+func RenderDocElementID(deID DocElementID) string {
+ if deID.SpecialID != "" {
+ return deID.SpecialID
+ }
+ prefix := ""
+ if deID.DocumentRefID != "" {
+ prefix = "DocumentRef-" + deID.DocumentRefID + ":"
+ }
+ return prefix + "SPDXRef-" + string(deID.ElementRefID)
+}
diff --git a/spdx/common/package.go b/spdx/common/package.go
new file mode 100644
index 0000000..e0635df
--- /dev/null
+++ b/spdx/common/package.go
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+package common
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+)
+
+type Supplier struct {
+ // can be "NOASSERTION"
+ Supplier string
+ // SupplierType can be one of "Person", "Organization", or empty if Supplier is "NOASSERTION"
+ SupplierType string
+}
+
+// UnmarshalJSON takes a supplier in the typical one-line format and parses it into a Supplier struct.
+// This function is also used when unmarshalling YAML
+func (s *Supplier) UnmarshalJSON(data []byte) error {
+ // the value is just a string presented as a slice of bytes
+ supplierStr := string(data)
+ supplierStr = strings.Trim(supplierStr, "\"")
+
+ if supplierStr == "NOASSERTION" {
+ s.Supplier = supplierStr
+ return nil
+ }
+
+ supplierFields := strings.SplitN(supplierStr, ": ", 2)
+
+ if len(supplierFields) != 2 {
+ return fmt.Errorf("failed to parse Supplier '%s'", supplierStr)
+ }
+
+ s.SupplierType = supplierFields[0]
+ s.Supplier = supplierFields[1]
+
+ return nil
+}
+
+// MarshalJSON converts the receiver into a slice of bytes representing a Supplier in string form.
+// This function is also used when marshalling to YAML
+func (s Supplier) MarshalJSON() ([]byte, error) {
+ if s.Supplier == "NOASSERTION" {
+ return json.Marshal(s.Supplier)
+ } else if s.SupplierType != "" && s.Supplier != "" {
+ return json.Marshal(fmt.Sprintf("%s: %s", s.SupplierType, s.Supplier))
+ }
+
+ return []byte{}, fmt.Errorf("failed to marshal invalid Supplier: %+v", s)
+}
+
+type Originator struct {
+ // can be "NOASSERTION"
+ Originator string
+ // OriginatorType can be one of "Person", "Organization", or empty if Originator is "NOASSERTION"
+ OriginatorType string
+}
+
+// UnmarshalJSON takes an originator in the typical one-line format and parses it into an Originator struct.
+// This function is also used when unmarshalling YAML
+func (o *Originator) UnmarshalJSON(data []byte) error {
+ // the value is just a string presented as a slice of bytes
+ originatorStr := string(data)
+ originatorStr = strings.Trim(originatorStr, "\"")
+
+ if originatorStr == "NOASSERTION" {
+ o.Originator = originatorStr
+ return nil
+ }
+
+ originatorFields := strings.SplitN(originatorStr, ": ", 2)
+
+ if len(originatorFields) != 2 {
+ return fmt.Errorf("failed to parse Originator '%s'", originatorStr)
+ }
+
+ o.OriginatorType = originatorFields[0]
+ o.Originator = originatorFields[1]
+
+ return nil
+}
+
+// MarshalJSON converts the receiver into a slice of bytes representing an Originator in string form.
+// This function is also used when marshalling to YAML
+func (o Originator) MarshalJSON() ([]byte, error) {
+ if o.Originator == "NOASSERTION" {
+ return json.Marshal(o.Originator)
+ } else if o.Originator != "" {
+ return json.Marshal(fmt.Sprintf("%s: %s", o.OriginatorType, o.Originator))
+ }
+
+ return []byte{}, nil
+}
+
+type PackageVerificationCode struct {
+ // Cardinality: mandatory, one if filesAnalyzed is true / omitted;
+ // zero (must be omitted) if filesAnalyzed is false
+ Value string `json:"packageVerificationCodeValue"`
+ // Spec also allows specifying files to exclude from the
+ // verification code algorithm; intended to enable exclusion of
+ // the SPDX document file itself.
+ ExcludedFiles []string `json:"packageVerificationCodeExcludedFiles"`
+}
diff --git a/spdx/common/snippet.go b/spdx/common/snippet.go
new file mode 100644
index 0000000..63afac3
--- /dev/null
+++ b/spdx/common/snippet.go
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+package common
+
+type SnippetRangePointer struct {
+ // 5.3: Snippet Byte Range: [start byte]:[end byte]
+ // Cardinality: mandatory, one
+ Offset int `json:"offset,omitempty"`
+
+ // 5.4: Snippet Line Range: [start line]:[end line]
+ // Cardinality: optional, one
+ LineNumber int `json:"lineNumber,omitempty"`
+
+ FileSPDXIdentifier ElementID `json:"reference"`
+}
+
+type SnippetRange struct {
+ StartPointer SnippetRangePointer `json:"startPointer"`
+ EndPointer SnippetRangePointer `json:"endPointer"`
+}