From 01f64ab66f6bb8c841dd75095b8e909c9fdd63b5 Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Wed, 15 Apr 2026 15:50:14 -0400 Subject: [PATCH 01/14] add options for ValidateLicenses to allow exclusions ValidateLicenses is unchanged for backward compatibility ValidateLicensesWithOptions was added and includes an options parameter with values ValidateLicensesWithOptions - FailComplexExpressions - anything with a conjunction - FailDeprecatedLicenses - FailAllLicenseRefs - FailAllDocumentRefs Example call: ``` valid, _ := ValidateLicensesWithOptions("MIT AND Apache-2.0", ValidateLicensesOptions{FailComplexExpressions: true}) // returns valid=false ``` These provide a way to fail fast for any license that is in one of these categories. --- spdxexp/satisfies.go | 165 +++++++++++++++++++++-- spdxexp/satisfies_test.go | 270 +++++++++++++++++++++++++++++++++++++- 2 files changed, 418 insertions(+), 17 deletions(-) diff --git a/spdxexp/satisfies.go b/spdxexp/satisfies.go index f2bc9d6..fa53efd 100644 --- a/spdxexp/satisfies.go +++ b/spdxexp/satisfies.go @@ -10,22 +10,107 @@ import ( // Returns true if all licenses are valid; otherwise, false. // Returns all the invalid licenses contained in the `licenses` argument. func ValidateLicenses(licenses []string) (bool, []string) { - // simple check for MIT covers the most common case and avoids the overhead of parsing for valid licenses - if len(licenses) == 1 && strings.EqualFold(licenses[0], "MIT") { - return true, []string{} - } + return ValidateLicensesWithOptions(licenses, ValidateLicensesOptions{}) +} - // if only one license, check for active license first since that is the next most common case - if len(licenses) == 1 { - if ok, _ := ActiveLicense(licenses[0]); ok { - return true, []string{} - } - } +// ValidateLicensesOptions controls how ValidateLicensesWithOptions validates input. +type ValidateLicensesOptions struct { + // FailComplexExpressions rejects SPDX license expressions (e.g. "MIT AND Apache-2.0"). + // Single license identifiers (including those with a WITH exception) are still allowed. + FailComplexExpressions bool + + // FailDeprecatedLicenses rejects deprecated SPDX license identifiers (e.g. "eCos-2.0"). + FailDeprecatedLicenses bool + + // FailAllLicenseRefs rejects all SPDX license references (e.g. "LicenseRef-MyLicense"). + FailAllLicenseRefs bool + + // FailAllDocumentRefs rejects all SPDX document references (e.g. "DocumentRef-MyDocument"). + FailAllDocumentRefs bool +} +// ValidateLicensesWithOptions checks if given licenses are valid according to SPDX. +// Returns true if all licenses are valid; otherwise, false. +// Returns all the invalid licenses contained in the `licenses` argument. +func ValidateLicensesWithOptions(licenses []string, options ValidateLicensesOptions) (bool, []string) { // handle all other cases with parsing, which will cover both single and multiple licenses and expressions valid := true invalidLicenses := []string{} for _, license := range licenses { + license = strings.TrimSpace(license) + + if isMIT(license) { + continue + } + + isAtomic := isAtomicLicense(license) + if isAtomic { + if ok, _ := activeLicense(license); ok { + continue + } + + if ok, _ := deprecatedLicense(license); ok { + if options.FailDeprecatedLicenses { + valid = false + invalidLicenses = append(invalidLicenses, license) + continue + } else { + // if not failing deprecated licenses, then consider it valid and continue + continue + } + } + + if options.FailAllLicenseRefs && options.FailAllDocumentRefs { + // if failing all LicenseRefs and DocumentRefs, then no need to continue processing as there + // are no other atomic license types that would be valid + valid = false + invalidLicenses = append(invalidLicenses, license) + continue + } + + if options.FailAllLicenseRefs { + if strings.HasPrefix(license, "LicenseRef-") { + valid = false + invalidLicenses = append(invalidLicenses, license) + continue + } + } + + if options.FailAllDocumentRefs { + if strings.HasPrefix(license, "DocumentRef-") { + valid = false + invalidLicenses = append(invalidLicenses, license) + continue + } + } + + // need to let this pass through to allow parsing LicenseRef and DocumentRef if either are allowed types + } + + if !isAtomic { + if hasException, licensePart, exceptionPart := isLicenseWithException(license); hasException { + // matches pattern "licensePart WITH exceptionPart", so validate both parts separately + if ok, _ := activeLicense(licensePart); ok { + if ok, _ := exceptionLicense(exceptionPart); ok { + continue + } + } + valid = false + invalidLicenses = append(invalidLicenses, license) + continue + } + } + + // all other non-atomic expressions are complex expressions with conjunctions (e.g. "MIT AND Apache-2.0"), + // so fail if complex expressions are not allowed + if options.FailComplexExpressions && !isAtomic { + valid = false + invalidLicenses = append(invalidLicenses, license) + continue + } + + // need to parse if allowing any of LicenseRef, DocumentRef, or complex expressions to be able to determine + // whether the license expression is valid if _, err := parse(license); err != nil { valid = false invalidLicenses = append(invalidLicenses, license) @@ -42,8 +127,10 @@ func Satisfies(testExpression string, allowedList []string) (bool, error) { return false, errors.New("allowedList requires at least one element, but is empty") } + testExpression = strings.TrimSpace(testExpression) + // simple check for MIT covers the most common case and avoids the overhead of parsing the testExpression - if strings.EqualFold(testExpression, "MIT") { + if isMIT(testExpression) { for _, allowed := range allowedList { if strings.EqualFold(allowed, "MIT") { return true, nil @@ -52,9 +139,18 @@ func Satisfies(testExpression string, allowedList []string) (bool, error) { return false, nil } - // if only one license in the test expression, check for active license first to avoid the overhead of parsing - if !strings.Contains(testExpression, " ") { - if ok, _ := ActiveLicense(testExpression); ok { + if isAtomicLicense(testExpression) { + // if only one license in the test expression, check for active license to avoid the overhead of parsing + if ok, _ := activeLicense(testExpression); ok { + for _, allowed := range allowedList { + if strings.EqualFold(allowed, testExpression) { + return true, nil + } + } + } + + // if only one license in the test expression, check for deprecated license to avoid the overhead of parsing + if ok, _ := deprecatedLicense(testExpression); ok { for _, allowed := range allowedList { if strings.EqualFold(allowed, testExpression) { return true, nil @@ -63,6 +159,20 @@ func Satisfies(testExpression string, allowedList []string) (bool, error) { } } + // if test expression is a single license with exception, check it now to avoid the overhead of parsing + if hasException, licensePart, exceptionPart := isLicenseWithException(testExpression); hasException { + // matches pattern "licensePart WITH exceptionPart", so validate both parts separately + if ok, _ := activeLicense(licensePart); ok { + if ok, _ := exceptionLicense(exceptionPart); ok { + for _, allowed := range allowedList { + if strings.EqualFold(allowed, testExpression) { + return true, nil + } + } + } + } + } + // handle all other cases with parsing, which will cover both single and multiple licenses and expressions expressionNode, err := parse(testExpression) if err != nil { @@ -103,6 +213,33 @@ func stringsToNodes(licenseStrings []string) ([]*node, error) { return nodes, nil } +// isMIT checks if the test expression is MIT, ignoring case and leading/trailing whitespace. +// NOTE: Caller should trim the test expression before calling this function to avoid false +// negatives (e.g. " MIT " would not match "MIT"). +func isMIT(testExpression string) bool { + return strings.EqualFold(testExpression, "MIT") +} + +// isAtomicLicense checks if the test expression is a single license identifier (e.g. "MIT"). +// NOTE: Caller should trim the test expression before calling this function to avoid false +// negatives (e.g. " MIT " would not be considered a single license). +func isAtomicLicense(testExpression string) bool { + return !strings.Contains(testExpression, " ") +} + +// isException checks if the test expression contains two licenses separated by WITH +// (e.g. "GPL-2.0-or-later WITH Bison-exception-2.2"). +// NOTE: Caller should trim the test expression before calling this function to avoid false +// negatives (e.g. " MIT " would not be considered a single license). +func isLicenseWithException(testExpression string) (bool, string, string) { + // split by " " and check if there are exactly 3 parts and the middle part is "WITH" + parts := strings.Split(testExpression, " ") + if len(parts) == 3 && strings.EqualFold(parts[1], "WITH") { + return true, parts[0], parts[2] + } + return false, "", "" +} + // isCompatible checks if expressionPart is compatible with allowed list. // Expression part is an array of licenses that are ANDed together. // Allowed is an array of licenses that can fulfill the expression. diff --git a/spdxexp/satisfies_test.go b/spdxexp/satisfies_test.go index e07fa80..91b93a5 100644 --- a/spdxexp/satisfies_test.go +++ b/spdxexp/satisfies_test.go @@ -41,6 +41,153 @@ func TestValidateLicenses(t *testing.T) { } } +func TestValidateLicensesWithOptions_FailComplexExpressions(t *testing.T) { + tests := []struct { + name string + inputLicenses []string + options ValidateLicensesOptions + allValid bool + invalidLicenses []string + }{ + { + name: "Expressions rejected", + inputLicenses: []string{"MIT AND Apache-2.0"}, + options: ValidateLicensesOptions{FailComplexExpressions: true}, + allValid: false, + invalidLicenses: []string{ + "MIT AND Apache-2.0", + }, + }, + { + name: "Mixed list rejects only expressions", + inputLicenses: []string{"MIT", "Apache-2.0", "LGPL-2.1-only OR MIT"}, + options: ValidateLicensesOptions{FailComplexExpressions: true}, + allValid: false, + invalidLicenses: []string{ + "LGPL-2.1-only OR MIT", + }, + }, + { + name: "WITH exception is not treated as complex expression", + inputLicenses: []string{"GPL-2.0-or-later WITH Bison-exception-2.2"}, + options: ValidateLicensesOptions{FailComplexExpressions: true}, + allValid: true, + invalidLicenses: []string{}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + valid, invalidLicenses := ValidateLicensesWithOptions(test.inputLicenses, test.options) + assert.EqualValues(t, test.invalidLicenses, invalidLicenses) + assert.Equal(t, test.allValid, valid) + }) + } +} + +func TestValidateLicensesWithOptions_FailDeprecatedLicenses(t *testing.T) { + // eCos-2.0 is a known deprecated SPDX license ID (see TestDeprecatedLicense). + license := "eCos-2.0" + + valid, invalidLicenses := ValidateLicensesWithOptions([]string{license}, ValidateLicensesOptions{}) + assert.True(t, valid) + assert.Empty(t, invalidLicenses) + + valid, invalidLicenses = ValidateLicensesWithOptions( + []string{license}, + ValidateLicensesOptions{FailDeprecatedLicenses: true}, + ) + assert.False(t, valid) + assert.EqualValues(t, []string{license}, invalidLicenses) +} + +func TestValidateLicensesWithOptions_AllOptions(t *testing.T) { + documentRef := "DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2" + licenseRef := "LicenseRef-MIT-Style-1" + deprecated := "eCos-2.0" + expression := "MIT AND Apache-2.0" + licenseWithException := "GPL-2.0-or-later WITH Bison-exception-2.2" + + tests := []struct { + name string + licenses []string + options ValidateLicensesOptions + valid bool + invalidLicenses []string + }{ + { + name: "Defaults allow deprecated, refs, and expressions", + licenses: []string{" MIT ", deprecated, licenseRef, documentRef, expression, licenseWithException}, + options: ValidateLicensesOptions{}, + valid: true, + invalidLicenses: []string{}, + }, + { + name: "FailDeprecatedLicenses rejects deprecated IDs", + licenses: []string{deprecated, "Apache-2.0"}, + options: ValidateLicensesOptions{FailDeprecatedLicenses: true}, + valid: false, + invalidLicenses: []string{deprecated}, + }, + { + name: "FailComplexExpressions rejects conjunction expressions", + licenses: []string{expression, licenseWithException}, + options: ValidateLicensesOptions{FailComplexExpressions: true}, + valid: false, + invalidLicenses: []string{expression}, + }, + { + name: "FailComplexExpressions does not duplicate invalid entries", + licenses: []string{"MIT AND APCHE-2.0"}, + options: ValidateLicensesOptions{FailComplexExpressions: true}, + valid: false, + invalidLicenses: []string{"MIT AND APCHE-2.0"}, + }, + { + name: "FailAllLicenseRefs rejects LicenseRef but allows DocumentRef", + licenses: []string{licenseRef, documentRef}, + options: ValidateLicensesOptions{FailAllLicenseRefs: true}, + valid: false, + invalidLicenses: []string{licenseRef}, + }, + { + name: "FailAllDocumentRefs rejects DocumentRef but allows LicenseRef", + licenses: []string{documentRef, licenseRef}, + options: ValidateLicensesOptions{FailAllDocumentRefs: true}, + valid: false, + invalidLicenses: []string{documentRef}, + }, + { + name: "FailAllLicenseRefs and FailAllDocumentRefs rejects any non-active atomic ref", + licenses: []string{licenseRef, documentRef, "CustomRef-foo"}, + options: ValidateLicensesOptions{FailAllLicenseRefs: true, FailAllDocumentRefs: true}, + valid: false, + invalidLicenses: []string{licenseRef, documentRef, "CustomRef-foo"}, + }, + { + name: "All flags together", + licenses: []string{deprecated, licenseRef, documentRef, expression, licenseWithException, "Apache-2.0"}, + options: ValidateLicensesOptions{ + FailComplexExpressions: true, + FailDeprecatedLicenses: true, + FailAllLicenseRefs: true, + FailAllDocumentRefs: true, + }, + valid: false, + invalidLicenses: []string{deprecated, licenseRef, documentRef, expression}, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + valid, invalidLicenses := ValidateLicensesWithOptions(test.licenses, test.options) + assert.Equal(t, test.valid, valid) + assert.EqualValues(t, test.invalidLicenses, invalidLicenses) + }) + } +} + // TestSatisfiesSingle lets you quickly test a single call to Satisfies with a specific license expression and allowed list of licenses. // To test a different expression, change the expression, allowed licenses, and expected result in the function body. // TO RUN: go test ./expression -run TestSatisfiesSingle @@ -56,6 +203,81 @@ func TestSatisfiesSingle(t *testing.T) { assert.Equal(t, expectedResult, actualResult) } +func TestSatisfies_FastPathValidation(t *testing.T) { + tests := []struct { + name string + repoExpression string + allowedList []string + satisfied bool + expectErr bool + expectedErr string + }{ + { + name: "MIT trims whitespace", + repoExpression: " MIT \t", + allowedList: []string{"MIT"}, + satisfied: true, + }, + { + name: "Atomic deprecated license matches allowed list", + repoExpression: " eCos-2.0 ", + allowedList: []string{"ECOS-2.0"}, + satisfied: true, + }, + { + name: "Atomic deprecated license not in allowed list", + repoExpression: "eCos-2.0", + allowedList: []string{"MIT"}, + satisfied: false, + }, + { + name: "Single license WITH exception exact match", + repoExpression: "GPL-2.0-or-later WITH Bison-exception-2.2", + allowedList: []string{"GPL-2.0-or-later WITH Bison-exception-2.2"}, + satisfied: true, + }, + { + name: "Single license WITH exception not in allowed list", + repoExpression: "GPL-2.0-or-later WITH Bison-exception-2.2", + allowedList: []string{"MIT"}, + satisfied: false, + }, + { + name: "Single license WITH exception matches allow list ignoring case", + repoExpression: "gpl-2.0-or-later with bison-exception-2.2", + allowedList: []string{"GPL-2.0-or-later WITH Bison-exception-2.2"}, + satisfied: true, + }, + { + name: "Single license WITH invalid exception returns error", + repoExpression: "GPL-2.0-or-later WITH NOT-A-REAL-EXCEPTION", + allowedList: []string{"GPL-2.0-or-later WITH NOT-A-REAL-EXCEPTION"}, + expectErr: true, + expectedErr: "unknown license 'NOT-A-REAL-EXCEPTION' at offset 22", + }, + { + name: "Single license WITH invalid license part returns error", + repoExpression: "NOT-A-REAL-LICENSE WITH Bison-exception-2.2", + allowedList: []string{"NOT-A-REAL-LICENSE WITH Bison-exception-2.2"}, + expectErr: true, + expectedErr: "unknown license 'NOT-A-REAL-LICENSE' at offset 0", + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + actualResult, err := Satisfies(test.repoExpression, test.allowedList) + if test.expectErr { + assert.EqualError(t, err, test.expectedErr) + return + } + assert.NoError(t, err) + assert.Equal(t, test.satisfied, actualResult) + }) + } +} + func TestSatisfies(t *testing.T) { tests := []struct { name string @@ -66,7 +288,6 @@ func TestSatisfies(t *testing.T) { }{ // TODO: Test error conditions (e.g. GPL is an invalid license, Apachie + has invalid + operator) // regression tests from spdx-satisfies.js - comments for satisfies function - // TODO: Commented out tests are not yet supported. {"MIT satisfies [MIT]", "MIT", []string{"MIT"}, true, nil}, {"miT satisfies [MIT]", "miT", []string{"MIT"}, true, nil}, {"MIT satisfies [mit]", "MIT", []string{"mit"}, true, nil}, @@ -109,7 +330,6 @@ func TestSatisfies(t *testing.T) { {"! Apache-3.0 satisfies [Apache-2.0-only]", "Apache-3.0", []string{"Apache-2.0-only"}, false, errors.New("unknown license 'Apache-3.0' at offset 0")}, // regression tests from spdx-satisfies.js - assert statements in README - // TODO: Commented out tests are not yet supported. {"MIT satisfies [MIT]", "MIT", []string{"MIT"}, true, nil}, {"MIT satisfies [ISC, MIT]", "MIT", []string{"ISC", "MIT"}, true, nil}, @@ -319,7 +539,51 @@ func TestExpandOr(t *testing.T) { // lic: nil, // ref: nil, // }, - // [][]string{{"MIT", "Apache-1.0+"}, {"DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2"}, {"GPL-2.0 with Bison-exception-2.2"}}}, + // // [][]string{{"MIT", "Apache-1.0+"}, {"DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2"}, {"GPL-2.0 with Bison-exception-2.2"}}}, + // [][]*node{ + // { + // { + // role: licenseNode, + // exp: nil, + // lic: &licenseNodePartial{ + // license: "MIT", hasPlus: false, + // hasException: false, exception: ""}, + // ref: nil, + // }, + // { + // role: licenseNode, + // exp: nil, + // lic: &licenseNodePartial{ + // license: "Apache-1.0", hasPlus: true, + // hasException: false, exception: ""}, + // ref: nil, + // }, + // }, + // { + // { + // role: licenseRefNode, + // exp: nil, + // lic: nil, + // ref: &referenceNodePartial{ + // hasDocumentRef: true, + // documentRef: "spdx-tool-1.2", + // licenseRef: "MIT-Style-2", + // }, + // }, + // { + // role: licenseNode, + // exp: nil, + // lic: &licenseNodePartial{ + // license: "GPL-2.0", + // hasPlus: false, + // hasException: true, + // exception: "Bison-exception-2.2", + // }, + // ref: nil, + // }, + // }, + // }, + // }, } for _, test := range tests { From 0db335faa9dfa6d3dd2ef333f3a9608ed9e66435 Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 07:03:51 -0400 Subject: [PATCH 02/14] make sure fall through to parsing happens --- spdxexp/satisfies.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/spdxexp/satisfies.go b/spdxexp/satisfies.go index fa53efd..2080eec 100644 --- a/spdxexp/satisfies.go +++ b/spdxexp/satisfies.go @@ -60,14 +60,6 @@ func ValidateLicensesWithOptions(licenses []string, options ValidateLicensesOpti } } - if options.FailAllLicenseRefs && options.FailAllDocumentRefs { - // if failing all LicenseRefs and DocumentRefs, then no need to continue processing as there - // are no other atomic license types that would be valid - valid = false - invalidLicenses = append(invalidLicenses, license) - continue - } - if options.FailAllLicenseRefs { if strings.HasPrefix(license, "LicenseRef-") { valid = false @@ -240,6 +232,7 @@ func isLicenseWithException(testExpression string) (bool, string, string) { return false, "", "" } + // isCompatible checks if expressionPart is compatible with allowed list. // Expression part is an array of licenses that are ANDed together. // Allowed is an array of licenses that can fulfill the expression. From 77d699f7e269816ef9c68f1531f6e57569ce6677 Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 07:43:16 -0400 Subject: [PATCH 03/14] expand license types covered by benchmarks also adds a simple test that makes sure benchmark use cases always pass to ensure improvements are not caused by use case failing early --- spdxexp/benchmark_satisfies_test.go | 19 +++++++++++-------- spdxexp/benchmark_validate_licenses_test.go | 19 +++++++++++-------- spdxexp/satisfies_test.go | 14 ++++++++++++++ 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/spdxexp/benchmark_satisfies_test.go b/spdxexp/benchmark_satisfies_test.go index 646884e..8fe25bc 100644 --- a/spdxexp/benchmark_satisfies_test.go +++ b/spdxexp/benchmark_satisfies_test.go @@ -12,14 +12,17 @@ type satisfiesBenchmarkScenario struct { var satisfiesBenchmarkScenarios = []satisfiesBenchmarkScenario{ // Scenario order is used as-is in the summary table. - {"MIT", "MIT"}, - {"mit", "mit"}, - {"Apache-2.0", "Apache-2.0"}, - {"Zed", "Zed"}, - {"MIT AND Apache-2.0", "MIT AND Apache-2.0"}, - {"MIT AND Apache-2.0 OR Zed", "MIT AND Apache-2.0 OR Zed"}, - {"GPL-2.0-or-later", "GPL-2.0-or-later"}, - {"GPL-2.0+", "GPL-2.0+"}, + {"MIT--exact", "MIT"}, + {"mit--caseinsensitive", "mit"}, + {"Apache-2.0--active-early", "Apache-2.0"}, + {"Zed--active-end", "Zed"}, + {"MIT AND Apache-2.0--complex", "MIT AND Apache-2.0"}, + {"MIT AND Apache-2.0 OR Zed--complex", "MIT AND Apache-2.0 OR Zed"}, + {"BSD-2-Clause-FreeBSD--deprecated", "BSD-2-Clause-FreeBSD"}, + {"GPL-2.0-or-later--range", "GPL-2.0-or-later"}, + {"Apache-1.0+--plus-range", "Apache-1.0+"}, + {"LicenseRef-scancode-adobe-postscript", "LicenseRef-scancode-adobe-postscript"}, + {"DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2", "DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2"}, } func BenchmarkSatisfies(b *testing.B) { diff --git a/spdxexp/benchmark_validate_licenses_test.go b/spdxexp/benchmark_validate_licenses_test.go index 0f2124e..99f11d8 100644 --- a/spdxexp/benchmark_validate_licenses_test.go +++ b/spdxexp/benchmark_validate_licenses_test.go @@ -12,14 +12,17 @@ type validateLicensesBenchmarkScenario struct { var validateLicensesBenchmarkScenarios = []validateLicensesBenchmarkScenario{ // Scenario order is used as-is in the summary table. - {"MIT", []string{"MIT"}}, - {"mit", []string{"mit"}}, - {"Apache-2.0", []string{"Apache-2.0"}}, - {"Zed", []string{"Zed"}}, - {"MIT AND Apache-2.0", []string{"MIT", "Apache-2.0"}}, - {"MIT AND Apache-2.0 OR Zed", []string{"MIT", "Apache-2.0", "Zed"}}, - {"GPL-2.0-or-later", []string{"GPL-2.0-or-later"}}, - {"GPL-2.0+", []string{"GPL-2.0+"}}, + {"MIT--exact", []string{"MIT"}}, + {"mit--caseinsensitive", []string{"mit"}}, + {"Apache-2.0--active-early", []string{"Apache-2.0"}}, + {"Zed--active-end", []string{"Zed"}}, + {"MIT AND Apache-2.0--complex", []string{"MIT", "Apache-2.0"}}, + {"MIT AND Apache-2.0 OR Zed--complex", []string{"MIT", "Apache-2.0", "Zed"}}, + {"BSD-2-Clause-FreeBSD--deprecated", []string{"BSD-2-Clause-FreeBSD"}}, + {"GPL-2.0-or-later--range", []string{"GPL-2.0-or-later"}}, + {"Apache-1.0+--plus-range", []string{"Apache-1.0+"}}, + {"LicenseRef-scancode-adobe-postscript", []string{"LicenseRef-scancode-adobe-postscript"}}, + {"DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2", []string{"DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2"}}, } func BenchmarkValidateLicenses(b *testing.B) { diff --git a/spdxexp/satisfies_test.go b/spdxexp/satisfies_test.go index 91b93a5..7fd953d 100644 --- a/spdxexp/satisfies_test.go +++ b/spdxexp/satisfies_test.go @@ -2678,3 +2678,17 @@ func ExampleValidateLicenses_allBad() { fmt.Println(ValidateLicenses([]string{"MTI", "Apache--2.0", "GPL"})) // Output: false [MTI Apache--2.0 GPL] } + +// TestValidateLicenses_BenchmarkExamples is a safety check to ensure benchmark emprovements are not due +// to changes behavior of ValidateLicenses function. +func TestValidateLicenses_BenchmarkExamples(t *testing.T) { + // This test is used to verify that the test expressions used in the benchmarks return expected results. + // If any of the test expressions are invalid, then there is likely an issue with the benchmark results and investigation would be needed. + for _, test := range validateLicensesBenchmarkScenarios { + t.Run(test.name, func(t *testing.T) { + valid, invalidLicenses := ValidateLicenses(test.testLicenses) + assert.True(t, valid, "Expected licenses to be valid for scenario: %s", test.name) + assert.Empty(t, invalidLicenses, "Expected no invalid licenses for scenario: %s", test.name) + }) + } +} From b0e18547e5d2b71bbff3bea8bd01aacd7be71cfe Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 07:53:14 -0400 Subject: [PATCH 04/14] check cost of removing space as well --- spdxexp/benchmark_satisfies_test.go | 2 +- spdxexp/benchmark_validate_licenses_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spdxexp/benchmark_satisfies_test.go b/spdxexp/benchmark_satisfies_test.go index 8fe25bc..7d7f341 100644 --- a/spdxexp/benchmark_satisfies_test.go +++ b/spdxexp/benchmark_satisfies_test.go @@ -13,7 +13,7 @@ type satisfiesBenchmarkScenario struct { var satisfiesBenchmarkScenarios = []satisfiesBenchmarkScenario{ // Scenario order is used as-is in the summary table. {"MIT--exact", "MIT"}, - {"mit--caseinsensitive", "mit"}, + {"mit--caseinsensitive", " mit "}, {"Apache-2.0--active-early", "Apache-2.0"}, {"Zed--active-end", "Zed"}, {"MIT AND Apache-2.0--complex", "MIT AND Apache-2.0"}, diff --git a/spdxexp/benchmark_validate_licenses_test.go b/spdxexp/benchmark_validate_licenses_test.go index 99f11d8..12861f1 100644 --- a/spdxexp/benchmark_validate_licenses_test.go +++ b/spdxexp/benchmark_validate_licenses_test.go @@ -13,7 +13,7 @@ type validateLicensesBenchmarkScenario struct { var validateLicensesBenchmarkScenarios = []validateLicensesBenchmarkScenario{ // Scenario order is used as-is in the summary table. {"MIT--exact", []string{"MIT"}}, - {"mit--caseinsensitive", []string{"mit"}}, + {"mit--caseinsensitive", []string{" mit "}}, {"Apache-2.0--active-early", []string{"Apache-2.0"}}, {"Zed--active-end", []string{"Zed"}}, {"MIT AND Apache-2.0--complex", []string{"MIT", "Apache-2.0"}}, From 8ef2a728006d11007c450b9981b9bf5666d6cba5 Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 09:34:54 -0400 Subject: [PATCH 05/14] switch license lookup to use Map instead of Slice --- cmd/doc.go | 1 + cmd/exceptions.go | 16 + cmd/license.go | 31 ++ spdxexp/license.go | 15 +- spdxexp/spdxlicenses/get_deprecated.go | 40 ++ spdxexp/spdxlicenses/get_exceptions.go | 91 ++++ spdxexp/spdxlicenses/get_licenses.go | 703 +++++++++++++++++++++++++ 7 files changed, 889 insertions(+), 8 deletions(-) diff --git a/cmd/doc.go b/cmd/doc.go index d20ae72..3e00eb9 100644 --- a/cmd/doc.go +++ b/cmd/doc.go @@ -10,6 +10,7 @@ spdxexp/license.go file. Command to run all extractions (run command from the /cmd directory): + cd cmd go run . extract -l -e Usage options: diff --git a/cmd/exceptions.go b/cmd/exceptions.go index 749bf5d..9674c40 100644 --- a/cmd/exceptions.go +++ b/cmd/exceptions.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "os" + "strings" ) type ExceptionData struct { @@ -64,6 +65,21 @@ func GetExceptions() []string { } getExceptionsContents = append(getExceptionsContents, ` } } + +`...) + + getExceptionsContents = append(getExceptionsContents, `var exceptionsMap = map[string]string{ +`...) + for _, id := range exceptionLicenseIDs { + getExceptionsContents = append(getExceptionsContents, ` "`+strings.ToUpper(id)+`": "`+id+`", +`...) + } + getExceptionsContents = append(getExceptionsContents, `} + +// GetExceptionsMap returns a map of exception license IDs keyed by uppercase ID. +func GetExceptionsMap() map[string]string { + return exceptionsMap +} `...) err = os.WriteFile("../spdxexp/spdxlicenses/get_exceptions.go", getExceptionsContents, 0600) diff --git a/cmd/license.go b/cmd/license.go index c051189..6adf391 100644 --- a/cmd/license.go +++ b/cmd/license.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "os" + "strings" ) type LicenseData struct { @@ -69,6 +70,21 @@ func GetLicenses() []string { } getLicensesContents = append(getLicensesContents, ` } } + +`...) + + getLicensesContents = append(getLicensesContents, `var licensesMap = map[string]string{ +`...) + for _, id := range activeLicenseIDs { + getLicensesContents = append(getLicensesContents, ` "`+strings.ToUpper(id)+`": "`+id+`", +`...) + } + getLicensesContents = append(getLicensesContents, `} + +// GetLicensesMap returns a map of active license IDs keyed by uppercase ID. +func GetLicensesMap() map[string]string { + return licensesMap +} `...) err = os.WriteFile("../spdxexp/spdxlicenses/get_licenses.go", getLicensesContents, 0600) @@ -93,6 +109,21 @@ func GetDeprecated() []string { } getDeprecatedContents = append(getDeprecatedContents, ` } } + +`...) + + getDeprecatedContents = append(getDeprecatedContents, `var deprecatedMap = map[string]string{ +`...) + for _, id := range deprecatedLicenseIDs { + getDeprecatedContents = append(getDeprecatedContents, ` "`+strings.ToUpper(id)+`": "`+id+`", +`...) + } + getDeprecatedContents = append(getDeprecatedContents, `} + +// GetDeprecatedMap returns a map of deprecated license IDs keyed by uppercase ID. +func GetDeprecatedMap() map[string]string { + return deprecatedMap +} `...) err = os.WriteFile("../spdxexp/spdxlicenses/get_deprecated.go", getDeprecatedContents, 0600) diff --git a/spdxexp/license.go b/spdxexp/license.go index a1800b0..822c0a4 100644 --- a/spdxexp/license.go +++ b/spdxexp/license.go @@ -8,7 +8,7 @@ import ( // activeLicense returns true if the id is an active license. func activeLicense(id string) (bool, string) { - return inLicenseList(spdxlicenses.GetLicenses(), id) + return inLicenseList(spdxlicenses.GetLicensesMap(), id) } // ActiveLicense returns true if the id is an active license. @@ -18,20 +18,19 @@ func ActiveLicense(id string) (bool, string) { // deprecatedLicense returns true if the id is a deprecated license. func deprecatedLicense(id string) (bool, string) { - return inLicenseList(spdxlicenses.GetDeprecated(), id) + return inLicenseList(spdxlicenses.GetDeprecatedMap(), id) } // exceptionLicense returns true if the id is an exception license. func exceptionLicense(id string) (bool, string) { - return inLicenseList(spdxlicenses.GetExceptions(), id) + return inLicenseList(spdxlicenses.GetExceptionsMap(), id) } // inLicenseList looks for id in the list of licenses. The check is case-insensitive (e.g. "mit" will match "MIT"). -func inLicenseList(licenses []string, id string) (bool, string) { - for _, license := range licenses { - if strings.EqualFold(license, id) { - return true, license - } +func inLicenseList(licenses map[string]string, id string) (bool, string) { + foundID, ok := licenses[strings.ToUpper(id)] + if ok { + return true, foundID } return false, id } diff --git a/spdxexp/spdxlicenses/get_deprecated.go b/spdxexp/spdxlicenses/get_deprecated.go index c2cbf3f..4bd1fb4 100644 --- a/spdxexp/spdxlicenses/get_deprecated.go +++ b/spdxexp/spdxlicenses/get_deprecated.go @@ -40,3 +40,43 @@ func GetDeprecated() []string { "wxWindows", } } + +var deprecatedMap = map[string]string{ + "AGPL-1.0": "AGPL-1.0", + "AGPL-3.0": "AGPL-3.0", + "BSD-2-CLAUSE-FREEBSD": "BSD-2-Clause-FreeBSD", + "BSD-2-CLAUSE-NETBSD": "BSD-2-Clause-NetBSD", + "BZIP2-1.0.5": "bzip2-1.0.5", + "ECOS-2.0": "eCos-2.0", + "GFDL-1.1": "GFDL-1.1", + "GFDL-1.2": "GFDL-1.2", + "GFDL-1.3": "GFDL-1.3", + "GPL-1.0": "GPL-1.0", + "GPL-1.0+": "GPL-1.0+", + "GPL-2.0": "GPL-2.0", + "GPL-2.0+": "GPL-2.0+", + "GPL-2.0-WITH-AUTOCONF-EXCEPTION": "GPL-2.0-with-autoconf-exception", + "GPL-2.0-WITH-BISON-EXCEPTION": "GPL-2.0-with-bison-exception", + "GPL-2.0-WITH-CLASSPATH-EXCEPTION": "GPL-2.0-with-classpath-exception", + "GPL-2.0-WITH-FONT-EXCEPTION": "GPL-2.0-with-font-exception", + "GPL-2.0-WITH-GCC-EXCEPTION": "GPL-2.0-with-GCC-exception", + "GPL-3.0": "GPL-3.0", + "GPL-3.0+": "GPL-3.0+", + "GPL-3.0-WITH-AUTOCONF-EXCEPTION": "GPL-3.0-with-autoconf-exception", + "GPL-3.0-WITH-GCC-EXCEPTION": "GPL-3.0-with-GCC-exception", + "LGPL-2.0": "LGPL-2.0", + "LGPL-2.0+": "LGPL-2.0+", + "LGPL-2.1": "LGPL-2.1", + "LGPL-2.1+": "LGPL-2.1+", + "LGPL-3.0": "LGPL-3.0", + "LGPL-3.0+": "LGPL-3.0+", + "NET-SNMP": "Net-SNMP", + "NUNIT": "Nunit", + "STANDARDML-NJ": "StandardML-NJ", + "WXWINDOWS": "wxWindows", +} + +// GetDeprecatedMap returns a map of deprecated license IDs keyed by uppercase ID. +func GetDeprecatedMap() map[string]string { + return deprecatedMap +} diff --git a/spdxexp/spdxlicenses/get_exceptions.go b/spdxexp/spdxlicenses/get_exceptions.go index 80a43b1..a83e024 100644 --- a/spdxexp/spdxlicenses/get_exceptions.go +++ b/spdxexp/spdxlicenses/get_exceptions.go @@ -91,3 +91,94 @@ func GetExceptions() []string { "x11vnc-openssl-exception", } } + +var exceptionsMap = map[string]string{ + "389-EXCEPTION": "389-exception", + "ASTERISK-EXCEPTION": "Asterisk-exception", + "ASTERISK-LINKING-PROTOCOLS-EXCEPTION": "Asterisk-linking-protocols-exception", + "AUTOCONF-EXCEPTION-2.0": "Autoconf-exception-2.0", + "AUTOCONF-EXCEPTION-3.0": "Autoconf-exception-3.0", + "AUTOCONF-EXCEPTION-GENERIC": "Autoconf-exception-generic", + "AUTOCONF-EXCEPTION-GENERIC-3.0": "Autoconf-exception-generic-3.0", + "AUTOCONF-EXCEPTION-MACRO": "Autoconf-exception-macro", + "BISON-EXCEPTION-1.24": "Bison-exception-1.24", + "BISON-EXCEPTION-2.2": "Bison-exception-2.2", + "BOOTLOADER-EXCEPTION": "Bootloader-exception", + "CGAL-LINKING-EXCEPTION": "CGAL-linking-exception", + "CLASSPATH-EXCEPTION-2.0": "Classpath-exception-2.0", + "CLASSPATH-EXCEPTION-2.0-SHORT": "Classpath-exception-2.0-short", + "CLISP-EXCEPTION-2.0": "CLISP-exception-2.0", + "CRYPTSETUP-OPENSSL-EXCEPTION": "cryptsetup-OpenSSL-exception", + "DIGIA-QT-LGPL-EXCEPTION-1.1": "Digia-Qt-LGPL-exception-1.1", + "DIGIRULE-FOSS-EXCEPTION": "DigiRule-FOSS-exception", + "ECOS-EXCEPTION-2.0": "eCos-exception-2.0", + "ERLANG-OTP-LINKING-EXCEPTION": "erlang-otp-linking-exception", + "FAWKES-RUNTIME-EXCEPTION": "Fawkes-Runtime-exception", + "FLTK-EXCEPTION": "FLTK-exception", + "FMT-EXCEPTION": "fmt-exception", + "FONT-EXCEPTION-2.0": "Font-exception-2.0", + "FREERTOS-EXCEPTION-2.0": "freertos-exception-2.0", + "GCC-EXCEPTION-2.0": "GCC-exception-2.0", + "GCC-EXCEPTION-2.0-NOTE": "GCC-exception-2.0-note", + "GCC-EXCEPTION-3.1": "GCC-exception-3.1", + "GMSH-EXCEPTION": "Gmsh-exception", + "GNAT-EXCEPTION": "GNAT-exception", + "GNOME-EXAMPLES-EXCEPTION": "GNOME-examples-exception", + "GNU-COMPILER-EXCEPTION": "GNU-compiler-exception", + "GNU-JAVAMAIL-EXCEPTION": "gnu-javamail-exception", + "GPL-3.0-389-DS-BASE-EXCEPTION": "GPL-3.0-389-ds-base-exception", + "GPL-3.0-INTERFACE-EXCEPTION": "GPL-3.0-interface-exception", + "GPL-3.0-LINKING-EXCEPTION": "GPL-3.0-linking-exception", + "GPL-3.0-LINKING-SOURCE-EXCEPTION": "GPL-3.0-linking-source-exception", + "GPL-CC-1.0": "GPL-CC-1.0", + "GSTREAMER-EXCEPTION-2005": "GStreamer-exception-2005", + "GSTREAMER-EXCEPTION-2008": "GStreamer-exception-2008", + "HARBOUR-EXCEPTION": "harbour-exception", + "I2P-GPL-JAVA-EXCEPTION": "i2p-gpl-java-exception", + "INDEPENDENT-MODULES-EXCEPTION": "Independent-modules-exception", + "KICAD-LIBRARIES-EXCEPTION": "KiCad-libraries-exception", + "KVIRC-OPENSSL-EXCEPTION": "kvirc-openssl-exception", + "LGPL-3.0-LINKING-EXCEPTION": "LGPL-3.0-linking-exception", + "LIBPRI-OPENH323-EXCEPTION": "libpri-OpenH323-exception", + "LIBTOOL-EXCEPTION": "Libtool-exception", + "LINUX-SYSCALL-NOTE": "Linux-syscall-note", + "LLGPL": "LLGPL", + "LLVM-EXCEPTION": "LLVM-exception", + "LZMA-EXCEPTION": "LZMA-exception", + "MIF-EXCEPTION": "mif-exception", + "MXML-EXCEPTION": "mxml-exception", + "OCAML-LGPL-LINKING-EXCEPTION": "OCaml-LGPL-linking-exception", + "OCCT-EXCEPTION-1.0": "OCCT-exception-1.0", + "OPENJDK-ASSEMBLY-EXCEPTION-1.0": "OpenJDK-assembly-exception-1.0", + "OPENVPN-OPENSSL-EXCEPTION": "openvpn-openssl-exception", + "PCRE2-EXCEPTION": "PCRE2-exception", + "POLYPARSE-EXCEPTION": "polyparse-exception", + "PS-OR-PDF-FONT-EXCEPTION-20170817": "PS-or-PDF-font-exception-20170817", + "QPL-1.0-INRIA-2004-EXCEPTION": "QPL-1.0-INRIA-2004-exception", + "QT-GPL-EXCEPTION-1.0": "Qt-GPL-exception-1.0", + "QT-LGPL-EXCEPTION-1.1": "Qt-LGPL-exception-1.1", + "QWT-EXCEPTION-1.0": "Qwt-exception-1.0", + "ROMIC-EXCEPTION": "romic-exception", + "RRDTOOL-FLOSS-EXCEPTION-2.0": "RRDtool-FLOSS-exception-2.0", + "RSYNC-LINKING-EXCEPTION": "rsync-linking-exception", + "SANE-EXCEPTION": "SANE-exception", + "SHL-2.0": "SHL-2.0", + "SHL-2.1": "SHL-2.1", + "SIMPLE-LIBRARY-USAGE-EXCEPTION": "Simple-Library-Usage-exception", + "SQLITESTUDIO-OPENSSL-EXCEPTION": "sqlitestudio-OpenSSL-exception", + "STUNNEL-EXCEPTION": "stunnel-exception", + "SWI-EXCEPTION": "SWI-exception", + "SWIFT-EXCEPTION": "Swift-exception", + "TEXINFO-EXCEPTION": "Texinfo-exception", + "U-BOOT-EXCEPTION-2.0": "u-boot-exception-2.0", + "UBDL-EXCEPTION": "UBDL-exception", + "UNIVERSAL-FOSS-EXCEPTION-1.0": "Universal-FOSS-exception-1.0", + "VSFTPD-OPENSSL-EXCEPTION": "vsftpd-openssl-exception", + "WXWINDOWS-EXCEPTION-3.1": "WxWindows-exception-3.1", + "X11VNC-OPENSSL-EXCEPTION": "x11vnc-openssl-exception", +} + +// GetExceptionsMap returns a map of exception license IDs keyed by uppercase ID. +func GetExceptionsMap() map[string]string { + return exceptionsMap +} diff --git a/spdxexp/spdxlicenses/get_licenses.go b/spdxexp/spdxlicenses/get_licenses.go index 861e7f0..09abbae 100644 --- a/spdxexp/spdxlicenses/get_licenses.go +++ b/spdxexp/spdxlicenses/get_licenses.go @@ -703,3 +703,706 @@ func GetLicenses() []string { "ZPL-2.1", } } + +var licensesMap = map[string]string{ + "0BSD": "0BSD", + "3D-SLICER-1.0": "3D-Slicer-1.0", + "AAL": "AAL", + "ABSTYLES": "Abstyles", + "ADACORE-DOC": "AdaCore-doc", + "ADOBE-2006": "Adobe-2006", + "ADOBE-DISPLAY-POSTSCRIPT": "Adobe-Display-PostScript", + "ADOBE-GLYPH": "Adobe-Glyph", + "ADOBE-UTOPIA": "Adobe-Utopia", + "ADSL": "ADSL", + "ADVANCED-CRYPTICS-DICTIONARY": "Advanced-Cryptics-Dictionary", + "AFL-1.1": "AFL-1.1", + "AFL-1.2": "AFL-1.2", + "AFL-2.0": "AFL-2.0", + "AFL-2.1": "AFL-2.1", + "AFL-3.0": "AFL-3.0", + "AFMPARSE": "Afmparse", + "AGPL-1.0-ONLY": "AGPL-1.0-only", + "AGPL-1.0-OR-LATER": "AGPL-1.0-or-later", + "AGPL-3.0-ONLY": "AGPL-3.0-only", + "AGPL-3.0-OR-LATER": "AGPL-3.0-or-later", + "ALADDIN": "Aladdin", + "ALGLIB-DOCUMENTATION": "ALGLIB-Documentation", + "AMD-NEWLIB": "AMD-newlib", + "AMDPLPA": "AMDPLPA", + "AML": "AML", + "AML-GLSLANG": "AML-glslang", + "AMPAS": "AMPAS", + "ANTLR-PD": "ANTLR-PD", + "ANTLR-PD-FALLBACK": "ANTLR-PD-fallback", + "ANY-OSI": "any-OSI", + "ANY-OSI-PERL-MODULES": "any-OSI-perl-modules", + "APACHE-1.0": "Apache-1.0", + "APACHE-1.1": "Apache-1.1", + "APACHE-2.0": "Apache-2.0", + "APAFML": "APAFML", + "APL-1.0": "APL-1.0", + "APP-S2P": "App-s2p", + "APSL-1.0": "APSL-1.0", + "APSL-1.1": "APSL-1.1", + "APSL-1.2": "APSL-1.2", + "APSL-2.0": "APSL-2.0", + "ARPHIC-1999": "Arphic-1999", + "ARTISTIC-1.0": "Artistic-1.0", + "ARTISTIC-1.0-CL8": "Artistic-1.0-cl8", + "ARTISTIC-1.0-PERL": "Artistic-1.0-Perl", + "ARTISTIC-2.0": "Artistic-2.0", + "ARTISTIC-DIST": "Artistic-dist", + "ASPELL-RU": "Aspell-RU", + "ASWF-DIGITAL-ASSETS-1.0": "ASWF-Digital-Assets-1.0", + "ASWF-DIGITAL-ASSETS-1.1": "ASWF-Digital-Assets-1.1", + "BAEKMUK": "Baekmuk", + "BAHYPH": "Bahyph", + "BARR": "Barr", + "BCRYPT-SOLAR-DESIGNER": "bcrypt-Solar-Designer", + "BEERWARE": "Beerware", + "BITSTREAM-CHARTER": "Bitstream-Charter", + "BITSTREAM-VERA": "Bitstream-Vera", + "BITTORRENT-1.0": "BitTorrent-1.0", + "BITTORRENT-1.1": "BitTorrent-1.1", + "BLESSING": "blessing", + "BLUEOAK-1.0.0": "BlueOak-1.0.0", + "BOEHM-GC": "Boehm-GC", + "BOEHM-GC-WITHOUT-FEE": "Boehm-GC-without-fee", + "BOLA-1.1": "BOLA-1.1", + "BORCEUX": "Borceux", + "BRIAN-GLADMAN-2-CLAUSE": "Brian-Gladman-2-Clause", + "BRIAN-GLADMAN-3-CLAUSE": "Brian-Gladman-3-Clause", + "BSD-1-CLAUSE": "BSD-1-Clause", + "BSD-2-CLAUSE": "BSD-2-Clause", + "BSD-2-CLAUSE-DARWIN": "BSD-2-Clause-Darwin", + "BSD-2-CLAUSE-FIRST-LINES": "BSD-2-Clause-first-lines", + "BSD-2-CLAUSE-PATENT": "BSD-2-Clause-Patent", + "BSD-2-CLAUSE-PKGCONF-DISCLAIMER": "BSD-2-Clause-pkgconf-disclaimer", + "BSD-2-CLAUSE-VIEWS": "BSD-2-Clause-Views", + "BSD-3-CLAUSE": "BSD-3-Clause", + "BSD-3-CLAUSE-ACPICA": "BSD-3-Clause-acpica", + "BSD-3-CLAUSE-ATTRIBUTION": "BSD-3-Clause-Attribution", + "BSD-3-CLAUSE-CLEAR": "BSD-3-Clause-Clear", + "BSD-3-CLAUSE-FLEX": "BSD-3-Clause-flex", + "BSD-3-CLAUSE-HP": "BSD-3-Clause-HP", + "BSD-3-CLAUSE-LBNL": "BSD-3-Clause-LBNL", + "BSD-3-CLAUSE-MODIFICATION": "BSD-3-Clause-Modification", + "BSD-3-CLAUSE-NO-MILITARY-LICENSE": "BSD-3-Clause-No-Military-License", + "BSD-3-CLAUSE-NO-NUCLEAR-LICENSE": "BSD-3-Clause-No-Nuclear-License", + "BSD-3-CLAUSE-NO-NUCLEAR-LICENSE-2014": "BSD-3-Clause-No-Nuclear-License-2014", + "BSD-3-CLAUSE-NO-NUCLEAR-WARRANTY": "BSD-3-Clause-No-Nuclear-Warranty", + "BSD-3-CLAUSE-OPEN-MPI": "BSD-3-Clause-Open-MPI", + "BSD-3-CLAUSE-SUN": "BSD-3-Clause-Sun", + "BSD-3-CLAUSE-TSO": "BSD-3-Clause-Tso", + "BSD-4-CLAUSE": "BSD-4-Clause", + "BSD-4-CLAUSE-SHORTENED": "BSD-4-Clause-Shortened", + "BSD-4-CLAUSE-UC": "BSD-4-Clause-UC", + "BSD-4.3RENO": "BSD-4.3RENO", + "BSD-4.3TAHOE": "BSD-4.3TAHOE", + "BSD-ADVERTISING-ACKNOWLEDGEMENT": "BSD-Advertising-Acknowledgement", + "BSD-ATTRIBUTION-HPND-DISCLAIMER": "BSD-Attribution-HPND-disclaimer", + "BSD-INFERNO-NETTVERK": "BSD-Inferno-Nettverk", + "BSD-MARK-MODIFICATIONS": "BSD-Mark-Modifications", + "BSD-PROTECTION": "BSD-Protection", + "BSD-SOURCE-BEGINNING-FILE": "BSD-Source-beginning-file", + "BSD-SOURCE-CODE": "BSD-Source-Code", + "BSD-SYSTEMICS": "BSD-Systemics", + "BSD-SYSTEMICS-W3WORKS": "BSD-Systemics-W3Works", + "BSL-1.0": "BSL-1.0", + "BUDDY": "Buddy", + "BUSL-1.1": "BUSL-1.1", + "BZIP2-1.0.6": "bzip2-1.0.6", + "C-UDA-1.0": "C-UDA-1.0", + "CAL-1.0": "CAL-1.0", + "CAL-1.0-COMBINED-WORK-EXCEPTION": "CAL-1.0-Combined-Work-Exception", + "CALDERA": "Caldera", + "CALDERA-NO-PREAMBLE": "Caldera-no-preamble", + "CAPEC-TOU": "CAPEC-tou", + "CATHARON": "Catharon", + "CATOSL-1.1": "CATOSL-1.1", + "CC-BY-1.0": "CC-BY-1.0", + "CC-BY-2.0": "CC-BY-2.0", + "CC-BY-2.5": "CC-BY-2.5", + "CC-BY-2.5-AU": "CC-BY-2.5-AU", + "CC-BY-3.0": "CC-BY-3.0", + "CC-BY-3.0-AT": "CC-BY-3.0-AT", + "CC-BY-3.0-AU": "CC-BY-3.0-AU", + "CC-BY-3.0-DE": "CC-BY-3.0-DE", + "CC-BY-3.0-IGO": "CC-BY-3.0-IGO", + "CC-BY-3.0-NL": "CC-BY-3.0-NL", + "CC-BY-3.0-US": "CC-BY-3.0-US", + "CC-BY-4.0": "CC-BY-4.0", + "CC-BY-NC-1.0": "CC-BY-NC-1.0", + "CC-BY-NC-2.0": "CC-BY-NC-2.0", + "CC-BY-NC-2.5": "CC-BY-NC-2.5", + "CC-BY-NC-3.0": "CC-BY-NC-3.0", + "CC-BY-NC-3.0-DE": "CC-BY-NC-3.0-DE", + "CC-BY-NC-4.0": "CC-BY-NC-4.0", + "CC-BY-NC-ND-1.0": "CC-BY-NC-ND-1.0", + "CC-BY-NC-ND-2.0": "CC-BY-NC-ND-2.0", + "CC-BY-NC-ND-2.5": "CC-BY-NC-ND-2.5", + "CC-BY-NC-ND-3.0": "CC-BY-NC-ND-3.0", + "CC-BY-NC-ND-3.0-DE": "CC-BY-NC-ND-3.0-DE", + "CC-BY-NC-ND-3.0-IGO": "CC-BY-NC-ND-3.0-IGO", + "CC-BY-NC-ND-4.0": "CC-BY-NC-ND-4.0", + "CC-BY-NC-SA-1.0": "CC-BY-NC-SA-1.0", + "CC-BY-NC-SA-2.0": "CC-BY-NC-SA-2.0", + "CC-BY-NC-SA-2.0-DE": "CC-BY-NC-SA-2.0-DE", + "CC-BY-NC-SA-2.0-FR": "CC-BY-NC-SA-2.0-FR", + "CC-BY-NC-SA-2.0-UK": "CC-BY-NC-SA-2.0-UK", + "CC-BY-NC-SA-2.5": "CC-BY-NC-SA-2.5", + "CC-BY-NC-SA-3.0": "CC-BY-NC-SA-3.0", + "CC-BY-NC-SA-3.0-DE": "CC-BY-NC-SA-3.0-DE", + "CC-BY-NC-SA-3.0-IGO": "CC-BY-NC-SA-3.0-IGO", + "CC-BY-NC-SA-4.0": "CC-BY-NC-SA-4.0", + "CC-BY-ND-1.0": "CC-BY-ND-1.0", + "CC-BY-ND-2.0": "CC-BY-ND-2.0", + "CC-BY-ND-2.5": "CC-BY-ND-2.5", + "CC-BY-ND-3.0": "CC-BY-ND-3.0", + "CC-BY-ND-3.0-DE": "CC-BY-ND-3.0-DE", + "CC-BY-ND-4.0": "CC-BY-ND-4.0", + "CC-BY-SA-1.0": "CC-BY-SA-1.0", + "CC-BY-SA-2.0": "CC-BY-SA-2.0", + "CC-BY-SA-2.0-UK": "CC-BY-SA-2.0-UK", + "CC-BY-SA-2.1-JP": "CC-BY-SA-2.1-JP", + "CC-BY-SA-2.5": "CC-BY-SA-2.5", + "CC-BY-SA-3.0": "CC-BY-SA-3.0", + "CC-BY-SA-3.0-AT": "CC-BY-SA-3.0-AT", + "CC-BY-SA-3.0-DE": "CC-BY-SA-3.0-DE", + "CC-BY-SA-3.0-IGO": "CC-BY-SA-3.0-IGO", + "CC-BY-SA-4.0": "CC-BY-SA-4.0", + "CC-PDDC": "CC-PDDC", + "CC-PDM-1.0": "CC-PDM-1.0", + "CC-SA-1.0": "CC-SA-1.0", + "CC0-1.0": "CC0-1.0", + "CDDL-1.0": "CDDL-1.0", + "CDDL-1.1": "CDDL-1.1", + "CDL-1.0": "CDL-1.0", + "CDLA-PERMISSIVE-1.0": "CDLA-Permissive-1.0", + "CDLA-PERMISSIVE-2.0": "CDLA-Permissive-2.0", + "CDLA-SHARING-1.0": "CDLA-Sharing-1.0", + "CECILL-1.0": "CECILL-1.0", + "CECILL-1.1": "CECILL-1.1", + "CECILL-2.0": "CECILL-2.0", + "CECILL-2.1": "CECILL-2.1", + "CECILL-B": "CECILL-B", + "CECILL-C": "CECILL-C", + "CERN-OHL-1.1": "CERN-OHL-1.1", + "CERN-OHL-1.2": "CERN-OHL-1.2", + "CERN-OHL-P-2.0": "CERN-OHL-P-2.0", + "CERN-OHL-S-2.0": "CERN-OHL-S-2.0", + "CERN-OHL-W-2.0": "CERN-OHL-W-2.0", + "CFITSIO": "CFITSIO", + "CHECK-CVS": "check-cvs", + "CHECKMK": "checkmk", + "CLARTISTIC": "ClArtistic", + "CLIPS": "Clips", + "CMU-MACH": "CMU-Mach", + "CMU-MACH-NODOC": "CMU-Mach-nodoc", + "CNRI-JYTHON": "CNRI-Jython", + "CNRI-PYTHON": "CNRI-Python", + "CNRI-PYTHON-GPL-COMPATIBLE": "CNRI-Python-GPL-Compatible", + "COIL-1.0": "COIL-1.0", + "COMMUNITY-SPEC-1.0": "Community-Spec-1.0", + "CONDOR-1.1": "Condor-1.1", + "COPYLEFT-NEXT-0.3.0": "copyleft-next-0.3.0", + "COPYLEFT-NEXT-0.3.1": "copyleft-next-0.3.1", + "CORNELL-LOSSLESS-JPEG": "Cornell-Lossless-JPEG", + "CPAL-1.0": "CPAL-1.0", + "CPL-1.0": "CPL-1.0", + "CPOL-1.02": "CPOL-1.02", + "CRONYX": "Cronyx", + "CROSSWORD": "Crossword", + "CRYPTOSWIFT": "CryptoSwift", + "CRYSTALSTACKER": "CrystalStacker", + "CUA-OPL-1.0": "CUA-OPL-1.0", + "CUBE": "Cube", + "CURL": "curl", + "CVE-TOU": "cve-tou", + "D-FSL-1.0": "D-FSL-1.0", + "DEC-3-CLAUSE": "DEC-3-Clause", + "DIFFMARK": "diffmark", + "DL-DE-BY-2.0": "DL-DE-BY-2.0", + "DL-DE-ZERO-2.0": "DL-DE-ZERO-2.0", + "DOC": "DOC", + "DOCBOOK-DTD": "DocBook-DTD", + "DOCBOOK-SCHEMA": "DocBook-Schema", + "DOCBOOK-STYLESHEET": "DocBook-Stylesheet", + "DOCBOOK-XML": "DocBook-XML", + "DOTSEQN": "Dotseqn", + "DRL-1.0": "DRL-1.0", + "DRL-1.1": "DRL-1.1", + "DSDP": "DSDP", + "DTOA": "dtoa", + "DVIPDFM": "dvipdfm", + "ECL-1.0": "ECL-1.0", + "ECL-2.0": "ECL-2.0", + "EFL-1.0": "EFL-1.0", + "EFL-2.0": "EFL-2.0", + "EGENIX": "eGenix", + "ELASTIC-2.0": "Elastic-2.0", + "ENTESSA": "Entessa", + "EPICS": "EPICS", + "EPL-1.0": "EPL-1.0", + "EPL-2.0": "EPL-2.0", + "ERLPL-1.1": "ErlPL-1.1", + "ESA-PL-PERMISSIVE-2.4": "ESA-PL-permissive-2.4", + "ESA-PL-STRONG-COPYLEFT-2.4": "ESA-PL-strong-copyleft-2.4", + "ESA-PL-WEAK-COPYLEFT-2.4": "ESA-PL-weak-copyleft-2.4", + "ETALAB-2.0": "etalab-2.0", + "EUDATAGRID": "EUDatagrid", + "EUPL-1.0": "EUPL-1.0", + "EUPL-1.1": "EUPL-1.1", + "EUPL-1.2": "EUPL-1.2", + "EUROSYM": "Eurosym", + "FAIR": "Fair", + "FBM": "FBM", + "FDK-AAC": "FDK-AAC", + "FERGUSON-TWOFISH": "Ferguson-Twofish", + "FRAMEWORX-1.0": "Frameworx-1.0", + "FREEBSD-DOC": "FreeBSD-DOC", + "FREEIMAGE": "FreeImage", + "FSFAP": "FSFAP", + "FSFAP-NO-WARRANTY-DISCLAIMER": "FSFAP-no-warranty-disclaimer", + "FSFUL": "FSFUL", + "FSFULLR": "FSFULLR", + "FSFULLRSD": "FSFULLRSD", + "FSFULLRWD": "FSFULLRWD", + "FSL-1.1-ALV2": "FSL-1.1-ALv2", + "FSL-1.1-MIT": "FSL-1.1-MIT", + "FTL": "FTL", + "FURUSETH": "Furuseth", + "FWLW": "fwlw", + "GAME-PROGRAMMING-GEMS": "Game-Programming-Gems", + "GCR-DOCS": "GCR-docs", + "GD": "GD", + "GENERIC-XTS": "generic-xts", + "GFDL-1.1-INVARIANTS-ONLY": "GFDL-1.1-invariants-only", + "GFDL-1.1-INVARIANTS-OR-LATER": "GFDL-1.1-invariants-or-later", + "GFDL-1.1-NO-INVARIANTS-ONLY": "GFDL-1.1-no-invariants-only", + "GFDL-1.1-NO-INVARIANTS-OR-LATER": "GFDL-1.1-no-invariants-or-later", + "GFDL-1.1-ONLY": "GFDL-1.1-only", + "GFDL-1.1-OR-LATER": "GFDL-1.1-or-later", + "GFDL-1.2-INVARIANTS-ONLY": "GFDL-1.2-invariants-only", + "GFDL-1.2-INVARIANTS-OR-LATER": "GFDL-1.2-invariants-or-later", + "GFDL-1.2-NO-INVARIANTS-ONLY": "GFDL-1.2-no-invariants-only", + "GFDL-1.2-NO-INVARIANTS-OR-LATER": "GFDL-1.2-no-invariants-or-later", + "GFDL-1.2-ONLY": "GFDL-1.2-only", + "GFDL-1.2-OR-LATER": "GFDL-1.2-or-later", + "GFDL-1.3-INVARIANTS-ONLY": "GFDL-1.3-invariants-only", + "GFDL-1.3-INVARIANTS-OR-LATER": "GFDL-1.3-invariants-or-later", + "GFDL-1.3-NO-INVARIANTS-ONLY": "GFDL-1.3-no-invariants-only", + "GFDL-1.3-NO-INVARIANTS-OR-LATER": "GFDL-1.3-no-invariants-or-later", + "GFDL-1.3-ONLY": "GFDL-1.3-only", + "GFDL-1.3-OR-LATER": "GFDL-1.3-or-later", + "GIFTWARE": "Giftware", + "GL2PS": "GL2PS", + "GLIDE": "Glide", + "GLULXE": "Glulxe", + "GLWTPL": "GLWTPL", + "GNUPLOT": "gnuplot", + "GPL-1.0-ONLY": "GPL-1.0-only", + "GPL-1.0-OR-LATER": "GPL-1.0-or-later", + "GPL-2.0-ONLY": "GPL-2.0-only", + "GPL-2.0-OR-LATER": "GPL-2.0-or-later", + "GPL-3.0-ONLY": "GPL-3.0-only", + "GPL-3.0-OR-LATER": "GPL-3.0-or-later", + "GRAPHICS-GEMS": "Graphics-Gems", + "GSOAP-1.3B": "gSOAP-1.3b", + "GTKBOOK": "gtkbook", + "GUTMANN": "Gutmann", + "HASKELLREPORT": "HaskellReport", + "HDF5": "HDF5", + "HDPARM": "hdparm", + "HIDAPI": "HIDAPI", + "HIPPOCRATIC-2.1": "Hippocratic-2.1", + "HP-1986": "HP-1986", + "HP-1989": "HP-1989", + "HPND": "HPND", + "HPND-DEC": "HPND-DEC", + "HPND-DOC": "HPND-doc", + "HPND-DOC-SELL": "HPND-doc-sell", + "HPND-EXPORT-US": "HPND-export-US", + "HPND-EXPORT-US-ACKNOWLEDGEMENT": "HPND-export-US-acknowledgement", + "HPND-EXPORT-US-MODIFY": "HPND-export-US-modify", + "HPND-EXPORT2-US": "HPND-export2-US", + "HPND-FENNEBERG-LIVINGSTON": "HPND-Fenneberg-Livingston", + "HPND-INRIA-IMAG": "HPND-INRIA-IMAG", + "HPND-INTEL": "HPND-Intel", + "HPND-KEVLIN-HENNEY": "HPND-Kevlin-Henney", + "HPND-MARKUS-KUHN": "HPND-Markus-Kuhn", + "HPND-MERCHANTABILITY-VARIANT": "HPND-merchantability-variant", + "HPND-MIT-DISCLAIMER": "HPND-MIT-disclaimer", + "HPND-NETREK": "HPND-Netrek", + "HPND-PBMPLUS": "HPND-Pbmplus", + "HPND-SELL-MIT-DISCLAIMER-XSERVER": "HPND-sell-MIT-disclaimer-xserver", + "HPND-SELL-REGEXPR": "HPND-sell-regexpr", + "HPND-SELL-VARIANT": "HPND-sell-variant", + "HPND-SELL-VARIANT-CRITICAL-SYSTEMS": "HPND-sell-variant-critical-systems", + "HPND-SELL-VARIANT-MIT-DISCLAIMER": "HPND-sell-variant-MIT-disclaimer", + "HPND-SELL-VARIANT-MIT-DISCLAIMER-REV": "HPND-sell-variant-MIT-disclaimer-rev", + "HPND-SMC": "HPND-SMC", + "HPND-UC": "HPND-UC", + "HPND-UC-EXPORT-US": "HPND-UC-export-US", + "HTMLTIDY": "HTMLTIDY", + "HYPHEN-BULGARIAN": "hyphen-bulgarian", + "IBM-PIBS": "IBM-pibs", + "ICU": "ICU", + "IEC-CODE-COMPONENTS-EULA": "IEC-Code-Components-EULA", + "IJG": "IJG", + "IJG-SHORT": "IJG-short", + "IMAGEMAGICK": "ImageMagick", + "IMATIX": "iMatix", + "IMLIB2": "Imlib2", + "INFO-ZIP": "Info-ZIP", + "INNER-NET-2.0": "Inner-Net-2.0", + "INNOSETUP": "InnoSetup", + "INTEL": "Intel", + "INTEL-ACPI": "Intel-ACPI", + "INTERBASE-1.0": "Interbase-1.0", + "IPA": "IPA", + "IPL-1.0": "IPL-1.0", + "ISC": "ISC", + "ISC-VEILLARD": "ISC-Veillard", + "ISO-PERMISSION": "ISO-permission", + "JAM": "Jam", + "JASPER-2.0": "JasPer-2.0", + "JOVE": "jove", + "JPL-IMAGE": "JPL-image", + "JPNIC": "JPNIC", + "JSON": "JSON", + "KASTRUP": "Kastrup", + "KAZLIB": "Kazlib", + "KNUTH-CTAN": "Knuth-CTAN", + "LAL-1.2": "LAL-1.2", + "LAL-1.3": "LAL-1.3", + "LATEX2E": "Latex2e", + "LATEX2E-TRANSLATED-NOTICE": "Latex2e-translated-notice", + "LEPTONICA": "Leptonica", + "LGPL-2.0-ONLY": "LGPL-2.0-only", + "LGPL-2.0-OR-LATER": "LGPL-2.0-or-later", + "LGPL-2.1-ONLY": "LGPL-2.1-only", + "LGPL-2.1-OR-LATER": "LGPL-2.1-or-later", + "LGPL-3.0-ONLY": "LGPL-3.0-only", + "LGPL-3.0-OR-LATER": "LGPL-3.0-or-later", + "LGPLLR": "LGPLLR", + "LIBPNG": "Libpng", + "LIBPNG-1.6.35": "libpng-1.6.35", + "LIBPNG-2.0": "libpng-2.0", + "LIBSELINUX-1.0": "libselinux-1.0", + "LIBTIFF": "libtiff", + "LIBUTIL-DAVID-NUGENT": "libutil-David-Nugent", + "LILIQ-P-1.1": "LiLiQ-P-1.1", + "LILIQ-R-1.1": "LiLiQ-R-1.1", + "LILIQ-RPLUS-1.1": "LiLiQ-Rplus-1.1", + "LINUX-MAN-PAGES-1-PARA": "Linux-man-pages-1-para", + "LINUX-MAN-PAGES-COPYLEFT": "Linux-man-pages-copyleft", + "LINUX-MAN-PAGES-COPYLEFT-2-PARA": "Linux-man-pages-copyleft-2-para", + "LINUX-MAN-PAGES-COPYLEFT-VAR": "Linux-man-pages-copyleft-var", + "LINUX-OPENIB": "Linux-OpenIB", + "LOOP": "LOOP", + "LPD-DOCUMENT": "LPD-document", + "LPL-1.0": "LPL-1.0", + "LPL-1.02": "LPL-1.02", + "LPPL-1.0": "LPPL-1.0", + "LPPL-1.1": "LPPL-1.1", + "LPPL-1.2": "LPPL-1.2", + "LPPL-1.3A": "LPPL-1.3a", + "LPPL-1.3C": "LPPL-1.3c", + "LSOF": "lsof", + "LUCIDA-BITMAP-FONTS": "Lucida-Bitmap-Fonts", + "LZMA-SDK-9.11-TO-9.20": "LZMA-SDK-9.11-to-9.20", + "LZMA-SDK-9.22": "LZMA-SDK-9.22", + "MACKERRAS-3-CLAUSE": "Mackerras-3-Clause", + "MACKERRAS-3-CLAUSE-ACKNOWLEDGMENT": "Mackerras-3-Clause-acknowledgment", + "MAGAZ": "magaz", + "MAILPRIO": "mailprio", + "MAKEINDEX": "MakeIndex", + "MAN2HTML": "man2html", + "MARTIN-BIRGMEIER": "Martin-Birgmeier", + "MCPHEE-SLIDESHOW": "McPhee-slideshow", + "METAMAIL": "metamail", + "MINPACK": "Minpack", + "MIPS": "MIPS", + "MIROS": "MirOS", + "MIT": "MIT", + "MIT-0": "MIT-0", + "MIT-ADVERTISING": "MIT-advertising", + "MIT-CLICK": "MIT-Click", + "MIT-CMU": "MIT-CMU", + "MIT-ENNA": "MIT-enna", + "MIT-FEH": "MIT-feh", + "MIT-FESTIVAL": "MIT-Festival", + "MIT-KHRONOS-OLD": "MIT-Khronos-old", + "MIT-MODERN-VARIANT": "MIT-Modern-Variant", + "MIT-OPEN-GROUP": "MIT-open-group", + "MIT-STK": "MIT-STK", + "MIT-TESTREGEX": "MIT-testregex", + "MIT-WU": "MIT-Wu", + "MITNFA": "MITNFA", + "MMIXWARE": "MMIXware", + "MMPL-1.0.1": "MMPL-1.0.1", + "MOTOSOTO": "Motosoto", + "MPEG-SSG": "MPEG-SSG", + "MPI-PERMISSIVE": "mpi-permissive", + "MPICH2": "mpich2", + "MPL-1.0": "MPL-1.0", + "MPL-1.1": "MPL-1.1", + "MPL-2.0": "MPL-2.0", + "MPL-2.0-NO-COPYLEFT-EXCEPTION": "MPL-2.0-no-copyleft-exception", + "MPLUS": "mplus", + "MS-LPL": "MS-LPL", + "MS-PL": "MS-PL", + "MS-RL": "MS-RL", + "MTLL": "MTLL", + "MULANPSL-1.0": "MulanPSL-1.0", + "MULANPSL-2.0": "MulanPSL-2.0", + "MULTICS": "Multics", + "MUP": "Mup", + "NAIST-2003": "NAIST-2003", + "NASA-1.3": "NASA-1.3", + "NAUMEN": "Naumen", + "NBPL-1.0": "NBPL-1.0", + "NCBI-PD": "NCBI-PD", + "NCGL-UK-2.0": "NCGL-UK-2.0", + "NCL": "NCL", + "NCSA": "NCSA", + "NETCDF": "NetCDF", + "NEWSLETR": "Newsletr", + "NGPL": "NGPL", + "NGREP": "ngrep", + "NICTA-1.0": "NICTA-1.0", + "NIST-PD": "NIST-PD", + "NIST-PD-FALLBACK": "NIST-PD-fallback", + "NIST-PD-TNT": "NIST-PD-TNT", + "NIST-SOFTWARE": "NIST-Software", + "NLOD-1.0": "NLOD-1.0", + "NLOD-2.0": "NLOD-2.0", + "NLPL": "NLPL", + "NOKIA": "Nokia", + "NOSL": "NOSL", + "NOWEB": "Noweb", + "NPL-1.0": "NPL-1.0", + "NPL-1.1": "NPL-1.1", + "NPOSL-3.0": "NPOSL-3.0", + "NRL": "NRL", + "NTIA-PD": "NTIA-PD", + "NTP": "NTP", + "NTP-0": "NTP-0", + "O-UDA-1.0": "O-UDA-1.0", + "OAR": "OAR", + "OCCT-PL": "OCCT-PL", + "OCLC-2.0": "OCLC-2.0", + "ODBL-1.0": "ODbL-1.0", + "ODC-BY-1.0": "ODC-By-1.0", + "OFFIS": "OFFIS", + "OFL-1.0": "OFL-1.0", + "OFL-1.0-NO-RFN": "OFL-1.0-no-RFN", + "OFL-1.0-RFN": "OFL-1.0-RFN", + "OFL-1.1": "OFL-1.1", + "OFL-1.1-NO-RFN": "OFL-1.1-no-RFN", + "OFL-1.1-RFN": "OFL-1.1-RFN", + "OGC-1.0": "OGC-1.0", + "OGDL-TAIWAN-1.0": "OGDL-Taiwan-1.0", + "OGL-CANADA-2.0": "OGL-Canada-2.0", + "OGL-UK-1.0": "OGL-UK-1.0", + "OGL-UK-2.0": "OGL-UK-2.0", + "OGL-UK-3.0": "OGL-UK-3.0", + "OGTSL": "OGTSL", + "OLDAP-1.1": "OLDAP-1.1", + "OLDAP-1.2": "OLDAP-1.2", + "OLDAP-1.3": "OLDAP-1.3", + "OLDAP-1.4": "OLDAP-1.4", + "OLDAP-2.0": "OLDAP-2.0", + "OLDAP-2.0.1": "OLDAP-2.0.1", + "OLDAP-2.1": "OLDAP-2.1", + "OLDAP-2.2": "OLDAP-2.2", + "OLDAP-2.2.1": "OLDAP-2.2.1", + "OLDAP-2.2.2": "OLDAP-2.2.2", + "OLDAP-2.3": "OLDAP-2.3", + "OLDAP-2.4": "OLDAP-2.4", + "OLDAP-2.5": "OLDAP-2.5", + "OLDAP-2.6": "OLDAP-2.6", + "OLDAP-2.7": "OLDAP-2.7", + "OLDAP-2.8": "OLDAP-2.8", + "OLFL-1.3": "OLFL-1.3", + "OML": "OML", + "OPENMDW-1.0": "OpenMDW-1.0", + "OPENPBS-2.3": "OpenPBS-2.3", + "OPENSSL": "OpenSSL", + "OPENSSL-STANDALONE": "OpenSSL-standalone", + "OPENVISION": "OpenVision", + "OPL-1.0": "OPL-1.0", + "OPL-UK-3.0": "OPL-UK-3.0", + "OPUBL-1.0": "OPUBL-1.0", + "OSC-1.0": "OSC-1.0", + "OSET-PL-2.1": "OSET-PL-2.1", + "OSL-1.0": "OSL-1.0", + "OSL-1.1": "OSL-1.1", + "OSL-2.0": "OSL-2.0", + "OSL-2.1": "OSL-2.1", + "OSL-3.0": "OSL-3.0", + "OSSP": "OSSP", + "PADL": "PADL", + "PARATYPE-FREE-FONT-1.3": "ParaType-Free-Font-1.3", + "PARITY-6.0.0": "Parity-6.0.0", + "PARITY-7.0.0": "Parity-7.0.0", + "PDDL-1.0": "PDDL-1.0", + "PHP-3.0": "PHP-3.0", + "PHP-3.01": "PHP-3.01", + "PIXAR": "Pixar", + "PKGCONF": "pkgconf", + "PLEXUS": "Plexus", + "PNMSTITCH": "pnmstitch", + "POLYFORM-NONCOMMERCIAL-1.0.0": "PolyForm-Noncommercial-1.0.0", + "POLYFORM-SMALL-BUSINESS-1.0.0": "PolyForm-Small-Business-1.0.0", + "POSTGRESQL": "PostgreSQL", + "PPL": "PPL", + "PSF-2.0": "PSF-2.0", + "PSFRAG": "psfrag", + "PSUTILS": "psutils", + "PYTHON-2.0": "Python-2.0", + "PYTHON-2.0.1": "Python-2.0.1", + "PYTHON-LDAP": "python-ldap", + "QHULL": "Qhull", + "QPL-1.0": "QPL-1.0", + "QPL-1.0-INRIA-2004": "QPL-1.0-INRIA-2004", + "RADVD": "radvd", + "RDISC": "Rdisc", + "RHECOS-1.1": "RHeCos-1.1", + "RPL-1.1": "RPL-1.1", + "RPL-1.5": "RPL-1.5", + "RPSL-1.0": "RPSL-1.0", + "RSA-MD": "RSA-MD", + "RSCPL": "RSCPL", + "RUBY": "Ruby", + "RUBY-PTY": "Ruby-pty", + "SAX-PD": "SAX-PD", + "SAX-PD-2.0": "SAX-PD-2.0", + "SAXPATH": "Saxpath", + "SCEA": "SCEA", + "SCHEMEREPORT": "SchemeReport", + "SENDMAIL": "Sendmail", + "SENDMAIL-8.23": "Sendmail-8.23", + "SENDMAIL-OPEN-SOURCE-1.1": "Sendmail-Open-Source-1.1", + "SGI-B-1.0": "SGI-B-1.0", + "SGI-B-1.1": "SGI-B-1.1", + "SGI-B-2.0": "SGI-B-2.0", + "SGI-OPENGL": "SGI-OpenGL", + "SGMLUG-PM": "SGMLUG-PM", + "SGP4": "SGP4", + "SHL-0.5": "SHL-0.5", + "SHL-0.51": "SHL-0.51", + "SIMPL-2.0": "SimPL-2.0", + "SISSL": "SISSL", + "SISSL-1.2": "SISSL-1.2", + "SL": "SL", + "SLEEPYCAT": "Sleepycat", + "SMAIL-GPL": "SMAIL-GPL", + "SMLNJ": "SMLNJ", + "SMPPL": "SMPPL", + "SNIA": "SNIA", + "SNPRINTF": "snprintf", + "SOFA": "SOFA", + "SOFTSURFER": "softSurfer", + "SOUNDEX": "Soundex", + "SPENCER-86": "Spencer-86", + "SPENCER-94": "Spencer-94", + "SPENCER-99": "Spencer-99", + "SPL-1.0": "SPL-1.0", + "SSH-KEYSCAN": "ssh-keyscan", + "SSH-OPENSSH": "SSH-OpenSSH", + "SSH-SHORT": "SSH-short", + "SSLEAY-STANDALONE": "SSLeay-standalone", + "SSPL-1.0": "SSPL-1.0", + "SUGARCRM-1.1.3": "SugarCRM-1.1.3", + "SUL-1.0": "SUL-1.0", + "SUN-PPP": "Sun-PPP", + "SUN-PPP-2000": "Sun-PPP-2000", + "SUNPRO": "SunPro", + "SWL": "SWL", + "SWRULE": "swrule", + "SYMLINKS": "Symlinks", + "TAPR-OHL-1.0": "TAPR-OHL-1.0", + "TCL": "TCL", + "TCP-WRAPPERS": "TCP-wrappers", + "TEKHVC": "TekHVC", + "TERMREADKEY": "TermReadKey", + "TGPPL-1.0": "TGPPL-1.0", + "THIRDEYE": "ThirdEye", + "THREEPARTTABLE": "threeparttable", + "TMATE": "TMate", + "TORQUE-1.1": "TORQUE-1.1", + "TOSL": "TOSL", + "TPDL": "TPDL", + "TPL-1.0": "TPL-1.0", + "TRUSTEDQSL": "TrustedQSL", + "TTWL": "TTWL", + "TTYP0": "TTYP0", + "TU-BERLIN-1.0": "TU-Berlin-1.0", + "TU-BERLIN-2.0": "TU-Berlin-2.0", + "UBUNTU-FONT-1.0": "Ubuntu-font-1.0", + "UCAR": "UCAR", + "UCL-1.0": "UCL-1.0", + "ULEM": "ulem", + "UMICH-MERIT": "UMich-Merit", + "UNICODE-3.0": "Unicode-3.0", + "UNICODE-DFS-2015": "Unicode-DFS-2015", + "UNICODE-DFS-2016": "Unicode-DFS-2016", + "UNICODE-TOU": "Unicode-TOU", + "UNIXCRYPT": "UnixCrypt", + "UNLICENSE": "Unlicense", + "UNLICENSE-LIBTELNET": "Unlicense-libtelnet", + "UNLICENSE-LIBWHIRLPOOL": "Unlicense-libwhirlpool", + "UNRAR": "UnRAR", + "UPL-1.0": "UPL-1.0", + "URT-RLE": "URT-RLE", + "VIM": "Vim", + "VIXIE-CRON": "Vixie-Cron", + "VOSTROM": "VOSTROM", + "VSL-1.0": "VSL-1.0", + "W3C": "W3C", + "W3C-19980720": "W3C-19980720", + "W3C-20150513": "W3C-20150513", + "W3M": "w3m", + "WATCOM-1.0": "Watcom-1.0", + "WIDGET-WORKSHOP": "Widget-Workshop", + "WORDNET": "WordNet", + "WSUIPA": "Wsuipa", + "WTFNMFPL": "WTFNMFPL", + "WTFPL": "WTFPL", + "WWL": "wwl", + "X11": "X11", + "X11-DISTRIBUTE-MODIFICATIONS-VARIANT": "X11-distribute-modifications-variant", + "X11-NO-PERMIT-PERSONS": "X11-no-permit-persons", + "X11-SWAPPED": "X11-swapped", + "XDEBUG-1.03": "Xdebug-1.03", + "XEROX": "Xerox", + "XFIG": "Xfig", + "XFREE86-1.1": "XFree86-1.1", + "XINETD": "xinetd", + "XKEYBOARD-CONFIG-ZINOVIEV": "xkeyboard-config-Zinoviev", + "XLOCK": "xlock", + "XNET": "Xnet", + "XPP": "xpp", + "XSKAT": "XSkat", + "XZOOM": "xzoom", + "YPL-1.0": "YPL-1.0", + "YPL-1.1": "YPL-1.1", + "ZED": "Zed", + "ZEEFF": "Zeeff", + "ZEND-2.0": "Zend-2.0", + "ZIMBRA-1.3": "Zimbra-1.3", + "ZIMBRA-1.4": "Zimbra-1.4", + "ZLIB": "Zlib", + "ZLIB-ACKNOWLEDGEMENT": "zlib-acknowledgement", + "ZPL-1.1": "ZPL-1.1", + "ZPL-2.0": "ZPL-2.0", + "ZPL-2.1": "ZPL-2.1", +} + +// GetLicensesMap returns a map of active license IDs keyed by uppercase ID. +func GetLicensesMap() map[string]string { + return licensesMap +} From 936c645af63ea5d36c92c48d597877471caa76dd Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 09:35:52 -0400 Subject: [PATCH 06/14] add separate cases for caseinsensitive and extra space --- spdxexp/benchmark_satisfies_test.go | 3 ++- spdxexp/benchmark_validate_licenses_test.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/spdxexp/benchmark_satisfies_test.go b/spdxexp/benchmark_satisfies_test.go index 7d7f341..e83cef0 100644 --- a/spdxexp/benchmark_satisfies_test.go +++ b/spdxexp/benchmark_satisfies_test.go @@ -13,7 +13,8 @@ type satisfiesBenchmarkScenario struct { var satisfiesBenchmarkScenarios = []satisfiesBenchmarkScenario{ // Scenario order is used as-is in the summary table. {"MIT--exact", "MIT"}, - {"mit--caseinsensitive", " mit "}, + {"mit--caseinsensitive", "mit"}, + {"mit--extra-space", " MIT "}, {"Apache-2.0--active-early", "Apache-2.0"}, {"Zed--active-end", "Zed"}, {"MIT AND Apache-2.0--complex", "MIT AND Apache-2.0"}, diff --git a/spdxexp/benchmark_validate_licenses_test.go b/spdxexp/benchmark_validate_licenses_test.go index 12861f1..2742e2c 100644 --- a/spdxexp/benchmark_validate_licenses_test.go +++ b/spdxexp/benchmark_validate_licenses_test.go @@ -13,7 +13,8 @@ type validateLicensesBenchmarkScenario struct { var validateLicensesBenchmarkScenarios = []validateLicensesBenchmarkScenario{ // Scenario order is used as-is in the summary table. {"MIT--exact", []string{"MIT"}}, - {"mit--caseinsensitive", []string{" mit "}}, + {"mit--caseinsensitive", []string{"mit"}}, + {"mit--extra-space", []string{" MIT "}}, {"Apache-2.0--active-early", []string{"Apache-2.0"}}, {"Zed--active-end", []string{"Zed"}}, {"MIT AND Apache-2.0--complex", []string{"MIT", "Apache-2.0"}}, From b28ea8b61edaa9dab97253b846d2af72f41c9224 Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 09:36:28 -0400 Subject: [PATCH 07/14] optimize for "MIT" letting activeLicense find " MIT " with extra space --- spdxexp/satisfies.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spdxexp/satisfies.go b/spdxexp/satisfies.go index 2080eec..96a5836 100644 --- a/spdxexp/satisfies.go +++ b/spdxexp/satisfies.go @@ -37,12 +37,16 @@ func ValidateLicensesWithOptions(licenses []string, options ValidateLicensesOpti valid := true invalidLicenses := []string{} for _, license := range licenses { - license = strings.TrimSpace(license) - + // By putting the isMIT check here, we can avoid the overhead of parsing for the most common case of MIT. + // Having it before trimming means that licenses with leading/trailing whitespace will not be validated + // as MIT by isMIT, but will still be correctly identified using activeLicense. As this is uncommon, it + // is an acceptable tradeoff to avoid the overhead of trimming for the more common case. if isMIT(license) { continue } + license = strings.TrimSpace(license) + isAtomic := isAtomicLicense(license) if isAtomic { if ok, _ := activeLicense(license); ok { From 2d1b7912e7744e65b8df698b3b523c7f3494d72f Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 11:16:11 -0400 Subject: [PATCH 08/14] fix linter error --- spdxexp/satisfies.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spdxexp/satisfies.go b/spdxexp/satisfies.go index 96a5836..a4627fd 100644 --- a/spdxexp/satisfies.go +++ b/spdxexp/satisfies.go @@ -58,10 +58,9 @@ func ValidateLicensesWithOptions(licenses []string, options ValidateLicensesOpti valid = false invalidLicenses = append(invalidLicenses, license) continue - } else { - // if not failing deprecated licenses, then consider it valid and continue - continue } + // if FailDeprecatedLicenses is false, then consider the deprecated license valid and continue + continue } if options.FailAllLicenseRefs { From 02fc36ab238ad52728c57440951f87ad033e08dd Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 13:04:09 -0400 Subject: [PATCH 09/14] Update cmd/doc.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- cmd/doc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/doc.go b/cmd/doc.go index 3e00eb9..33da144 100644 --- a/cmd/doc.go +++ b/cmd/doc.go @@ -10,7 +10,7 @@ spdxexp/license.go file. Command to run all extractions (run command from the /cmd directory): - cd cmd + cd cmd go run . extract -l -e Usage options: From 503f295beb547db86ce61846117533e7f6d3041c Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 13:05:47 -0400 Subject: [PATCH 10/14] Update spdxexp/satisfies_test.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- spdxexp/satisfies_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spdxexp/satisfies_test.go b/spdxexp/satisfies_test.go index 7fd953d..a73c33d 100644 --- a/spdxexp/satisfies_test.go +++ b/spdxexp/satisfies_test.go @@ -2679,8 +2679,8 @@ func ExampleValidateLicenses_allBad() { // Output: false [MTI Apache--2.0 GPL] } -// TestValidateLicenses_BenchmarkExamples is a safety check to ensure benchmark emprovements are not due -// to changes behavior of ValidateLicenses function. +// TestValidateLicenses_BenchmarkExamples is a safety check to ensure benchmark improvements are not due +// to changes in behavior of the ValidateLicenses function. func TestValidateLicenses_BenchmarkExamples(t *testing.T) { // This test is used to verify that the test expressions used in the benchmarks return expected results. // If any of the test expressions are invalid, then there is likely an issue with the benchmark results and investigation would be needed. From fd0ec02d2cf500c058e92bf8ba0e2c2866d9ac6d Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 13:42:52 -0400 Subject: [PATCH 11/14] fix exception check to treat deprecated licenses as valid unless options configured to reject add test that would have caught this --- spdxexp/satisfies.go | 9 ++++-- spdxexp/satisfies_test.go | 64 +++++++++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/spdxexp/satisfies.go b/spdxexp/satisfies.go index a4627fd..b2ab1f2 100644 --- a/spdxexp/satisfies.go +++ b/spdxexp/satisfies.go @@ -85,10 +85,15 @@ func ValidateLicensesWithOptions(licenses []string, options ValidateLicensesOpti if !isAtomic { if hasException, licensePart, exceptionPart := isLicenseWithException(license); hasException { // matches pattern "licensePart WITH exceptionPart", so validate both parts separately - if ok, _ := activeLicense(licensePart); ok { - if ok, _ := exceptionLicense(exceptionPart); ok { + if ok, _ := exceptionLicense(exceptionPart); ok { + if ok, _ := activeLicense(licensePart); ok { continue } + if !options.FailDeprecatedLicenses { + if ok, _ := deprecatedLicense(licensePart); ok { + continue + } + } } valid = false invalidLicenses = append(invalidLicenses, license) diff --git a/spdxexp/satisfies_test.go b/spdxexp/satisfies_test.go index a73c33d..29c0afe 100644 --- a/spdxexp/satisfies_test.go +++ b/spdxexp/satisfies_test.go @@ -87,18 +87,58 @@ func TestValidateLicensesWithOptions_FailComplexExpressions(t *testing.T) { func TestValidateLicensesWithOptions_FailDeprecatedLicenses(t *testing.T) { // eCos-2.0 is a known deprecated SPDX license ID (see TestDeprecatedLicense). - license := "eCos-2.0" - - valid, invalidLicenses := ValidateLicensesWithOptions([]string{license}, ValidateLicensesOptions{}) - assert.True(t, valid) - assert.Empty(t, invalidLicenses) - - valid, invalidLicenses = ValidateLicensesWithOptions( - []string{license}, - ValidateLicensesOptions{FailDeprecatedLicenses: true}, - ) - assert.False(t, valid) - assert.EqualValues(t, []string{license}, invalidLicenses) + deprecatedLicense := "eCos-2.0" + + tests := []struct { + name string + inputLicenses []string + options ValidateLicensesOptions + allValid bool + invalidLicenses []string + }{ + { + name: "Deprecated license rejected", + inputLicenses: []string{deprecatedLicense}, + options: ValidateLicensesOptions{FailDeprecatedLicenses: true}, + allValid: false, + invalidLicenses: []string{ + deprecatedLicense, + }, + }, + { + name: "Mixed list rejects only deprecated licenses", + inputLicenses: []string{"MIT", "Apache-2.0", deprecatedLicense}, + options: ValidateLicensesOptions{FailDeprecatedLicenses: true}, + allValid: false, + invalidLicenses: []string{ + deprecatedLicense, + }, + }, + { + name: "WITH exception rejects deprecated license if FailDeprecatedLicenses is true", + inputLicenses: []string{deprecatedLicense + " WITH Bison-exception-2.2"}, + options: ValidateLicensesOptions{FailDeprecatedLicenses: true}, + allValid: false, + invalidLicenses: []string{ + deprecatedLicense + " WITH Bison-exception-2.2", + }, + }, + { + name: "WITH exception allows deprecated license if FailDeprecatedLicenses is false", + inputLicenses: []string{deprecatedLicense + " WITH Bison-exception-2.2"}, + options: ValidateLicensesOptions{FailDeprecatedLicenses: false}, + allValid: true, + invalidLicenses: []string{}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + valid, invalidLicenses := ValidateLicensesWithOptions(test.inputLicenses, test.options) + assert.EqualValues(t, test.invalidLicenses, invalidLicenses) + assert.Equal(t, test.allValid, valid) + }) + } } func TestValidateLicensesWithOptions_AllOptions(t *testing.T) { From 364dd9a1445a2f7bd7d0a4c1c12488888f83bccb Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 13:52:30 -0400 Subject: [PATCH 12/14] remove comment that isMIT ignore whitespace --- spdxexp/satisfies.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/spdxexp/satisfies.go b/spdxexp/satisfies.go index b2ab1f2..d714b3c 100644 --- a/spdxexp/satisfies.go +++ b/spdxexp/satisfies.go @@ -37,6 +37,7 @@ func ValidateLicensesWithOptions(licenses []string, options ValidateLicensesOpti valid := true invalidLicenses := []string{} for _, license := range licenses { + // MIT is the most common license, so check for it first before doing any processing to optimize for this case. // By putting the isMIT check here, we can avoid the overhead of parsing for the most common case of MIT. // Having it before trimming means that licenses with leading/trailing whitespace will not be validated // as MIT by isMIT, but will still be correctly identified using activeLicense. As this is uncommon, it @@ -127,9 +128,11 @@ func Satisfies(testExpression string, allowedList []string) (bool, error) { return false, errors.New("allowedList requires at least one element, but is empty") } - testExpression = strings.TrimSpace(testExpression) - - // simple check for MIT covers the most common case and avoids the overhead of parsing the testExpression + // MIT is the most common license, so check for it first before doing any processing to optimize for this case. + // By putting the isMIT check here, we can avoid the overhead of parsing for the most common case of MIT. + // Having it before trimming means that licenses with leading/trailing whitespace will not be validated + // as MIT by isMIT, but will still be correctly identified using activeLicense. As this is uncommon, it + // is an acceptable tradeoff to avoid the overhead of trimming for the more common case. if isMIT(testExpression) { for _, allowed := range allowedList { if strings.EqualFold(allowed, "MIT") { @@ -139,6 +142,8 @@ func Satisfies(testExpression string, allowedList []string) (bool, error) { return false, nil } + testExpression = strings.TrimSpace(testExpression) + if isAtomicLicense(testExpression) { // if only one license in the test expression, check for active license to avoid the overhead of parsing if ok, _ := activeLicense(testExpression); ok { @@ -213,7 +218,7 @@ func stringsToNodes(licenseStrings []string) ([]*node, error) { return nodes, nil } -// isMIT checks if the test expression is MIT, ignoring case and leading/trailing whitespace. +// isMIT checks if the test expression is MIT, ignoring case. // NOTE: Caller should trim the test expression before calling this function to avoid false // negatives (e.g. " MIT " would not match "MIT"). func isMIT(testExpression string) bool { From 609007dc15cf4a2f74017b12415a40cb0f65d8dd Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 14:25:24 -0400 Subject: [PATCH 13/14] use strings.Fields to split exception expressions --- spdxexp/satisfies.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spdxexp/satisfies.go b/spdxexp/satisfies.go index d714b3c..4f7c59c 100644 --- a/spdxexp/satisfies.go +++ b/spdxexp/satisfies.go @@ -238,7 +238,7 @@ func isAtomicLicense(testExpression string) bool { // negatives (e.g. " MIT " would not be considered a single license). func isLicenseWithException(testExpression string) (bool, string, string) { // split by " " and check if there are exactly 3 parts and the middle part is "WITH" - parts := strings.Split(testExpression, " ") + parts := strings.Fields(testExpression) if len(parts) == 3 && strings.EqualFold(parts[1], "WITH") { return true, parts[0], parts[2] } From c35ff9356c8ba254a2dc3a8847cc15c38581d914 Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Thu, 16 Apr 2026 15:11:16 -0400 Subject: [PATCH 14/14] do not expose license maps also corrects formatting issues and puts public functions at top of generated files so they are easier to find --- cmd/exceptions.go | 32 +- cmd/license.go | 63 +- spdxexp/license.go | 15 +- spdxexp/satisfies.go | 3 +- spdxexp/satisfies_test.go | 10 +- spdxexp/spdxlicenses/get_deprecated.go | 90 +- spdxexp/spdxlicenses/get_exceptions.go | 192 ++-- spdxexp/spdxlicenses/get_licenses.go | 1416 ++++++++++++------------ 8 files changed, 962 insertions(+), 859 deletions(-) diff --git a/cmd/exceptions.go b/cmd/exceptions.go index 9674c40..bc094f2 100644 --- a/cmd/exceptions.go +++ b/cmd/exceptions.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "go/format" "os" "strings" ) @@ -55,6 +56,27 @@ func extractExceptionLicenseIDs() error { // Code generated by go-spdx cmd/exceptions.go. DO NOT EDIT. // Source: https://github.com/spdx/license-list-data specifies official SPDX license list. +import "strings" + +// IsException does a case-insensitive lookup for the exception id in the exceptions map. +// It returns true and the case-sensitive ID if found, otherwise false and the original id. +func IsException(id string) (bool, string) { + foundID, ok := exceptionsMap[strings.ToUpper(id)] + if ok { + return true, foundID + } + return false, id +} + +// GetExceptionsMap returns a map of exception license IDs keyed by uppercase ID. +func GetExceptionsMap() map[string]string { + copied := make(map[string]string, len(exceptionsMap)) + for k, v := range exceptionsMap { + copied[k] = v + } + return copied +} + // GetExceptions returns a slice of exception license IDs. func GetExceptions() []string { return []string{ @@ -75,13 +97,13 @@ func GetExceptions() []string { `...) } getExceptionsContents = append(getExceptionsContents, `} - -// GetExceptionsMap returns a map of exception license IDs keyed by uppercase ID. -func GetExceptionsMap() map[string]string { - return exceptionsMap -} `...) + getExceptionsContents, err = format.Source(getExceptionsContents) + if err != nil { + return fmt.Errorf("format generated get_exceptions.go: %w", err) + } + err = os.WriteFile("../spdxexp/spdxlicenses/get_exceptions.go", getExceptionsContents, 0600) if err != nil { return err diff --git a/cmd/license.go b/cmd/license.go index 6adf391..22f1366 100644 --- a/cmd/license.go +++ b/cmd/license.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "go/format" "os" "strings" ) @@ -60,6 +61,27 @@ func extractLicenseIDs() error { // Code generated by go-spdx cmd/license.go. DO NOT EDIT. // Source: https://github.com/spdx/license-list-data specifies official SPDX license list. +import "strings" + +// IsActiveLicense does a case-insensitive lookup for the license id in the active licenses map. +// It returns true and the case-sensitive ID if found, otherwise false and the original id. +func IsActiveLicense(id string) (bool, string) { + foundID, ok := licensesMap[strings.ToUpper(id)] + if ok { + return true, foundID + } + return false, id +} + +// GetLicensesMap returns a map of active license IDs keyed by uppercase ID. +func GetLicensesMap() map[string]string { + copied := make(map[string]string, len(licensesMap)) + for k, v := range licensesMap { + copied[k] = v + } + return copied +} + // GetLicenses returns a slice of active license IDs. func GetLicenses() []string { return []string{ @@ -80,13 +102,13 @@ func GetLicenses() []string { `...) } getLicensesContents = append(getLicensesContents, `} - -// GetLicensesMap returns a map of active license IDs keyed by uppercase ID. -func GetLicensesMap() map[string]string { - return licensesMap -} `...) + getLicensesContents, err = format.Source(getLicensesContents) + if err != nil { + return fmt.Errorf("format generated get_licenses.go: %w", err) + } + err = os.WriteFile("../spdxexp/spdxlicenses/get_licenses.go", getLicensesContents, 0600) if err != nil { return err @@ -99,6 +121,27 @@ func GetLicensesMap() map[string]string { // Code generated by go-spdx cmd/license.go. DO NOT EDIT. // Source: https://github.com/spdx/license-list-data specifies official SPDX license list. +import "strings" + +// IsDeprecatedLicense does a case-insensitive lookup for the license id in the deprecated licenses map. +// It returns true and the case-sensitive ID if found, otherwise false and the original id. +func IsDeprecatedLicense(id string) (bool, string) { + foundID, ok := deprecatedMap[strings.ToUpper(id)] + if ok { + return true, foundID + } + return false, id +} + +// GetDeprecatedMap returns a map of deprecated license IDs keyed by uppercase ID. +func GetDeprecatedMap() map[string]string { + copied := make(map[string]string, len(deprecatedMap)) + for k, v := range deprecatedMap { + copied[k] = v + } + return copied +} + // GetDeprecated returns a slice of deprecated license IDs. func GetDeprecated() []string { return []string{ @@ -119,13 +162,13 @@ func GetDeprecated() []string { `...) } getDeprecatedContents = append(getDeprecatedContents, `} - -// GetDeprecatedMap returns a map of deprecated license IDs keyed by uppercase ID. -func GetDeprecatedMap() map[string]string { - return deprecatedMap -} `...) + getDeprecatedContents, err = format.Source(getDeprecatedContents) + if err != nil { + return fmt.Errorf("format generated get_deprecated.go: %w", err) + } + err = os.WriteFile("../spdxexp/spdxlicenses/get_deprecated.go", getDeprecatedContents, 0600) if err != nil { return err diff --git a/spdxexp/license.go b/spdxexp/license.go index 822c0a4..be8e26c 100644 --- a/spdxexp/license.go +++ b/spdxexp/license.go @@ -8,7 +8,7 @@ import ( // activeLicense returns true if the id is an active license. func activeLicense(id string) (bool, string) { - return inLicenseList(spdxlicenses.GetLicensesMap(), id) + return spdxlicenses.IsActiveLicense(id) } // ActiveLicense returns true if the id is an active license. @@ -18,21 +18,12 @@ func ActiveLicense(id string) (bool, string) { // deprecatedLicense returns true if the id is a deprecated license. func deprecatedLicense(id string) (bool, string) { - return inLicenseList(spdxlicenses.GetDeprecatedMap(), id) + return spdxlicenses.IsDeprecatedLicense(id) } // exceptionLicense returns true if the id is an exception license. func exceptionLicense(id string) (bool, string) { - return inLicenseList(spdxlicenses.GetExceptionsMap(), id) -} - -// inLicenseList looks for id in the list of licenses. The check is case-insensitive (e.g. "mit" will match "MIT"). -func inLicenseList(licenses map[string]string, id string) (bool, string) { - foundID, ok := licenses[strings.ToUpper(id)] - if ok { - return true, foundID - } - return false, id + return spdxlicenses.IsException(id) } const ( diff --git a/spdxexp/satisfies.go b/spdxexp/satisfies.go index 4f7c59c..5ad0d60 100644 --- a/spdxexp/satisfies.go +++ b/spdxexp/satisfies.go @@ -93,7 +93,7 @@ func ValidateLicensesWithOptions(licenses []string, options ValidateLicensesOpti if !options.FailDeprecatedLicenses { if ok, _ := deprecatedLicense(licensePart); ok { continue - } + } } } valid = false @@ -245,7 +245,6 @@ func isLicenseWithException(testExpression string) (bool, string, string) { return false, "", "" } - // isCompatible checks if expressionPart is compatible with allowed list. // Expression part is an array of licenses that are ANDed together. // Allowed is an array of licenses that can fulfill the expression. diff --git a/spdxexp/satisfies_test.go b/spdxexp/satisfies_test.go index 29c0afe..cae9fce 100644 --- a/spdxexp/satisfies_test.go +++ b/spdxexp/satisfies_test.go @@ -115,10 +115,10 @@ func TestValidateLicensesWithOptions_FailDeprecatedLicenses(t *testing.T) { }, }, { - name: "WITH exception rejects deprecated license if FailDeprecatedLicenses is true", - inputLicenses: []string{deprecatedLicense + " WITH Bison-exception-2.2"}, - options: ValidateLicensesOptions{FailDeprecatedLicenses: true}, - allValid: false, + name: "WITH exception rejects deprecated license if FailDeprecatedLicenses is true", + inputLicenses: []string{deprecatedLicense + " WITH Bison-exception-2.2"}, + options: ValidateLicensesOptions{FailDeprecatedLicenses: true}, + allValid: false, invalidLicenses: []string{ deprecatedLicense + " WITH Bison-exception-2.2", }, @@ -250,7 +250,7 @@ func TestSatisfies_FastPathValidation(t *testing.T) { allowedList []string satisfied bool expectErr bool - expectedErr string + expectedErr string }{ { name: "MIT trims whitespace", diff --git a/spdxexp/spdxlicenses/get_deprecated.go b/spdxexp/spdxlicenses/get_deprecated.go index 4bd1fb4..0f0d386 100644 --- a/spdxexp/spdxlicenses/get_deprecated.go +++ b/spdxexp/spdxlicenses/get_deprecated.go @@ -3,6 +3,27 @@ package spdxlicenses // Code generated by go-spdx cmd/license.go. DO NOT EDIT. // Source: https://github.com/spdx/license-list-data specifies official SPDX license list. +import "strings" + +// IsDeprecatedLicense does a case-insensitive lookup for the license id in the deprecated licenses map. +// It returns true and the case-sensitive ID if found, otherwise false and the original id. +func IsDeprecatedLicense(id string) (bool, string) { + foundID, ok := deprecatedMap[strings.ToUpper(id)] + if ok { + return true, foundID + } + return false, id +} + +// GetDeprecatedMap returns a map of deprecated license IDs keyed by uppercase ID. +func GetDeprecatedMap() map[string]string { + copied := make(map[string]string, len(deprecatedMap)) + for k, v := range deprecatedMap { + copied[k] = v + } + return copied +} + // GetDeprecated returns a slice of deprecated license IDs. func GetDeprecated() []string { return []string{ @@ -42,41 +63,36 @@ func GetDeprecated() []string { } var deprecatedMap = map[string]string{ - "AGPL-1.0": "AGPL-1.0", - "AGPL-3.0": "AGPL-3.0", - "BSD-2-CLAUSE-FREEBSD": "BSD-2-Clause-FreeBSD", - "BSD-2-CLAUSE-NETBSD": "BSD-2-Clause-NetBSD", - "BZIP2-1.0.5": "bzip2-1.0.5", - "ECOS-2.0": "eCos-2.0", - "GFDL-1.1": "GFDL-1.1", - "GFDL-1.2": "GFDL-1.2", - "GFDL-1.3": "GFDL-1.3", - "GPL-1.0": "GPL-1.0", - "GPL-1.0+": "GPL-1.0+", - "GPL-2.0": "GPL-2.0", - "GPL-2.0+": "GPL-2.0+", - "GPL-2.0-WITH-AUTOCONF-EXCEPTION": "GPL-2.0-with-autoconf-exception", - "GPL-2.0-WITH-BISON-EXCEPTION": "GPL-2.0-with-bison-exception", - "GPL-2.0-WITH-CLASSPATH-EXCEPTION": "GPL-2.0-with-classpath-exception", - "GPL-2.0-WITH-FONT-EXCEPTION": "GPL-2.0-with-font-exception", - "GPL-2.0-WITH-GCC-EXCEPTION": "GPL-2.0-with-GCC-exception", - "GPL-3.0": "GPL-3.0", - "GPL-3.0+": "GPL-3.0+", - "GPL-3.0-WITH-AUTOCONF-EXCEPTION": "GPL-3.0-with-autoconf-exception", - "GPL-3.0-WITH-GCC-EXCEPTION": "GPL-3.0-with-GCC-exception", - "LGPL-2.0": "LGPL-2.0", - "LGPL-2.0+": "LGPL-2.0+", - "LGPL-2.1": "LGPL-2.1", - "LGPL-2.1+": "LGPL-2.1+", - "LGPL-3.0": "LGPL-3.0", - "LGPL-3.0+": "LGPL-3.0+", - "NET-SNMP": "Net-SNMP", - "NUNIT": "Nunit", - "STANDARDML-NJ": "StandardML-NJ", - "WXWINDOWS": "wxWindows", -} - -// GetDeprecatedMap returns a map of deprecated license IDs keyed by uppercase ID. -func GetDeprecatedMap() map[string]string { - return deprecatedMap + "AGPL-1.0": "AGPL-1.0", + "AGPL-3.0": "AGPL-3.0", + "BSD-2-CLAUSE-FREEBSD": "BSD-2-Clause-FreeBSD", + "BSD-2-CLAUSE-NETBSD": "BSD-2-Clause-NetBSD", + "BZIP2-1.0.5": "bzip2-1.0.5", + "ECOS-2.0": "eCos-2.0", + "GFDL-1.1": "GFDL-1.1", + "GFDL-1.2": "GFDL-1.2", + "GFDL-1.3": "GFDL-1.3", + "GPL-1.0": "GPL-1.0", + "GPL-1.0+": "GPL-1.0+", + "GPL-2.0": "GPL-2.0", + "GPL-2.0+": "GPL-2.0+", + "GPL-2.0-WITH-AUTOCONF-EXCEPTION": "GPL-2.0-with-autoconf-exception", + "GPL-2.0-WITH-BISON-EXCEPTION": "GPL-2.0-with-bison-exception", + "GPL-2.0-WITH-CLASSPATH-EXCEPTION": "GPL-2.0-with-classpath-exception", + "GPL-2.0-WITH-FONT-EXCEPTION": "GPL-2.0-with-font-exception", + "GPL-2.0-WITH-GCC-EXCEPTION": "GPL-2.0-with-GCC-exception", + "GPL-3.0": "GPL-3.0", + "GPL-3.0+": "GPL-3.0+", + "GPL-3.0-WITH-AUTOCONF-EXCEPTION": "GPL-3.0-with-autoconf-exception", + "GPL-3.0-WITH-GCC-EXCEPTION": "GPL-3.0-with-GCC-exception", + "LGPL-2.0": "LGPL-2.0", + "LGPL-2.0+": "LGPL-2.0+", + "LGPL-2.1": "LGPL-2.1", + "LGPL-2.1+": "LGPL-2.1+", + "LGPL-3.0": "LGPL-3.0", + "LGPL-3.0+": "LGPL-3.0+", + "NET-SNMP": "Net-SNMP", + "NUNIT": "Nunit", + "STANDARDML-NJ": "StandardML-NJ", + "WXWINDOWS": "wxWindows", } diff --git a/spdxexp/spdxlicenses/get_exceptions.go b/spdxexp/spdxlicenses/get_exceptions.go index a83e024..2a580d9 100644 --- a/spdxexp/spdxlicenses/get_exceptions.go +++ b/spdxexp/spdxlicenses/get_exceptions.go @@ -3,6 +3,27 @@ package spdxlicenses // Code generated by go-spdx cmd/exceptions.go. DO NOT EDIT. // Source: https://github.com/spdx/license-list-data specifies official SPDX license list. +import "strings" + +// IsException does a case-insensitive lookup for the exception id in the exceptions map. +// It returns true and the case-sensitive ID if found, otherwise false and the original id. +func IsException(id string) (bool, string) { + foundID, ok := exceptionsMap[strings.ToUpper(id)] + if ok { + return true, foundID + } + return false, id +} + +// GetExceptionsMap returns a map of exception license IDs keyed by uppercase ID. +func GetExceptionsMap() map[string]string { + copied := make(map[string]string, len(exceptionsMap)) + for k, v := range exceptionsMap { + copied[k] = v + } + return copied +} + // GetExceptions returns a slice of exception license IDs. func GetExceptions() []string { return []string{ @@ -93,92 +114,87 @@ func GetExceptions() []string { } var exceptionsMap = map[string]string{ - "389-EXCEPTION": "389-exception", - "ASTERISK-EXCEPTION": "Asterisk-exception", - "ASTERISK-LINKING-PROTOCOLS-EXCEPTION": "Asterisk-linking-protocols-exception", - "AUTOCONF-EXCEPTION-2.0": "Autoconf-exception-2.0", - "AUTOCONF-EXCEPTION-3.0": "Autoconf-exception-3.0", - "AUTOCONF-EXCEPTION-GENERIC": "Autoconf-exception-generic", - "AUTOCONF-EXCEPTION-GENERIC-3.0": "Autoconf-exception-generic-3.0", - "AUTOCONF-EXCEPTION-MACRO": "Autoconf-exception-macro", - "BISON-EXCEPTION-1.24": "Bison-exception-1.24", - "BISON-EXCEPTION-2.2": "Bison-exception-2.2", - "BOOTLOADER-EXCEPTION": "Bootloader-exception", - "CGAL-LINKING-EXCEPTION": "CGAL-linking-exception", - "CLASSPATH-EXCEPTION-2.0": "Classpath-exception-2.0", - "CLASSPATH-EXCEPTION-2.0-SHORT": "Classpath-exception-2.0-short", - "CLISP-EXCEPTION-2.0": "CLISP-exception-2.0", - "CRYPTSETUP-OPENSSL-EXCEPTION": "cryptsetup-OpenSSL-exception", - "DIGIA-QT-LGPL-EXCEPTION-1.1": "Digia-Qt-LGPL-exception-1.1", - "DIGIRULE-FOSS-EXCEPTION": "DigiRule-FOSS-exception", - "ECOS-EXCEPTION-2.0": "eCos-exception-2.0", - "ERLANG-OTP-LINKING-EXCEPTION": "erlang-otp-linking-exception", - "FAWKES-RUNTIME-EXCEPTION": "Fawkes-Runtime-exception", - "FLTK-EXCEPTION": "FLTK-exception", - "FMT-EXCEPTION": "fmt-exception", - "FONT-EXCEPTION-2.0": "Font-exception-2.0", - "FREERTOS-EXCEPTION-2.0": "freertos-exception-2.0", - "GCC-EXCEPTION-2.0": "GCC-exception-2.0", - "GCC-EXCEPTION-2.0-NOTE": "GCC-exception-2.0-note", - "GCC-EXCEPTION-3.1": "GCC-exception-3.1", - "GMSH-EXCEPTION": "Gmsh-exception", - "GNAT-EXCEPTION": "GNAT-exception", - "GNOME-EXAMPLES-EXCEPTION": "GNOME-examples-exception", - "GNU-COMPILER-EXCEPTION": "GNU-compiler-exception", - "GNU-JAVAMAIL-EXCEPTION": "gnu-javamail-exception", - "GPL-3.0-389-DS-BASE-EXCEPTION": "GPL-3.0-389-ds-base-exception", - "GPL-3.0-INTERFACE-EXCEPTION": "GPL-3.0-interface-exception", - "GPL-3.0-LINKING-EXCEPTION": "GPL-3.0-linking-exception", - "GPL-3.0-LINKING-SOURCE-EXCEPTION": "GPL-3.0-linking-source-exception", - "GPL-CC-1.0": "GPL-CC-1.0", - "GSTREAMER-EXCEPTION-2005": "GStreamer-exception-2005", - "GSTREAMER-EXCEPTION-2008": "GStreamer-exception-2008", - "HARBOUR-EXCEPTION": "harbour-exception", - "I2P-GPL-JAVA-EXCEPTION": "i2p-gpl-java-exception", - "INDEPENDENT-MODULES-EXCEPTION": "Independent-modules-exception", - "KICAD-LIBRARIES-EXCEPTION": "KiCad-libraries-exception", - "KVIRC-OPENSSL-EXCEPTION": "kvirc-openssl-exception", - "LGPL-3.0-LINKING-EXCEPTION": "LGPL-3.0-linking-exception", - "LIBPRI-OPENH323-EXCEPTION": "libpri-OpenH323-exception", - "LIBTOOL-EXCEPTION": "Libtool-exception", - "LINUX-SYSCALL-NOTE": "Linux-syscall-note", - "LLGPL": "LLGPL", - "LLVM-EXCEPTION": "LLVM-exception", - "LZMA-EXCEPTION": "LZMA-exception", - "MIF-EXCEPTION": "mif-exception", - "MXML-EXCEPTION": "mxml-exception", - "OCAML-LGPL-LINKING-EXCEPTION": "OCaml-LGPL-linking-exception", - "OCCT-EXCEPTION-1.0": "OCCT-exception-1.0", - "OPENJDK-ASSEMBLY-EXCEPTION-1.0": "OpenJDK-assembly-exception-1.0", - "OPENVPN-OPENSSL-EXCEPTION": "openvpn-openssl-exception", - "PCRE2-EXCEPTION": "PCRE2-exception", - "POLYPARSE-EXCEPTION": "polyparse-exception", - "PS-OR-PDF-FONT-EXCEPTION-20170817": "PS-or-PDF-font-exception-20170817", - "QPL-1.0-INRIA-2004-EXCEPTION": "QPL-1.0-INRIA-2004-exception", - "QT-GPL-EXCEPTION-1.0": "Qt-GPL-exception-1.0", - "QT-LGPL-EXCEPTION-1.1": "Qt-LGPL-exception-1.1", - "QWT-EXCEPTION-1.0": "Qwt-exception-1.0", - "ROMIC-EXCEPTION": "romic-exception", - "RRDTOOL-FLOSS-EXCEPTION-2.0": "RRDtool-FLOSS-exception-2.0", - "RSYNC-LINKING-EXCEPTION": "rsync-linking-exception", - "SANE-EXCEPTION": "SANE-exception", - "SHL-2.0": "SHL-2.0", - "SHL-2.1": "SHL-2.1", - "SIMPLE-LIBRARY-USAGE-EXCEPTION": "Simple-Library-Usage-exception", - "SQLITESTUDIO-OPENSSL-EXCEPTION": "sqlitestudio-OpenSSL-exception", - "STUNNEL-EXCEPTION": "stunnel-exception", - "SWI-EXCEPTION": "SWI-exception", - "SWIFT-EXCEPTION": "Swift-exception", - "TEXINFO-EXCEPTION": "Texinfo-exception", - "U-BOOT-EXCEPTION-2.0": "u-boot-exception-2.0", - "UBDL-EXCEPTION": "UBDL-exception", - "UNIVERSAL-FOSS-EXCEPTION-1.0": "Universal-FOSS-exception-1.0", - "VSFTPD-OPENSSL-EXCEPTION": "vsftpd-openssl-exception", - "WXWINDOWS-EXCEPTION-3.1": "WxWindows-exception-3.1", - "X11VNC-OPENSSL-EXCEPTION": "x11vnc-openssl-exception", -} - -// GetExceptionsMap returns a map of exception license IDs keyed by uppercase ID. -func GetExceptionsMap() map[string]string { - return exceptionsMap + "389-EXCEPTION": "389-exception", + "ASTERISK-EXCEPTION": "Asterisk-exception", + "ASTERISK-LINKING-PROTOCOLS-EXCEPTION": "Asterisk-linking-protocols-exception", + "AUTOCONF-EXCEPTION-2.0": "Autoconf-exception-2.0", + "AUTOCONF-EXCEPTION-3.0": "Autoconf-exception-3.0", + "AUTOCONF-EXCEPTION-GENERIC": "Autoconf-exception-generic", + "AUTOCONF-EXCEPTION-GENERIC-3.0": "Autoconf-exception-generic-3.0", + "AUTOCONF-EXCEPTION-MACRO": "Autoconf-exception-macro", + "BISON-EXCEPTION-1.24": "Bison-exception-1.24", + "BISON-EXCEPTION-2.2": "Bison-exception-2.2", + "BOOTLOADER-EXCEPTION": "Bootloader-exception", + "CGAL-LINKING-EXCEPTION": "CGAL-linking-exception", + "CLASSPATH-EXCEPTION-2.0": "Classpath-exception-2.0", + "CLASSPATH-EXCEPTION-2.0-SHORT": "Classpath-exception-2.0-short", + "CLISP-EXCEPTION-2.0": "CLISP-exception-2.0", + "CRYPTSETUP-OPENSSL-EXCEPTION": "cryptsetup-OpenSSL-exception", + "DIGIA-QT-LGPL-EXCEPTION-1.1": "Digia-Qt-LGPL-exception-1.1", + "DIGIRULE-FOSS-EXCEPTION": "DigiRule-FOSS-exception", + "ECOS-EXCEPTION-2.0": "eCos-exception-2.0", + "ERLANG-OTP-LINKING-EXCEPTION": "erlang-otp-linking-exception", + "FAWKES-RUNTIME-EXCEPTION": "Fawkes-Runtime-exception", + "FLTK-EXCEPTION": "FLTK-exception", + "FMT-EXCEPTION": "fmt-exception", + "FONT-EXCEPTION-2.0": "Font-exception-2.0", + "FREERTOS-EXCEPTION-2.0": "freertos-exception-2.0", + "GCC-EXCEPTION-2.0": "GCC-exception-2.0", + "GCC-EXCEPTION-2.0-NOTE": "GCC-exception-2.0-note", + "GCC-EXCEPTION-3.1": "GCC-exception-3.1", + "GMSH-EXCEPTION": "Gmsh-exception", + "GNAT-EXCEPTION": "GNAT-exception", + "GNOME-EXAMPLES-EXCEPTION": "GNOME-examples-exception", + "GNU-COMPILER-EXCEPTION": "GNU-compiler-exception", + "GNU-JAVAMAIL-EXCEPTION": "gnu-javamail-exception", + "GPL-3.0-389-DS-BASE-EXCEPTION": "GPL-3.0-389-ds-base-exception", + "GPL-3.0-INTERFACE-EXCEPTION": "GPL-3.0-interface-exception", + "GPL-3.0-LINKING-EXCEPTION": "GPL-3.0-linking-exception", + "GPL-3.0-LINKING-SOURCE-EXCEPTION": "GPL-3.0-linking-source-exception", + "GPL-CC-1.0": "GPL-CC-1.0", + "GSTREAMER-EXCEPTION-2005": "GStreamer-exception-2005", + "GSTREAMER-EXCEPTION-2008": "GStreamer-exception-2008", + "HARBOUR-EXCEPTION": "harbour-exception", + "I2P-GPL-JAVA-EXCEPTION": "i2p-gpl-java-exception", + "INDEPENDENT-MODULES-EXCEPTION": "Independent-modules-exception", + "KICAD-LIBRARIES-EXCEPTION": "KiCad-libraries-exception", + "KVIRC-OPENSSL-EXCEPTION": "kvirc-openssl-exception", + "LGPL-3.0-LINKING-EXCEPTION": "LGPL-3.0-linking-exception", + "LIBPRI-OPENH323-EXCEPTION": "libpri-OpenH323-exception", + "LIBTOOL-EXCEPTION": "Libtool-exception", + "LINUX-SYSCALL-NOTE": "Linux-syscall-note", + "LLGPL": "LLGPL", + "LLVM-EXCEPTION": "LLVM-exception", + "LZMA-EXCEPTION": "LZMA-exception", + "MIF-EXCEPTION": "mif-exception", + "MXML-EXCEPTION": "mxml-exception", + "OCAML-LGPL-LINKING-EXCEPTION": "OCaml-LGPL-linking-exception", + "OCCT-EXCEPTION-1.0": "OCCT-exception-1.0", + "OPENJDK-ASSEMBLY-EXCEPTION-1.0": "OpenJDK-assembly-exception-1.0", + "OPENVPN-OPENSSL-EXCEPTION": "openvpn-openssl-exception", + "PCRE2-EXCEPTION": "PCRE2-exception", + "POLYPARSE-EXCEPTION": "polyparse-exception", + "PS-OR-PDF-FONT-EXCEPTION-20170817": "PS-or-PDF-font-exception-20170817", + "QPL-1.0-INRIA-2004-EXCEPTION": "QPL-1.0-INRIA-2004-exception", + "QT-GPL-EXCEPTION-1.0": "Qt-GPL-exception-1.0", + "QT-LGPL-EXCEPTION-1.1": "Qt-LGPL-exception-1.1", + "QWT-EXCEPTION-1.0": "Qwt-exception-1.0", + "ROMIC-EXCEPTION": "romic-exception", + "RRDTOOL-FLOSS-EXCEPTION-2.0": "RRDtool-FLOSS-exception-2.0", + "RSYNC-LINKING-EXCEPTION": "rsync-linking-exception", + "SANE-EXCEPTION": "SANE-exception", + "SHL-2.0": "SHL-2.0", + "SHL-2.1": "SHL-2.1", + "SIMPLE-LIBRARY-USAGE-EXCEPTION": "Simple-Library-Usage-exception", + "SQLITESTUDIO-OPENSSL-EXCEPTION": "sqlitestudio-OpenSSL-exception", + "STUNNEL-EXCEPTION": "stunnel-exception", + "SWI-EXCEPTION": "SWI-exception", + "SWIFT-EXCEPTION": "Swift-exception", + "TEXINFO-EXCEPTION": "Texinfo-exception", + "U-BOOT-EXCEPTION-2.0": "u-boot-exception-2.0", + "UBDL-EXCEPTION": "UBDL-exception", + "UNIVERSAL-FOSS-EXCEPTION-1.0": "Universal-FOSS-exception-1.0", + "VSFTPD-OPENSSL-EXCEPTION": "vsftpd-openssl-exception", + "WXWINDOWS-EXCEPTION-3.1": "WxWindows-exception-3.1", + "X11VNC-OPENSSL-EXCEPTION": "x11vnc-openssl-exception", } diff --git a/spdxexp/spdxlicenses/get_licenses.go b/spdxexp/spdxlicenses/get_licenses.go index 09abbae..d885f1e 100644 --- a/spdxexp/spdxlicenses/get_licenses.go +++ b/spdxexp/spdxlicenses/get_licenses.go @@ -3,6 +3,27 @@ package spdxlicenses // Code generated by go-spdx cmd/license.go. DO NOT EDIT. // Source: https://github.com/spdx/license-list-data specifies official SPDX license list. +import "strings" + +// IsActiveLicense does a case-insensitive lookup for the license id in the active licenses map. +// It returns true and the case-sensitive ID if found, otherwise false and the original id. +func IsActiveLicense(id string) (bool, string) { + foundID, ok := licensesMap[strings.ToUpper(id)] + if ok { + return true, foundID + } + return false, id +} + +// GetLicensesMap returns a map of active license IDs keyed by uppercase ID. +func GetLicensesMap() map[string]string { + copied := make(map[string]string, len(licensesMap)) + for k, v := range licensesMap { + copied[k] = v + } + return copied +} + // GetLicenses returns a slice of active license IDs. func GetLicenses() []string { return []string{ @@ -705,704 +726,699 @@ func GetLicenses() []string { } var licensesMap = map[string]string{ - "0BSD": "0BSD", - "3D-SLICER-1.0": "3D-Slicer-1.0", - "AAL": "AAL", - "ABSTYLES": "Abstyles", - "ADACORE-DOC": "AdaCore-doc", - "ADOBE-2006": "Adobe-2006", - "ADOBE-DISPLAY-POSTSCRIPT": "Adobe-Display-PostScript", - "ADOBE-GLYPH": "Adobe-Glyph", - "ADOBE-UTOPIA": "Adobe-Utopia", - "ADSL": "ADSL", - "ADVANCED-CRYPTICS-DICTIONARY": "Advanced-Cryptics-Dictionary", - "AFL-1.1": "AFL-1.1", - "AFL-1.2": "AFL-1.2", - "AFL-2.0": "AFL-2.0", - "AFL-2.1": "AFL-2.1", - "AFL-3.0": "AFL-3.0", - "AFMPARSE": "Afmparse", - "AGPL-1.0-ONLY": "AGPL-1.0-only", - "AGPL-1.0-OR-LATER": "AGPL-1.0-or-later", - "AGPL-3.0-ONLY": "AGPL-3.0-only", - "AGPL-3.0-OR-LATER": "AGPL-3.0-or-later", - "ALADDIN": "Aladdin", - "ALGLIB-DOCUMENTATION": "ALGLIB-Documentation", - "AMD-NEWLIB": "AMD-newlib", - "AMDPLPA": "AMDPLPA", - "AML": "AML", - "AML-GLSLANG": "AML-glslang", - "AMPAS": "AMPAS", - "ANTLR-PD": "ANTLR-PD", - "ANTLR-PD-FALLBACK": "ANTLR-PD-fallback", - "ANY-OSI": "any-OSI", - "ANY-OSI-PERL-MODULES": "any-OSI-perl-modules", - "APACHE-1.0": "Apache-1.0", - "APACHE-1.1": "Apache-1.1", - "APACHE-2.0": "Apache-2.0", - "APAFML": "APAFML", - "APL-1.0": "APL-1.0", - "APP-S2P": "App-s2p", - "APSL-1.0": "APSL-1.0", - "APSL-1.1": "APSL-1.1", - "APSL-1.2": "APSL-1.2", - "APSL-2.0": "APSL-2.0", - "ARPHIC-1999": "Arphic-1999", - "ARTISTIC-1.0": "Artistic-1.0", - "ARTISTIC-1.0-CL8": "Artistic-1.0-cl8", - "ARTISTIC-1.0-PERL": "Artistic-1.0-Perl", - "ARTISTIC-2.0": "Artistic-2.0", - "ARTISTIC-DIST": "Artistic-dist", - "ASPELL-RU": "Aspell-RU", - "ASWF-DIGITAL-ASSETS-1.0": "ASWF-Digital-Assets-1.0", - "ASWF-DIGITAL-ASSETS-1.1": "ASWF-Digital-Assets-1.1", - "BAEKMUK": "Baekmuk", - "BAHYPH": "Bahyph", - "BARR": "Barr", - "BCRYPT-SOLAR-DESIGNER": "bcrypt-Solar-Designer", - "BEERWARE": "Beerware", - "BITSTREAM-CHARTER": "Bitstream-Charter", - "BITSTREAM-VERA": "Bitstream-Vera", - "BITTORRENT-1.0": "BitTorrent-1.0", - "BITTORRENT-1.1": "BitTorrent-1.1", - "BLESSING": "blessing", - "BLUEOAK-1.0.0": "BlueOak-1.0.0", - "BOEHM-GC": "Boehm-GC", - "BOEHM-GC-WITHOUT-FEE": "Boehm-GC-without-fee", - "BOLA-1.1": "BOLA-1.1", - "BORCEUX": "Borceux", - "BRIAN-GLADMAN-2-CLAUSE": "Brian-Gladman-2-Clause", - "BRIAN-GLADMAN-3-CLAUSE": "Brian-Gladman-3-Clause", - "BSD-1-CLAUSE": "BSD-1-Clause", - "BSD-2-CLAUSE": "BSD-2-Clause", - "BSD-2-CLAUSE-DARWIN": "BSD-2-Clause-Darwin", - "BSD-2-CLAUSE-FIRST-LINES": "BSD-2-Clause-first-lines", - "BSD-2-CLAUSE-PATENT": "BSD-2-Clause-Patent", - "BSD-2-CLAUSE-PKGCONF-DISCLAIMER": "BSD-2-Clause-pkgconf-disclaimer", - "BSD-2-CLAUSE-VIEWS": "BSD-2-Clause-Views", - "BSD-3-CLAUSE": "BSD-3-Clause", - "BSD-3-CLAUSE-ACPICA": "BSD-3-Clause-acpica", - "BSD-3-CLAUSE-ATTRIBUTION": "BSD-3-Clause-Attribution", - "BSD-3-CLAUSE-CLEAR": "BSD-3-Clause-Clear", - "BSD-3-CLAUSE-FLEX": "BSD-3-Clause-flex", - "BSD-3-CLAUSE-HP": "BSD-3-Clause-HP", - "BSD-3-CLAUSE-LBNL": "BSD-3-Clause-LBNL", - "BSD-3-CLAUSE-MODIFICATION": "BSD-3-Clause-Modification", - "BSD-3-CLAUSE-NO-MILITARY-LICENSE": "BSD-3-Clause-No-Military-License", - "BSD-3-CLAUSE-NO-NUCLEAR-LICENSE": "BSD-3-Clause-No-Nuclear-License", - "BSD-3-CLAUSE-NO-NUCLEAR-LICENSE-2014": "BSD-3-Clause-No-Nuclear-License-2014", - "BSD-3-CLAUSE-NO-NUCLEAR-WARRANTY": "BSD-3-Clause-No-Nuclear-Warranty", - "BSD-3-CLAUSE-OPEN-MPI": "BSD-3-Clause-Open-MPI", - "BSD-3-CLAUSE-SUN": "BSD-3-Clause-Sun", - "BSD-3-CLAUSE-TSO": "BSD-3-Clause-Tso", - "BSD-4-CLAUSE": "BSD-4-Clause", - "BSD-4-CLAUSE-SHORTENED": "BSD-4-Clause-Shortened", - "BSD-4-CLAUSE-UC": "BSD-4-Clause-UC", - "BSD-4.3RENO": "BSD-4.3RENO", - "BSD-4.3TAHOE": "BSD-4.3TAHOE", - "BSD-ADVERTISING-ACKNOWLEDGEMENT": "BSD-Advertising-Acknowledgement", - "BSD-ATTRIBUTION-HPND-DISCLAIMER": "BSD-Attribution-HPND-disclaimer", - "BSD-INFERNO-NETTVERK": "BSD-Inferno-Nettverk", - "BSD-MARK-MODIFICATIONS": "BSD-Mark-Modifications", - "BSD-PROTECTION": "BSD-Protection", - "BSD-SOURCE-BEGINNING-FILE": "BSD-Source-beginning-file", - "BSD-SOURCE-CODE": "BSD-Source-Code", - "BSD-SYSTEMICS": "BSD-Systemics", - "BSD-SYSTEMICS-W3WORKS": "BSD-Systemics-W3Works", - "BSL-1.0": "BSL-1.0", - "BUDDY": "Buddy", - "BUSL-1.1": "BUSL-1.1", - "BZIP2-1.0.6": "bzip2-1.0.6", - "C-UDA-1.0": "C-UDA-1.0", - "CAL-1.0": "CAL-1.0", - "CAL-1.0-COMBINED-WORK-EXCEPTION": "CAL-1.0-Combined-Work-Exception", - "CALDERA": "Caldera", - "CALDERA-NO-PREAMBLE": "Caldera-no-preamble", - "CAPEC-TOU": "CAPEC-tou", - "CATHARON": "Catharon", - "CATOSL-1.1": "CATOSL-1.1", - "CC-BY-1.0": "CC-BY-1.0", - "CC-BY-2.0": "CC-BY-2.0", - "CC-BY-2.5": "CC-BY-2.5", - "CC-BY-2.5-AU": "CC-BY-2.5-AU", - "CC-BY-3.0": "CC-BY-3.0", - "CC-BY-3.0-AT": "CC-BY-3.0-AT", - "CC-BY-3.0-AU": "CC-BY-3.0-AU", - "CC-BY-3.0-DE": "CC-BY-3.0-DE", - "CC-BY-3.0-IGO": "CC-BY-3.0-IGO", - "CC-BY-3.0-NL": "CC-BY-3.0-NL", - "CC-BY-3.0-US": "CC-BY-3.0-US", - "CC-BY-4.0": "CC-BY-4.0", - "CC-BY-NC-1.0": "CC-BY-NC-1.0", - "CC-BY-NC-2.0": "CC-BY-NC-2.0", - "CC-BY-NC-2.5": "CC-BY-NC-2.5", - "CC-BY-NC-3.0": "CC-BY-NC-3.0", - "CC-BY-NC-3.0-DE": "CC-BY-NC-3.0-DE", - "CC-BY-NC-4.0": "CC-BY-NC-4.0", - "CC-BY-NC-ND-1.0": "CC-BY-NC-ND-1.0", - "CC-BY-NC-ND-2.0": "CC-BY-NC-ND-2.0", - "CC-BY-NC-ND-2.5": "CC-BY-NC-ND-2.5", - "CC-BY-NC-ND-3.0": "CC-BY-NC-ND-3.0", - "CC-BY-NC-ND-3.0-DE": "CC-BY-NC-ND-3.0-DE", - "CC-BY-NC-ND-3.0-IGO": "CC-BY-NC-ND-3.0-IGO", - "CC-BY-NC-ND-4.0": "CC-BY-NC-ND-4.0", - "CC-BY-NC-SA-1.0": "CC-BY-NC-SA-1.0", - "CC-BY-NC-SA-2.0": "CC-BY-NC-SA-2.0", - "CC-BY-NC-SA-2.0-DE": "CC-BY-NC-SA-2.0-DE", - "CC-BY-NC-SA-2.0-FR": "CC-BY-NC-SA-2.0-FR", - "CC-BY-NC-SA-2.0-UK": "CC-BY-NC-SA-2.0-UK", - "CC-BY-NC-SA-2.5": "CC-BY-NC-SA-2.5", - "CC-BY-NC-SA-3.0": "CC-BY-NC-SA-3.0", - "CC-BY-NC-SA-3.0-DE": "CC-BY-NC-SA-3.0-DE", - "CC-BY-NC-SA-3.0-IGO": "CC-BY-NC-SA-3.0-IGO", - "CC-BY-NC-SA-4.0": "CC-BY-NC-SA-4.0", - "CC-BY-ND-1.0": "CC-BY-ND-1.0", - "CC-BY-ND-2.0": "CC-BY-ND-2.0", - "CC-BY-ND-2.5": "CC-BY-ND-2.5", - "CC-BY-ND-3.0": "CC-BY-ND-3.0", - "CC-BY-ND-3.0-DE": "CC-BY-ND-3.0-DE", - "CC-BY-ND-4.0": "CC-BY-ND-4.0", - "CC-BY-SA-1.0": "CC-BY-SA-1.0", - "CC-BY-SA-2.0": "CC-BY-SA-2.0", - "CC-BY-SA-2.0-UK": "CC-BY-SA-2.0-UK", - "CC-BY-SA-2.1-JP": "CC-BY-SA-2.1-JP", - "CC-BY-SA-2.5": "CC-BY-SA-2.5", - "CC-BY-SA-3.0": "CC-BY-SA-3.0", - "CC-BY-SA-3.0-AT": "CC-BY-SA-3.0-AT", - "CC-BY-SA-3.0-DE": "CC-BY-SA-3.0-DE", - "CC-BY-SA-3.0-IGO": "CC-BY-SA-3.0-IGO", - "CC-BY-SA-4.0": "CC-BY-SA-4.0", - "CC-PDDC": "CC-PDDC", - "CC-PDM-1.0": "CC-PDM-1.0", - "CC-SA-1.0": "CC-SA-1.0", - "CC0-1.0": "CC0-1.0", - "CDDL-1.0": "CDDL-1.0", - "CDDL-1.1": "CDDL-1.1", - "CDL-1.0": "CDL-1.0", - "CDLA-PERMISSIVE-1.0": "CDLA-Permissive-1.0", - "CDLA-PERMISSIVE-2.0": "CDLA-Permissive-2.0", - "CDLA-SHARING-1.0": "CDLA-Sharing-1.0", - "CECILL-1.0": "CECILL-1.0", - "CECILL-1.1": "CECILL-1.1", - "CECILL-2.0": "CECILL-2.0", - "CECILL-2.1": "CECILL-2.1", - "CECILL-B": "CECILL-B", - "CECILL-C": "CECILL-C", - "CERN-OHL-1.1": "CERN-OHL-1.1", - "CERN-OHL-1.2": "CERN-OHL-1.2", - "CERN-OHL-P-2.0": "CERN-OHL-P-2.0", - "CERN-OHL-S-2.0": "CERN-OHL-S-2.0", - "CERN-OHL-W-2.0": "CERN-OHL-W-2.0", - "CFITSIO": "CFITSIO", - "CHECK-CVS": "check-cvs", - "CHECKMK": "checkmk", - "CLARTISTIC": "ClArtistic", - "CLIPS": "Clips", - "CMU-MACH": "CMU-Mach", - "CMU-MACH-NODOC": "CMU-Mach-nodoc", - "CNRI-JYTHON": "CNRI-Jython", - "CNRI-PYTHON": "CNRI-Python", - "CNRI-PYTHON-GPL-COMPATIBLE": "CNRI-Python-GPL-Compatible", - "COIL-1.0": "COIL-1.0", - "COMMUNITY-SPEC-1.0": "Community-Spec-1.0", - "CONDOR-1.1": "Condor-1.1", - "COPYLEFT-NEXT-0.3.0": "copyleft-next-0.3.0", - "COPYLEFT-NEXT-0.3.1": "copyleft-next-0.3.1", - "CORNELL-LOSSLESS-JPEG": "Cornell-Lossless-JPEG", - "CPAL-1.0": "CPAL-1.0", - "CPL-1.0": "CPL-1.0", - "CPOL-1.02": "CPOL-1.02", - "CRONYX": "Cronyx", - "CROSSWORD": "Crossword", - "CRYPTOSWIFT": "CryptoSwift", - "CRYSTALSTACKER": "CrystalStacker", - "CUA-OPL-1.0": "CUA-OPL-1.0", - "CUBE": "Cube", - "CURL": "curl", - "CVE-TOU": "cve-tou", - "D-FSL-1.0": "D-FSL-1.0", - "DEC-3-CLAUSE": "DEC-3-Clause", - "DIFFMARK": "diffmark", - "DL-DE-BY-2.0": "DL-DE-BY-2.0", - "DL-DE-ZERO-2.0": "DL-DE-ZERO-2.0", - "DOC": "DOC", - "DOCBOOK-DTD": "DocBook-DTD", - "DOCBOOK-SCHEMA": "DocBook-Schema", - "DOCBOOK-STYLESHEET": "DocBook-Stylesheet", - "DOCBOOK-XML": "DocBook-XML", - "DOTSEQN": "Dotseqn", - "DRL-1.0": "DRL-1.0", - "DRL-1.1": "DRL-1.1", - "DSDP": "DSDP", - "DTOA": "dtoa", - "DVIPDFM": "dvipdfm", - "ECL-1.0": "ECL-1.0", - "ECL-2.0": "ECL-2.0", - "EFL-1.0": "EFL-1.0", - "EFL-2.0": "EFL-2.0", - "EGENIX": "eGenix", - "ELASTIC-2.0": "Elastic-2.0", - "ENTESSA": "Entessa", - "EPICS": "EPICS", - "EPL-1.0": "EPL-1.0", - "EPL-2.0": "EPL-2.0", - "ERLPL-1.1": "ErlPL-1.1", - "ESA-PL-PERMISSIVE-2.4": "ESA-PL-permissive-2.4", - "ESA-PL-STRONG-COPYLEFT-2.4": "ESA-PL-strong-copyleft-2.4", - "ESA-PL-WEAK-COPYLEFT-2.4": "ESA-PL-weak-copyleft-2.4", - "ETALAB-2.0": "etalab-2.0", - "EUDATAGRID": "EUDatagrid", - "EUPL-1.0": "EUPL-1.0", - "EUPL-1.1": "EUPL-1.1", - "EUPL-1.2": "EUPL-1.2", - "EUROSYM": "Eurosym", - "FAIR": "Fair", - "FBM": "FBM", - "FDK-AAC": "FDK-AAC", - "FERGUSON-TWOFISH": "Ferguson-Twofish", - "FRAMEWORX-1.0": "Frameworx-1.0", - "FREEBSD-DOC": "FreeBSD-DOC", - "FREEIMAGE": "FreeImage", - "FSFAP": "FSFAP", - "FSFAP-NO-WARRANTY-DISCLAIMER": "FSFAP-no-warranty-disclaimer", - "FSFUL": "FSFUL", - "FSFULLR": "FSFULLR", - "FSFULLRSD": "FSFULLRSD", - "FSFULLRWD": "FSFULLRWD", - "FSL-1.1-ALV2": "FSL-1.1-ALv2", - "FSL-1.1-MIT": "FSL-1.1-MIT", - "FTL": "FTL", - "FURUSETH": "Furuseth", - "FWLW": "fwlw", - "GAME-PROGRAMMING-GEMS": "Game-Programming-Gems", - "GCR-DOCS": "GCR-docs", - "GD": "GD", - "GENERIC-XTS": "generic-xts", - "GFDL-1.1-INVARIANTS-ONLY": "GFDL-1.1-invariants-only", - "GFDL-1.1-INVARIANTS-OR-LATER": "GFDL-1.1-invariants-or-later", - "GFDL-1.1-NO-INVARIANTS-ONLY": "GFDL-1.1-no-invariants-only", - "GFDL-1.1-NO-INVARIANTS-OR-LATER": "GFDL-1.1-no-invariants-or-later", - "GFDL-1.1-ONLY": "GFDL-1.1-only", - "GFDL-1.1-OR-LATER": "GFDL-1.1-or-later", - "GFDL-1.2-INVARIANTS-ONLY": "GFDL-1.2-invariants-only", - "GFDL-1.2-INVARIANTS-OR-LATER": "GFDL-1.2-invariants-or-later", - "GFDL-1.2-NO-INVARIANTS-ONLY": "GFDL-1.2-no-invariants-only", - "GFDL-1.2-NO-INVARIANTS-OR-LATER": "GFDL-1.2-no-invariants-or-later", - "GFDL-1.2-ONLY": "GFDL-1.2-only", - "GFDL-1.2-OR-LATER": "GFDL-1.2-or-later", - "GFDL-1.3-INVARIANTS-ONLY": "GFDL-1.3-invariants-only", - "GFDL-1.3-INVARIANTS-OR-LATER": "GFDL-1.3-invariants-or-later", - "GFDL-1.3-NO-INVARIANTS-ONLY": "GFDL-1.3-no-invariants-only", - "GFDL-1.3-NO-INVARIANTS-OR-LATER": "GFDL-1.3-no-invariants-or-later", - "GFDL-1.3-ONLY": "GFDL-1.3-only", - "GFDL-1.3-OR-LATER": "GFDL-1.3-or-later", - "GIFTWARE": "Giftware", - "GL2PS": "GL2PS", - "GLIDE": "Glide", - "GLULXE": "Glulxe", - "GLWTPL": "GLWTPL", - "GNUPLOT": "gnuplot", - "GPL-1.0-ONLY": "GPL-1.0-only", - "GPL-1.0-OR-LATER": "GPL-1.0-or-later", - "GPL-2.0-ONLY": "GPL-2.0-only", - "GPL-2.0-OR-LATER": "GPL-2.0-or-later", - "GPL-3.0-ONLY": "GPL-3.0-only", - "GPL-3.0-OR-LATER": "GPL-3.0-or-later", - "GRAPHICS-GEMS": "Graphics-Gems", - "GSOAP-1.3B": "gSOAP-1.3b", - "GTKBOOK": "gtkbook", - "GUTMANN": "Gutmann", - "HASKELLREPORT": "HaskellReport", - "HDF5": "HDF5", - "HDPARM": "hdparm", - "HIDAPI": "HIDAPI", - "HIPPOCRATIC-2.1": "Hippocratic-2.1", - "HP-1986": "HP-1986", - "HP-1989": "HP-1989", - "HPND": "HPND", - "HPND-DEC": "HPND-DEC", - "HPND-DOC": "HPND-doc", - "HPND-DOC-SELL": "HPND-doc-sell", - "HPND-EXPORT-US": "HPND-export-US", - "HPND-EXPORT-US-ACKNOWLEDGEMENT": "HPND-export-US-acknowledgement", - "HPND-EXPORT-US-MODIFY": "HPND-export-US-modify", - "HPND-EXPORT2-US": "HPND-export2-US", - "HPND-FENNEBERG-LIVINGSTON": "HPND-Fenneberg-Livingston", - "HPND-INRIA-IMAG": "HPND-INRIA-IMAG", - "HPND-INTEL": "HPND-Intel", - "HPND-KEVLIN-HENNEY": "HPND-Kevlin-Henney", - "HPND-MARKUS-KUHN": "HPND-Markus-Kuhn", - "HPND-MERCHANTABILITY-VARIANT": "HPND-merchantability-variant", - "HPND-MIT-DISCLAIMER": "HPND-MIT-disclaimer", - "HPND-NETREK": "HPND-Netrek", - "HPND-PBMPLUS": "HPND-Pbmplus", - "HPND-SELL-MIT-DISCLAIMER-XSERVER": "HPND-sell-MIT-disclaimer-xserver", - "HPND-SELL-REGEXPR": "HPND-sell-regexpr", - "HPND-SELL-VARIANT": "HPND-sell-variant", - "HPND-SELL-VARIANT-CRITICAL-SYSTEMS": "HPND-sell-variant-critical-systems", - "HPND-SELL-VARIANT-MIT-DISCLAIMER": "HPND-sell-variant-MIT-disclaimer", - "HPND-SELL-VARIANT-MIT-DISCLAIMER-REV": "HPND-sell-variant-MIT-disclaimer-rev", - "HPND-SMC": "HPND-SMC", - "HPND-UC": "HPND-UC", - "HPND-UC-EXPORT-US": "HPND-UC-export-US", - "HTMLTIDY": "HTMLTIDY", - "HYPHEN-BULGARIAN": "hyphen-bulgarian", - "IBM-PIBS": "IBM-pibs", - "ICU": "ICU", - "IEC-CODE-COMPONENTS-EULA": "IEC-Code-Components-EULA", - "IJG": "IJG", - "IJG-SHORT": "IJG-short", - "IMAGEMAGICK": "ImageMagick", - "IMATIX": "iMatix", - "IMLIB2": "Imlib2", - "INFO-ZIP": "Info-ZIP", - "INNER-NET-2.0": "Inner-Net-2.0", - "INNOSETUP": "InnoSetup", - "INTEL": "Intel", - "INTEL-ACPI": "Intel-ACPI", - "INTERBASE-1.0": "Interbase-1.0", - "IPA": "IPA", - "IPL-1.0": "IPL-1.0", - "ISC": "ISC", - "ISC-VEILLARD": "ISC-Veillard", - "ISO-PERMISSION": "ISO-permission", - "JAM": "Jam", - "JASPER-2.0": "JasPer-2.0", - "JOVE": "jove", - "JPL-IMAGE": "JPL-image", - "JPNIC": "JPNIC", - "JSON": "JSON", - "KASTRUP": "Kastrup", - "KAZLIB": "Kazlib", - "KNUTH-CTAN": "Knuth-CTAN", - "LAL-1.2": "LAL-1.2", - "LAL-1.3": "LAL-1.3", - "LATEX2E": "Latex2e", - "LATEX2E-TRANSLATED-NOTICE": "Latex2e-translated-notice", - "LEPTONICA": "Leptonica", - "LGPL-2.0-ONLY": "LGPL-2.0-only", - "LGPL-2.0-OR-LATER": "LGPL-2.0-or-later", - "LGPL-2.1-ONLY": "LGPL-2.1-only", - "LGPL-2.1-OR-LATER": "LGPL-2.1-or-later", - "LGPL-3.0-ONLY": "LGPL-3.0-only", - "LGPL-3.0-OR-LATER": "LGPL-3.0-or-later", - "LGPLLR": "LGPLLR", - "LIBPNG": "Libpng", - "LIBPNG-1.6.35": "libpng-1.6.35", - "LIBPNG-2.0": "libpng-2.0", - "LIBSELINUX-1.0": "libselinux-1.0", - "LIBTIFF": "libtiff", - "LIBUTIL-DAVID-NUGENT": "libutil-David-Nugent", - "LILIQ-P-1.1": "LiLiQ-P-1.1", - "LILIQ-R-1.1": "LiLiQ-R-1.1", - "LILIQ-RPLUS-1.1": "LiLiQ-Rplus-1.1", - "LINUX-MAN-PAGES-1-PARA": "Linux-man-pages-1-para", - "LINUX-MAN-PAGES-COPYLEFT": "Linux-man-pages-copyleft", - "LINUX-MAN-PAGES-COPYLEFT-2-PARA": "Linux-man-pages-copyleft-2-para", - "LINUX-MAN-PAGES-COPYLEFT-VAR": "Linux-man-pages-copyleft-var", - "LINUX-OPENIB": "Linux-OpenIB", - "LOOP": "LOOP", - "LPD-DOCUMENT": "LPD-document", - "LPL-1.0": "LPL-1.0", - "LPL-1.02": "LPL-1.02", - "LPPL-1.0": "LPPL-1.0", - "LPPL-1.1": "LPPL-1.1", - "LPPL-1.2": "LPPL-1.2", - "LPPL-1.3A": "LPPL-1.3a", - "LPPL-1.3C": "LPPL-1.3c", - "LSOF": "lsof", - "LUCIDA-BITMAP-FONTS": "Lucida-Bitmap-Fonts", - "LZMA-SDK-9.11-TO-9.20": "LZMA-SDK-9.11-to-9.20", - "LZMA-SDK-9.22": "LZMA-SDK-9.22", - "MACKERRAS-3-CLAUSE": "Mackerras-3-Clause", - "MACKERRAS-3-CLAUSE-ACKNOWLEDGMENT": "Mackerras-3-Clause-acknowledgment", - "MAGAZ": "magaz", - "MAILPRIO": "mailprio", - "MAKEINDEX": "MakeIndex", - "MAN2HTML": "man2html", - "MARTIN-BIRGMEIER": "Martin-Birgmeier", - "MCPHEE-SLIDESHOW": "McPhee-slideshow", - "METAMAIL": "metamail", - "MINPACK": "Minpack", - "MIPS": "MIPS", - "MIROS": "MirOS", - "MIT": "MIT", - "MIT-0": "MIT-0", - "MIT-ADVERTISING": "MIT-advertising", - "MIT-CLICK": "MIT-Click", - "MIT-CMU": "MIT-CMU", - "MIT-ENNA": "MIT-enna", - "MIT-FEH": "MIT-feh", - "MIT-FESTIVAL": "MIT-Festival", - "MIT-KHRONOS-OLD": "MIT-Khronos-old", - "MIT-MODERN-VARIANT": "MIT-Modern-Variant", - "MIT-OPEN-GROUP": "MIT-open-group", - "MIT-STK": "MIT-STK", - "MIT-TESTREGEX": "MIT-testregex", - "MIT-WU": "MIT-Wu", - "MITNFA": "MITNFA", - "MMIXWARE": "MMIXware", - "MMPL-1.0.1": "MMPL-1.0.1", - "MOTOSOTO": "Motosoto", - "MPEG-SSG": "MPEG-SSG", - "MPI-PERMISSIVE": "mpi-permissive", - "MPICH2": "mpich2", - "MPL-1.0": "MPL-1.0", - "MPL-1.1": "MPL-1.1", - "MPL-2.0": "MPL-2.0", - "MPL-2.0-NO-COPYLEFT-EXCEPTION": "MPL-2.0-no-copyleft-exception", - "MPLUS": "mplus", - "MS-LPL": "MS-LPL", - "MS-PL": "MS-PL", - "MS-RL": "MS-RL", - "MTLL": "MTLL", - "MULANPSL-1.0": "MulanPSL-1.0", - "MULANPSL-2.0": "MulanPSL-2.0", - "MULTICS": "Multics", - "MUP": "Mup", - "NAIST-2003": "NAIST-2003", - "NASA-1.3": "NASA-1.3", - "NAUMEN": "Naumen", - "NBPL-1.0": "NBPL-1.0", - "NCBI-PD": "NCBI-PD", - "NCGL-UK-2.0": "NCGL-UK-2.0", - "NCL": "NCL", - "NCSA": "NCSA", - "NETCDF": "NetCDF", - "NEWSLETR": "Newsletr", - "NGPL": "NGPL", - "NGREP": "ngrep", - "NICTA-1.0": "NICTA-1.0", - "NIST-PD": "NIST-PD", - "NIST-PD-FALLBACK": "NIST-PD-fallback", - "NIST-PD-TNT": "NIST-PD-TNT", - "NIST-SOFTWARE": "NIST-Software", - "NLOD-1.0": "NLOD-1.0", - "NLOD-2.0": "NLOD-2.0", - "NLPL": "NLPL", - "NOKIA": "Nokia", - "NOSL": "NOSL", - "NOWEB": "Noweb", - "NPL-1.0": "NPL-1.0", - "NPL-1.1": "NPL-1.1", - "NPOSL-3.0": "NPOSL-3.0", - "NRL": "NRL", - "NTIA-PD": "NTIA-PD", - "NTP": "NTP", - "NTP-0": "NTP-0", - "O-UDA-1.0": "O-UDA-1.0", - "OAR": "OAR", - "OCCT-PL": "OCCT-PL", - "OCLC-2.0": "OCLC-2.0", - "ODBL-1.0": "ODbL-1.0", - "ODC-BY-1.0": "ODC-By-1.0", - "OFFIS": "OFFIS", - "OFL-1.0": "OFL-1.0", - "OFL-1.0-NO-RFN": "OFL-1.0-no-RFN", - "OFL-1.0-RFN": "OFL-1.0-RFN", - "OFL-1.1": "OFL-1.1", - "OFL-1.1-NO-RFN": "OFL-1.1-no-RFN", - "OFL-1.1-RFN": "OFL-1.1-RFN", - "OGC-1.0": "OGC-1.0", - "OGDL-TAIWAN-1.0": "OGDL-Taiwan-1.0", - "OGL-CANADA-2.0": "OGL-Canada-2.0", - "OGL-UK-1.0": "OGL-UK-1.0", - "OGL-UK-2.0": "OGL-UK-2.0", - "OGL-UK-3.0": "OGL-UK-3.0", - "OGTSL": "OGTSL", - "OLDAP-1.1": "OLDAP-1.1", - "OLDAP-1.2": "OLDAP-1.2", - "OLDAP-1.3": "OLDAP-1.3", - "OLDAP-1.4": "OLDAP-1.4", - "OLDAP-2.0": "OLDAP-2.0", - "OLDAP-2.0.1": "OLDAP-2.0.1", - "OLDAP-2.1": "OLDAP-2.1", - "OLDAP-2.2": "OLDAP-2.2", - "OLDAP-2.2.1": "OLDAP-2.2.1", - "OLDAP-2.2.2": "OLDAP-2.2.2", - "OLDAP-2.3": "OLDAP-2.3", - "OLDAP-2.4": "OLDAP-2.4", - "OLDAP-2.5": "OLDAP-2.5", - "OLDAP-2.6": "OLDAP-2.6", - "OLDAP-2.7": "OLDAP-2.7", - "OLDAP-2.8": "OLDAP-2.8", - "OLFL-1.3": "OLFL-1.3", - "OML": "OML", - "OPENMDW-1.0": "OpenMDW-1.0", - "OPENPBS-2.3": "OpenPBS-2.3", - "OPENSSL": "OpenSSL", - "OPENSSL-STANDALONE": "OpenSSL-standalone", - "OPENVISION": "OpenVision", - "OPL-1.0": "OPL-1.0", - "OPL-UK-3.0": "OPL-UK-3.0", - "OPUBL-1.0": "OPUBL-1.0", - "OSC-1.0": "OSC-1.0", - "OSET-PL-2.1": "OSET-PL-2.1", - "OSL-1.0": "OSL-1.0", - "OSL-1.1": "OSL-1.1", - "OSL-2.0": "OSL-2.0", - "OSL-2.1": "OSL-2.1", - "OSL-3.0": "OSL-3.0", - "OSSP": "OSSP", - "PADL": "PADL", - "PARATYPE-FREE-FONT-1.3": "ParaType-Free-Font-1.3", - "PARITY-6.0.0": "Parity-6.0.0", - "PARITY-7.0.0": "Parity-7.0.0", - "PDDL-1.0": "PDDL-1.0", - "PHP-3.0": "PHP-3.0", - "PHP-3.01": "PHP-3.01", - "PIXAR": "Pixar", - "PKGCONF": "pkgconf", - "PLEXUS": "Plexus", - "PNMSTITCH": "pnmstitch", - "POLYFORM-NONCOMMERCIAL-1.0.0": "PolyForm-Noncommercial-1.0.0", - "POLYFORM-SMALL-BUSINESS-1.0.0": "PolyForm-Small-Business-1.0.0", - "POSTGRESQL": "PostgreSQL", - "PPL": "PPL", - "PSF-2.0": "PSF-2.0", - "PSFRAG": "psfrag", - "PSUTILS": "psutils", - "PYTHON-2.0": "Python-2.0", - "PYTHON-2.0.1": "Python-2.0.1", - "PYTHON-LDAP": "python-ldap", - "QHULL": "Qhull", - "QPL-1.0": "QPL-1.0", - "QPL-1.0-INRIA-2004": "QPL-1.0-INRIA-2004", - "RADVD": "radvd", - "RDISC": "Rdisc", - "RHECOS-1.1": "RHeCos-1.1", - "RPL-1.1": "RPL-1.1", - "RPL-1.5": "RPL-1.5", - "RPSL-1.0": "RPSL-1.0", - "RSA-MD": "RSA-MD", - "RSCPL": "RSCPL", - "RUBY": "Ruby", - "RUBY-PTY": "Ruby-pty", - "SAX-PD": "SAX-PD", - "SAX-PD-2.0": "SAX-PD-2.0", - "SAXPATH": "Saxpath", - "SCEA": "SCEA", - "SCHEMEREPORT": "SchemeReport", - "SENDMAIL": "Sendmail", - "SENDMAIL-8.23": "Sendmail-8.23", - "SENDMAIL-OPEN-SOURCE-1.1": "Sendmail-Open-Source-1.1", - "SGI-B-1.0": "SGI-B-1.0", - "SGI-B-1.1": "SGI-B-1.1", - "SGI-B-2.0": "SGI-B-2.0", - "SGI-OPENGL": "SGI-OpenGL", - "SGMLUG-PM": "SGMLUG-PM", - "SGP4": "SGP4", - "SHL-0.5": "SHL-0.5", - "SHL-0.51": "SHL-0.51", - "SIMPL-2.0": "SimPL-2.0", - "SISSL": "SISSL", - "SISSL-1.2": "SISSL-1.2", - "SL": "SL", - "SLEEPYCAT": "Sleepycat", - "SMAIL-GPL": "SMAIL-GPL", - "SMLNJ": "SMLNJ", - "SMPPL": "SMPPL", - "SNIA": "SNIA", - "SNPRINTF": "snprintf", - "SOFA": "SOFA", - "SOFTSURFER": "softSurfer", - "SOUNDEX": "Soundex", - "SPENCER-86": "Spencer-86", - "SPENCER-94": "Spencer-94", - "SPENCER-99": "Spencer-99", - "SPL-1.0": "SPL-1.0", - "SSH-KEYSCAN": "ssh-keyscan", - "SSH-OPENSSH": "SSH-OpenSSH", - "SSH-SHORT": "SSH-short", - "SSLEAY-STANDALONE": "SSLeay-standalone", - "SSPL-1.0": "SSPL-1.0", - "SUGARCRM-1.1.3": "SugarCRM-1.1.3", - "SUL-1.0": "SUL-1.0", - "SUN-PPP": "Sun-PPP", - "SUN-PPP-2000": "Sun-PPP-2000", - "SUNPRO": "SunPro", - "SWL": "SWL", - "SWRULE": "swrule", - "SYMLINKS": "Symlinks", - "TAPR-OHL-1.0": "TAPR-OHL-1.0", - "TCL": "TCL", - "TCP-WRAPPERS": "TCP-wrappers", - "TEKHVC": "TekHVC", - "TERMREADKEY": "TermReadKey", - "TGPPL-1.0": "TGPPL-1.0", - "THIRDEYE": "ThirdEye", - "THREEPARTTABLE": "threeparttable", - "TMATE": "TMate", - "TORQUE-1.1": "TORQUE-1.1", - "TOSL": "TOSL", - "TPDL": "TPDL", - "TPL-1.0": "TPL-1.0", - "TRUSTEDQSL": "TrustedQSL", - "TTWL": "TTWL", - "TTYP0": "TTYP0", - "TU-BERLIN-1.0": "TU-Berlin-1.0", - "TU-BERLIN-2.0": "TU-Berlin-2.0", - "UBUNTU-FONT-1.0": "Ubuntu-font-1.0", - "UCAR": "UCAR", - "UCL-1.0": "UCL-1.0", - "ULEM": "ulem", - "UMICH-MERIT": "UMich-Merit", - "UNICODE-3.0": "Unicode-3.0", - "UNICODE-DFS-2015": "Unicode-DFS-2015", - "UNICODE-DFS-2016": "Unicode-DFS-2016", - "UNICODE-TOU": "Unicode-TOU", - "UNIXCRYPT": "UnixCrypt", - "UNLICENSE": "Unlicense", - "UNLICENSE-LIBTELNET": "Unlicense-libtelnet", - "UNLICENSE-LIBWHIRLPOOL": "Unlicense-libwhirlpool", - "UNRAR": "UnRAR", - "UPL-1.0": "UPL-1.0", - "URT-RLE": "URT-RLE", - "VIM": "Vim", - "VIXIE-CRON": "Vixie-Cron", - "VOSTROM": "VOSTROM", - "VSL-1.0": "VSL-1.0", - "W3C": "W3C", - "W3C-19980720": "W3C-19980720", - "W3C-20150513": "W3C-20150513", - "W3M": "w3m", - "WATCOM-1.0": "Watcom-1.0", - "WIDGET-WORKSHOP": "Widget-Workshop", - "WORDNET": "WordNet", - "WSUIPA": "Wsuipa", - "WTFNMFPL": "WTFNMFPL", - "WTFPL": "WTFPL", - "WWL": "wwl", - "X11": "X11", - "X11-DISTRIBUTE-MODIFICATIONS-VARIANT": "X11-distribute-modifications-variant", - "X11-NO-PERMIT-PERSONS": "X11-no-permit-persons", - "X11-SWAPPED": "X11-swapped", - "XDEBUG-1.03": "Xdebug-1.03", - "XEROX": "Xerox", - "XFIG": "Xfig", - "XFREE86-1.1": "XFree86-1.1", - "XINETD": "xinetd", - "XKEYBOARD-CONFIG-ZINOVIEV": "xkeyboard-config-Zinoviev", - "XLOCK": "xlock", - "XNET": "Xnet", - "XPP": "xpp", - "XSKAT": "XSkat", - "XZOOM": "xzoom", - "YPL-1.0": "YPL-1.0", - "YPL-1.1": "YPL-1.1", - "ZED": "Zed", - "ZEEFF": "Zeeff", - "ZEND-2.0": "Zend-2.0", - "ZIMBRA-1.3": "Zimbra-1.3", - "ZIMBRA-1.4": "Zimbra-1.4", - "ZLIB": "Zlib", - "ZLIB-ACKNOWLEDGEMENT": "zlib-acknowledgement", - "ZPL-1.1": "ZPL-1.1", - "ZPL-2.0": "ZPL-2.0", - "ZPL-2.1": "ZPL-2.1", -} - -// GetLicensesMap returns a map of active license IDs keyed by uppercase ID. -func GetLicensesMap() map[string]string { - return licensesMap + "0BSD": "0BSD", + "3D-SLICER-1.0": "3D-Slicer-1.0", + "AAL": "AAL", + "ABSTYLES": "Abstyles", + "ADACORE-DOC": "AdaCore-doc", + "ADOBE-2006": "Adobe-2006", + "ADOBE-DISPLAY-POSTSCRIPT": "Adobe-Display-PostScript", + "ADOBE-GLYPH": "Adobe-Glyph", + "ADOBE-UTOPIA": "Adobe-Utopia", + "ADSL": "ADSL", + "ADVANCED-CRYPTICS-DICTIONARY": "Advanced-Cryptics-Dictionary", + "AFL-1.1": "AFL-1.1", + "AFL-1.2": "AFL-1.2", + "AFL-2.0": "AFL-2.0", + "AFL-2.1": "AFL-2.1", + "AFL-3.0": "AFL-3.0", + "AFMPARSE": "Afmparse", + "AGPL-1.0-ONLY": "AGPL-1.0-only", + "AGPL-1.0-OR-LATER": "AGPL-1.0-or-later", + "AGPL-3.0-ONLY": "AGPL-3.0-only", + "AGPL-3.0-OR-LATER": "AGPL-3.0-or-later", + "ALADDIN": "Aladdin", + "ALGLIB-DOCUMENTATION": "ALGLIB-Documentation", + "AMD-NEWLIB": "AMD-newlib", + "AMDPLPA": "AMDPLPA", + "AML": "AML", + "AML-GLSLANG": "AML-glslang", + "AMPAS": "AMPAS", + "ANTLR-PD": "ANTLR-PD", + "ANTLR-PD-FALLBACK": "ANTLR-PD-fallback", + "ANY-OSI": "any-OSI", + "ANY-OSI-PERL-MODULES": "any-OSI-perl-modules", + "APACHE-1.0": "Apache-1.0", + "APACHE-1.1": "Apache-1.1", + "APACHE-2.0": "Apache-2.0", + "APAFML": "APAFML", + "APL-1.0": "APL-1.0", + "APP-S2P": "App-s2p", + "APSL-1.0": "APSL-1.0", + "APSL-1.1": "APSL-1.1", + "APSL-1.2": "APSL-1.2", + "APSL-2.0": "APSL-2.0", + "ARPHIC-1999": "Arphic-1999", + "ARTISTIC-1.0": "Artistic-1.0", + "ARTISTIC-1.0-CL8": "Artistic-1.0-cl8", + "ARTISTIC-1.0-PERL": "Artistic-1.0-Perl", + "ARTISTIC-2.0": "Artistic-2.0", + "ARTISTIC-DIST": "Artistic-dist", + "ASPELL-RU": "Aspell-RU", + "ASWF-DIGITAL-ASSETS-1.0": "ASWF-Digital-Assets-1.0", + "ASWF-DIGITAL-ASSETS-1.1": "ASWF-Digital-Assets-1.1", + "BAEKMUK": "Baekmuk", + "BAHYPH": "Bahyph", + "BARR": "Barr", + "BCRYPT-SOLAR-DESIGNER": "bcrypt-Solar-Designer", + "BEERWARE": "Beerware", + "BITSTREAM-CHARTER": "Bitstream-Charter", + "BITSTREAM-VERA": "Bitstream-Vera", + "BITTORRENT-1.0": "BitTorrent-1.0", + "BITTORRENT-1.1": "BitTorrent-1.1", + "BLESSING": "blessing", + "BLUEOAK-1.0.0": "BlueOak-1.0.0", + "BOEHM-GC": "Boehm-GC", + "BOEHM-GC-WITHOUT-FEE": "Boehm-GC-without-fee", + "BOLA-1.1": "BOLA-1.1", + "BORCEUX": "Borceux", + "BRIAN-GLADMAN-2-CLAUSE": "Brian-Gladman-2-Clause", + "BRIAN-GLADMAN-3-CLAUSE": "Brian-Gladman-3-Clause", + "BSD-1-CLAUSE": "BSD-1-Clause", + "BSD-2-CLAUSE": "BSD-2-Clause", + "BSD-2-CLAUSE-DARWIN": "BSD-2-Clause-Darwin", + "BSD-2-CLAUSE-FIRST-LINES": "BSD-2-Clause-first-lines", + "BSD-2-CLAUSE-PATENT": "BSD-2-Clause-Patent", + "BSD-2-CLAUSE-PKGCONF-DISCLAIMER": "BSD-2-Clause-pkgconf-disclaimer", + "BSD-2-CLAUSE-VIEWS": "BSD-2-Clause-Views", + "BSD-3-CLAUSE": "BSD-3-Clause", + "BSD-3-CLAUSE-ACPICA": "BSD-3-Clause-acpica", + "BSD-3-CLAUSE-ATTRIBUTION": "BSD-3-Clause-Attribution", + "BSD-3-CLAUSE-CLEAR": "BSD-3-Clause-Clear", + "BSD-3-CLAUSE-FLEX": "BSD-3-Clause-flex", + "BSD-3-CLAUSE-HP": "BSD-3-Clause-HP", + "BSD-3-CLAUSE-LBNL": "BSD-3-Clause-LBNL", + "BSD-3-CLAUSE-MODIFICATION": "BSD-3-Clause-Modification", + "BSD-3-CLAUSE-NO-MILITARY-LICENSE": "BSD-3-Clause-No-Military-License", + "BSD-3-CLAUSE-NO-NUCLEAR-LICENSE": "BSD-3-Clause-No-Nuclear-License", + "BSD-3-CLAUSE-NO-NUCLEAR-LICENSE-2014": "BSD-3-Clause-No-Nuclear-License-2014", + "BSD-3-CLAUSE-NO-NUCLEAR-WARRANTY": "BSD-3-Clause-No-Nuclear-Warranty", + "BSD-3-CLAUSE-OPEN-MPI": "BSD-3-Clause-Open-MPI", + "BSD-3-CLAUSE-SUN": "BSD-3-Clause-Sun", + "BSD-3-CLAUSE-TSO": "BSD-3-Clause-Tso", + "BSD-4-CLAUSE": "BSD-4-Clause", + "BSD-4-CLAUSE-SHORTENED": "BSD-4-Clause-Shortened", + "BSD-4-CLAUSE-UC": "BSD-4-Clause-UC", + "BSD-4.3RENO": "BSD-4.3RENO", + "BSD-4.3TAHOE": "BSD-4.3TAHOE", + "BSD-ADVERTISING-ACKNOWLEDGEMENT": "BSD-Advertising-Acknowledgement", + "BSD-ATTRIBUTION-HPND-DISCLAIMER": "BSD-Attribution-HPND-disclaimer", + "BSD-INFERNO-NETTVERK": "BSD-Inferno-Nettverk", + "BSD-MARK-MODIFICATIONS": "BSD-Mark-Modifications", + "BSD-PROTECTION": "BSD-Protection", + "BSD-SOURCE-BEGINNING-FILE": "BSD-Source-beginning-file", + "BSD-SOURCE-CODE": "BSD-Source-Code", + "BSD-SYSTEMICS": "BSD-Systemics", + "BSD-SYSTEMICS-W3WORKS": "BSD-Systemics-W3Works", + "BSL-1.0": "BSL-1.0", + "BUDDY": "Buddy", + "BUSL-1.1": "BUSL-1.1", + "BZIP2-1.0.6": "bzip2-1.0.6", + "C-UDA-1.0": "C-UDA-1.0", + "CAL-1.0": "CAL-1.0", + "CAL-1.0-COMBINED-WORK-EXCEPTION": "CAL-1.0-Combined-Work-Exception", + "CALDERA": "Caldera", + "CALDERA-NO-PREAMBLE": "Caldera-no-preamble", + "CAPEC-TOU": "CAPEC-tou", + "CATHARON": "Catharon", + "CATOSL-1.1": "CATOSL-1.1", + "CC-BY-1.0": "CC-BY-1.0", + "CC-BY-2.0": "CC-BY-2.0", + "CC-BY-2.5": "CC-BY-2.5", + "CC-BY-2.5-AU": "CC-BY-2.5-AU", + "CC-BY-3.0": "CC-BY-3.0", + "CC-BY-3.0-AT": "CC-BY-3.0-AT", + "CC-BY-3.0-AU": "CC-BY-3.0-AU", + "CC-BY-3.0-DE": "CC-BY-3.0-DE", + "CC-BY-3.0-IGO": "CC-BY-3.0-IGO", + "CC-BY-3.0-NL": "CC-BY-3.0-NL", + "CC-BY-3.0-US": "CC-BY-3.0-US", + "CC-BY-4.0": "CC-BY-4.0", + "CC-BY-NC-1.0": "CC-BY-NC-1.0", + "CC-BY-NC-2.0": "CC-BY-NC-2.0", + "CC-BY-NC-2.5": "CC-BY-NC-2.5", + "CC-BY-NC-3.0": "CC-BY-NC-3.0", + "CC-BY-NC-3.0-DE": "CC-BY-NC-3.0-DE", + "CC-BY-NC-4.0": "CC-BY-NC-4.0", + "CC-BY-NC-ND-1.0": "CC-BY-NC-ND-1.0", + "CC-BY-NC-ND-2.0": "CC-BY-NC-ND-2.0", + "CC-BY-NC-ND-2.5": "CC-BY-NC-ND-2.5", + "CC-BY-NC-ND-3.0": "CC-BY-NC-ND-3.0", + "CC-BY-NC-ND-3.0-DE": "CC-BY-NC-ND-3.0-DE", + "CC-BY-NC-ND-3.0-IGO": "CC-BY-NC-ND-3.0-IGO", + "CC-BY-NC-ND-4.0": "CC-BY-NC-ND-4.0", + "CC-BY-NC-SA-1.0": "CC-BY-NC-SA-1.0", + "CC-BY-NC-SA-2.0": "CC-BY-NC-SA-2.0", + "CC-BY-NC-SA-2.0-DE": "CC-BY-NC-SA-2.0-DE", + "CC-BY-NC-SA-2.0-FR": "CC-BY-NC-SA-2.0-FR", + "CC-BY-NC-SA-2.0-UK": "CC-BY-NC-SA-2.0-UK", + "CC-BY-NC-SA-2.5": "CC-BY-NC-SA-2.5", + "CC-BY-NC-SA-3.0": "CC-BY-NC-SA-3.0", + "CC-BY-NC-SA-3.0-DE": "CC-BY-NC-SA-3.0-DE", + "CC-BY-NC-SA-3.0-IGO": "CC-BY-NC-SA-3.0-IGO", + "CC-BY-NC-SA-4.0": "CC-BY-NC-SA-4.0", + "CC-BY-ND-1.0": "CC-BY-ND-1.0", + "CC-BY-ND-2.0": "CC-BY-ND-2.0", + "CC-BY-ND-2.5": "CC-BY-ND-2.5", + "CC-BY-ND-3.0": "CC-BY-ND-3.0", + "CC-BY-ND-3.0-DE": "CC-BY-ND-3.0-DE", + "CC-BY-ND-4.0": "CC-BY-ND-4.0", + "CC-BY-SA-1.0": "CC-BY-SA-1.0", + "CC-BY-SA-2.0": "CC-BY-SA-2.0", + "CC-BY-SA-2.0-UK": "CC-BY-SA-2.0-UK", + "CC-BY-SA-2.1-JP": "CC-BY-SA-2.1-JP", + "CC-BY-SA-2.5": "CC-BY-SA-2.5", + "CC-BY-SA-3.0": "CC-BY-SA-3.0", + "CC-BY-SA-3.0-AT": "CC-BY-SA-3.0-AT", + "CC-BY-SA-3.0-DE": "CC-BY-SA-3.0-DE", + "CC-BY-SA-3.0-IGO": "CC-BY-SA-3.0-IGO", + "CC-BY-SA-4.0": "CC-BY-SA-4.0", + "CC-PDDC": "CC-PDDC", + "CC-PDM-1.0": "CC-PDM-1.0", + "CC-SA-1.0": "CC-SA-1.0", + "CC0-1.0": "CC0-1.0", + "CDDL-1.0": "CDDL-1.0", + "CDDL-1.1": "CDDL-1.1", + "CDL-1.0": "CDL-1.0", + "CDLA-PERMISSIVE-1.0": "CDLA-Permissive-1.0", + "CDLA-PERMISSIVE-2.0": "CDLA-Permissive-2.0", + "CDLA-SHARING-1.0": "CDLA-Sharing-1.0", + "CECILL-1.0": "CECILL-1.0", + "CECILL-1.1": "CECILL-1.1", + "CECILL-2.0": "CECILL-2.0", + "CECILL-2.1": "CECILL-2.1", + "CECILL-B": "CECILL-B", + "CECILL-C": "CECILL-C", + "CERN-OHL-1.1": "CERN-OHL-1.1", + "CERN-OHL-1.2": "CERN-OHL-1.2", + "CERN-OHL-P-2.0": "CERN-OHL-P-2.0", + "CERN-OHL-S-2.0": "CERN-OHL-S-2.0", + "CERN-OHL-W-2.0": "CERN-OHL-W-2.0", + "CFITSIO": "CFITSIO", + "CHECK-CVS": "check-cvs", + "CHECKMK": "checkmk", + "CLARTISTIC": "ClArtistic", + "CLIPS": "Clips", + "CMU-MACH": "CMU-Mach", + "CMU-MACH-NODOC": "CMU-Mach-nodoc", + "CNRI-JYTHON": "CNRI-Jython", + "CNRI-PYTHON": "CNRI-Python", + "CNRI-PYTHON-GPL-COMPATIBLE": "CNRI-Python-GPL-Compatible", + "COIL-1.0": "COIL-1.0", + "COMMUNITY-SPEC-1.0": "Community-Spec-1.0", + "CONDOR-1.1": "Condor-1.1", + "COPYLEFT-NEXT-0.3.0": "copyleft-next-0.3.0", + "COPYLEFT-NEXT-0.3.1": "copyleft-next-0.3.1", + "CORNELL-LOSSLESS-JPEG": "Cornell-Lossless-JPEG", + "CPAL-1.0": "CPAL-1.0", + "CPL-1.0": "CPL-1.0", + "CPOL-1.02": "CPOL-1.02", + "CRONYX": "Cronyx", + "CROSSWORD": "Crossword", + "CRYPTOSWIFT": "CryptoSwift", + "CRYSTALSTACKER": "CrystalStacker", + "CUA-OPL-1.0": "CUA-OPL-1.0", + "CUBE": "Cube", + "CURL": "curl", + "CVE-TOU": "cve-tou", + "D-FSL-1.0": "D-FSL-1.0", + "DEC-3-CLAUSE": "DEC-3-Clause", + "DIFFMARK": "diffmark", + "DL-DE-BY-2.0": "DL-DE-BY-2.0", + "DL-DE-ZERO-2.0": "DL-DE-ZERO-2.0", + "DOC": "DOC", + "DOCBOOK-DTD": "DocBook-DTD", + "DOCBOOK-SCHEMA": "DocBook-Schema", + "DOCBOOK-STYLESHEET": "DocBook-Stylesheet", + "DOCBOOK-XML": "DocBook-XML", + "DOTSEQN": "Dotseqn", + "DRL-1.0": "DRL-1.0", + "DRL-1.1": "DRL-1.1", + "DSDP": "DSDP", + "DTOA": "dtoa", + "DVIPDFM": "dvipdfm", + "ECL-1.0": "ECL-1.0", + "ECL-2.0": "ECL-2.0", + "EFL-1.0": "EFL-1.0", + "EFL-2.0": "EFL-2.0", + "EGENIX": "eGenix", + "ELASTIC-2.0": "Elastic-2.0", + "ENTESSA": "Entessa", + "EPICS": "EPICS", + "EPL-1.0": "EPL-1.0", + "EPL-2.0": "EPL-2.0", + "ERLPL-1.1": "ErlPL-1.1", + "ESA-PL-PERMISSIVE-2.4": "ESA-PL-permissive-2.4", + "ESA-PL-STRONG-COPYLEFT-2.4": "ESA-PL-strong-copyleft-2.4", + "ESA-PL-WEAK-COPYLEFT-2.4": "ESA-PL-weak-copyleft-2.4", + "ETALAB-2.0": "etalab-2.0", + "EUDATAGRID": "EUDatagrid", + "EUPL-1.0": "EUPL-1.0", + "EUPL-1.1": "EUPL-1.1", + "EUPL-1.2": "EUPL-1.2", + "EUROSYM": "Eurosym", + "FAIR": "Fair", + "FBM": "FBM", + "FDK-AAC": "FDK-AAC", + "FERGUSON-TWOFISH": "Ferguson-Twofish", + "FRAMEWORX-1.0": "Frameworx-1.0", + "FREEBSD-DOC": "FreeBSD-DOC", + "FREEIMAGE": "FreeImage", + "FSFAP": "FSFAP", + "FSFAP-NO-WARRANTY-DISCLAIMER": "FSFAP-no-warranty-disclaimer", + "FSFUL": "FSFUL", + "FSFULLR": "FSFULLR", + "FSFULLRSD": "FSFULLRSD", + "FSFULLRWD": "FSFULLRWD", + "FSL-1.1-ALV2": "FSL-1.1-ALv2", + "FSL-1.1-MIT": "FSL-1.1-MIT", + "FTL": "FTL", + "FURUSETH": "Furuseth", + "FWLW": "fwlw", + "GAME-PROGRAMMING-GEMS": "Game-Programming-Gems", + "GCR-DOCS": "GCR-docs", + "GD": "GD", + "GENERIC-XTS": "generic-xts", + "GFDL-1.1-INVARIANTS-ONLY": "GFDL-1.1-invariants-only", + "GFDL-1.1-INVARIANTS-OR-LATER": "GFDL-1.1-invariants-or-later", + "GFDL-1.1-NO-INVARIANTS-ONLY": "GFDL-1.1-no-invariants-only", + "GFDL-1.1-NO-INVARIANTS-OR-LATER": "GFDL-1.1-no-invariants-or-later", + "GFDL-1.1-ONLY": "GFDL-1.1-only", + "GFDL-1.1-OR-LATER": "GFDL-1.1-or-later", + "GFDL-1.2-INVARIANTS-ONLY": "GFDL-1.2-invariants-only", + "GFDL-1.2-INVARIANTS-OR-LATER": "GFDL-1.2-invariants-or-later", + "GFDL-1.2-NO-INVARIANTS-ONLY": "GFDL-1.2-no-invariants-only", + "GFDL-1.2-NO-INVARIANTS-OR-LATER": "GFDL-1.2-no-invariants-or-later", + "GFDL-1.2-ONLY": "GFDL-1.2-only", + "GFDL-1.2-OR-LATER": "GFDL-1.2-or-later", + "GFDL-1.3-INVARIANTS-ONLY": "GFDL-1.3-invariants-only", + "GFDL-1.3-INVARIANTS-OR-LATER": "GFDL-1.3-invariants-or-later", + "GFDL-1.3-NO-INVARIANTS-ONLY": "GFDL-1.3-no-invariants-only", + "GFDL-1.3-NO-INVARIANTS-OR-LATER": "GFDL-1.3-no-invariants-or-later", + "GFDL-1.3-ONLY": "GFDL-1.3-only", + "GFDL-1.3-OR-LATER": "GFDL-1.3-or-later", + "GIFTWARE": "Giftware", + "GL2PS": "GL2PS", + "GLIDE": "Glide", + "GLULXE": "Glulxe", + "GLWTPL": "GLWTPL", + "GNUPLOT": "gnuplot", + "GPL-1.0-ONLY": "GPL-1.0-only", + "GPL-1.0-OR-LATER": "GPL-1.0-or-later", + "GPL-2.0-ONLY": "GPL-2.0-only", + "GPL-2.0-OR-LATER": "GPL-2.0-or-later", + "GPL-3.0-ONLY": "GPL-3.0-only", + "GPL-3.0-OR-LATER": "GPL-3.0-or-later", + "GRAPHICS-GEMS": "Graphics-Gems", + "GSOAP-1.3B": "gSOAP-1.3b", + "GTKBOOK": "gtkbook", + "GUTMANN": "Gutmann", + "HASKELLREPORT": "HaskellReport", + "HDF5": "HDF5", + "HDPARM": "hdparm", + "HIDAPI": "HIDAPI", + "HIPPOCRATIC-2.1": "Hippocratic-2.1", + "HP-1986": "HP-1986", + "HP-1989": "HP-1989", + "HPND": "HPND", + "HPND-DEC": "HPND-DEC", + "HPND-DOC": "HPND-doc", + "HPND-DOC-SELL": "HPND-doc-sell", + "HPND-EXPORT-US": "HPND-export-US", + "HPND-EXPORT-US-ACKNOWLEDGEMENT": "HPND-export-US-acknowledgement", + "HPND-EXPORT-US-MODIFY": "HPND-export-US-modify", + "HPND-EXPORT2-US": "HPND-export2-US", + "HPND-FENNEBERG-LIVINGSTON": "HPND-Fenneberg-Livingston", + "HPND-INRIA-IMAG": "HPND-INRIA-IMAG", + "HPND-INTEL": "HPND-Intel", + "HPND-KEVLIN-HENNEY": "HPND-Kevlin-Henney", + "HPND-MARKUS-KUHN": "HPND-Markus-Kuhn", + "HPND-MERCHANTABILITY-VARIANT": "HPND-merchantability-variant", + "HPND-MIT-DISCLAIMER": "HPND-MIT-disclaimer", + "HPND-NETREK": "HPND-Netrek", + "HPND-PBMPLUS": "HPND-Pbmplus", + "HPND-SELL-MIT-DISCLAIMER-XSERVER": "HPND-sell-MIT-disclaimer-xserver", + "HPND-SELL-REGEXPR": "HPND-sell-regexpr", + "HPND-SELL-VARIANT": "HPND-sell-variant", + "HPND-SELL-VARIANT-CRITICAL-SYSTEMS": "HPND-sell-variant-critical-systems", + "HPND-SELL-VARIANT-MIT-DISCLAIMER": "HPND-sell-variant-MIT-disclaimer", + "HPND-SELL-VARIANT-MIT-DISCLAIMER-REV": "HPND-sell-variant-MIT-disclaimer-rev", + "HPND-SMC": "HPND-SMC", + "HPND-UC": "HPND-UC", + "HPND-UC-EXPORT-US": "HPND-UC-export-US", + "HTMLTIDY": "HTMLTIDY", + "HYPHEN-BULGARIAN": "hyphen-bulgarian", + "IBM-PIBS": "IBM-pibs", + "ICU": "ICU", + "IEC-CODE-COMPONENTS-EULA": "IEC-Code-Components-EULA", + "IJG": "IJG", + "IJG-SHORT": "IJG-short", + "IMAGEMAGICK": "ImageMagick", + "IMATIX": "iMatix", + "IMLIB2": "Imlib2", + "INFO-ZIP": "Info-ZIP", + "INNER-NET-2.0": "Inner-Net-2.0", + "INNOSETUP": "InnoSetup", + "INTEL": "Intel", + "INTEL-ACPI": "Intel-ACPI", + "INTERBASE-1.0": "Interbase-1.0", + "IPA": "IPA", + "IPL-1.0": "IPL-1.0", + "ISC": "ISC", + "ISC-VEILLARD": "ISC-Veillard", + "ISO-PERMISSION": "ISO-permission", + "JAM": "Jam", + "JASPER-2.0": "JasPer-2.0", + "JOVE": "jove", + "JPL-IMAGE": "JPL-image", + "JPNIC": "JPNIC", + "JSON": "JSON", + "KASTRUP": "Kastrup", + "KAZLIB": "Kazlib", + "KNUTH-CTAN": "Knuth-CTAN", + "LAL-1.2": "LAL-1.2", + "LAL-1.3": "LAL-1.3", + "LATEX2E": "Latex2e", + "LATEX2E-TRANSLATED-NOTICE": "Latex2e-translated-notice", + "LEPTONICA": "Leptonica", + "LGPL-2.0-ONLY": "LGPL-2.0-only", + "LGPL-2.0-OR-LATER": "LGPL-2.0-or-later", + "LGPL-2.1-ONLY": "LGPL-2.1-only", + "LGPL-2.1-OR-LATER": "LGPL-2.1-or-later", + "LGPL-3.0-ONLY": "LGPL-3.0-only", + "LGPL-3.0-OR-LATER": "LGPL-3.0-or-later", + "LGPLLR": "LGPLLR", + "LIBPNG": "Libpng", + "LIBPNG-1.6.35": "libpng-1.6.35", + "LIBPNG-2.0": "libpng-2.0", + "LIBSELINUX-1.0": "libselinux-1.0", + "LIBTIFF": "libtiff", + "LIBUTIL-DAVID-NUGENT": "libutil-David-Nugent", + "LILIQ-P-1.1": "LiLiQ-P-1.1", + "LILIQ-R-1.1": "LiLiQ-R-1.1", + "LILIQ-RPLUS-1.1": "LiLiQ-Rplus-1.1", + "LINUX-MAN-PAGES-1-PARA": "Linux-man-pages-1-para", + "LINUX-MAN-PAGES-COPYLEFT": "Linux-man-pages-copyleft", + "LINUX-MAN-PAGES-COPYLEFT-2-PARA": "Linux-man-pages-copyleft-2-para", + "LINUX-MAN-PAGES-COPYLEFT-VAR": "Linux-man-pages-copyleft-var", + "LINUX-OPENIB": "Linux-OpenIB", + "LOOP": "LOOP", + "LPD-DOCUMENT": "LPD-document", + "LPL-1.0": "LPL-1.0", + "LPL-1.02": "LPL-1.02", + "LPPL-1.0": "LPPL-1.0", + "LPPL-1.1": "LPPL-1.1", + "LPPL-1.2": "LPPL-1.2", + "LPPL-1.3A": "LPPL-1.3a", + "LPPL-1.3C": "LPPL-1.3c", + "LSOF": "lsof", + "LUCIDA-BITMAP-FONTS": "Lucida-Bitmap-Fonts", + "LZMA-SDK-9.11-TO-9.20": "LZMA-SDK-9.11-to-9.20", + "LZMA-SDK-9.22": "LZMA-SDK-9.22", + "MACKERRAS-3-CLAUSE": "Mackerras-3-Clause", + "MACKERRAS-3-CLAUSE-ACKNOWLEDGMENT": "Mackerras-3-Clause-acknowledgment", + "MAGAZ": "magaz", + "MAILPRIO": "mailprio", + "MAKEINDEX": "MakeIndex", + "MAN2HTML": "man2html", + "MARTIN-BIRGMEIER": "Martin-Birgmeier", + "MCPHEE-SLIDESHOW": "McPhee-slideshow", + "METAMAIL": "metamail", + "MINPACK": "Minpack", + "MIPS": "MIPS", + "MIROS": "MirOS", + "MIT": "MIT", + "MIT-0": "MIT-0", + "MIT-ADVERTISING": "MIT-advertising", + "MIT-CLICK": "MIT-Click", + "MIT-CMU": "MIT-CMU", + "MIT-ENNA": "MIT-enna", + "MIT-FEH": "MIT-feh", + "MIT-FESTIVAL": "MIT-Festival", + "MIT-KHRONOS-OLD": "MIT-Khronos-old", + "MIT-MODERN-VARIANT": "MIT-Modern-Variant", + "MIT-OPEN-GROUP": "MIT-open-group", + "MIT-STK": "MIT-STK", + "MIT-TESTREGEX": "MIT-testregex", + "MIT-WU": "MIT-Wu", + "MITNFA": "MITNFA", + "MMIXWARE": "MMIXware", + "MMPL-1.0.1": "MMPL-1.0.1", + "MOTOSOTO": "Motosoto", + "MPEG-SSG": "MPEG-SSG", + "MPI-PERMISSIVE": "mpi-permissive", + "MPICH2": "mpich2", + "MPL-1.0": "MPL-1.0", + "MPL-1.1": "MPL-1.1", + "MPL-2.0": "MPL-2.0", + "MPL-2.0-NO-COPYLEFT-EXCEPTION": "MPL-2.0-no-copyleft-exception", + "MPLUS": "mplus", + "MS-LPL": "MS-LPL", + "MS-PL": "MS-PL", + "MS-RL": "MS-RL", + "MTLL": "MTLL", + "MULANPSL-1.0": "MulanPSL-1.0", + "MULANPSL-2.0": "MulanPSL-2.0", + "MULTICS": "Multics", + "MUP": "Mup", + "NAIST-2003": "NAIST-2003", + "NASA-1.3": "NASA-1.3", + "NAUMEN": "Naumen", + "NBPL-1.0": "NBPL-1.0", + "NCBI-PD": "NCBI-PD", + "NCGL-UK-2.0": "NCGL-UK-2.0", + "NCL": "NCL", + "NCSA": "NCSA", + "NETCDF": "NetCDF", + "NEWSLETR": "Newsletr", + "NGPL": "NGPL", + "NGREP": "ngrep", + "NICTA-1.0": "NICTA-1.0", + "NIST-PD": "NIST-PD", + "NIST-PD-FALLBACK": "NIST-PD-fallback", + "NIST-PD-TNT": "NIST-PD-TNT", + "NIST-SOFTWARE": "NIST-Software", + "NLOD-1.0": "NLOD-1.0", + "NLOD-2.0": "NLOD-2.0", + "NLPL": "NLPL", + "NOKIA": "Nokia", + "NOSL": "NOSL", + "NOWEB": "Noweb", + "NPL-1.0": "NPL-1.0", + "NPL-1.1": "NPL-1.1", + "NPOSL-3.0": "NPOSL-3.0", + "NRL": "NRL", + "NTIA-PD": "NTIA-PD", + "NTP": "NTP", + "NTP-0": "NTP-0", + "O-UDA-1.0": "O-UDA-1.0", + "OAR": "OAR", + "OCCT-PL": "OCCT-PL", + "OCLC-2.0": "OCLC-2.0", + "ODBL-1.0": "ODbL-1.0", + "ODC-BY-1.0": "ODC-By-1.0", + "OFFIS": "OFFIS", + "OFL-1.0": "OFL-1.0", + "OFL-1.0-NO-RFN": "OFL-1.0-no-RFN", + "OFL-1.0-RFN": "OFL-1.0-RFN", + "OFL-1.1": "OFL-1.1", + "OFL-1.1-NO-RFN": "OFL-1.1-no-RFN", + "OFL-1.1-RFN": "OFL-1.1-RFN", + "OGC-1.0": "OGC-1.0", + "OGDL-TAIWAN-1.0": "OGDL-Taiwan-1.0", + "OGL-CANADA-2.0": "OGL-Canada-2.0", + "OGL-UK-1.0": "OGL-UK-1.0", + "OGL-UK-2.0": "OGL-UK-2.0", + "OGL-UK-3.0": "OGL-UK-3.0", + "OGTSL": "OGTSL", + "OLDAP-1.1": "OLDAP-1.1", + "OLDAP-1.2": "OLDAP-1.2", + "OLDAP-1.3": "OLDAP-1.3", + "OLDAP-1.4": "OLDAP-1.4", + "OLDAP-2.0": "OLDAP-2.0", + "OLDAP-2.0.1": "OLDAP-2.0.1", + "OLDAP-2.1": "OLDAP-2.1", + "OLDAP-2.2": "OLDAP-2.2", + "OLDAP-2.2.1": "OLDAP-2.2.1", + "OLDAP-2.2.2": "OLDAP-2.2.2", + "OLDAP-2.3": "OLDAP-2.3", + "OLDAP-2.4": "OLDAP-2.4", + "OLDAP-2.5": "OLDAP-2.5", + "OLDAP-2.6": "OLDAP-2.6", + "OLDAP-2.7": "OLDAP-2.7", + "OLDAP-2.8": "OLDAP-2.8", + "OLFL-1.3": "OLFL-1.3", + "OML": "OML", + "OPENMDW-1.0": "OpenMDW-1.0", + "OPENPBS-2.3": "OpenPBS-2.3", + "OPENSSL": "OpenSSL", + "OPENSSL-STANDALONE": "OpenSSL-standalone", + "OPENVISION": "OpenVision", + "OPL-1.0": "OPL-1.0", + "OPL-UK-3.0": "OPL-UK-3.0", + "OPUBL-1.0": "OPUBL-1.0", + "OSC-1.0": "OSC-1.0", + "OSET-PL-2.1": "OSET-PL-2.1", + "OSL-1.0": "OSL-1.0", + "OSL-1.1": "OSL-1.1", + "OSL-2.0": "OSL-2.0", + "OSL-2.1": "OSL-2.1", + "OSL-3.0": "OSL-3.0", + "OSSP": "OSSP", + "PADL": "PADL", + "PARATYPE-FREE-FONT-1.3": "ParaType-Free-Font-1.3", + "PARITY-6.0.0": "Parity-6.0.0", + "PARITY-7.0.0": "Parity-7.0.0", + "PDDL-1.0": "PDDL-1.0", + "PHP-3.0": "PHP-3.0", + "PHP-3.01": "PHP-3.01", + "PIXAR": "Pixar", + "PKGCONF": "pkgconf", + "PLEXUS": "Plexus", + "PNMSTITCH": "pnmstitch", + "POLYFORM-NONCOMMERCIAL-1.0.0": "PolyForm-Noncommercial-1.0.0", + "POLYFORM-SMALL-BUSINESS-1.0.0": "PolyForm-Small-Business-1.0.0", + "POSTGRESQL": "PostgreSQL", + "PPL": "PPL", + "PSF-2.0": "PSF-2.0", + "PSFRAG": "psfrag", + "PSUTILS": "psutils", + "PYTHON-2.0": "Python-2.0", + "PYTHON-2.0.1": "Python-2.0.1", + "PYTHON-LDAP": "python-ldap", + "QHULL": "Qhull", + "QPL-1.0": "QPL-1.0", + "QPL-1.0-INRIA-2004": "QPL-1.0-INRIA-2004", + "RADVD": "radvd", + "RDISC": "Rdisc", + "RHECOS-1.1": "RHeCos-1.1", + "RPL-1.1": "RPL-1.1", + "RPL-1.5": "RPL-1.5", + "RPSL-1.0": "RPSL-1.0", + "RSA-MD": "RSA-MD", + "RSCPL": "RSCPL", + "RUBY": "Ruby", + "RUBY-PTY": "Ruby-pty", + "SAX-PD": "SAX-PD", + "SAX-PD-2.0": "SAX-PD-2.0", + "SAXPATH": "Saxpath", + "SCEA": "SCEA", + "SCHEMEREPORT": "SchemeReport", + "SENDMAIL": "Sendmail", + "SENDMAIL-8.23": "Sendmail-8.23", + "SENDMAIL-OPEN-SOURCE-1.1": "Sendmail-Open-Source-1.1", + "SGI-B-1.0": "SGI-B-1.0", + "SGI-B-1.1": "SGI-B-1.1", + "SGI-B-2.0": "SGI-B-2.0", + "SGI-OPENGL": "SGI-OpenGL", + "SGMLUG-PM": "SGMLUG-PM", + "SGP4": "SGP4", + "SHL-0.5": "SHL-0.5", + "SHL-0.51": "SHL-0.51", + "SIMPL-2.0": "SimPL-2.0", + "SISSL": "SISSL", + "SISSL-1.2": "SISSL-1.2", + "SL": "SL", + "SLEEPYCAT": "Sleepycat", + "SMAIL-GPL": "SMAIL-GPL", + "SMLNJ": "SMLNJ", + "SMPPL": "SMPPL", + "SNIA": "SNIA", + "SNPRINTF": "snprintf", + "SOFA": "SOFA", + "SOFTSURFER": "softSurfer", + "SOUNDEX": "Soundex", + "SPENCER-86": "Spencer-86", + "SPENCER-94": "Spencer-94", + "SPENCER-99": "Spencer-99", + "SPL-1.0": "SPL-1.0", + "SSH-KEYSCAN": "ssh-keyscan", + "SSH-OPENSSH": "SSH-OpenSSH", + "SSH-SHORT": "SSH-short", + "SSLEAY-STANDALONE": "SSLeay-standalone", + "SSPL-1.0": "SSPL-1.0", + "SUGARCRM-1.1.3": "SugarCRM-1.1.3", + "SUL-1.0": "SUL-1.0", + "SUN-PPP": "Sun-PPP", + "SUN-PPP-2000": "Sun-PPP-2000", + "SUNPRO": "SunPro", + "SWL": "SWL", + "SWRULE": "swrule", + "SYMLINKS": "Symlinks", + "TAPR-OHL-1.0": "TAPR-OHL-1.0", + "TCL": "TCL", + "TCP-WRAPPERS": "TCP-wrappers", + "TEKHVC": "TekHVC", + "TERMREADKEY": "TermReadKey", + "TGPPL-1.0": "TGPPL-1.0", + "THIRDEYE": "ThirdEye", + "THREEPARTTABLE": "threeparttable", + "TMATE": "TMate", + "TORQUE-1.1": "TORQUE-1.1", + "TOSL": "TOSL", + "TPDL": "TPDL", + "TPL-1.0": "TPL-1.0", + "TRUSTEDQSL": "TrustedQSL", + "TTWL": "TTWL", + "TTYP0": "TTYP0", + "TU-BERLIN-1.0": "TU-Berlin-1.0", + "TU-BERLIN-2.0": "TU-Berlin-2.0", + "UBUNTU-FONT-1.0": "Ubuntu-font-1.0", + "UCAR": "UCAR", + "UCL-1.0": "UCL-1.0", + "ULEM": "ulem", + "UMICH-MERIT": "UMich-Merit", + "UNICODE-3.0": "Unicode-3.0", + "UNICODE-DFS-2015": "Unicode-DFS-2015", + "UNICODE-DFS-2016": "Unicode-DFS-2016", + "UNICODE-TOU": "Unicode-TOU", + "UNIXCRYPT": "UnixCrypt", + "UNLICENSE": "Unlicense", + "UNLICENSE-LIBTELNET": "Unlicense-libtelnet", + "UNLICENSE-LIBWHIRLPOOL": "Unlicense-libwhirlpool", + "UNRAR": "UnRAR", + "UPL-1.0": "UPL-1.0", + "URT-RLE": "URT-RLE", + "VIM": "Vim", + "VIXIE-CRON": "Vixie-Cron", + "VOSTROM": "VOSTROM", + "VSL-1.0": "VSL-1.0", + "W3C": "W3C", + "W3C-19980720": "W3C-19980720", + "W3C-20150513": "W3C-20150513", + "W3M": "w3m", + "WATCOM-1.0": "Watcom-1.0", + "WIDGET-WORKSHOP": "Widget-Workshop", + "WORDNET": "WordNet", + "WSUIPA": "Wsuipa", + "WTFNMFPL": "WTFNMFPL", + "WTFPL": "WTFPL", + "WWL": "wwl", + "X11": "X11", + "X11-DISTRIBUTE-MODIFICATIONS-VARIANT": "X11-distribute-modifications-variant", + "X11-NO-PERMIT-PERSONS": "X11-no-permit-persons", + "X11-SWAPPED": "X11-swapped", + "XDEBUG-1.03": "Xdebug-1.03", + "XEROX": "Xerox", + "XFIG": "Xfig", + "XFREE86-1.1": "XFree86-1.1", + "XINETD": "xinetd", + "XKEYBOARD-CONFIG-ZINOVIEV": "xkeyboard-config-Zinoviev", + "XLOCK": "xlock", + "XNET": "Xnet", + "XPP": "xpp", + "XSKAT": "XSkat", + "XZOOM": "xzoom", + "YPL-1.0": "YPL-1.0", + "YPL-1.1": "YPL-1.1", + "ZED": "Zed", + "ZEEFF": "Zeeff", + "ZEND-2.0": "Zend-2.0", + "ZIMBRA-1.3": "Zimbra-1.3", + "ZIMBRA-1.4": "Zimbra-1.4", + "ZLIB": "Zlib", + "ZLIB-ACKNOWLEDGEMENT": "zlib-acknowledgement", + "ZPL-1.1": "ZPL-1.1", + "ZPL-2.0": "ZPL-2.0", + "ZPL-2.1": "ZPL-2.1", }