Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/models/license.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type { Sortable } from '../_helpers/sortable'
import type { LicenseAcknowledgement } from '../enums/licenseAcknowledgement'
import type { SpdxId } from '../spdx'
import type { Attachment } from './attachment'
import { PropertyRepository } from './property'

/**
* (SPDX) License Expression.
Expand Down Expand Up @@ -64,11 +65,13 @@ class DisjunctiveLicenseBase {
acknowledgement?: LicenseAcknowledgement
text?: Attachment
#url?: URL | string
properties: PropertyRepository

constructor (op: OptionalDisjunctiveLicenseProperties = {}) {
this.acknowledgement = op.acknowledgement
this.text = op.text
this.url = op.url
this.properties = op.properties ?? new PropertyRepository()
}

get url (): URL | string | undefined {
Expand All @@ -86,6 +89,7 @@ interface OptionalDisjunctiveLicenseProperties {
acknowledgement?: DisjunctiveLicenseBase['acknowledgement']
text?: DisjunctiveLicenseBase['text']
url?: DisjunctiveLicenseBase['url']
properties?: DisjunctiveLicenseBase['properties']
}

export interface OptionalNamedLicenseProperties extends OptionalDisjunctiveLicenseProperties {}
Expand Down
12 changes: 10 additions & 2 deletions src/serialize/json/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,36 +529,44 @@ export class LicenseNormalizer extends BaseJsonNormalizer<Models.License> {
}

#normalizeNamedLicense (data: Models.NamedLicense, options: NormalizerOptions): Normalized.NamedLicense {
const spec = this._factory.spec
const url = escapeUri(data.url?.toString())
return {
license: {
name: data.name,
acknowledgement: this._factory.spec.supportsLicenseAcknowledgement
acknowledgement: spec.supportsLicenseAcknowledgement
? data.acknowledgement
: undefined,
text: data.text === undefined
? undefined
: this._factory.makeForAttachment().normalize(data.text, options),
url: JsonSchema.isIriReference(url)
? url
: undefined,
properties: spec.supportsProperties(data) && data.properties.size > 0
? this._factory.makeForProperty().normalizeIterable(data.properties, options)
: undefined
}
}
}

#normalizeSpdxLicense (data: Models.SpdxLicense, options: NormalizerOptions): Normalized.SpdxLicense {
const spec = this._factory.spec
const url = escapeUri(data.url?.toString())
return {
license: {
id: data.id,
acknowledgement: this._factory.spec.supportsLicenseAcknowledgement
acknowledgement: spec.supportsLicenseAcknowledgement
? data.acknowledgement
: undefined,
text: data.text === undefined
? undefined
: this._factory.makeForAttachment().normalize(data.text, options),
url: JsonSchema.isIriReference(url)
? url
: undefined,
properties: spec.supportsProperties(data) && data.properties.size > 0
? this._factory.makeForProperty().normalizeIterable(data.properties, options)
: undefined
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/serialize/json/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ export namespace Normalized {
acknowledgement?: Enums.LicenseAcknowledgement
text?: Attachment
url?: string
properties?: Property[]
}
}

Expand All @@ -206,6 +207,7 @@ export namespace Normalized {
acknowledgement?: Enums.LicenseAcknowledgement
text?: Attachment
url?: string
properties?: Property[]
}
}

Expand Down
30 changes: 24 additions & 6 deletions src/serialize/xml/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -699,12 +699,20 @@ export class LicenseNormalizer extends BaseXmlNormalizer<Models.License> {
}

#normalizeNamedLicense (data: Models.NamedLicense, options: NormalizerOptions): SimpleXml.Element {
const url = escapeUri(data.url?.toString())
const spec = this._factory.spec
const url = escapeUri(data.url?.toString())
const properties: SimpleXml.Element | undefined = spec.supportsProperties(data) && data.properties.size > 0
? {
type: 'element',
name: 'properties',
children: this._factory.makeForProperty().normalizeIterable(data.properties, options, 'property')
}
: undefined
return {
type: 'element',
name: 'license',
attributes: {
acknowledgement: this._factory.spec.supportsLicenseAcknowledgement
acknowledgement: spec.supportsLicenseAcknowledgement
? data.acknowledgement
: undefined
},
Expand All @@ -715,18 +723,27 @@ export class LicenseNormalizer extends BaseXmlNormalizer<Models.License> {
: this._factory.makeForAttachment().normalize(data.text, options, 'text'),
XmlSchema.isAnyURI(url)
? makeTextElement(url, 'url')
: undefined
: undefined,
properties
].filter(isNotUndefined)
}
}

#normalizeSpdxLicense (data: Models.SpdxLicense, options: NormalizerOptions): SimpleXml.Element {
const url = escapeUri(data.url?.toString())
const spec = this._factory.spec
const url = escapeUri(data.url?.toString())
const properties: SimpleXml.Element | undefined = spec.supportsProperties(data) && data.properties.size > 0
? {
type: 'element',
name: 'properties',
children: this._factory.makeForProperty().normalizeIterable(data.properties, options, 'property')
}
: undefined
return {
type: 'element',
name: 'license',
attributes: {
acknowledgement: this._factory.spec.supportsLicenseAcknowledgement
acknowledgement: spec.supportsLicenseAcknowledgement
? data.acknowledgement
: undefined
},
Expand All @@ -737,7 +754,8 @@ export class LicenseNormalizer extends BaseXmlNormalizer<Models.License> {
: this._factory.makeForAttachment().normalize(data.text, options, 'text'),
XmlSchema.isAnyURI(url)
? makeTextElement(url, 'url')
: undefined
: undefined,
properties
].filter(isNotUndefined)
}
}
Expand Down
17 changes: 12 additions & 5 deletions src/spec/_protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Copyright (c) OWASP Foundation. All Rights Reserved.
*/

