1# Copyright (c) 2021 The Linux Foundation
2#
3# SPDX-License-Identifier: Apache-2.0
4
5from enum import Enum
6
7
8# DocumentConfig contains settings used to configure how the SPDX Document
9# should be built.
10class DocumentConfig:
11    def __init__(self):
12        super(DocumentConfig, self).__init__()
13
14        # name of document
15        self.name = ""
16
17        # namespace for this document
18        self.namespace = ""
19
20        # standardized DocumentRef- (including that prefix) that the other
21        # docs will use to refer to this one
22        self.docRefID = ""
23
24
25# Document contains the data assembled by the SBOM builder, to be used to
26# create the actual SPDX Document.
27class Document:
28    # initialize with a DocumentConfig
29    def __init__(self, cfg):
30        super(Document, self).__init__()
31
32        # configuration - DocumentConfig
33        self.cfg = cfg
34
35        # dict of SPDX ID => Package
36        self.pkgs = {}
37
38        # relationships "owned" by this Document, _not_ those "owned" by its
39        # Packages or Files; will likely be just DESCRIBES
40        self.relationships = []
41
42        # dict of filename (ignoring its directory) => number of times it has
43        # been seen while adding files to this Document; used to calculate
44        # useful SPDX IDs
45        self.timesSeen = {}
46
47        # dict of absolute path on disk => File
48        self.fileLinks = {}
49
50        # set of other Documents that our elements' Relationships refer to
51        self.externalDocuments = set()
52
53        # set of LicenseRef- custom licenses to be declared
54        # may or may not include "LicenseRef-" license prefix
55        self.customLicenseIDs = set()
56
57        # this Document's SHA1 hash, filled in _after_ the Document has been
58        # written to disk, so that others can refer to it
59        self.myDocSHA1 = ""
60
61
62# PackageConfig contains settings used to configure how an SPDX Package should
63# be built.
64class PackageConfig:
65    def __init__(self):
66        super(PackageConfig, self).__init__()
67
68        # package name
69        self.name = ""
70
71        # SPDX ID, including "SPDXRef-"
72        self.spdxID = ""
73
74        # primary package purpose (ex. "LIBRARY", "APPLICATION", etc.)
75        self.primaryPurpose = ""
76
77        # package URL
78        self.url = ""
79
80        # package version
81        self.version = ""
82
83        # package revision
84        self.revision = ""
85
86        # package external references
87        self.externalReferences = []
88
89        # the Package's declared license
90        self.declaredLicense = "NOASSERTION"
91
92        # the Package's copyright text
93        self.copyrightText = "NOASSERTION"
94
95        # absolute path of the "root" directory on disk, to be used as the
96        # base directory from which this Package's Files will calculate their
97        # relative paths
98        # may want to note this in a Package comment field
99        self.relativeBaseDir = ""
100
101
102# Package contains the data assembled by the SBOM builder, to be used to
103# create the actual SPDX Package.
104class Package:
105    # initialize with:
106    # 1) PackageConfig
107    # 2) the Document that owns this Package
108    def __init__(self, cfg, doc):
109        super(Package, self).__init__()
110
111        # configuration - PackageConfig
112        self.cfg = cfg
113
114        # Document that owns this Package
115        self.doc = doc
116
117        # verification code, calculated per section 7.9 of SPDX spec v2.3
118        self.verificationCode = ""
119
120        # concluded license for this Package, if
121        # cfg.shouldConcludePackageLicense == True; NOASSERTION otherwise
122        self.concludedLicense = "NOASSERTION"
123
124        # list of licenses found in this Package's Files
125        self.licenseInfoFromFiles = []
126
127        # Files in this Package
128        # dict of SPDX ID => File
129        self.files = {}
130
131        # Relationships "owned" by this Package (e.g., this Package is left
132        # side)
133        self.rlns = []
134
135        # If this Package was a target, which File was its main build product?
136        self.targetBuildFile = None
137
138
139# RelationshipDataElementType defines whether a RelationshipData element
140# (e.g., the "owner" or the "other" element) is a File, a target Package,
141# a Package's ID (as other only, and only where owner type is DOCUMENT),
142# or the SPDX document itself (as owner only).
143class RelationshipDataElementType(Enum):
144    UNKNOWN = 0
145    FILENAME = 1
146    TARGETNAME = 2
147    PACKAGEID = 3
148    DOCUMENT = 4
149
150
151# RelationshipData contains the pre-analysis data about a relationship between
152# Files and/or Packages/targets. It is eventually parsed into a corresponding
153# Relationship after we have organized the SPDX Package and File data.
154class RelationshipData:
155    def __init__(self):
156        super(RelationshipData, self).__init__()
157
158        # for the "owner" element (e.g., the left side of the Relationship),
159        # is it a filename or a target name (e.g., a Package in the build doc)
160        self.ownerType = RelationshipDataElementType.UNKNOWN
161
162        # owner file absolute path (if ownerType is FILENAME)
163        self.ownerFileAbspath = ""
164
165        # owner target name (if ownerType is TARGETNAME)
166        self.ownerTargetName = ""
167
168        # owner SPDX Document (if ownerType is DOCUMENT)
169        self.ownerDocument = None
170
171        # for the "other" element (e.g., the right side of the Relationship),
172        # is it a filename or a target name (e.g., a Package in the build doc)
173        self.otherType = RelationshipDataElementType.UNKNOWN
174
175        # other file absolute path (if otherType is FILENAME)
176        self.otherFileAbspath = ""
177
178        # other target name (if otherType is TARGETNAME)
179        self.otherTargetName = ""
180
181        # other package ID (if ownerType is DOCUMENT and otherType is PACKAGEID)
182        self.otherPackageID = ""
183
184        # text string with Relationship type
185        # from table 68 in section 11.1 of SPDX spec v2.3
186        self.rlnType = ""
187
188
189# Relationship contains the post-analysis, processed data about a relationship
190# in a form suitable for creating the actual SPDX Relationship in a particular
191# Document's context.
192class Relationship:
193    def __init__(self):
194        super(Relationship, self).__init__()
195
196        # SPDX ID for left side of relationship
197        # including "SPDXRef-" as well as "DocumentRef-" if needed
198        self.refA = ""
199
200        # SPDX ID for right side of relationship
201        # including "SPDXRef-" as well as "DocumentRef-" if needed
202        self.refB = ""
203
204        # text string with Relationship type
205        # from table 68 in section 11.1 of SPDX spec v2.3
206        self.rlnType = ""
207
208
209# File contains the data needed to create a File element in the context of a
210# particular SPDX Document and Package.
211class File:
212    # initialize with:
213    # 1) Document containing this File
214    # 2) Package containing this File
215    def __init__(self, doc, pkg):
216        super(File, self).__init__()
217
218        # absolute path to this file on disk
219        self.abspath = ""
220
221        # relative path for this file, measured from the owning Package's
222        # cfg.relativeBaseDir
223        self.relpath = ""
224
225        # SPDX ID for this file, including "SPDXRef-"
226        self.spdxID = ""
227
228        # SHA1 hash
229        self.sha1 = ""
230
231        # SHA256 hash, if pkg.cfg.doSHA256 == True; empty string otherwise
232        self.sha256 = ""
233
234        # MD5 hash, if pkg.cfg.doMD5 == True; empty string otherwise
235        self.md5 = ""
236
237        # concluded license, if pkg.cfg.shouldConcludeFileLicenses == True;
238        # "NOASSERTION" otherwise
239        self.concludedLicense = "NOASSERTION"
240
241        # license info in file
242        self.licenseInfoInFile = []
243
244        # copyright text
245        self.copyrightText = "NOASSERTION"
246
247        # Relationships "owned" by this File (e.g., this File is left side)
248        self.rlns = []
249
250        # Package that owns this File
251        self.pkg = pkg
252
253        # Document that owns this File
254        self.doc = doc
255