diff options
author | Richard Hughes <richard@hughsie.com> | 2015-03-09 10:56:53 +0000 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2015-03-09 11:03:33 +0000 |
commit | 7dfe4bc3a7394cc5dc5831f2c36bc2818583cadc (patch) | |
tree | 274515f8d41989169b0fc4eed39bf5a91fb0b216 | |
parent | 28b97cd484e8f99b509ab1c97050e31fc831d3dc (diff) | |
download | appstream-glib-7dfe4bc3a7394cc5dc5831f2c36bc2818583cadc.tar.gz |
Support parsing .inf files into an AsApp
-rw-r--r-- | data/tests/example.inf | 4 | ||||
-rw-r--r-- | libappstream-builder/plugins/asb-plugin-firmware.c | 124 | ||||
-rw-r--r-- | libappstream-glib/Makefile.am | 1 | ||||
-rw-r--r-- | libappstream-glib/as-app-inf.c | 187 | ||||
-rw-r--r-- | libappstream-glib/as-app-private.h | 4 | ||||
-rw-r--r-- | libappstream-glib/as-app.c | 10 | ||||
-rw-r--r-- | libappstream-glib/as-app.h | 2 | ||||
-rw-r--r-- | libappstream-glib/as-self-test.c | 51 |
8 files changed, 270 insertions, 113 deletions
diff --git a/data/tests/example.inf b/data/tests/example.inf index 62b1d21..c6e2a87 100644 --- a/data/tests/example.inf +++ b/data/tests/example.inf @@ -9,6 +9,10 @@ DriverVer=03/03/2015,2.0.2 PnpLockdown=1 CatalogFile=firmware.cat +; nonstandard +[Location] +URLs = "http://www.hughski.com/foo.cab" + [Manufacturer] %MfgName% = Hughski,NTamd64 diff --git a/libappstream-builder/plugins/asb-plugin-firmware.c b/libappstream-builder/plugins/asb-plugin-firmware.c index 20916f8..b0ec5e4 100644 --- a/libappstream-builder/plugins/asb-plugin-firmware.c +++ b/libappstream-builder/plugins/asb-plugin-firmware.c @@ -64,24 +64,6 @@ asb_plugin_check_filename (AsbPlugin *plugin, const gchar *filename) } /** - * asb_plugin_firmware_sanitize_guid: - */ -static gchar * -asb_plugin_firmware_sanitize_guid (const gchar *id) -{ - GString *id_new; - guint i; - - id_new = g_string_sized_new (strlen (id)); - - for (i = 0; id[i] != '\0'; i++) { - if (g_ascii_isalnum (id[i]) || id[i] == '-') - g_string_append_c (id_new, id[i]); - } - return g_string_free (id_new, FALSE); -} - -/** * asb_plugin_firmware_get_source_package: */ static gchar * @@ -124,107 +106,33 @@ asb_plugin_process_filename (AsbPlugin *plugin, const gchar *tmpdir, GError **error) { - guint64 timestamp; - guint i; + AsRelease *release; + GError *error_local = NULL; _cleanup_free_ gchar *checksum = NULL; - _cleanup_free_ gchar *class = NULL; - _cleanup_free_ gchar *comment = NULL; _cleanup_free_ gchar *filename_full = NULL; - _cleanup_free_ gchar *id_new = NULL; - _cleanup_free_ gchar *id = NULL; _cleanup_free_ gchar *location_checksum = NULL; - _cleanup_free_ gchar *location_url = NULL; - _cleanup_free_ gchar *name = NULL; _cleanup_free_ gchar *srcpkg = NULL; - _cleanup_free_ gchar *vendor = NULL; - _cleanup_free_ gchar *version = NULL; - _cleanup_keyfile_unref_ GKeyFile *kf = NULL; _cleanup_object_unref_ AsbApp *app = NULL; - _cleanup_object_unref_ AsIcon *icon = NULL; - _cleanup_object_unref_ AsProvide *provide = NULL; - _cleanup_object_unref_ AsRelease *release = NULL; - - /* fix up the inf file */ - filename_full = g_build_filename (tmpdir, filename, NULL); - kf = g_key_file_new (); - if (!as_inf_load_file (kf, filename_full, AS_INF_LOAD_FLAG_NONE, error)) - return FALSE; /* parse */ - class = g_key_file_get_string (kf, "Version", "Class", NULL); - if (class == NULL) { - g_set_error_literal (error, - ASB_PLUGIN_ERROR, - ASB_PLUGIN_ERROR_NOT_SUPPORTED, - "Driver class is missing"); - return FALSE; - } - if (g_strcmp0 (class, "Firmware") != 0) { - g_set_error (error, - ASB_PLUGIN_ERROR, - ASB_PLUGIN_ERROR_NOT_SUPPORTED, - "Driver class is '%s', not 'Firmware'", class); - return FALSE; - } - - /* get the GUID */ - id = g_key_file_get_string (kf, "Version", "ClassGuid", NULL); - if (id == NULL) { + filename_full = g_build_filename (tmpdir, filename, NULL); + app = asb_app_new (pkg, NULL); + if (!as_app_parse_file (AS_APP (app), filename_full, + AS_APP_PARSE_FLAG_NONE, &error_local)) { g_set_error_literal (error, ASB_PLUGIN_ERROR, ASB_PLUGIN_ERROR_NOT_SUPPORTED, - "Driver ID is missing"); - return FALSE; - } - - /* strip any curley brackets */ - id_new = asb_plugin_firmware_sanitize_guid (id); - app = asb_app_new (pkg, id_new); - as_app_set_id_kind (AS_APP (app), AS_ID_KIND_FIRMWARE); - - /* add localizable strings */ - vendor = g_key_file_get_string (kf, "Version", "Provider", NULL); - if (vendor == NULL) - vendor = g_key_file_get_string (kf, "Version", "MfgName", NULL); - if (vendor == NULL) - vendor = g_key_file_get_string (kf, "Strings", "Provider", NULL); - if (vendor != NULL) - as_app_set_developer_name (AS_APP (app), NULL, vendor, -1); - name = g_key_file_get_string (kf, "Strings", "FirmwareDesc", NULL); - if (name != NULL) - as_app_set_name (AS_APP (app), NULL, name, -1); - comment = g_key_file_get_string (kf, "SourceDisksNames", "1", NULL); - if (comment == NULL) - comment = g_key_file_get_string (kf, "Strings", "DiskName", NULL); - if (comment != NULL) - as_app_set_comment (AS_APP (app), NULL, comment, -1); - - /* parse the DriverVer */ - version = as_inf_get_driver_version (kf, ×tamp, error); - if (version == NULL) + error_local->message); return FALSE; - - /* add a release with no real description */ - release = as_release_new (); - as_release_set_version (release, version, -1); - as_release_set_timestamp (release, timestamp); - as_app_add_release (AS_APP (app), release); - - /* this is a Linux extension */ - location_url = g_key_file_get_string (kf, "Location", "URLs", NULL); - if (location_url != NULL) { - _cleanup_strv_free_ gchar **location_urls = NULL; - location_urls = g_strsplit (location_url, ",", -1); - for (i = 0; location_urls[i] != NULL; i++) - as_release_add_location (release, location_urls[i], -1); } - /* checksum the .cab file */ + /* add the checksum for the .cab file */ checksum = asb_plugin_firmware_get_checksum (asb_package_get_filename (pkg), G_CHECKSUM_SHA1, error); if (checksum == NULL) return FALSE; + release = as_app_get_release_default (AS_APP (app)); as_release_set_checksum (release, G_CHECKSUM_SHA1, checksum, -1); /* this is a hack */ @@ -232,15 +140,7 @@ asb_plugin_process_filename (AsbPlugin *plugin, if (srcpkg != NULL) asb_package_set_source_pkgname (pkg, srcpkg); - /* add icon */ - icon = as_icon_new (); - as_icon_set_kind (icon, AS_ICON_KIND_STOCK); - as_icon_set_name (icon, "application-x-executable", -1); - as_app_add_icon (AS_APP (app), icon); - asb_plugin_add_app (apps, AS_APP (app)); - - /* add provide */ return TRUE; } @@ -303,7 +203,9 @@ asb_plugin_merge (AsbPlugin *plugin, GList *list) /* remove the source package name, which doesn't make sense */ for (l = list; l != NULL; l = l->next) { app = AS_APP (l->data); - if (as_app_get_id_kind (app) == AS_ID_KIND_FIRMWARE) - as_app_set_source_pkgname (app, NULL, -1); + if (as_app_get_id_kind (app) != AS_ID_KIND_FIRMWARE) + continue; + as_app_set_source_pkgname (app, NULL, -1); + as_app_remove_metadata (app, "FirmwareBasename"); } } diff --git a/libappstream-glib/Makefile.am b/libappstream-glib/Makefile.am index cfde3c6..9491b2b 100644 --- a/libappstream-glib/Makefile.am +++ b/libappstream-glib/Makefile.am @@ -86,6 +86,7 @@ libappstream_glib_include_HEADERS = \ libappstream_glib_la_SOURCES = \ as-app.c \ as-app-desktop.c \ + as-app-inf.c \ as-app-private.h \ as-app-validate.c \ as-bundle.c \ diff --git a/libappstream-glib/as-app-inf.c b/libappstream-glib/as-app-inf.c new file mode 100644 index 0000000..3bb8481 --- /dev/null +++ b/libappstream-glib/as-app-inf.c @@ -0,0 +1,187 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2013-2015 Richard Hughes <richard@hughsie.com> + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <fnmatch.h> +#include <string.h> + +#include "as-app-private.h" +#include "as-cleanup.h" +#include "as-inf.h" +//#include "as-utils.h" + +/** + * as_app_parse_inf_sanitize_guid: + */ +static gchar * +as_app_parse_inf_sanitize_guid (const gchar *guid) +{ + GString *id; + guint i; + + id = g_string_sized_new (strlen (guid)); + + for (i = 0; guid[i] != '\0'; i++) { + if (g_ascii_isalnum (guid[i]) || guid[i] == '-') + g_string_append_c (id, guid[i]); + } + return g_string_free (id, FALSE); +} + +/** + * as_app_parse_inf_file: + **/ +gboolean +as_app_parse_inf_file (AsApp *app, + const gchar *filename, + AsAppParseFlags flags, + GError **error) +{ + guint64 timestamp; + guint i; + _cleanup_error_free_ GError *error_local = NULL; + _cleanup_free_ gchar *class = NULL; + _cleanup_free_ gchar *comment = NULL; + _cleanup_free_ gchar *filename_full = NULL; + _cleanup_free_ gchar *firmware_basename = NULL; + _cleanup_free_ gchar *guid = NULL; + _cleanup_free_ gchar *id = NULL; + _cleanup_free_ gchar *location_checksum = NULL; + _cleanup_free_ gchar *location_url = NULL; + _cleanup_free_ gchar *name = NULL; + _cleanup_free_ gchar *srcpkg = NULL; + _cleanup_free_ gchar *vendor = NULL; + _cleanup_free_ gchar *version = NULL; + _cleanup_keyfile_unref_ GKeyFile *kf = NULL; + _cleanup_object_unref_ AsIcon *icon = NULL; + _cleanup_object_unref_ AsProvide *provide = NULL; + _cleanup_object_unref_ AsRelease *release = NULL; + _cleanup_strv_free_ gchar **source_keys = NULL; + + /* load file */ + kf = g_key_file_new (); + if (!as_inf_load_file (kf, filename, AS_INF_LOAD_FLAG_NONE, &error_local)) { + g_set_error (error, + AS_APP_ERROR, + AS_APP_ERROR_INVALID_TYPE, + "Failed to parse %s: %s", + filename, error_local->message); + return FALSE; + } + + /* get the type of .inf file */ + class = g_key_file_get_string (kf, "Version", "Class", NULL); + if (class == NULL) { + g_set_error_literal (error, + AS_APP_ERROR, + AS_APP_ERROR_INVALID_TYPE, + "Driver class is missing"); + return FALSE; + } + if (g_strcmp0 (class, "Firmware") != 0) { + g_set_error (error, + AS_APP_ERROR, + AS_APP_ERROR_INVALID_TYPE, + "Driver class is '%s', not 'Firmware'", class); + return FALSE; + } + as_app_set_id_kind (app, AS_ID_KIND_FIRMWARE); + + /* get the GUID */ + guid = g_key_file_get_string (kf, "Version", "ClassGuid", NULL); + if (guid == NULL) { + g_set_error_literal (error, + AS_APP_ERROR, + AS_APP_ERROR_INVALID_TYPE, + "Driver ID is missing"); + return FALSE; + } + + /* strip any curley brackets */ + id = as_app_parse_inf_sanitize_guid (guid); + as_app_set_id (app, id, -1); + + /* get vendor */ + vendor = g_key_file_get_string (kf, "Version", "Provider", NULL); + if (vendor == NULL) + vendor = g_key_file_get_string (kf, "Version", "MfgName", NULL); + if (vendor == NULL) /* FIXME: is a hack */ + vendor = g_key_file_get_string (kf, "Strings", "Provider", NULL); + if (vendor != NULL) + as_app_set_developer_name (app, NULL, vendor, -1); + + /* get name */ + name = g_key_file_get_string (kf, "Strings", "FirmwareDesc", NULL); + if (name != NULL) + as_app_set_name (app, NULL, name, -1); + + /* get comment */ + comment = g_key_file_get_string (kf, "SourceDisksNames", "1", NULL); + if (comment == NULL) /* FIXME: is a hack */ + comment = g_key_file_get_string (kf, "Strings", "DiskName", NULL); + if (comment != NULL) + as_app_set_comment (app, NULL, comment, -1); + + /* parse the DriverVer */ + version = as_inf_get_driver_version (kf, ×tamp, error); + if (version == NULL) + return FALSE; + + /* find the firmware file we're installing */ + source_keys = g_key_file_get_keys (kf, "SourceDisksFiles", NULL, NULL); + if (source_keys != NULL && g_strv_length (source_keys) == 1) { + firmware_basename = g_strdup (source_keys[0]); + } else { + firmware_basename = g_key_file_get_string (kf, + "Firmware_CopyFiles", + "value000", NULL); + } + if (firmware_basename == NULL) { + g_set_error (error, + AS_APP_ERROR, + AS_APP_ERROR_INVALID_TYPE, + "no SourceDisksFiles or Firmware_CopyFiles"); + return FALSE; + } + as_app_add_metadata (app, "FirmwareBasename", firmware_basename, -1); + + /* add a release with no real description */ + release = as_release_new (); + as_release_set_version (release, version, -1); + as_release_set_timestamp (release, timestamp); + as_app_add_release (app, release); + + /* this is a Linux extension */ + location_url = g_key_file_get_string (kf, "Location", "URLs", NULL); + if (location_url != NULL) { + _cleanup_strv_free_ gchar **location_urls = NULL; + location_urls = g_strsplit (location_url, ",", -1); + for (i = 0; location_urls[i] != NULL; i++) + as_release_add_location (release, location_urls[i], -1); + } + + /* add icon */ + icon = as_icon_new (); + as_icon_set_kind (icon, AS_ICON_KIND_STOCK); + as_icon_set_name (icon, "application-x-executable", -1); + as_app_add_icon (app, icon); + + return TRUE; +} diff --git a/libappstream-glib/as-app-private.h b/libappstream-glib/as-app-private.h index 63d3530..d5e74d7 100644 --- a/libappstream-glib/as-app-private.h +++ b/libappstream-glib/as-app-private.h @@ -94,6 +94,10 @@ gboolean as_app_parse_desktop_file (AsApp *app, const gchar *filename, AsAppParseFlags flags, GError **error); +gboolean as_app_parse_inf_file (AsApp *app, + const gchar *filename, + AsAppParseFlags flags, + GError **error); G_END_DECLS diff --git a/libappstream-glib/as-app.c b/libappstream-glib/as-app.c index 6b5c53c..4fadc7f 100644 --- a/libappstream-glib/as-app.c +++ b/libappstream-glib/as-app.c @@ -143,6 +143,8 @@ as_app_source_kind_from_string (const gchar *source_kind) return AS_APP_SOURCE_KIND_METAINFO; if (g_strcmp0 (source_kind, "desktop") == 0) return AS_APP_SOURCE_KIND_DESKTOP; + if (g_strcmp0 (source_kind, "inf") == 0) + return AS_APP_SOURCE_KIND_INF; return AS_APP_SOURCE_KIND_UNKNOWN; } @@ -167,6 +169,8 @@ as_app_source_kind_to_string (AsAppSourceKind source_kind) return "metainfo"; if (source_kind == AS_APP_SOURCE_KIND_DESKTOP) return "desktop"; + if (source_kind == AS_APP_SOURCE_KIND_INF) + return "inf"; return NULL; } @@ -237,6 +241,8 @@ as_app_guess_source_kind (const gchar *filename) return AS_APP_SOURCE_KIND_METAINFO; if (g_str_has_suffix (filename, ".xml")) return AS_APP_SOURCE_KIND_APPSTREAM; + if (g_str_has_suffix (filename, ".inf")) + return AS_APP_SOURCE_KIND_INF; return AS_APP_SOURCE_KIND_UNKNOWN; } @@ -4500,6 +4506,10 @@ as_app_parse_file (AsApp *app, if (!as_app_parse_appdata_file (app, filename, flags, error)) return FALSE; break; + case AS_APP_SOURCE_KIND_INF: + if (!as_app_parse_inf_file (app, filename, flags, error)) + return FALSE; + break; default: g_set_error (error, AS_APP_ERROR, diff --git a/libappstream-glib/as-app.h b/libappstream-glib/as-app.h index 59d104a..d3cd076 100644 --- a/libappstream-glib/as-app.h +++ b/libappstream-glib/as-app.h @@ -163,6 +163,7 @@ typedef enum { * @AS_APP_SOURCE_KIND_DESKTOP: Sourced from a desktop file * @AS_APP_SOURCE_KIND_APPDATA: Sourced from a AppData file * @AS_APP_SOURCE_KIND_METAINFO: Sourced from a MetaInfo file + * @AS_APP_SOURCE_KIND_INF: Sourced from a inf file * * The source kind. **/ @@ -172,6 +173,7 @@ typedef enum { AS_APP_SOURCE_KIND_DESKTOP, /* Since: 0.1.4 */ AS_APP_SOURCE_KIND_APPDATA, /* Since: 0.1.4 */ AS_APP_SOURCE_KIND_METAINFO, /* Since: 0.1.7 */ + AS_APP_SOURCE_KIND_INF, /* Since: 0.3.5 */ /*< private >*/ AS_APP_SOURCE_KIND_LAST } AsAppSourceKind; diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c index 33f3b96..b81a84a 100644 --- a/libappstream-glib/as-self-test.c +++ b/libappstream-glib/as-self-test.c @@ -1458,7 +1458,7 @@ as_test_app_validate_style_func (void) } static void -as_test_app_parse_file_func (void) +as_test_app_parse_file_desktop_func (void) { AsIcon *ic; GError *error = NULL; @@ -1521,6 +1521,52 @@ as_test_app_parse_file_func (void) } static void +as_test_app_parse_file_inf_func (void) +{ + AsIcon *ic; + AsRelease *rel; + GError *error = NULL; + GPtrArray *releases; + gboolean ret; + _cleanup_free_ gchar *filename = NULL; + _cleanup_object_unref_ AsApp *app = NULL; + + /* create an AsApp from a desktop file */ + app = as_app_new (); + filename = as_test_get_filename ("example.inf"); + ret = as_app_parse_file (app, + filename, + AS_APP_PARSE_FLAG_NONE, + &error); + g_assert_no_error (error); + g_assert (ret); + + /* test things we found */ + g_assert_cmpstr (as_app_get_name (app, "C"), ==, "ColorHug Firmware"); + g_assert_cmpstr (as_app_get_comment (app, "C"), ==, + "Firmware for the ColorHug Colorimeter"); + g_assert_cmpstr (as_app_get_source_file (app), ==, filename); + + /* check icon */ + g_assert_cmpint (as_app_get_icons(app)->len, ==, 1); + ic = as_app_get_icon_default (app); + g_assert (ic != NULL); + g_assert_cmpstr (as_icon_get_name (ic), ==, "application-x-executable"); + g_assert_cmpint (as_icon_get_kind (ic), ==, AS_ICON_KIND_STOCK); + g_assert_cmpint (as_icon_get_width (ic), ==, 0); + g_assert_cmpint (as_icon_get_height (ic), ==, 0); + + /* check releases */ + releases = as_app_get_releases (app); + g_assert_cmpint (releases->len, ==, 1); + rel = g_ptr_array_index (releases, 0); + g_assert_cmpstr (as_release_get_location_default (rel), ==, "http://www.hughski.com/foo.cab"); + g_assert_cmpint (as_release_get_timestamp (rel), ==, 1425340800); + g_assert_cmpstr (as_release_get_version (rel), ==, "2.0.2"); + //g_assert_cmpstr (as_release_get_description (rel), ==, "XXX"); +} + +static void as_test_app_no_markup_func (void) { GError *error = NULL; @@ -3708,7 +3754,8 @@ main (int argc, char **argv) g_test_add_func ("/AppStream/app{validate-file-bad}", as_test_app_validate_file_bad_func); g_test_add_func ("/AppStream/app{validate-meta-bad}", as_test_app_validate_meta_bad_func); g_test_add_func ("/AppStream/app{validate-intltool}", as_test_app_validate_intltool_func); - g_test_add_func ("/AppStream/app{parse-file}", as_test_app_parse_file_func); + g_test_add_func ("/AppStream/app{parse-file:desktop}", as_test_app_parse_file_desktop_func); + g_test_add_func ("/AppStream/app{parse-file:inf}", as_test_app_parse_file_inf_func); g_test_add_func ("/AppStream/app{no-markup}", as_test_app_no_markup_func); g_test_add_func ("/AppStream/app{subsume}", as_test_app_subsume_func); g_test_add_func ("/AppStream/app{search}", as_test_app_search_func); |