import type { ComponentType, ExternalReferenceType, HashAlgorithm, Vulnerability } from '../enums'
import type { HashContent } from '../models'
import { type HashContent, NamedLicense, SpdxLicense } from '../models'
import type { Format, Version } from './enums'

/**
Expand Down Expand Up @@ -79,6 +79,7 @@ export class _Spec implements _SpecProtocol {
readonly #supportsLicenseAcknowledgement: boolean
readonly #supportsServices: boolean
readonly #supportsToolsComponentsServices: boolean
readonly #supportsLicenseProperties: boolean

/* eslint-disable-next-line @typescript-eslint/max-params -- architectural decision */
constructor (
Expand All @@ -101,7 +102,8 @@ export class _Spec implements _SpecProtocol {
supportsExternalReferenceHashes: boolean,
supportsLicenseAcknowledgement: boolean,
supportsServices: boolean,
supportsToolsComponentsServices: boolean
supportsToolsComponentsServices: boolean,
supportsLicenseProperties: boolean
) {
this.#version = version
this.#formats = new Set(formats)
Expand All @@ -123,6 +125,7 @@ export class _Spec implements _SpecProtocol {
this.#supportsLicenseAcknowledgement = supportsLicenseAcknowledgement
this.#supportsServices = supportsServices
this.#supportsToolsComponentsServices = supportsToolsComponentsServices
this.#supportsLicenseProperties = supportsLicenseProperties
}

get version (): Version {
Expand Down Expand Up @@ -166,9 +169,13 @@ export class _Spec implements _SpecProtocol {
return this.#requiresComponentVersion
}

supportsProperties (): boolean {
// currently a global allow/deny -- might work based on input, in the future
return this.#supportsProperties
supportsProperties (model: any): boolean {
switch (true) {
case model instanceof NamedLicense || model instanceof SpdxLicense:
return this.#supportsLicenseProperties
default:
return this.#supportsProperties
}
}

get supportsVulnerabilities (): boolean {
Expand Down
6 changes: 6 additions & 0 deletions src/spec/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export const Spec1dot2: Readonly<_SpecProtocol> = Object.freeze(new _Spec(
false,
false,
true,
false,
false
))

Expand Down Expand Up @@ -154,6 +155,7 @@ export const Spec1dot3: Readonly<_SpecProtocol> = Object.freeze(new _Spec(
true,
false,
true,
false,
false
))

Expand Down Expand Up @@ -226,6 +228,7 @@ export const Spec1dot4: Readonly<_SpecProtocol> = Object.freeze(new _Spec(
true,
false,
true,
false,
false
))

Expand Down Expand Up @@ -327,6 +330,7 @@ export const Spec1dot5: Readonly<_SpecProtocol> = Object.freeze(new _Spec(
true,
false,
true,
true,
true
))

Expand Down Expand Up @@ -433,6 +437,7 @@ export const Spec1dot6: Readonly<_SpecProtocol> = Object.freeze(new _Spec(
true,
true,
true,
true,
true
))

Expand Down Expand Up @@ -547,6 +552,7 @@ export const Spec1dot7: Readonly<_SpecProtocol> = Object.freeze(new _Spec(
true,
true,
true,
true,
true
))

Expand Down
13 changes: 11 additions & 2 deletions tests/_data/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,11 @@ function createComplexStructure () {
contentType: 'text/plain',
encoding: Enums.AttachmentEncoding.Base64
}),
url: 'https://localhost/license'
url: 'https://localhost/license',
properties: new Models.PropertyRepository([
new Models.Property('a', 'b'),
new Models.Property('primaryLicense', 'true')
])
}))
component.licenses.add((function (license) {
license.text = new Models.Attachment('TUlUIExpY2Vuc2UKLi4uClRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLi4u')
Expand All @@ -167,7 +171,12 @@ function createComplexStructure () {
license.url = new URL('https://spdx.org/licenses/MIT.html')
license.acknowledgement = Enums.LicenseAcknowledgement.Declared
return license
})(new Models.SpdxLicense('MIT')))
})(new Models.SpdxLicense('MIT', {
properties: new Models.PropertyRepository([
new Models.Property('c', 'd'),
new Models.Property('primaryLicense', 'false')
])
})))
component.publisher = 'the publisher'
component.purl = new PackageURL('npm', 'acme', 'dummy-component', '1337-beta', undefined, undefined)
component.scope = Enums.ComponentScope.Required
Expand Down
24 changes: 22 additions & 2 deletions tests/_data/normalizeResults/json_sortedLists_spec1.5.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 22 additions & 2 deletions tests/_data/normalizeResults/json_sortedLists_spec1.6.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 22 additions & 2 deletions tests/_data/normalizeResults/json_sortedLists_spec1.7.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading