mirror of
https://github.com/anchore/syft.git
synced 2026-11-01 15:06:36 +01:00
fix: lookup alternate scheme on url->licenseID (#4588)
--------- Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
This commit is contained in:
@@ -163,7 +163,8 @@ func cleanLicenseID(id string) string {
|
||||
return strings.ReplaceAll(cleanID, "-", "")
|
||||
}
|
||||
|
||||
// buildURLToLicenseMap creates a mapping from license URLs (from seeAlso fields) to license IDs
|
||||
// buildURLToLicenseMap creates a mapping from license URLs (from seeAlso fields) to license IDs.
|
||||
// URLs are stored without scheme (http:// or https://) so that a single lookup covers both.
|
||||
func buildURLToLicenseMap(result LicenseList) map[string]string {
|
||||
urlMap := make(map[string]string)
|
||||
|
||||
@@ -175,7 +176,7 @@ func buildURLToLicenseMap(result LicenseList) map[string]string {
|
||||
if replacement != nil {
|
||||
// Map deprecated license URLs to the replacement license
|
||||
for _, url := range l.SeeAlso {
|
||||
urlMap[url] = replacement.ID
|
||||
urlMap[stripScheme(url)] = replacement.ID
|
||||
}
|
||||
}
|
||||
continue
|
||||
@@ -183,9 +184,17 @@ func buildURLToLicenseMap(result LicenseList) map[string]string {
|
||||
|
||||
// Add URLs from non-deprecated licenses
|
||||
for _, url := range l.SeeAlso {
|
||||
urlMap[url] = l.ID
|
||||
urlMap[stripScheme(url)] = l.ID
|
||||
}
|
||||
}
|
||||
|
||||
return urlMap
|
||||
}
|
||||
|
||||
// stripScheme removes http:// or https:// prefix from a URL.
|
||||
// This allows a single map entry to match both schemes.
|
||||
func stripScheme(url string) string {
|
||||
url = strings.TrimPrefix(url, "https://")
|
||||
url = strings.TrimPrefix(url, "http://")
|
||||
return url
|
||||
}
|
||||
|
||||
@@ -41,10 +41,12 @@ type LicenseInfo struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
// LicenseByURL returns the license ID and name for a given URL from the SPDX license list
|
||||
// The URL should match one of the URLs in the seeAlso field of an SPDX license
|
||||
// LicenseByURL returns the license ID and name for a given URL from the SPDX license list.
|
||||
// The URL should match one of the URLs in the seeAlso field of an SPDX license.
|
||||
// The scheme (http:// or https://) is stripped before lookup, so both schemes match.
|
||||
func LicenseByURL(url string) (LicenseInfo, bool) {
|
||||
url = strings.TrimSpace(url)
|
||||
url = stripScheme(url)
|
||||
if id, exists := urlToLicense[url]; exists {
|
||||
return LicenseInfo{
|
||||
ID: id,
|
||||
@@ -52,3 +54,11 @@ func LicenseByURL(url string) (LicenseInfo, bool) {
|
||||
}
|
||||
return LicenseInfo{}, false
|
||||
}
|
||||
|
||||
// stripScheme removes http:// or https:// prefix from a URL.
|
||||
// This allows a single map entry to match both schemes.
|
||||
func stripScheme(url string) string {
|
||||
url = strings.TrimPrefix(url, "https://")
|
||||
url = strings.TrimPrefix(url, "http://")
|
||||
return url
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -76,6 +76,96 @@ func TestLicenseByURL(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLicenseByURL_AlternateScheme(t *testing.T) {
|
||||
// Test that URLs work with alternate schemes (http ↔ https) even if only one is in the SPDX list
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
wantID string
|
||||
wantFound bool
|
||||
}{
|
||||
{
|
||||
name: "Apache URL with http when https is in list",
|
||||
url: "http://www.apache.org/licenses/LICENSE-2.0",
|
||||
wantID: "Apache-2.0",
|
||||
wantFound: true,
|
||||
},
|
||||
{
|
||||
name: "BSD-3-Clause with http when https is in list",
|
||||
url: "http://opensource.org/licenses/BSD-3-Clause",
|
||||
wantID: "BSD-3-Clause",
|
||||
wantFound: true,
|
||||
},
|
||||
{
|
||||
name: "Unknown URL with http still not found",
|
||||
url: "http://example.com/not-a-real-license",
|
||||
wantID: "",
|
||||
wantFound: false,
|
||||
},
|
||||
{
|
||||
name: "Unknown URL with https still not found",
|
||||
url: "https://example.com/not-a-real-license",
|
||||
wantID: "",
|
||||
wantFound: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
info, found := LicenseByURL(tt.url)
|
||||
if found != tt.wantFound {
|
||||
t.Errorf("LicenseByURL() found = %v, want %v", found, tt.wantFound)
|
||||
}
|
||||
if found && info.ID != tt.wantID {
|
||||
t.Errorf("LicenseByURL() ID = %v, want %v", info.ID, tt.wantID)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStripScheme(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "https scheme stripped",
|
||||
url: "https://example.com/license",
|
||||
want: "example.com/license",
|
||||
},
|
||||
{
|
||||
name: "http scheme stripped",
|
||||
url: "http://example.com/license",
|
||||
want: "example.com/license",
|
||||
},
|
||||
{
|
||||
name: "ftp scheme not stripped",
|
||||
url: "ftp://example.com/license",
|
||||
want: "ftp://example.com/license",
|
||||
},
|
||||
{
|
||||
name: "no scheme unchanged",
|
||||
url: "example.com/license",
|
||||
want: "example.com/license",
|
||||
},
|
||||
{
|
||||
name: "empty string unchanged",
|
||||
url: "",
|
||||
want: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := stripScheme(tt.url)
|
||||
if got != tt.want {
|
||||
t.Errorf("stripScheme() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLicenseByURL_DeprecatedLicenses(t *testing.T) {
|
||||
// Test that deprecated license URLs map to their replacement licenses
|
||||
// For example, GPL-2.0+ should map to GPL-2.0-or-later
|
||||
|
||||
Reference in New Issue
Block a user