github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/internal/spdxlicense/generate/license.go (about) 1 package main 2 3 import ( 4 "strings" 5 6 "github.com/scylladb/go-set/strset" 7 ) 8 9 type LicenseList struct { 10 Version string `json:"licenseListVersion"` 11 Licenses []License `json:"licenses"` 12 } 13 14 type License struct { 15 ID string `json:"licenseId"` 16 Name string `json:"name"` 17 Text string `json:"licenseText"` 18 Deprecated bool `json:"isDeprecatedLicenseId"` 19 OSIApproved bool `json:"isOsiApproved"` 20 SeeAlso []string `json:"seeAlso"` 21 } 22 23 // findReplacementLicense returns a replacement license for a deprecated license 24 func (ll LicenseList) findReplacementLicense(deprecated License) *License { 25 for _, l := range ll.Licenses { 26 if l.canReplace(deprecated) { 27 return &l 28 } 29 } 30 31 return nil 32 } 33 34 func (l License) canReplace(deprecated License) bool { 35 // don't replace a license with a deprecated license 36 if l.Deprecated { 37 return false 38 } 39 40 // We want to replace deprecated licenses with non-deprecated counterparts 41 // For more information, see: https://github.com/spdx/license-list-XML/issues/1676 42 switch { 43 case strings.ReplaceAll(l.ID, "-only", "") == deprecated.ID: 44 return true 45 case strings.ReplaceAll(l.ID, "-or-later", "+") == deprecated.ID: 46 return true 47 case l.ID == "BSD-2-Clause" && deprecated.ID == "BSD-2-Clause-NetBSD": 48 return true 49 case l.ID == "BSD-2-Clause-Views" && deprecated.ID == "BSD-2-Clause-FreeBSD": 50 return true 51 case l.ID == "bzip2-1.0.6" && deprecated.ID == "bzip2-1.0.5": 52 return true 53 case l.ID == "SMLNJ" && deprecated.ID == "StandardML-NJ": 54 return true 55 } 56 57 if l.Name != deprecated.Name { 58 return false 59 } 60 61 if l.OSIApproved != deprecated.OSIApproved { 62 return false 63 } 64 65 if len(l.SeeAlso) != len(deprecated.SeeAlso) { 66 return false 67 } 68 69 for i, sa := range l.SeeAlso { 70 if sa != deprecated.SeeAlso[i] { 71 return false 72 } 73 } 74 75 return l.ID == deprecated.ID 76 } 77 78 func buildLicenseIDPermutations(cleanID string) (perms []string) { 79 lv := findLicenseVersion(cleanID) 80 vp := versionPermutations(lv) 81 82 permSet := strset.New() 83 version := strings.Join(lv, ".") 84 for _, p := range vp { 85 permSet.Add(strings.Replace(cleanID, version, p, 1)) 86 } 87 88 permSet.Add(cleanID) 89 return permSet.List() 90 } 91 92 func findLicenseVersion(license string) (version []string) { 93 versionList := versionMatch.FindAllStringSubmatch(license, -1) 94 95 if len(versionList) == 0 { 96 return version 97 } 98 99 for i, v := range versionList[0] { 100 if v != "" && i != 0 { 101 version = append(version, v) 102 } 103 } 104 105 return version 106 } 107 108 func versionPermutations(version []string) []string { 109 ver := append([]string(nil), version...) 110 perms := strset.New() 111 for i := 1; i <= 3; i++ { 112 if len(ver) < i+1 { 113 ver = append(ver, "0") 114 } 115 116 perm := strings.Join(ver[:i], ".") 117 badCount := strings.Count(perm, "0") + strings.Count(perm, ".") 118 119 if badCount != len(perm) { 120 perms.Add(perm) 121 } 122 } 123 124 return perms.List() 125 }