/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2016-2024 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 2.1 * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 2.1 of the license, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ /** * SECTION:asc-utils * @short_description: Common utility functions for AppStream-Compose. * @include: appstream-compose.h */ #include "config.h" #include "asc-utils.h" #include "as-utils-private.h" /** * asc_build_component_global_id: * @component_id: an AppStream component ID. * @checksum: a MD5 hashsum as string generated from the component's combined metadata. * * Builds a global component ID from a component-id * and a (usually MD5) checksum generated from the component data. * * The global-id is used as a global, unique identifier for a component. * (while the component-ID is local, e.g. for one source). * Its primary usecase is to identify a media directory on the filesystem which is * associated with this component. **/ gchar * asc_build_component_global_id (const gchar *component_id, const gchar *checksum) { gboolean rdns_split; g_auto(GStrv) parts = NULL; if (as_is_empty (component_id)) return NULL; if (as_is_empty (checksum)) checksum = "last"; g_return_val_if_fail (strlen (component_id) > 2, NULL); /* check whether we can build the gcid by using the reverse domain name, * or whether we should use the simple standard splitter. */ rdns_split = FALSE; parts = g_strsplit (component_id, ".", 3); if (g_strv_length (parts) == 3) { /* check if we have a valid TLD. If so, use the reverse-domain-name splitting. */ if (as_utils_is_tld (parts[0])) rdns_split = TRUE; } if (rdns_split) { g_autofree gchar *tld_part = NULL; g_autofree gchar *domain_part = NULL; tld_part = g_utf8_strdown (parts[0], -1); domain_part = g_utf8_strdown (parts[1], -1); return g_strdup_printf ("%s/%s/%s/%s", tld_part, domain_part, parts[2], checksum); } else { g_autofree gchar *cid_low = NULL; g_autofree gchar *pdiv_part = NULL; g_autofree gchar *sdiv_part = NULL; cid_low = g_utf8_strdown (component_id, -1); pdiv_part = g_utf8_substring (cid_low, 0, 1); sdiv_part = g_utf8_substring (cid_low, 0, 2); return g_strdup_printf ("%s/%s/%s/%s", pdiv_part, sdiv_part, cid_low, checksum); } } /** * asc_filename_from_url: * @url: The URL to extract a filename from. * * Generate a filename from a web-URL that can be used to store the * file on disk after download. */ gchar * asc_filename_from_url (const gchar *url) { gchar *tmp; g_autofree gchar *unescaped = NULL; if (url == NULL) return NULL; unescaped = g_uri_unescape_string (url, NULL); tmp = g_strstr_len (unescaped, -1, "?"); if (tmp != NULL) tmp[0] = '\0'; tmp = g_strstr_len (unescaped, -1, "#"); if (tmp != NULL) tmp[0] = '\0'; /* we couldn't extract a suitable name, so just give it a random string as result */ if (unescaped[0] == '\0') return as_random_alnum_string (4); return g_path_get_basename (unescaped); }