github.com/anchore/syft@v1.38.2/syft/license/license.go (about)

     1  // package license provides common methods for working with SPDX license data
     2  package license
     3  
     4  import (
     5  	"fmt"
     6  	"runtime/debug"
     7  	"strings"
     8  
     9  	"github.com/github/go-spdx/v2/spdxexp"
    10  
    11  	"github.com/anchore/syft/internal/spdxlicense"
    12  )
    13  
    14  type Type string
    15  
    16  const (
    17  	Declared  Type = "declared"
    18  	Concluded Type = "concluded"
    19  )
    20  
    21  // trimFileSuffix removes common file extensions from the end of a string
    22  func trimFileSuffix(s string) string {
    23  	suffixes := []string{".txt", ".pdf", ".html", ".htm", ".md", ".markdown", ".rst", ".doc", ".docx", ".rtf", ".tex", ".xml", ".json"}
    24  	lower := strings.ToLower(s)
    25  	for _, suffix := range suffixes {
    26  		if strings.HasSuffix(lower, suffix) {
    27  			return s[:len(s)-len(suffix)]
    28  		}
    29  	}
    30  	return s
    31  }
    32  
    33  func ParseExpression(expression string) (ex string, err error) {
    34  	// https://github.com/anchore/syft/issues/1837
    35  	// The current spdx library can panic when parsing some expressions
    36  	// This is a temporary fix to recover and patch until we can investigate and contribute
    37  	// a fix to the upstream github library
    38  	defer func() {
    39  		if r := recover(); r != nil {
    40  			err = fmt.Errorf("recovered from panic while parsing license expression at: \n%s", string(debug.Stack()))
    41  		}
    42  	}()
    43  
    44  	// Try with the original expression first
    45  	licenseID, exists := spdxlicense.ID(expression)
    46  	if exists {
    47  		return licenseID, nil
    48  	}
    49  
    50  	// Check if the expression is a URL and try to look it up
    51  	if info, found := spdxlicense.LicenseByURL(expression); found {
    52  		return info.ID, nil
    53  	}
    54  
    55  	// Try with trimmed file suffix
    56  	trimmed := trimFileSuffix(expression)
    57  	if trimmed != expression {
    58  		// Try as a URL with the trimmed version
    59  		if info, found := spdxlicense.LicenseByURL(trimmed); found {
    60  			return info.ID, nil
    61  		}
    62  	}
    63  
    64  	// If it doesn't exist initially in the SPDX list it might be a more complex expression
    65  	// ignored variable is any invalid expressions
    66  	// TODO: contribute to spdxexp to expose deprecated license IDs
    67  	// https://github.com/anchore/syft/issues/1814
    68  	valid, _ := spdxexp.ValidateLicenses([]string{expression})
    69  	if !valid {
    70  		return "", fmt.Errorf("invalid SPDX expression: %s", expression)
    71  	}
    72  
    73  	return expression, nil
    74  }