Files
aquasecurity-trivy/pkg/licensing/normalize.go

679 lines
44 KiB
Go

package licensing
import (
"regexp"
"slices"
"strings"
"github.com/samber/lo/it"
expr "github.com/aquasecurity/trivy/pkg/licensing/expression"
)
func licence(name string, hasPlus bool) expr.SimpleExpr {
return expr.SimpleExpr{License: name, HasPlus: hasPlus}
}
var mapping = map[string]expr.SimpleExpr{
// Simple mappings (i.e. that could be parsed by SpdxExpression.parse, at least without space)
// modified from https://github.com/oss-review-toolkit/ort/blob/fc5389c2cfd9c8b009794c8a11f5c91321b7a730/utils/spdx/src/main/resources/simple-license-mapping.yml
// Ambiguous simple mappings (mapping reason not obvious without additional information)
"AFL": licence(expr.AFL30, false),
"AGPL": licence(expr.AGPL30, false),
"AL-2": licence(expr.Apache20, false),
"AL-2.0": licence(expr.Apache20, false),
"APACHE": licence(expr.Apache20, false),
"APACHE-STYLE": licence(expr.Apache20, false),
"ARTISTIC": licence(expr.Artistic20, false),
"ASL": licence(expr.Apache20, false),
"BSD": licence(expr.BSD3Clause, false),
"BSD*": licence(expr.BSD3Clause, false),
"BSD-LIKE": licence(expr.BSD3Clause, false),
"BSD-STYLE": licence(expr.BSD3Clause, false),
"BSD-VARIANT": licence(expr.BSD3Clause, false),
"CDDL": licence(expr.CDDL10, false),
"ECLIPSE": licence(expr.EPL10, false),
"EPL": licence(expr.EPL10, false),
"EUPL": licence(expr.EUPL10, false),
"FDL": licence(expr.GFDL13, true),
"GFDL": licence(expr.GFDL13, true),
"GPL": licence(expr.GPL20, true),
"LGPL": licence(expr.LGPL20, true),
"MPL": licence(expr.MPL20, false),
"NETSCAPE": licence(expr.NPL11, false),
"PYTHON": licence(expr.Python20, false),
"ZOPE": licence(expr.ZPL21, false),
// Non-ambiguous simple mappings
"AFL-2": licence(expr.AFL20, false),
"AGPL-1.0": licence(expr.AGPL10, false),
"AGPL-3.0": licence(expr.AGPL30, false),
"APACHE-1": licence(expr.Apache10, false),
"APACHE-2": licence(expr.Apache20, false),
"APL-2": licence(expr.Apache20, false),
"APL-2.0": licence(expr.Apache20, false),
"ARTISTIC-1.0-CL-8": licence(expr.Artistic10cl8, false),
"ASF-1": licence(expr.Apache10, false),
"ASF-1.0": licence(expr.Apache10, false),
"ASF-1.1": licence(expr.Apache11, false),
"ASF-2": licence(expr.Apache20, false),
"ASF-2.0": licence(expr.Apache20, false),
"ASL-1": licence(expr.Apache10, false),
"ASL-1.0": licence(expr.Apache10, false),
"ASL-1.1": licence(expr.Apache11, false),
"ASL-2": licence(expr.Apache20, false),
"ASL-2.0": licence(expr.Apache20, false),
"BCL": licence(expr.BCL, false),
"BOOST": licence(expr.BSL10, false),
"BOOST-1.0": licence(expr.BSL10, false),
"BOUNCY": licence(expr.MIT, false),
"BSD-1": licence(expr.BSD1Clause, false),
"BSD-2": licence(expr.BSD2Clause, false),
"BSD-3": licence(expr.BSD3Clause, false),
"BSD-3-CLAUSE": licence(expr.BSD3Clause, false),
"BSD-4": licence(expr.BSD4Clause, false),
"BSL": licence(expr.BSL10, false),
"CC0": licence(expr.CC010, false),
"CDDL-1": licence(expr.CDDL10, false),
"COMMONS-CLAUSE": licence(expr.CommonsClause, false),
"CPAL": licence(expr.CPAL10, false),
"CPL": licence(expr.CPL10, false),
"CPL-1.0": licence(expr.CPL10, false),
"ECLIPSE-1.0": licence(expr.EPL10, false),
"ECLIPSE-2.0": licence(expr.EPL20, false),
"EDL-1.0": licence(expr.BSD3Clause, false),
"EXPAT": licence(expr.MIT, false),
"FACEBOOK-2-CLAUSE": licence(expr.Facebook2Clause, false),
"FACEBOOK-3-CLAUSE": licence(expr.Facebook3Clause, false),
"FACEBOOK-EXAMPLES": licence(expr.FacebookExamples, false),
"GFDL-1.1": licence(expr.GFDL11, false),
"GFDL-1.1-INVARIANTS": licence(expr.GFDL11WithInvariants, false),
"GFDL-1.1-NO-INVARIANTS": licence(expr.GFDL11NoInvariants, false),
"GFDL-NIV-1.1": licence(expr.GFDL11NoInvariants, false),
"GFDL-1.2": licence(expr.GFDL12, false),
"GFDL-1.2-INVARIANTS": licence(expr.GFDL12WithInvariants, false),
"GFDL-1.2-NO-INVARIANTS": licence(expr.GFDL12NoInvariants, false),
"GFDL-NIV-1.2": licence(expr.GFDL12NoInvariants, false),
"GFDL-1.3": licence(expr.GFDL13, false),
"GFDL-1.3-INVARIANTS": licence(expr.GFDL13WithInvariants, false),
"GFDL-1.3-NO-INVARIANTS": licence(expr.GFDL13NoInvariants, false),
"GFDL-NIV-1.3": licence(expr.GFDL13NoInvariants, false),
"GO": licence(expr.BSD3Clause, false),
"GPL-1": licence(expr.GPL10, false),
"GPL-1.0": licence(expr.GPL10, false),
"GPL-2": licence(expr.GPL20, false),
"GPL-2+-WITH-BISON-EXCEPTION": licence(expr.GPL20withbisonexception, true),
"GPL-2.0": licence(expr.GPL20, false),
"GPL-2.0-WITH-AUTOCONF-EXCEPTION": licence(expr.GPL20withautoconfexception, false),
"GPL-2.0-WITH-BISON-EXCEPTION": licence(expr.GPL20withbisonexception, false),
"GPL-2.0-WITH-CLASSPATH-EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"GPL-2.0-WITH-FONT-EXCEPTION": licence(expr.GPL20withfontexception, false),
"GPL-2.0-WITH-GCC-EXCEPTION": licence(expr.GPL20withGCCexception, false),
"GPL-3": licence(expr.GPL30, false),
"GPL-3+-WITH-BISON-EXCEPTION": licence(expr.GPL20withbisonexception, true),
"GPL-3.0": licence(expr.GPL30, false),
"GPL-3.0-WITH-AUTOCONF-EXCEPTION": licence(expr.GPL30withautoconfexception, false),
"GPL-3.0-WITH-GCC-EXCEPTION": licence(expr.GPL30withGCCexception, false),
"GPLV2+CE": licence(expr.GPL20withclasspathexception, true),
"GUST-FONT": licence(expr.GUSTFont, false),
"HSQLDB": licence(expr.BSD3Clause, false),
"ISCL": licence(expr.ISC, false),
"JQUERY": licence(expr.MIT, false),
"LGPL-2": licence(expr.LGPL20, false),
"LGPL-2.0": licence(expr.LGPL20, false),
"LGPL-2.1": licence(expr.LGPL21, false),
"LGPL-3": licence(expr.LGPL30, false),
"LGPL-3.0": licence(expr.LGPL30, false),
"LIL-1.0": licence(expr.Lil10, false),
"MIT-LIKE": licence(expr.MIT, false),
"MIT-STYLE": licence(expr.MIT, false),
"MPL-1": licence(expr.MPL10, false),
"MPL-2": licence(expr.MPL20, false),
"OFL-1.1": licence(expr.OFL11, false),
"OPENSSL": licence(expr.OpenSSL, false),
"OPENVISION": licence(expr.OpenVision, false),
"OSL-1": licence(expr.OSL10, false),
"OSL-2": licence(expr.OSL20, false),
"OSL-3": licence(expr.OSL30, false),
"PIL": licence(expr.PIL, false),
"PYTHON-2": licence(expr.Python20, false),
"PYTHON-2.0-COMPLETE": licence(expr.Python20complete, false),
"QPL-1": licence(expr.QPL10, false),
"UPL-1": licence(expr.UPL10, false),
"W3CL": licence(expr.W3C, false),
"WTF": licence(expr.WTFPL, false),
"ZEND-2": licence(expr.Zend20, false),
"ZOPE-1.1": licence(expr.ZPL11, false),
"ZOPE-2.0": licence(expr.ZPL20, false),
"ZOPE-2.1": licence(expr.ZPL21, false),
// Non simple declared mappings
// modified from https://github.com/oss-review-toolkit/ort/blob/fc5389c2cfd9c8b009794c8a11f5c91321b7a730/utils/spdx/src/main/resources/declared-license-mapping.yml
// Ambiguous declared mappings (mapping reason not obvious without additional information)
"ACADEMIC FREE LICENSE (AFL)": licence(expr.AFL21, false),
"APACHE SOFTWARE LICENSES": licence(expr.Apache20, false),
"APACHE SOFTWARE": licence(expr.Apache20, false),
"APPLE PUBLIC SOURCE": licence(expr.APSL10, false),
"BSD SOFTWARE": licence(expr.BSD2Clause, false),
"BSD STYLE": licence(expr.BSD3Clause, false),
"COMMON DEVELOPMENT AND DISTRIBUTION": licence(expr.CDDL10, false),
"CREATIVE COMMONS - BY": licence(expr.CCBY30, false),
"CREATIVE COMMONS ATTRIBUTION": licence(expr.CCBY30, false),
"CREATIVE COMMONS": licence(expr.CCBY30, false),
"ECLIPSE PUBLIC LICENSE (EPL)": licence(expr.EPL10, false),
"GENERAL PUBLIC LICENSE (GPL)": licence(expr.GPL20, true),
"GNU FREE DOCUMENTATION LICENSE (FDL)": licence(expr.GFDL13, true),
"GNU GENERAL PUBLIC LIBRARY": licence(expr.GPL30, true),
"GNU GENERAL PUBLIC LICENSE (GPL)": licence(expr.GPL30, true),
"GNU GPL": licence(expr.GPL20, false),
"GNU LESSER GENERAL PUBLIC LICENSE (LGPL)": licence(expr.LGPL21, false),
"GNU LESSER GENERAL PUBLIC": licence(expr.LGPL21, false),
"GNU LESSER PUBLIC": licence(expr.LGPL21, false),
"GNU LESSER": licence(expr.LGPL21, false),
"GNU LGPL": licence(expr.LGPL21, false),
"GNU LIBRARY OR LESSER GENERAL PUBLIC LICENSE (LGPL)": licence(expr.LGPL21, false),
"GNU PUBLIC": licence(expr.GPL20, true),
"GPL (WITH DUAL LICENSING OPTION)": licence(expr.GPL20, false),
"GPLV2 WITH EXCEPTIONS": licence(expr.GPL20withclasspathexception, false),
"INDIVIDUAL BSD": licence(expr.BSD3Clause, false),
"LESSER GENERAL PUBLIC LICENSE (LGPL)": licence(expr.LGPL21, true),
"LGPL WITH EXCEPTIONS": licence(expr.LGPL30, false),
"LPGL, SEE LICENSE FILE.": licence(expr.LGPL30, true),
"MOZILLA PUBLIC": licence(expr.MPL20, false),
"ZOPE PUBLIC": licence(expr.ZPL21, false),
// Non-ambiguous declared mappings
"(NEW) BSD": licence(expr.BSD3Clause, false),
"2-CLAUSE BSD": licence(expr.BSD2Clause, false),
"2-CLAUSE BSDL": licence(expr.BSD2Clause, false),
"3-CLAUSE BDSL": licence(expr.BSD3Clause, false),
"3-CLAUSE BSD": licence(expr.BSD3Clause, false),
"ACADEMIC FREE LICENSE (AFL-2.1": licence(expr.AFL21, false),
"AFFERO GENERAL PUBLIC LICENSE (AGPL-3": licence(expr.AGPL30, false),
"APACHE 2 STYLE": licence(expr.Apache20, false),
"APACHE LICENSE, ASL-2.0": licence(expr.Apache20, false),
"APACHE LICENSE, VERSION 2.0 (HTTP://WWW.APACHE.ORG/LICENSES/LICENSE-2.0": licence(expr.Apache20, false),
"APACHE PUBLIC-1.1": licence(expr.Apache11, false),
"APACHE PUBLIC-2": licence(expr.Apache20, false),
"APACHE PUBLIC-2.0": licence(expr.Apache20, false),
"APACHE SOFTWARE LICENSE (APACHE-2": licence(expr.Apache20, false),
"APACHE SOFTWARE LICENSE (APACHE-2.0": licence(expr.Apache20, false),
"APACHE SOFTWARE-1.1": licence(expr.Apache11, false),
"APACHE SOFTWARE-2": licence(expr.Apache20, false),
"APACHE SOFTWARE-2.0": licence(expr.Apache20, false),
"APACHE VERSION 2.0, JANUARY 2004": licence(expr.Apache20, false),
"APACHE-2.0 */ ' " =END --": licence(expr.Apache20, false),
"BERKELEY SOFTWARE DISTRIBUTION (BSD)": licence(expr.BSD2Clause, false),
"BOOST SOFTWARE LICENSE 1.0 (BSL-1.0": licence(expr.BSL10, false),
"BOOST SOFTWARE": licence(expr.BSL10, false),
"BOUNCY CASTLE": licence(expr.MIT, false),
"BSD (3-CLAUSE)": licence(expr.BSD3Clause, false),
"BSD - SEE NDG/HTTPSCLIENT/LICENSE FILE FOR DETAILS": licence(expr.BSD3Clause, false),
"BSD 2 CLAUSE": licence(expr.BSD2Clause, false),
"BSD 2-CLAUSE": licence(expr.BSD2Clause, false),
"BSD 3 CLAUSE": licence(expr.BSD3Clause, false),
"BSD 3-CLAUSE NEW": licence(expr.BSD3Clause, false),
"BSD 3-CLAUSE \"NEW\" OR \"REVISED\" LICENSE (BSD-3-CLAUSE)": licence(expr.BSD3Clause, false),
"BSD 3-CLAUSE": licence(expr.BSD3Clause, false),
"BSD 4 CLAUSE": licence(expr.BSD4Clause, false),
"BSD 4-CLAUSE": licence(expr.BSD4Clause, false),
"BSD FOUR CLAUSE": licence(expr.BSD4Clause, false),
"BSD LICENSE FOR HSQL": licence(expr.BSD3Clause, false),
"BSD NEW": licence(expr.BSD3Clause, false),
"BSD THREE CLAUSE": licence(expr.BSD3Clause, false),
"BSD TWO CLAUSE": licence(expr.BSD2Clause, false),
"BSD-3 CLAUSE": licence(expr.BSD3Clause, false),
"BSD-STYLE + ATTRIBUTION": licence(expr.BSD3ClauseAttribution, false),
"CC BY-NC-SA-2.0": licence(expr.CCBYNCSA20, false),
"CC BY-NC-SA-2.5": licence(expr.CCBYNCSA25, false),
"CC BY-NC-SA-3.0": licence(expr.CCBYNCSA30, false),
"CC BY-NC-SA-4.0": licence(expr.CCBYNCSA40, false),
"CC BY-SA-2.0": licence(expr.CCBYSA20, false),
"CC BY-SA-2.5": licence(expr.CCBYSA25, false),
"CC BY-SA-3.0": licence(expr.CCBYSA30, false),
"CC BY-SA-4.0": licence(expr.CCBYSA40, false),
"CC0 1.0 UNIVERSAL (CC0 1.0) PUBLIC DOMAIN DEDICATION": licence(expr.CC010, false),
"CC0 1.0 UNIVERSAL": licence(expr.CC010, false),
"COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)-1.0": licence(expr.CDDL10, false),
"COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)-1.1": licence(expr.CDDL11, false),
"COMMON DEVELOPMENT AND DISTRIBUTION LICENSE 1.0 (CDDL-1.0": licence(expr.CDDL10, false),
"COMMON DEVELOPMENT AND DISTRIBUTION LICENSE 1.1 (CDDL-1.1": licence(expr.CDDL11, false),
"COMMON PUBLIC": licence(expr.CPL10, false),
"COMMON PUBLIC-1.0": licence(expr.CPL10, false),
"CREATIVE COMMONS - ATTRIBUTION 4.0 INTERNATIONAL": licence(expr.CCBY40, false),
"CREATIVE COMMONS 3.0 BY-SA": licence(expr.CCBYSA30, false),
"CREATIVE COMMONS ATTRIBUTION 3.0 UNPORTED (CC BY-3.0": licence(expr.CCBY30, false),
"CREATIVE COMMONS ATTRIBUTION 4.0 INTERNATIONAL (CC BY-4.0": licence(expr.CCBY40, false),
"CREATIVE COMMONS ATTRIBUTION 4.0 INTERNATIONAL PUBLIC": licence(expr.CCBY40, false),
"CREATIVE COMMONS ATTRIBUTION-1.0": licence(expr.CCBY10, false),
"CREATIVE COMMONS ATTRIBUTION-2.5": licence(expr.CCBY25, false),
"CREATIVE COMMONS ATTRIBUTION-3.0": licence(expr.CCBY30, false),
"CREATIVE COMMONS ATTRIBUTION-4.0": licence(expr.CCBY40, false),
"CREATIVE COMMONS ATTRIBUTION-NONCOMMERCIAL 4.0 INTERNATIONAL": licence(expr.CCBYNC40, false),
"CREATIVE COMMONS ATTRIBUTION-NONCOMMERCIAL-NODERIVATIVES 4.0 INTERNATIONAL": licence(expr.CCBYNCND40, false),
"CREATIVE COMMONS ATTRIBUTION-NONCOMMERCIAL-SHAREALIKE 3.0 UNPORTED (CC BY-NC-SA-3.0": licence(expr.CCBYNCSA30, false),
"CREATIVE COMMONS ATTRIBUTION-NONCOMMERCIAL-SHAREALIKE 4.0 INTERNATIONAL PUBLIC": licence(expr.CCBYNCSA40, false),
"CREATIVE COMMONS CC0": licence(expr.CC010, false),
"CREATIVE COMMONS GNU LGPL-2.1": licence(expr.LGPL21, false),
"CREATIVE COMMONS LICENSE ATTRIBUTION-NODERIVS 3.0 UNPORTED": licence(expr.CCBYNCND30, false),
"CREATIVE COMMONS LICENSE ATTRIBUTION-NONCOMMERCIAL-SHAREALIKE 3.0 UNPORTED": licence(expr.CCBYNCSA30, false),
"CREATIVE COMMONS ZERO": licence(expr.CC010, false),
"CREATIVE COMMONS-3.0": licence(expr.CCBY30, false),
"ECLIPSE DISTRIBUTION LICENSE (EDL)-1.0": licence(expr.BSD3Clause, false),
"ECLIPSE DISTRIBUTION LICENSE (NEW BSD LICENSE)": licence(expr.BSD3Clause, false),
"ECLIPSE DISTRIBUTION-1.0": licence(expr.BSD3Clause, false),
"ECLIPSE PUBLIC LICENSE (EPL)-1.0": licence(expr.EPL10, false),
"ECLIPSE PUBLIC LICENSE (EPL)-2.0": licence(expr.EPL20, false),
"ECLIPSE PUBLIC LICENSE 1.0 (EPL-1.0": licence(expr.EPL10, false),
"ECLIPSE PUBLIC LICENSE 2.0 (EPL-2.0": licence(expr.EPL20, false),
"ECLIPSE PUBLIC": licence(expr.EPL10, false),
"ECLIPSE PUBLIC-1.0": licence(expr.EPL10, false),
"ECLIPSE PUBLIC-2.0": licence(expr.EPL20, false),
"ECLIPSE PUBLISH-1.0": licence(expr.EPL10, false),
"EPL (ECLIPSE PUBLIC LICENSE)-1.0": licence(expr.EPL10, false),
"EU PUBLIC LICENSE 1.0 (EUPL-1.0": licence(expr.EUPL10, false),
"EU PUBLIC LICENSE 1.1 (EUPL-1.1": licence(expr.EUPL11, false),
"EUROPEAN UNION PUBLIC LICENSE (EUPL-1.0": licence(expr.EUPL10, false),
"EUROPEAN UNION PUBLIC LICENSE (EUPL-1.1": licence(expr.EUPL11, false),
"EUROPEAN UNION PUBLIC LICENSE 1.0 (EUPL-1.0": licence(expr.EUPL10, false),
"EUROPEAN UNION PUBLIC LICENSE 1.1 (EUPL-1.1": licence(expr.EUPL11, false),
"EUROPEAN UNION PUBLIC-1.0": licence(expr.EUPL10, false),
"EUROPEAN UNION PUBLIC-1.1": licence(expr.EUPL11, false),
"EXPAT (MIT/X11)": licence(expr.MIT, false),
"GENERAL PUBLIC LICENSE 2.0 (GPL)": licence(expr.GPL20, false),
"GNU AFFERO GENERAL PUBLIC LICENSE V3 (AGPL-3": licence(expr.AGPL30, false),
"GNU AFFERO GENERAL PUBLIC LICENSE V3 (AGPL-3.0": licence(expr.AGPL30, false),
"GNU AFFERO GENERAL PUBLIC LICENSE V3 OR LATER (AGPL3+)": licence(expr.AGPL30, true),
"GNU AFFERO GENERAL PUBLIC LICENSE V3 OR LATER (AGPLV3+)": licence(expr.AGPL30, true),
"GNU AFFERO GENERAL PUBLIC-3": licence(expr.AGPL30, false),
"GNU FREE DOCUMENTATION LICENSE (GFDL-1.3": licence(expr.GFDL13, false),
"GNU GENERAL LESSER PUBLIC LICENSE (LGPL)-2.1": licence(expr.LGPL21, false),
"GNU GENERAL LESSER PUBLIC LICENSE (LGPL)-3.0": licence(expr.LGPL30, false),
"GNU GENERAL PUBLIC LICENSE (GPL), VERSION 2, WITH CLASSPATH EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"GNU GENERAL PUBLIC LICENSE (GPL), VERSION 2, WITH THE CLASSPATH EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"GNU GENERAL PUBLIC LICENSE (GPL)-2": licence(expr.GPL20, false),
"GNU GENERAL PUBLIC LICENSE (GPL)-3": licence(expr.GPL30, false),
"GNU GENERAL PUBLIC LICENSE V2 (GPL-2": licence(expr.GPL20, false),
"GNU GENERAL PUBLIC LICENSE V2 OR LATER (GPLV2+)": licence(expr.GPL20, true),
"GNU GENERAL PUBLIC LICENSE V2.0 ONLY, WITH CLASSPATH EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"GNU GENERAL PUBLIC LICENSE V3 (GPL-3": licence(expr.GPL30, false),
"GNU GENERAL PUBLIC LICENSE V3 OR LATER (GPLV3+)": licence(expr.GPL30, true),
"GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL-2": licence(expr.GPL20, false),
"GNU GENERAL PUBLIC LICENSE VERSION 2, JUNE 1991": licence(expr.GPL20, false),
"GNU GENERAL PUBLIC LICENSE VERSION 3 (GPL-3": licence(expr.GPL30, false),
"GNU GENERAL PUBLIC LICENSE, VERSION 2 (GPL2), WITH THE CLASSPATH EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"GNU GENERAL PUBLIC LICENSE, VERSION 2 WITH THE CLASSPATH EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"GNU GENERAL PUBLIC LICENSE, VERSION 2 WITH THE GNU CLASSPATH EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"GNU GENERAL PUBLIC LICENSE, VERSION 2, WITH THE CLASSPATH EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"GNU GENERAL PUBLIC-2": licence(expr.GPL20, false),
"GNU GENERAL PUBLIC-3": licence(expr.GPL30, false),
"GNU GPL-2": licence(expr.GPL20, false),
"GNU GPL-3": licence(expr.GPL30, false),
"GNU LESSER GENERAL PUBLIC LICENSE (LGPL)-2": licence(expr.LGPL20, false),
"GNU LESSER GENERAL PUBLIC LICENSE (LGPL)-2.0": licence(expr.LGPL20, false),
"GNU LESSER GENERAL PUBLIC LICENSE (LGPL)-2.1": licence(expr.LGPL21, false),
"GNU LESSER GENERAL PUBLIC LICENSE (LGPL)-3": licence(expr.LGPL30, false),
"GNU LESSER GENERAL PUBLIC LICENSE (LGPL)-3.0": licence(expr.LGPL30, false),
"GNU LESSER GENERAL PUBLIC LICENSE (LGPL-2": licence(expr.LGPL20, false),
"GNU LESSER GENERAL PUBLIC LICENSE (LGPL-2.0": licence(expr.LGPL20, false),
"GNU LESSER GENERAL PUBLIC LICENSE (LGPL-2.1": licence(expr.LGPL21, false),
"GNU LESSER GENERAL PUBLIC LICENSE (LGPL-3": licence(expr.LGPL30, false),
"GNU LESSER GENERAL PUBLIC LICENSE (LGPL-3.0": licence(expr.LGPL30, false),
"GNU LESSER GENERAL PUBLIC LICENSE V2 (LGPL-2": licence(expr.LGPL20, false),
"GNU LESSER GENERAL PUBLIC LICENSE V2 OR LATER (LGPLV2+)": licence(expr.LGPL20, true),
"GNU LESSER GENERAL PUBLIC LICENSE V3 (LGPL-3": licence(expr.LGPL30, false),
"GNU LESSER GENERAL PUBLIC LICENSE V3 OR LATER (LGPLV3+)": licence(expr.LGPL30, true),
"GNU LESSER GENERAL PUBLIC LICENSE VERSION 2.1 (LGPL-2.1": licence(expr.LGPL21, false),
"GNU LESSER GENERAL PUBLIC LICENSE VERSION 2.1, FEBRUARY 1999": licence(expr.LGPL21, false),
"GNU LESSER GENERAL PUBLIC LICENSE, VERSION 2.1, FEBRUARY 1999": licence(expr.LGPL21, false),
"GNU LESSER GENERAL PUBLIC-2": licence(expr.LGPL20, false),
"GNU LESSER GENERAL PUBLIC-2.0": licence(expr.LGPL20, false),
"GNU LESSER GENERAL PUBLIC-2.1": licence(expr.LGPL21, false),
"GNU LESSER GENERAL PUBLIC-3": licence(expr.LGPL30, false),
"GNU LESSER GENERAL PUBLIC-3.0": licence(expr.LGPL30, false),
"GNU LGP (GNU GENERAL PUBLIC LICENSE)-2": licence(expr.LGPL20, false),
"GNU LGPL (GNU LESSER GENERAL PUBLIC LICENSE)-2.1": licence(expr.LGPL21, false),
"GNU LGPL-2": licence(expr.LGPL20, false),
"GNU LGPL-2.0": licence(expr.LGPL20, false),
"GNU LGPL-2.1": licence(expr.LGPL21, false),
"GNU LGPL-3": licence(expr.LGPL30, false),
"GNU LGPL-3.0": licence(expr.LGPL30, false),
"GNU LIBRARY GENERAL PUBLIC-2.0": licence(expr.LGPL20, false),
"GNU LIBRARY GENERAL PUBLIC-2.1": licence(expr.LGPL21, false),
"GNU LIBRARY OR LESSER GENERAL PUBLIC LICENSE VERSION 2.0 (LGPL-2": licence(expr.LGPL20, false),
"GNU LIBRARY OR LESSER GENERAL PUBLIC LICENSE VERSION 3.0 (LGPL-3": licence(expr.LGPL30, false),
"GPL (≥ 3)": licence(expr.GPL30, true),
"GPL 2 WITH CLASSPATH EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"GPL V2 WITH CLASSPATH EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"GPL-2+ WITH AUTOCONF EXCEPTION": licence(expr.GPL20withautoconfexception, true),
"GPL-3+ WITH AUTOCONF EXCEPTION": licence(expr.GPL30withautoconfexception, true),
"GPL2 W/ CPE": licence(expr.GPL20withclasspathexception, false),
"GPLV2 LICENSE, INCLUDES THE CLASSPATH EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"GPLV2 WITH CLASSPATH EXCEPTION": licence(expr.GPL20withclasspathexception, false),
"HSQLDB LICENSE, A BSD OPEN SOURCE": licence(expr.BSD3Clause, false),
"HTTP://ANT-CONTRIB.SOURCEFORGE.NET/TASKS/LICENSE.TXT": licence(expr.Apache11, false),
"HTTP://ASM.OW2.ORG/LICENSE.HTML": licence(expr.BSD3Clause, false),
"HTTP://CREATIVECOMMONS.ORG/PUBLICDOMAIN/ZERO/1.0/LEGALCODE": licence(expr.CC010, false),
"HTTP://EN.WIKIPEDIA.ORG/WIKI/ZLIB_LICENSE": licence(expr.Zlib, false),
"HTTP://JSON.CODEPLEX.COM/LICENSE": licence(expr.MIT, false),
"HTTP://POLYMER.GITHUB.IO/LICENSE.TXT": licence(expr.BSD3Clause, false),
"HTTP://WWW.APACHE.ORG/LICENSES/LICENSE-2.0": licence(expr.Apache20, false),
"HTTP://WWW.APACHE.ORG/LICENSES/LICENSE-2.0.HTML": licence(expr.Apache20, false),
"HTTP://WWW.APACHE.ORG/LICENSES/LICENSE-2.0.TXT": licence(expr.Apache20, false),
"HTTP://WWW.GNU.ORG/COPYLEFT/LESSER.HTML": licence(expr.LGPL30, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-NC-ND/1.0": licence(expr.CCBYNCND10, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-NC-ND/2.0": licence(expr.CCBYNCND20, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-NC-ND/2.5": licence(expr.CCBYNCND25, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-NC-ND/3.0": licence(expr.CCBYNCND30, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-NC-ND/4.0": licence(expr.CCBYNCND40, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-NC-SA/1.0": licence(expr.CCBYNCSA10, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-NC-SA/2.0": licence(expr.CCBYNCSA20, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-NC-SA/2.5": licence(expr.CCBYNCSA25, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-NC-SA/3.0": licence(expr.CCBYNCSA30, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-NC-SA/4.0": licence(expr.CCBYNCSA40, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-ND/1.0": licence(expr.CCBYND10, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-ND/2.0": licence(expr.CCBYND20, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-ND/2.5": licence(expr.CCBYND25, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-ND/3.0": licence(expr.CCBYND30, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-ND/4.0": licence(expr.CCBYND40, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-SA/1.0": licence(expr.CCBYSA10, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-SA/2.0": licence(expr.CCBYSA20, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-SA/2.5": licence(expr.CCBYSA25, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-SA/3.0": licence(expr.CCBYSA30, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY-SA/4.0": licence(expr.CCBYSA40, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY/1.0": licence(expr.CCBY10, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY/2.0": licence(expr.CCBY20, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY/2.5": licence(expr.CCBY25, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY/3.0": licence(expr.CCBY30, false),
"HTTPS://CREATIVECOMMONS.ORG/LICENSES/BY/4.0": licence(expr.CCBY40, false),
"HTTPS://CREATIVECOMMONS.ORG/PUBLICDOMAIN/ZERO/1.0/": licence(expr.CC010, false),
"HTTPS://GITHUB.COM/DOTNET/CORE-SETUP/BLOB/MASTER/LICENSE.TXT": licence(expr.MIT, false),
"HTTPS://GITHUB.COM/DOTNET/COREFX/BLOB/MASTER/LICENSE.TXT": licence(expr.MIT, false),
"HTTPS://RAW.GITHUB.COM/RDFLIB/RDFLIB/MASTER/LICENSE": licence(expr.BSD3Clause, false),
"HTTPS://RAW.GITHUBUSERCONTENT.COM/ASPNET/ASPNETCORE/2.0.0/LICENSE.TXT": licence(expr.Apache20, false),
"HTTPS://RAW.GITHUBUSERCONTENT.COM/ASPNET/HOME/2.0.0/LICENSE.TXT": licence(expr.Apache20, false),
"HTTPS://RAW.GITHUBUSERCONTENT.COM/NUGET/NUGET.CLIENT/DEV/LICENSE.TXT": licence(expr.Apache20, false),
"HTTPS://WWW.APACHE.ORG/LICENSES/LICENSE-2.0": licence(expr.Apache20, false),
"HTTPS://WWW.ECLIPSE.ORG/LEGAL/EPL-V10.HTML": licence(expr.EPL10, false),
"HTTPS://WWW.ECLIPSE.ORG/LEGAL/EPL-V20.HTML": licence(expr.EPL20, false),
"IBM PUBLIC": licence(expr.IPL10, false),
"ISC LICENSE (ISCL)": licence(expr.ISC, false),
"JYTHON SOFTWARE": licence(expr.Python20, false),
"KIRKK.COM BSD": licence(expr.BSD3Clause, false),
"LESSER GENERAL PUBLIC LICENSE, VERSION 3 OR GREATER": licence(expr.LGPL30, true),
"LICENSE AGREEMENT FOR OPEN SOURCE COMPUTER VISION LIBRARY (3-CLAUSE BSD LICENSE)": licence(expr.BSD3Clause, false),
"MIT (HTTP://MOOTOOLS.NET/LICENSE.TXT)": licence(expr.MIT, false),
"MIT / HTTP://REM.MIT-LICENSE.ORG": licence(expr.MIT, false),
"MIT LICENSE (HTTP://OPENSOURCE.ORG/LICENSES/MIT)": licence(expr.MIT, false),
"MIT LICENSE (MIT)": licence(expr.MIT, false),
"MIT LICENSE(MIT)": licence(expr.MIT, false),
"MIT LICENSED. HTTP://WWW.OPENSOURCE.ORG/LICENSES/MIT-LICENSE.PHP": licence(expr.MIT, false),
"MIT/EXPAT": licence(expr.MIT, false),
"MOCKRUNNER LICENSE, BASED ON APACHE SOFTWARE-1.1": licence(expr.Apache11, false),
"MODIFIED BSD": licence(expr.BSD3Clause, false),
"MOZILLA PUBLIC LICENSE 1.0 (MPL)": licence(expr.MPL10, false),
"MOZILLA PUBLIC LICENSE 1.1 (MPL-1.1": licence(expr.MPL11, false),
"MOZILLA PUBLIC LICENSE 2.0 (MPL-2.0": licence(expr.MPL20, false),
"MOZILLA PUBLIC-1.0": licence(expr.MPL10, false),
"MOZILLA PUBLIC-1.1": licence(expr.MPL11, false),
"MOZILLA PUBLIC-2.0": licence(expr.MPL20, false),
"NCSA OPEN SOURCE": licence(expr.NCSA, false),
"NETSCAPE PUBLIC LICENSE (NPL)": licence(expr.NPL10, false),
"NETSCAPE PUBLIC": licence(expr.NPL10, false),
"NEW BSD": licence(expr.BSD3Clause, false),
"OPEN SOFTWARE LICENSE 3.0 (OSL-3.0": licence(expr.OSL30, false),
"OPEN SOFTWARE-3.0": licence(expr.OSL30, false),
"PERL ARTISTIC-2": licence(expr.Artistic10Perl, false),
// Note: public domain without a specific license should not be mapped
// see https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files
// and https://opensource.google/documentation/reference/thirdparty/licenses#unencumbered
"PUBLIC DOMAIN (CC0-1.0)": licence(expr.CC010, false),
"PUBLIC DOMAIN, PER CREATIVE COMMONS CC0": licence(expr.CC010, false),
"QT PUBLIC LICENSE (QPL)": licence(expr.QPL10, false),
"QT PUBLIC": licence(expr.QPL10, false),
"REVISED BSD": licence(expr.BSD3Clause, false),
"RUBY'S": licence(expr.Ruby, false),
"SEQUENCE LIBRARY LICENSE (BSD-LIKE)": licence(expr.BSD3Clause, false),
"SIL OPEN FONT LICENSE 1.1 (OFL-1.1": licence(expr.OFL11, false),
"SIL OPEN FONT-1.1": licence(expr.OFL11, false),
"SIMPLIFIED BSD LISCENCE": licence(expr.BSD2Clause, false),
"SIMPLIFIED BSD": licence(expr.BSD2Clause, false),
"SUN INDUSTRY STANDARDS SOURCE LICENSE (SISSL)": licence(expr.SISSL, false),
"THREE-CLAUSE BSD-STYLE": licence(expr.BSD3Clause, false),
"TWO-CLAUSE BSD-STYLE": licence(expr.BSD2Clause, false),
"UNIVERSAL PERMISSIVE LICENSE (UPL)": licence(expr.UPL10, false),
"UNIVERSAL PERMISSIVE-1.0": licence(expr.UPL10, false),
"UNLICENSE (UNLICENSE)": licence(expr.Unlicense, false),
"W3C SOFTWARE": licence(expr.W3C, false),
"ZLIB / LIBPNG": licence(expr.ZlibAcknowledgement, false),
"ZLIB/LIBPNG": licence(expr.ZlibAcknowledgement, false),
"['MIT']": licence(expr.MIT, false),
}
const (
LicenseTextPrefix = "text://"
LicenseFilePrefix = "file://"
CustomLicensePrefix = "CUSTOM License"
)
// pythonLicenseExceptions contains licenses that we cannot separate correctly using our logic.
// first word after separator (or/and) => license name
var pythonLicenseExceptions = map[string]string{
"lesser": "GNU Library or Lesser General Public License (LGPL)",
"distribution": "Common Development and Distribution License 1.0 (CDDL-1.0)",
"disclaimer": "Historical Permission Notice and Disclaimer (HPND)",
}
// Split licenses without considering "and"/"or"
// examples:
// 'GPL-1+,GPL-2' => {"GPL-1+", "GPL-2"}
// 'GPL-1+ or Artistic or Artistic-dist' => {"GPL-1+", "Artistic", "Artistic-dist"}
// 'LGPLv3+_or_GPLv2+' => {"LGPLv3+", "GPLv2"}
// 'BSD-3-CLAUSE and GPL-2' => {"BSD-3-CLAUSE", "GPL-2"}
// 'GPL-1+ or Artistic, and BSD-4-clause-POWERDOG' => {"GPL-1+", "Artistic", "BSD-4-clause-POWERDOG"}
// 'BSD 3-Clause License or Apache License, Version 2.0' => {"BSD 3-Clause License", "Apache License, Version 2.0"}
var licenseSplitRegexp = regexp.MustCompile("(,?[_ ]+(?:or|and)[_ ]+)|(,[ ]*)")
// Typical keywords for license texts
var licenseTextKeywords = []string{
"http://",
"https://",
"(c)",
"as-is",
";",
"hereby",
"permission to use",
"permission is",
"use in source",
"use, copy, modify",
"using",
}
func isLicenseText(str string) bool {
for _, keyword := range licenseTextKeywords {
if strings.Contains(str, keyword) {
return true
}
}
return false
}
func TrimLicenseText(text string) string {
s := strings.Split(text, " ")
n := min(len(s), 3)
return strings.Join(s[:n], " ") + "..."
}
// version number match
var versionRegexpString = "([A-UW-Z)])( LICENSE)?\\s*[,(-]?\\s*(V|V\\.|VER|VER\\.|VERSION|VERSION-|-)?\\s*([1-9](\\.\\d)*)[)]?"
// case insensitive version match anywhere in string
var versionRegexp = regexp.MustCompile("(?i)" + versionRegexpString)
// version suffix match
var versionSuffixRegexp = regexp.MustCompile(versionRegexpString + "$")
// suffixes from https://spdx.dev/learn/handling-license-info/
var onlySuffixes = [2]string{"-ONLY", " ONLY"}
var plusSuffixes = [3]string{"+", "-OR-LATER", " OR LATER"}
func standardizeKeyAndSuffix(name string) expr.SimpleExpr {
// Standardize space, including newline
name = strings.Join(strings.Fields(name), " ")
name = strings.ToUpper(name)
// Do not perform any further normalization for URLs
if strings.HasPrefix(name, "HTTP") {
return expr.SimpleExpr{License: name, HasPlus: false}
}
name = strings.ReplaceAll(name, "LICENCE", "LICENSE")
name = strings.TrimPrefix(name, "THE ")
name = strings.TrimSuffix(name, " LICENSE")
name = strings.TrimSuffix(name, " LICENSED")
name = strings.TrimSuffix(name, "-LICENSE")
name = strings.TrimSuffix(name, "-LICENSED")
// Remove License and Licensed suffixes except for licenses already containing those suffixes such as Unlicense
if name != "UNLICENSE" {
name = strings.TrimSuffix(name, "LICENSE")
}
if name != "UNLICENSED" {
name = strings.TrimSuffix(name, "LICENSED")
}
hasPlus := false
for _, s := range plusSuffixes {
if strings.HasSuffix(name, s) {
name = strings.TrimSuffix(name, s)
hasPlus = true
}
}
for _, s := range onlySuffixes {
name = strings.TrimSuffix(name, s)
}
name = versionSuffixRegexp.ReplaceAllString(name, "$1-$4")
return expr.SimpleExpr{License: name, HasPlus: hasPlus}
}
func NormalizeLicenses(licenses []string) []string {
seq := it.UniqMap(slices.Values(licenses), normalizeLicense)
seq = it.Compact(seq)
normalized := slices.Collect(seq)
if len(normalized) == 0 {
return nil
}
return normalized
}
func normalizeLicense(name string) string {
return NormalizeLicenseExpression(expr.SimpleExpr{License: name}).String()
}
func NormalizeLicenseExpression(exp expr.Expression) expr.Expression {
switch e := exp.(type) {
case expr.SimpleExpr:
return normalizeSimpleExpr(e)
case expr.CompoundExpr:
return normalizeCompoundExpr(e)
}
return exp
}
func normalizeSimpleExpr(e expr.SimpleExpr) expr.Expression {
// Always trim leading and trailing spaces, even if we don't find this license in `mapping`.
name := strings.TrimSpace(e.License)
normalized := standardizeKeyAndSuffix(name)
if found, ok := mapping[normalized.License]; ok {
return expr.SimpleExpr{License: found.License, HasPlus: e.HasPlus || found.HasPlus || normalized.HasPlus}
}
// If not found in mapping, try to get the canonical SPDX license ID
if canonical, ok := expr.SPDXLicenseID(normalized.License); ok {
return expr.SimpleExpr{License: canonical, HasPlus: e.HasPlus || normalized.HasPlus}
}
return expr.SimpleExpr{License: name, HasPlus: e.HasPlus}
}
func normalizeCompoundExpr(e expr.CompoundExpr) expr.Expression {
if e.Conjunction() != expr.TokenWith {
return e // Do not normalize compound expressions other than "WITH"
}
normalized := standardizeKeyAndSuffix(e.String())
if found, ok := mapping[normalized.License]; ok {
return expr.SimpleExpr{License: found.License, HasPlus: found.HasPlus || normalized.HasPlus}
}
return e // Do not normalize compound expressions that are not found in `mapping`
}
func SplitLicenses(str string) []string {
if str == "" {
return nil
}
if isLicenseText(strings.ToLower(str)) {
return []string{
LicenseTextPrefix + str,
}
}
var licenses []string
for _, maybeLic := range licenseSplitRegexp.Split(str, -1) {
lower := strings.ToLower(maybeLic)
firstWord, _, _ := strings.Cut(lower, " ")
if len(licenses) > 0 {
// e.g. `Apache License, Version 2.0`
if firstWord == "ver" || firstWord == "version" {
licenses[len(licenses)-1] += ", " + maybeLic
continue
// e.g. `GNU Lesser General Public License v2 or later (LGPLv2+)`
} else if firstWord == "later" {
licenses[len(licenses)-1] += " or " + maybeLic
continue
} else if lic, ok := pythonLicenseExceptions[firstWord]; ok {
// Check `or` and `and` separators
if lic == licenses[len(licenses)-1]+" or "+maybeLic || lic == licenses[len(licenses)-1]+" and "+maybeLic {
licenses[len(licenses)-1] = lic
}
continue
}
}
licenses = append(licenses, maybeLic)
}
return licenses
}
// Split license string considering spaces as separator
// e.g. MPL 2.0 GPL2+ => {"MPL2.0", "GPL2+"}
func LaxSplitLicenses(str string) []string {
if str == "" {
return nil
}
var licenses []string
var afterWith bool
str = versionRegexp.ReplaceAllString(str, "$1-$4")
for s := range strings.FieldsSeq(str) {
s = strings.Trim(s, "()")
switch s {
case "":
continue
case "AND", "OR":
continue
case "WITH":
afterWith = true
continue
default:
normalizedLicense := normalizeLicense(s)
if afterWith && len(licenses) > 0 {
// If we found "WITH" operator, we should not split the license
// e.g. "GPL-2 WITH Autoconf exception" => {"GPL-2 WITH Autoconf exception"}
licenses[len(licenses)-1] += " WITH " + normalizedLicense
afterWith = false
} else {
licenses = append(licenses, normalizedLicense)
}
}
}
return licenses
}