Skip to content

Commit b40f739

Browse files
authored
fix: XML serialize normalizedString and token properly (#646)
fixes #638 --------- Signed-off-by: Jan Kowalleck <[email protected]>
1 parent ce6991b commit b40f739

File tree

9 files changed

+43
-1
lines changed

9 files changed

+43
-1
lines changed

cyclonedx/model/__init__.py

+9
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ def flow(self, flow: DataFlow) -> None:
113113

114114
@property
115115
@serializable.xml_name('.')
116+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
116117
def classification(self) -> str:
117118
"""
118119
Data classification tags data according to its type, sensitivity, and value if altered, stolen, or destroyed.
@@ -182,6 +183,7 @@ def __init__(
182183
@property
183184
@serializable.xml_attribute()
184185
@serializable.xml_name('content-type')
186+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
185187
def content_type(self) -> str:
186188
"""
187189
Specifies the content type of the text. Defaults to text/plain if not specified.
@@ -468,6 +470,7 @@ def alg(self, alg: HashAlgorithm) -> None:
468470

469471
@property
470472
@serializable.xml_name('.')
473+
@serializable.xml_string(serializable.XmlStringSerializationType.TOKEN)
471474
def content(self) -> str:
472475
"""
473476
Hash value content.
@@ -889,6 +892,7 @@ def name(self, name: str) -> None:
889892

890893
@property
891894
@serializable.xml_name('.')
895+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
892896
def value(self) -> Optional[str]:
893897
"""
894898
Value of this Property.
@@ -1128,6 +1132,7 @@ def __init__(
11281132

11291133
@property
11301134
@serializable.xml_sequence(1)
1135+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
11311136
def vendor(self) -> Optional[str]:
11321137
"""
11331138
The name of the vendor who created the tool.
@@ -1143,6 +1148,7 @@ def vendor(self, vendor: Optional[str]) -> None:
11431148

11441149
@property
11451150
@serializable.xml_sequence(2)
1151+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
11461152
def name(self) -> Optional[str]:
11471153
"""
11481154
The name of the tool.
@@ -1158,6 +1164,7 @@ def name(self, name: Optional[str]) -> None:
11581164

11591165
@property
11601166
@serializable.xml_sequence(3)
1167+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
11611168
def version(self) -> Optional[str]:
11621169
"""
11631170
The version of the tool.
@@ -1268,6 +1275,7 @@ def timestamp(self, timestamp: Optional[datetime]) -> None:
12681275
self._timestamp = timestamp
12691276

12701277
@property
1278+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
12711279
def name(self) -> Optional[str]:
12721280
"""
12731281
The name of the individual who performed the action.
@@ -1282,6 +1290,7 @@ def name(self, name: Optional[str]) -> None:
12821290
self._name = name
12831291

12841292
@property
1293+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
12851294
def email(self) -> Optional[str]:
12861295
"""
12871296
The email address of the individual who performed the action.

cyclonedx/model/component.py

+10
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def __init__(
9494

9595
@property
9696
@serializable.xml_sequence(1)
97+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
9798
def uid(self) -> Optional[str]:
9899
"""
99100
A unique identifier of the commit. This may be version control specific. For example, Subversion uses revision
@@ -155,6 +156,7 @@ def committer(self, committer: Optional[IdentifiableAction]) -> None:
155156

156157
@property
157158
@serializable.xml_sequence(5)
159+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
158160
def message(self) -> Optional[str]:
159161
"""
160162
The text description of the contents of the commit.
@@ -1151,6 +1153,7 @@ def type(self, type: ComponentType) -> None:
11511153
self._type = type
11521154

11531155
@property
1156+
@serializable.xml_string(serializable.XmlStringSerializationType.TOKEN)
11541157
def mime_type(self) -> Optional[str]:
11551158
"""
11561159
Get any declared mime-type for this Component.
@@ -1256,6 +1259,7 @@ def authors(self, authors: Iterable[OrganizationalContact]) -> None:
12561259
@serializable.view(SchemaVersion1Dot5)
12571260
@serializable.view(SchemaVersion1Dot6) # todo: this is deprecated in v1.6?
12581261
@serializable.xml_sequence(4)
1262+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
12591263
def author(self) -> Optional[str]:
12601264
"""
12611265
The person(s) or organization(s) that authored the component.
@@ -1271,6 +1275,7 @@ def author(self, author: Optional[str]) -> None:
12711275

12721276
@property
12731277
@serializable.xml_sequence(5)
1278+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
12741279
def publisher(self) -> Optional[str]:
12751280
"""
12761281
The person(s) or organization(s) that published the component
@@ -1286,6 +1291,7 @@ def publisher(self, publisher: Optional[str]) -> None:
12861291

12871292
@property
12881293
@serializable.xml_sequence(6)
1294+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
12891295
def group(self) -> Optional[str]:
12901296
"""
12911297
The grouping name or identifier. This will often be a shortened, single name of the company or project that
@@ -1305,6 +1311,7 @@ def group(self, group: Optional[str]) -> None:
13051311

13061312
@property
13071313
@serializable.xml_sequence(7)
1314+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
13081315
def name(self) -> str:
13091316
"""
13101317
The name of the component.
@@ -1328,6 +1335,7 @@ def name(self, name: str) -> None:
13281335
@serializable.include_none(SchemaVersion1Dot2, '')
13291336
@serializable.include_none(SchemaVersion1Dot3, '')
13301337
@serializable.xml_sequence(8)
1338+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
13311339
def version(self) -> Optional[str]:
13321340
"""
13331341
The component version. The version should ideally comply with semantic versioning but is not enforced.
@@ -1348,6 +1356,7 @@ def version(self, version: Optional[str]) -> None:
13481356

13491357
@property
13501358
@serializable.xml_sequence(9)
1359+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
13511360
def description(self) -> Optional[str]:
13521361
"""
13531362
Get the description of this Component.
@@ -1419,6 +1428,7 @@ def licenses(self, licenses: Iterable[License]) -> None:
14191428

14201429
@property
14211430
@serializable.xml_sequence(13)
1431+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
14221432
def copyright(self) -> Optional[str]:
14231433
"""
14241434
An optional copyright notice informing users of the underlying claims to copyright ownership in a published

cyclonedx/model/contact.py

+4
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ def __init__(
213213

214214
@property
215215
@serializable.xml_sequence(1)
216+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
216217
def name(self) -> Optional[str]:
217218
"""
218219
Get the name of the contact.
@@ -228,6 +229,7 @@ def name(self, name: Optional[str]) -> None:
228229

229230
@property
230231
@serializable.xml_sequence(2)
232+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
231233
def email(self) -> Optional[str]:
232234
"""
233235
Get the email of the contact.
@@ -243,6 +245,7 @@ def email(self, email: Optional[str]) -> None:
243245

244246
@property
245247
@serializable.xml_sequence(3)
248+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
246249
def phone(self) -> Optional[str]:
247250
"""
248251
Get the phone of the contact.
@@ -305,6 +308,7 @@ def __init__(
305308

306309
@property
307310
@serializable.xml_sequence(10)
311+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
308312
def name(self) -> Optional[str]:
309313
"""
310314
Get the name of the organization.

cyclonedx/model/issue.py

+4
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def __init__(
6060
self.url = url
6161

6262
@property
63+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
6364
def name(self) -> Optional[str]:
6465
"""
6566
The name of the source. For example "National Vulnerability Database", "NVD", and "Apache".
@@ -151,6 +152,7 @@ def type(self, type: IssueClassification) -> None:
151152

152153
@property
153154
@serializable.xml_sequence(1)
155+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
154156
def id(self) -> Optional[str]:
155157
"""
156158
The identifier of the issue assigned by the source of the issue.
@@ -166,6 +168,7 @@ def id(self, id: Optional[str]) -> None:
166168

167169
@property
168170
@serializable.xml_sequence(2)
171+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
169172
def name(self) -> Optional[str]:
170173
"""
171174
The name of the issue.
@@ -181,6 +184,7 @@ def name(self, name: Optional[str]) -> None:
181184

182185
@property
183186
@serializable.xml_sequence(3)
187+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
184188
def description(self) -> Optional[str]:
185189
"""
186190
A description of the issue.

cyclonedx/model/license.py

+2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ def id(self, id: Optional[str]) -> None:
109109

110110
@property
111111
@serializable.xml_sequence(1)
112+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
112113
def name(self) -> Optional[str]:
113114
"""
114115
If SPDX does not define the license used, this field may be used to provide the license name.
@@ -257,6 +258,7 @@ def __init__(
257258

258259
@property
259260
@serializable.xml_name('.')
261+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
260262
@serializable.json_name('expression')
261263
def value(self) -> str:
262264
"""

cyclonedx/model/release_note.py

+3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def __init__(
6161

6262
@property
6363
@serializable.xml_sequence(1)
64+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
6465
def type(self) -> str:
6566
"""
6667
The software versioning type.
@@ -148,6 +149,7 @@ def timestamp(self, timestamp: Optional[datetime]) -> None:
148149

149150
@property
150151
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'alias')
152+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
151153
@serializable.xml_sequence(7)
152154
def aliases(self) -> 'SortedSet[str]':
153155
"""
@@ -165,6 +167,7 @@ def aliases(self, aliases: Iterable[str]) -> None:
165167

166168
@property
167169
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'tag')
170+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
168171
@serializable.xml_sequence(8)
169172
def tags(self) -> 'SortedSet[str]':
170173
"""

cyclonedx/model/service.py

+4
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ def provider(self, provider: Optional[OrganizationalEntity]) -> None:
119119

120120
@property
121121
@serializable.xml_sequence(2)
122+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
122123
def group(self) -> Optional[str]:
123124
"""
124125
The grouping name, namespace, or identifier. This will often be a shortened, single name of the company or
@@ -135,6 +136,7 @@ def group(self, group: Optional[str]) -> None:
135136

136137
@property
137138
@serializable.xml_sequence(3)
139+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
138140
def name(self) -> str:
139141
"""
140142
The name of the service. This will often be a shortened, single name of the service.
@@ -150,6 +152,7 @@ def name(self, name: str) -> None:
150152

151153
@property
152154
@serializable.xml_sequence(4)
155+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
153156
def version(self) -> Optional[str]:
154157
"""
155158
The service version.
@@ -165,6 +168,7 @@ def version(self, version: Optional[str]) -> None:
165168

166169
@property
167170
@serializable.xml_sequence(5)
171+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
168172
def description(self) -> Optional[str]:
169173
"""
170174
Specifies a description for the service.

cyclonedx/model/vulnerability.py

+6
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def __init__(
8484

8585
@property
8686
@serializable.xml_sequence(1)
87+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
8788
def version(self) -> Optional[str]:
8889
"""
8990
A single version of a component or service.
@@ -354,6 +355,7 @@ def __init__(
354355

355356
@property
356357
@serializable.xml_sequence(1)
358+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
357359
def title(self) -> Optional[str]:
358360
"""
359361
The title of this advisory.
@@ -422,6 +424,7 @@ def __init__(
422424

423425
@property
424426
@serializable.xml_sequence(1)
427+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
425428
def name(self) -> Optional[str]:
426429
"""
427430
Name of this Source.
@@ -493,6 +496,7 @@ def __init__(
493496

494497
@property
495498
@serializable.xml_sequence(1)
499+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
496500
def id(self) -> Optional[str]:
497501
"""
498502
The identifier that uniquely identifies the vulnerability in the associated Source. For example: CVE-2021-39182.
@@ -803,6 +807,7 @@ def method(self, score_source: Optional[VulnerabilityScoreSource]) -> None:
803807

804808
@property
805809
@serializable.xml_sequence(5)
810+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
806811
def vector(self) -> Optional[str]:
807812
"""
808813
The textual representation of the metric values used to score the vulnerability - also known as the vector.
@@ -994,6 +999,7 @@ def bom_ref(self) -> BomRef:
994999

9951000
@property
9961001
@serializable.xml_sequence(1)
1002+
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
9971003
def id(self) -> Optional[str]:
9981004
"""
9991005
The identifier that uniquely identifies the vulnerability. For example: CVE-2021-39182.

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ keywords = [
6969
[tool.poetry.dependencies]
7070
python = "^3.8"
7171
packageurl-python = ">=0.11, <2"
72-
py-serializable = ">=1.0.3, <2"
72+
py-serializable = "^1.1.0"
7373
sortedcontainers = "^2.4.0"
7474
license-expression = "^30"
7575
jsonschema = { version = "^4.18", extras=['format'], optional=true }

0 commit comments

Comments
 (0)