diff options
author | Richard Hughes <richard@hughsie.com> | 2015-10-07 13:41:45 +0100 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2015-10-07 13:41:45 +0100 |
commit | a19e0452a9ac84d7c79d6ea4accd99909ae684b3 (patch) | |
tree | 5bd9d54363f31465cb5f35437a16262d9d787997 | |
parent | 8e4c8c8073d954b811ef334bcfc678c05f78bddb (diff) | |
download | appstream-glib-wip/hughsie/AsStoreCab.tar.gz |
-rw-r--r-- | libappstream-builder/asb-self-test.c | 2 | ||||
-rw-r--r-- | libappstream-builder/plugins/asb-plugin-firmware.c | 2 | ||||
-rw-r--r-- | libappstream-glib/as-app-inf.c | 7 | ||||
-rw-r--r-- | libappstream-glib/as-self-test.c | 2 | ||||
-rw-r--r-- | libappstream-glib/as-store-cab.c | 283 | ||||
-rw-r--r-- | libappstream-glib/as-store-cab.h | 2 |
6 files changed, 221 insertions, 77 deletions
diff --git a/libappstream-builder/asb-self-test.c b/libappstream-builder/asb-self-test.c index 56cdcd2..f959ca4 100644 --- a/libappstream-builder/asb-self-test.c +++ b/libappstream-builder/asb-self-test.c @@ -267,7 +267,7 @@ asb_test_plugin_loader_func (void) /* get the list of plugins */ plugins = asb_plugin_loader_get_plugins (loader); - g_assert_cmpint (plugins->len, >=, 15); + g_assert_cmpint (plugins->len, >=, 14); plugin = g_ptr_array_index (plugins, 0); g_assert (plugin != NULL); g_assert (plugin->module != NULL); diff --git a/libappstream-builder/plugins/asb-plugin-firmware.c b/libappstream-builder/plugins/asb-plugin-firmware.c index 2ef9b5c..5e7d845 100644 --- a/libappstream-builder/plugins/asb-plugin-firmware.c +++ b/libappstream-builder/plugins/asb-plugin-firmware.c @@ -131,7 +131,7 @@ asb_plugin_firmware_refine (AsbPlugin *plugin, as_release_add_checksum (release, csum); /* set the internal checksum */ - fw_basename = as_app_get_metadata_item (inf, "FirmwareBasename"); + fw_basename = as_release_get_filename (release); if (fw_basename != NULL) { g_autofree gchar *checksum_bin = NULL; g_autofree gchar *fn_bin = NULL; diff --git a/libappstream-glib/as-app-inf.c b/libappstream-glib/as-app-inf.c index e3824fe..411fb56 100644 --- a/libappstream-glib/as-app-inf.c +++ b/libappstream-glib/as-app-inf.c @@ -208,18 +208,13 @@ as_app_parse_inf_file (AsApp *app, "no SourceDisksFiles or Firmware_CopyFiles"); return FALSE; } - as_app_add_metadata (app, "FirmwareBasename", firmware_basename); - - /* optional */ - catalog_basename = g_key_file_get_string (kf, "Version", "CatalogFile", NULL); - if (catalog_basename != NULL) - as_app_add_metadata (app, "CatalogBasename", catalog_basename); /* add a release with no real description */ if (version != NULL) { release = as_release_new (); as_release_set_version (release, version); as_release_set_timestamp (release, timestamp); + as_release_set_filename (release, firmware_basename); as_app_add_release (app, release); } diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c index 8ceb6cc..c4b79bf 100644 --- a/libappstream-glib/as-self-test.c +++ b/libappstream-glib/as-self-test.c @@ -2879,6 +2879,8 @@ as_test_store_cab_func (void) "<releases>\n" "<release version=\"2.0.2\" timestamp=\"1424116753\">\n" "<location>http://www.hughski.com/downloads/colorhug2/firmware/colorhug-2.0.2.cab</location>\n" + "<checksum target=\"container\" type=\"sha1\">6301e24ae5fb2aa73c336fd40a5d2f1835afe088</checksum>\n" + "<checksum target=\"content\" type=\"sha1\">767a8a7b8a7b350b513f57761204b4aaa657aa44</checksum>\n" "<description><p>This unstable release adds the following features:</p>" "<ul><li>Add TakeReadingArray to enable panel latency measurements</li>" "<li>Speed up the auto-scaled measurements considerably, using 256ms as" diff --git a/libappstream-glib/as-store-cab.c b/libappstream-glib/as-store-cab.c index 0684e97..8a7243f 100644 --- a/libappstream-glib/as-store-cab.c +++ b/libappstream-glib/as-store-cab.c @@ -43,6 +43,96 @@ as_store_cab_cb (GCabFile *file, gpointer user_data) } /** + * as_store_cab_verify_checksum_cab: + **/ +static gboolean +as_store_cab_verify_checksum_cab (AsRelease *release, + GBytes *bytes, + GError **error) +{ + AsChecksum *csum_tmp; + g_autofree gchar *actual = NULL; + + /* nothing already set, so just add */ + actual = g_compute_checksum_for_bytes (G_CHECKSUM_SHA1, bytes); + csum_tmp = as_release_get_checksum_by_target (release, AS_CHECKSUM_TARGET_CONTAINER); + if (csum_tmp == NULL) { + g_autoptr(AsChecksum) csum = NULL; + csum = as_checksum_new (); + as_checksum_set_kind (csum, G_CHECKSUM_SHA1); + as_checksum_set_target (csum, AS_CHECKSUM_TARGET_CONTAINER); + as_checksum_set_value (csum, actual); + as_release_add_checksum (release, csum); + return TRUE; + } + + /* check it matches */ + if (g_strcmp0 (actual, as_checksum_get_value (csum_tmp)) != 0) { + g_set_error (error, + AS_STORE_ERROR, + AS_STORE_ERROR_FAILED, + "container checksum invalid, expected %s, got %s", + as_checksum_get_value (csum_tmp), actual); + return FALSE; + } + + /* success */ + return TRUE; +} + +/** + * as_store_cab_verify_checksum_fw: + **/ +static gboolean +as_store_cab_verify_checksum_fw (AsRelease *release, + const gchar *tmp_path, + GError **error) +{ + AsChecksum *csum_tmp; + g_autofree gchar *rel_basename = NULL; + g_autofree gchar *rel_fn = NULL; + g_autofree gchar *actual = NULL; + + /* get the firmware filename */ + rel_basename = g_path_get_basename (as_release_get_filename (release)); + rel_fn = g_build_filename (tmp_path, rel_basename, NULL); + + /* add this information to the release objects */ + if (g_file_test (rel_fn, G_FILE_TEST_EXISTS)) { + gsize len; + g_autofree gchar *data = NULL; + if (!g_file_get_contents (rel_fn, &data, &len, error)) + return NULL; + actual = g_compute_checksum_for_data (G_CHECKSUM_SHA1, (guchar *)data, len); + } + + /* nothing already set, so just add */ + csum_tmp = as_release_get_checksum_by_target (release, AS_CHECKSUM_TARGET_CONTENT); + if (csum_tmp == NULL) { + g_autoptr(AsChecksum) csum = NULL; + csum = as_checksum_new (); + as_checksum_set_kind (csum, G_CHECKSUM_SHA1); + as_checksum_set_target (csum, AS_CHECKSUM_TARGET_CONTENT); + as_checksum_set_value (csum, actual); + as_release_add_checksum (release, csum); + return TRUE; + } + + /* check it matches */ + if (g_strcmp0 (actual, as_checksum_get_value (csum_tmp)) != 0) { + g_set_error (error, + AS_STORE_ERROR, + AS_STORE_ERROR_FAILED, + "contents checksum invalid, expected %s, got %s", + as_checksum_get_value (csum_tmp), actual); + return FALSE; + } + + /* success */ + return TRUE; +} + +/** * as_store_cab_set_release_blobs: **/ static gboolean @@ -110,25 +200,26 @@ as_store_cab_set_release_blobs (AsRelease *release, const gchar *tmp_path, GErro } /** - * as_store_cab_from_stream: + * as_store_cab_from_bytes: **/ -static gboolean -as_store_cab_from_stream (AsStore *store, - GInputStream *input_stream, - guint64 size, - GCancellable *cancellable, - GError **error) +gboolean +as_store_cab_from_bytes (AsStore *store, + GBytes *bytes, + GCancellable *cancellable, + GError **error) { g_autoptr(GCabCabinet) gcab = NULL; g_autoptr(GError) error_local = NULL; g_autofree gchar *tmp_path = NULL; g_autoptr(GFile) tmp_file = NULL; + g_autoptr(GInputStream) input_stream = NULL; g_autoptr(GPtrArray) filelist = NULL; g_autoptr(GPtrArray) apps = NULL; guint i; /* open the file */ gcab = gcab_cabinet_new (); + input_stream = g_memory_input_stream_new_from_bytes (bytes); if (!gcab_cabinet_load (gcab, input_stream, NULL, &error_local)) { g_set_error (error, AS_STORE_ERROR, @@ -176,47 +267,46 @@ as_store_cab_from_stream (AsStore *store, g_debug ("found file %i\t%s", i, fn); /* if inf or metainfo, add */ - switch (as_app_guess_source_kind (fn)) { - case AS_APP_SOURCE_KIND_METAINFO: - tmp_fn = g_build_filename (tmp_path, fn, NULL); - app = as_app_new (); - if (!as_app_parse_file (app, tmp_fn, - AS_APP_PARSE_FLAG_NONE, &error_local)) { - g_set_error (error, + if (as_app_guess_source_kind (fn) != AS_APP_SOURCE_KIND_METAINFO) + continue; + + tmp_fn = g_build_filename (tmp_path, fn, NULL); + app = as_app_new (); + if (!as_app_parse_file (app, tmp_fn, + AS_APP_PARSE_FLAG_NONE, &error_local)) { + g_set_error (error, + AS_STORE_ERROR, + AS_STORE_ERROR_FAILED, + "%s could not be loaded: %s", + tmp_fn, + error_local->message); + return FALSE; + } + + /* check release was valid */ + rel = as_app_get_release_default (app); + if (rel == NULL) { + g_set_error_literal (error, AS_STORE_ERROR, AS_STORE_ERROR_FAILED, - "%s could not be loaded: %s", - tmp_fn, - error_local->message); - return FALSE; - } - - /* check release was valid */ - rel = as_app_get_release_default (app); - if (rel == NULL) { - g_set_error_literal (error, - AS_STORE_ERROR, - AS_STORE_ERROR_FAILED, - "no releases in metainfo file"); - return FALSE; - } - - /* fix up legacy files */ - if (as_release_get_filename (rel) == NULL) - as_release_set_filename (rel, "firmware.bin"); - - /* this is the size of the cab file itself */ - if (size > 0 && as_release_get_size (rel, AS_SIZE_KIND_DOWNLOAD) == 0) - as_release_set_size (rel, AS_SIZE_KIND_DOWNLOAD, size); - - g_ptr_array_add (apps, g_object_ref (app)); - break; - case AS_APP_SOURCE_KIND_INF: - /* FIXME: can we handle this? */ - break; - default: - break; + "no releases in metainfo file"); + return FALSE; } + + /* fix up legacy files */ + if (as_release_get_filename (rel) == NULL) + as_release_set_filename (rel, "firmware.bin"); + + /* this is the size of the cab file itself */ + if (as_release_get_size (rel, AS_SIZE_KIND_DOWNLOAD) == 0) + as_release_set_size (rel, AS_SIZE_KIND_DOWNLOAD, + g_bytes_get_size (bytes)); + + /* set the container checksum */ + if (!as_store_cab_verify_checksum_cab (rel, bytes, error)) + return FALSE; + + g_ptr_array_add (apps, g_object_ref (app)); } /* add firmware blobs referenced by the metainfo or inf files */ @@ -228,6 +318,8 @@ as_store_cab_from_stream (AsStore *store, AsRelease *rel = g_ptr_array_index (releases, j); if (!as_store_cab_set_release_blobs (rel, tmp_path, error)) return FALSE; + if (!as_store_cab_verify_checksum_fw (rel, tmp_path, error)) + return FALSE; } } @@ -237,6 +329,63 @@ as_store_cab_from_stream (AsStore *store, as_store_add_app (store, app_tmp); } + /* if we provided an .inf file check the values matched */ + for (i = 0; i < filelist->len; i++) { + AsApp *app_tmp; + AsRelease *rel_inf; + AsRelease *rel_metainfo; + const gchar *fn; + g_autoptr(AsApp) app_inf = NULL; + g_autofree gchar *tmp_fn = NULL; + + fn = g_ptr_array_index (filelist, i); + if (as_app_guess_source_kind (fn) != AS_APP_SOURCE_KIND_INF) + continue; + + /* get the id from the store */ + app_inf = as_app_new (); + tmp_fn = g_build_filename (tmp_path, fn, NULL); + if (!as_app_parse_file (app_inf, tmp_fn, AS_APP_PARSE_FLAG_NONE, error)) + return FALSE; + app_tmp = as_store_get_app_by_provide (store, + AS_PROVIDE_KIND_FIRMWARE_FLASHED, + as_app_get_id (app_inf)); + if (app_tmp == NULL) { + g_set_error (error, + AS_STORE_ERROR, + AS_STORE_ERROR_FAILED, + "no metainfo file with provide %s", + as_app_get_id (app_inf)); + return FALSE; + } + + /* check the version matches */ + rel_inf = as_app_get_release_default (app_inf); + rel_metainfo = as_app_get_release_default (app_inf); + if (g_strcmp0 (as_release_get_version (rel_inf), + as_release_get_version (rel_metainfo)) != 0) { + g_set_error (error, + AS_STORE_ERROR, + AS_STORE_ERROR_FAILED, + "metainfo version is %s while inf has %s", + as_release_get_version (rel_metainfo), + as_release_get_version (rel_inf)); + return FALSE; + } + + /* verify Firmware_CopyFiles matches */ + if (g_strcmp0 (as_release_get_filename (rel_inf), + as_release_get_filename (rel_metainfo)) != 0) { + g_set_error (error, + AS_STORE_ERROR, + AS_STORE_ERROR_FAILED, + "metainfo filename is %s while inf has %s", + as_release_get_filename (rel_metainfo), + as_release_get_filename (rel_inf)); + return FALSE; + } + } + /* delete temp files */ for (i = 0; i < filelist->len; i++) { const gchar *fn; @@ -252,22 +401,6 @@ as_store_cab_from_stream (AsStore *store, } /** - * as_store_cab_from_bytes: - **/ -gboolean -as_store_cab_from_bytes (AsStore *store, - GBytes *bytes, - GCancellable *cancellable, - GError **error) -{ - g_autoptr(GInputStream) input_stream = NULL; - input_stream = g_memory_input_stream_new_from_bytes (bytes); - return as_store_cab_from_stream (store, input_stream, - g_bytes_get_size (bytes), - cancellable, error); -} - -/** * as_store_cab_from_file: **/ gboolean @@ -277,6 +410,7 @@ as_store_cab_from_file (AsStore *store, GError **error) { guint64 size; + g_autoptr(GBytes) bytes; g_autoptr(GError) error_local = NULL; g_autoptr(GFileInfo) info = NULL; g_autoptr(GInputStream) input_stream = NULL; @@ -287,6 +421,18 @@ as_store_cab_from_file (AsStore *store, origin = g_file_get_basename (file); as_store_set_origin (store, origin); + /* open file */ + input_stream = G_INPUT_STREAM (g_file_read (file, cancellable, &error_local)); + if (input_stream == NULL) { + filename = g_file_get_path (file); + g_set_error (error, + AS_STORE_ERROR, + AS_STORE_ERROR_FAILED, + "Failed to open %s: %s", + filename, error_local->message); + return FALSE; + } + /* get size */ info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, cancellable, &error_local); @@ -295,24 +441,25 @@ as_store_cab_from_file (AsStore *store, g_set_error (error, AS_STORE_ERROR, AS_STORE_ERROR_FAILED, - "Failed to get info for %s: %s", + "Failed to get info from %s: %s", filename, error_local->message); return FALSE; } - size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE); - /* open file */ - input_stream = G_INPUT_STREAM (g_file_read (file, cancellable, &error_local)); - if (input_stream == NULL) { + /* slurp it all */ + size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE); + bytes = g_input_stream_read_bytes (input_stream, size, + cancellable, &error_local); + if (bytes == NULL) { filename = g_file_get_path (file); g_set_error (error, AS_STORE_ERROR, AS_STORE_ERROR_FAILED, - "Failed to open %s: %s", + "Failed to read %s: %s", filename, error_local->message); return FALSE; } /* parse */ - return as_store_cab_from_stream (store, input_stream, size, cancellable, error); + return as_store_cab_from_bytes (store, bytes, cancellable, error); } diff --git a/libappstream-glib/as-store-cab.h b/libappstream-glib/as-store-cab.h index 474e9eb..7cba6e8 100644 --- a/libappstream-glib/as-store-cab.h +++ b/libappstream-glib/as-store-cab.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2013-2014 Richard Hughes <richard@hughsie.com> + * Copyright (C) 2015 Richard Hughes <richard@hughsie.com> * * Licensed under the GNU Lesser General Public License Version 2.1 * |