From 1681d0514ad07848b1ca3ddc10287b213075c812 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Wed, 9 Dec 2015 13:48:08 +0000 Subject: Add as_utils_license_to_spdx() This moves the Fedora-Legal->SPDX conversion code from libappstream-builder to libappstream-glib, which allows front ends like GNOME Software to display a valid SPDX ID when no AppStream or AppData information is available. It also fixes the multi-token search which was not working before. --- libappstream-builder/asb-package-rpm.c | 88 +-------------------------- libappstream-glib/as-self-test.c | 5 ++ libappstream-glib/as-utils.c | 105 +++++++++++++++++++++++++++++++++ libappstream-glib/as-utils.h | 1 + 4 files changed, 114 insertions(+), 85 deletions(-) diff --git a/libappstream-builder/asb-package-rpm.c b/libappstream-builder/asb-package-rpm.c index 9c5fe0d..42b15cd 100644 --- a/libappstream-builder/asb-package-rpm.c +++ b/libappstream-builder/asb-package-rpm.c @@ -78,72 +78,8 @@ static void asb_package_rpm_set_license (AsbPackage *pkg, const gchar *license) { guint i; - guint j; g_autofree gchar *new = NULL; g_auto(GStrv) tokens = NULL; - struct { - const gchar *fedora; - const gchar *spdx; - } convert[] = { - { "AGPLv3", "AGPL-3.0" }, - { "AGPLv3+", "AGPL-3.0" }, - { "AGPLv3 with exceptions", "AGPL-3.0" }, - { "AGPLv3+ with exceptions", "AGPL-3.0" }, - { "Artistic 2.0", "Artistic-2.0" }, - { "Artistic", "Artistic-1.0" }, - { "Artistic clarified", "Artistic-2.0" }, - { "ASL 1.1", "Apache-1.1" }, - { "ASL 2.0", "Apache-2.0" }, - { "Boost", "BSL-1.0" }, - { "BSD", "BSD-3-Clause" }, - { "BSD with advertising", "BSD-3-Clause" }, - { "CC0", "CC0-1.0" }, - { "CC-BY", "CC-BY-3.0" }, - { "CC-BY-SA", "CC-BY-SA-3.0" }, - { "CDDL", "CDDL-1.0" }, - { "CeCILL-C", "CECILL-C" }, - { "CeCILL", "CECILL-2.0" }, - { "CPAL", "CPAL-1.0" }, - { "CPL", "CPL-1.0" }, - { "EPL", "EPL-1.0" }, - { "Free Art", "ClArtistic" }, - { "GFDL", "GFDL-1.3" }, - { "GPL+", "GPL-1.0+" }, - { "GPLv2", "GPL-2.0" }, - { "GPLv2+", "GPL-2.0+" }, - { "GPLV2", "GPL-2.0" }, - { "GPLv2 with exceptions", "GPL-2.0-with-font-exception" }, - { "GPLv2+ with exceptions", "GPL-2.0-with-font-exception" }, - { "GPLv3", "GPL-3.0" }, - { "GPLv3+", "GPL-3.0+" }, - { "GPLV3+", "GPL-3.0+" }, - { "GPLv3+ with exceptions", "GPL-3.0+" }, - { "GPLv3 with exceptions", "GPL-3.0-with-GCC-exception" }, - { "GPL+ with exceptions", "GPL-2.0-with-font-exception" }, - { "IBM", "IPL-1.0" }, - { "LGPL+", "LGPL-2.1+" }, - { "LGPLv2.1", "LGPL-2.1" }, - { "LGPLv2", "LGPL-2.1" }, - { "LGPLv2+", "LGPL-2.1+" }, - { "LGPLv2 with exceptions", "LGPL-2.0" }, - { "LGPLv2+ with exceptions", "LGPL-2.0+" }, - { "LGPLv3", "LGPL-3.0" }, - { "LGPLv3+", "LGPL-3.0+" }, - { "LPPL", "LPPL-1.3c" }, - { "MIT with advertising", "MIT" }, - { "MPLv1.0", "MPL-1.0" }, - { "MPLv1.1", "MPL-1.1" }, - { "MPLv2.0", "MPL-2.0" }, - { "Netscape", "NPL-1.1" }, - { "OFL", "OFL-1.1" }, - { "Python", "Python-2.0" }, - { "QPL", "QPL-1.0" }, - { "QPL with exceptions", "QPL-1.0" }, - { "SPL", "SPL-1.0" }, - { "zlib", "Zlib" }, - { "ZPLv2.0", "ZPL-2.0" }, - { "Unlicense", "CC0-1.0" }, - { NULL, NULL } }; /* this isn't supposed to happen */ if (license == NULL) { @@ -152,9 +88,9 @@ asb_package_rpm_set_license (AsbPackage *pkg, const gchar *license) return; } - /* tokenize the license string and try to convert the Fedora license - * string to a SPDX license the best we can */ - tokens = as_utils_spdx_license_tokenize (license); + /* tokenize the license string and log non SPDX licenses */ + new = as_utils_license_to_spdx (license); + tokens = as_utils_spdx_license_tokenize (new); for (i = 0; tokens[i] != NULL; i++) { /* ignore */ @@ -168,30 +104,12 @@ asb_package_rpm_set_license (AsbPackage *pkg, const gchar *license) if (tokens[i][0] == '@') continue; - /* convert */ - for (j = 0; convert[j].fedora != NULL; j++) { - if (g_strcmp0 (tokens[i], convert[j].fedora) == 0) { - g_free (tokens[i]); - tokens[i] = g_strdup_printf ("@%s", convert[j].spdx); - asb_package_log (pkg, - ASB_PACKAGE_LOG_LEVEL_DEBUG, - "Converting Fedora license " - "'%s' to SPDX '%s'", - convert[j].fedora, - convert[j].spdx); - break; - } - } - if (convert[j].fedora != NULL) - continue; - /* no matching SPDX entry */ asb_package_log (pkg, ASB_PACKAGE_LOG_LEVEL_WARNING, "Unable to currently map Fedora " "license '%s' to SPDX", tokens[i]); } - new = as_utils_spdx_license_detokenize (tokens); asb_package_set_license (pkg, new); } diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c index 5a2a14d..0730676 100644 --- a/libappstream-glib/as-self-test.c +++ b/libappstream-glib/as-self-test.c @@ -3508,6 +3508,11 @@ as_test_utils_spdx_token_func (void) g_assert (as_utils_is_spdx_license ("CC0 AND GFDL-1.3")); g_assert (as_utils_is_spdx_license ("NOASSERTION")); g_assert (!as_utils_is_spdx_license ("CC0 dave")); + + /* importing non-SPDX formats */ + tmp = as_utils_license_to_spdx ("CC0 and (Public Domain and GPLv3+ with exceptions)"); + g_assert_cmpstr (tmp, ==, "CC0-1.0 AND (LicenseRef-public-domain AND GPL-3.0+)"); + g_free (tmp); } static void diff --git a/libappstream-glib/as-utils.c b/libappstream-glib/as-utils.c index 2ed13cf..7e8d71c 100644 --- a/libappstream-glib/as-utils.c +++ b/libappstream-glib/as-utils.c @@ -790,6 +790,111 @@ as_utils_is_spdx_license (const gchar *license) return TRUE; } +/** + * as_utils_license_to_spdx: + * @license: a not-quite SPDX license string, e.g. "GPLv3+" + * + * Converts a non-SPDX license into an SPDX format string where possible. + * + * Returns: the best-effort SPDX license string + * + * Since: 0.2.5 + **/ +gchar * +as_utils_license_to_spdx (const gchar *license) +{ + GString *str; + guint i; + guint j; + guint license_len; + struct { + const gchar *old; + const gchar *new; + } convert[] = { + { " with exceptions", NULL }, + { " with advertising", NULL }, + { " and ", " AND " }, + { " or ", " OR " }, + { "AGPLv3+", "AGPL-3.0" }, + { "AGPLv3", "AGPL-3.0" }, + { "Artistic 2.0", "Artistic-2.0" }, + { "Artistic clarified", "Artistic-2.0" }, + { "Artistic", "Artistic-1.0" }, + { "ASL 1.1", "Apache-1.1" }, + { "ASL 2.0", "Apache-2.0" }, + { "Boost", "BSL-1.0" }, + { "BSD", "BSD-3-Clause" }, + { "CC0", "CC0-1.0" }, + { "CC-BY-SA", "CC-BY-SA-3.0" }, + { "CC-BY", "CC-BY-3.0" }, + { "CDDL", "CDDL-1.0" }, + { "CeCILL-C", "CECILL-C" }, + { "CeCILL", "CECILL-2.0" }, + { "CPAL", "CPAL-1.0" }, + { "CPL", "CPL-1.0" }, + { "EPL", "EPL-1.0" }, + { "Free Art", "ClArtistic" }, + { "GFDL", "GFDL-1.3" }, + { "GPL+", "GPL-1.0+" }, + { "GPLv2+", "GPL-2.0+" }, + { "GPLv2", "GPL-2.0" }, + { "GPLv3+", "GPL-3.0+" }, + { "GPLv3", "GPL-3.0" }, + { "IBM", "IPL-1.0" }, + { "LGPL+", "LGPL-2.1+" }, + { "LGPLv2.1", "LGPL-2.1" }, + { "LGPLv2+", "LGPL-2.1+" }, + { "LGPLv2", "LGPL-2.1" }, + { "LGPLv3+", "LGPL-3.0+" }, + { "LGPLv3", "LGPL-3.0" }, + { "LPPL", "LPPL-1.3c" }, + { "MPLv1.0", "MPL-1.0" }, + { "MPLv1.1", "MPL-1.1" }, + { "MPLv2.0", "MPL-2.0" }, + { "Netscape", "NPL-1.1" }, + { "OFL", "OFL-1.1" }, + { "Python", "Python-2.0" }, + { "QPL", "QPL-1.0" }, + { "SPL", "SPL-1.0" }, + { "zlib", "Zlib" }, + { "ZPLv2.0", "ZPL-2.0" }, + { "Unlicense", "CC0-1.0" }, + { "Public Domain", "LicenseRef-public-domain" }, + { "Copyright only", "LicenseRef-public-domain" }, + { "Proprietary", "LicenseRef-proprietary" }, + { "Commercial", "LicenseRef-proprietary" }, + { NULL, NULL } }; + + /* nothing set */ + if (license == NULL) + return NULL; + + /* already in SPDX format */ + if (as_utils_is_spdx_license (license)) + return g_strdup (license); + + /* go through the string looking for case-insensitive matches */ + str = g_string_new (""); + license_len = strlen (license); + for (i = 0; i < license_len; i++) { + gboolean found = FALSE; + for (j = 0; convert[j].old != NULL; j++) { + guint old_len = strlen (convert[j].old); + if (g_ascii_strncasecmp (license + i, + convert[j].old, + old_len) != 0) + continue; + if (convert[j].new != NULL) + g_string_append (str, convert[j].new); + i += old_len - 1; + found = TRUE; + } + if (!found) + g_string_append_c (str, license[i]); + } + return g_string_free (str, FALSE); +} + /** * as_pixbuf_blur_private: **/ diff --git a/libappstream-glib/as-utils.h b/libappstream-glib/as-utils.h index 44bfa39..93e4db4 100644 --- a/libappstream-glib/as-utils.h +++ b/libappstream-glib/as-utils.h @@ -145,6 +145,7 @@ gboolean as_utils_is_category_id (const gchar *category_id); gboolean as_utils_is_blacklisted_id (const gchar *desktop_id); gchar **as_utils_spdx_license_tokenize (const gchar *license); gchar *as_utils_spdx_license_detokenize (gchar **license_tokens); +gchar *as_utils_license_to_spdx (const gchar *license); gchar *as_utils_find_icon_filename (const gchar *destdir, const gchar *search, GError **error); -- cgit v1.2.1