summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2015-08-01 20:38:41 +0100
committerRichard Hughes <richard@hughsie.com>2015-08-03 10:36:29 +0100
commit469621479081476b080e9de3a7ba019867b6d51a (patch)
tree90b377184ff4aeac2a675763a1673d00ec562c23
parent686e844e22a81bbdc39a27b7cd2cced582808b02 (diff)
downloadappstream-glib-469621479081476b080e9de3a7ba019867b6d51a.tar.gz
Add AsChecksum
Also, partially revert the 'add filename' commit and move the filename to the checksum. This allows us to store the checksum of the firmware file as well as well as the .cab container. This allows us to validate the firmware on devices using fwupd.
-rw-r--r--client/as-util.c8
-rw-r--r--docs/api/appstream-glib-docs.sgml1
-rw-r--r--libappstream-builder/asb-self-test.c16
-rw-r--r--libappstream-builder/plugins/asb-plugin-appdata.c6
-rw-r--r--libappstream-builder/plugins/asb-plugin-firmware.c57
-rw-r--r--libappstream-glib/Makefile.am5
-rw-r--r--libappstream-glib/appstream-glib.h1
-rw-r--r--libappstream-glib/as-app.c16
-rw-r--r--libappstream-glib/as-checksum-private.h48
-rw-r--r--libappstream-glib/as-checksum.c423
-rw-r--r--libappstream-glib/as-checksum.h101
-rw-r--r--libappstream-glib/as-release.c237
-rw-r--r--libappstream-glib/as-release.h19
-rw-r--r--libappstream-glib/as-self-test.c87
-rw-r--r--libappstream-glib/as-tag.c1
-rw-r--r--libappstream-glib/as-tag.gperf1
-rw-r--r--libappstream-glib/as-tag.h2
17 files changed, 867 insertions, 162 deletions
diff --git a/client/as-util.c b/client/as-util.c
index 8e5cdda..2fb5d56 100644
--- a/client/as-util.c
+++ b/client/as-util.c
@@ -3365,6 +3365,7 @@ as_util_mirror_local_firmware (AsUtilPrivate *priv, gchar **values, GError **err
if (releases->len == 0)
continue;
for (j = 0; j < releases->len; j++) {
+ AsChecksum *csum;
const gchar *tmp;
_cleanup_free_ gchar *loc = NULL;
_cleanup_free_ gchar *fn = NULL;
@@ -3372,8 +3373,11 @@ as_util_mirror_local_firmware (AsUtilPrivate *priv, gchar **values, GError **err
/* get the release filename, but fall back to
* the default location basename if unset */
- tmp = as_release_get_filename (rel);
- if (tmp != NULL) {
+ csum = as_release_get_checksum_by_target (rel, AS_CHECKSUM_TARGET_CONTAINER);
+ if (csum != NULL) {
+ tmp = as_checksum_get_filename (csum);
+ if (tmp == NULL)
+ continue;
fn = g_strdup (tmp);
} else {
tmp = as_release_get_location_default (rel);
diff --git a/docs/api/appstream-glib-docs.sgml b/docs/api/appstream-glib-docs.sgml
index 3d5fe88..c6e0f9b 100644
--- a/docs/api/appstream-glib-docs.sgml
+++ b/docs/api/appstream-glib-docs.sgml
@@ -34,6 +34,7 @@
</para>
</partintro>
<xi:include href="xml/as-app.xml"/>
+ <xi:include href="xml/as-checksum.xml"/>
<xi:include href="xml/as-icon.xml"/>
<xi:include href="xml/as-image.xml"/>
<xi:include href="xml/as-release.xml"/>
diff --git a/libappstream-builder/asb-self-test.c b/libappstream-builder/asb-self-test.c
index 67d612b..df366ea 100644
--- a/libappstream-builder/asb-self-test.c
+++ b/libappstream-builder/asb-self-test.c
@@ -428,8 +428,8 @@ asb_test_context_test_func (AsbTestContextMode mode)
"<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 type=\"sha1\">522aeefdcc7f27658d73de76107fe62550c61868</checksum>\n"
- "<filename>colorhug-als-2.0.2.cab</filename>\n"
+ "<checksum filename=\"colorhug-als-2.0.2.cab\" target=\"container\" type=\"sha1\">522aeefdcc7f27658d73de76107fe62550c61868</checksum>\n"
+ "<checksum filename=\"firmware.bin\" 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 "
@@ -931,8 +931,8 @@ asb_test_firmware_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 type=\"sha1\">522aeefdcc7f27658d73de76107fe62550c61868</checksum>\n"
- "<filename>colorhug-als-2.0.2.cab</filename>\n"
+ "<checksum filename=\"colorhug-als-2.0.2.cab\" target=\"container\" type=\"sha1\">522aeefdcc7f27658d73de76107fe62550c61868</checksum>\n"
+ "<checksum filename=\"firmware.bin\" 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 "
@@ -940,16 +940,16 @@ asb_test_firmware_func (void)
"</release>\n"
"<release version=\"2.0.1\" timestamp=\"1424116753\">\n"
"<location>http://www.hughski.com/downloads/colorhug2/firmware/colorhug-2.0.1.cab</location>\n"
- "<checksum type=\"sha1\">c7cc46d54d8d4ba452b677a2367214efbaa40fd5</checksum>\n"
- "<filename>colorhug-als-2.0.1.cab</filename>\n"
+ "<checksum filename=\"colorhug-als-2.0.1.cab\" target=\"container\" type=\"sha1\">c7cc46d54d8d4ba452b677a2367214efbaa40fd5</checksum>\n"
+ "<checksum filename=\"firmware.bin\" target=\"content\" type=\"sha1\">767a8a7b8a7b350b513f57761204b4aaa657aa44</checksum>\n"
"<description><p>This unstable release adds the following features:</p>"
"<ul><li>Use TakeReadings() to do a quick non-adaptive measurement</li>"
"<li>Scale XYZ measurement with a constant factor to make the CCMX more "
"sane</li></ul></description>\n"
"</release>\n"
"<release version=\"2.0.0\" timestamp=\"1425168000\">\n"
- "<checksum type=\"sha1\">186ad37fe3e63acc843b8727ac1add4ac15f0bf8</checksum>\n"
- "<filename>colorhug-als-2.0.0.cab</filename>\n"
+ "<checksum filename=\"colorhug-als-2.0.0.cab\" target=\"container\" type=\"sha1\">186ad37fe3e63acc843b8727ac1add4ac15f0bf8</checksum>\n"
+ "<checksum filename=\"firmware.bin\" target=\"content\" type=\"sha1\">767a8a7b8a7b350b513f57761204b4aaa657aa44</checksum>\n"
"</release>\n"
"</releases>\n"
"</component>\n"
diff --git a/libappstream-builder/plugins/asb-plugin-appdata.c b/libappstream-builder/plugins/asb-plugin-appdata.c
index f2d7ef2..0f084fe 100644
--- a/libappstream-builder/plugins/asb-plugin-appdata.c
+++ b/libappstream-builder/plugins/asb-plugin-appdata.c
@@ -303,9 +303,9 @@ asb_plugin_process_app (AsbPlugin *plugin,
/* get possible sources */
if (asb_package_get_kind (pkg) == ASB_PACKAGE_KIND_FIRMWARE) {
- appdata_filename = g_strdup_printf ("%s/%s.metainfo.xml",
- tmpdir,
- as_app_get_metadata_item (AS_APP (app), "FirmwareBasename"));
+ appdata_filename = g_build_filename (tmpdir,
+ as_app_get_metadata_item (AS_APP (app), "MetainfoBasename"),
+ NULL);
} else {
_cleanup_free_ gchar *appdata_basename = NULL;
appdata_basename = asb_plugin_appdata_get_fn_for_app (AS_APP (app));
diff --git a/libappstream-builder/plugins/asb-plugin-firmware.c b/libappstream-builder/plugins/asb-plugin-firmware.c
index 96367ff..abac939 100644
--- a/libappstream-builder/plugins/asb-plugin-firmware.c
+++ b/libappstream-builder/plugins/asb-plugin-firmware.c
@@ -41,6 +41,8 @@ void
asb_plugin_add_globs (AsbPlugin *plugin, GPtrArray *globs)
{
asb_plugin_add_glob (globs, "*.inf");
+ asb_plugin_add_glob (globs, "*.bin");
+ asb_plugin_add_glob (globs, "*.cap");
}
/**
@@ -64,10 +66,10 @@ asb_plugin_check_filename (AsbPlugin *plugin, const gchar *filename)
}
/**
- * asb_plugin_firmware_get_basename:
+ * asb_plugin_firmware_get_metainfo_fn:
*/
static gchar *
-asb_plugin_firmware_get_basename (const gchar *filename)
+asb_plugin_firmware_get_metainfo_fn (const gchar *filename)
{
gchar *basename;
gchar *tmp;
@@ -76,7 +78,7 @@ asb_plugin_firmware_get_basename (const gchar *filename)
tmp = g_strrstr (basename, ".inf");
if (tmp != NULL)
*tmp = '\0';
- return basename;
+ return g_strdup_printf ("%s.metainfo.xml", basename);
}
/**
@@ -108,11 +110,13 @@ asb_plugin_process_filename (AsbPlugin *plugin,
{
AsRelease *release;
GError *error_local = NULL;
+ const gchar *fw_basename = NULL;
_cleanup_free_ gchar *checksum = NULL;
_cleanup_free_ gchar *filename_full = NULL;
_cleanup_free_ gchar *location_checksum = NULL;
- _cleanup_free_ gchar *fw_basename = NULL;
+ _cleanup_free_ gchar *metainfo_fn = NULL;
_cleanup_object_unref_ AsbApp *app = NULL;
+ _cleanup_object_unref_ AsChecksum *csum = NULL;
/* parse */
filename_full = g_build_filename (tmpdir, filename, NULL);
@@ -133,15 +137,43 @@ asb_plugin_process_filename (AsbPlugin *plugin,
if (checksum == NULL)
return FALSE;
release = as_app_get_release_default (AS_APP (app));
- as_release_set_checksum (release, G_CHECKSUM_SHA1, checksum, -1);
- /* for the adddata plugin; removed in asb_plugin_merge() */
- fw_basename = asb_plugin_firmware_get_basename (filename);
- if (fw_basename != NULL)
- as_app_add_metadata (AS_APP (app), "FirmwareBasename", fw_basename, -1);
+ /* add checksum */
+ 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, checksum);
+ as_checksum_set_filename (csum, asb_package_get_basename (pkg));
+ as_release_add_checksum (release, csum);
- /* added so we can mirror files */
- as_release_set_filename (release, asb_package_get_basename (pkg), -1);
+ /* for the adddata plugin; removed in asb_plugin_merge() */
+ metainfo_fn = asb_plugin_firmware_get_metainfo_fn (filename);
+ if (metainfo_fn != NULL)
+ as_app_add_metadata (AS_APP (app), "MetainfoBasename", metainfo_fn, -1);
+
+ /* set the internal checksum */
+ fw_basename = as_app_get_metadata_item (AS_APP (app), "FirmwareBasename");
+ if (fw_basename != NULL) {
+ _cleanup_free_ gchar *checksum_bin = NULL;
+ _cleanup_free_ gchar *fn_bin = NULL;
+ _cleanup_object_unref_ AsChecksum *csum_bin = NULL;
+
+ /* add the checksum for the .bin file */
+ fn_bin = g_build_filename (tmpdir, fw_basename, NULL);
+ checksum_bin = asb_plugin_firmware_get_checksum (fn_bin,
+ G_CHECKSUM_SHA1,
+ error);
+ if (checksum_bin == NULL)
+ return FALSE;
+
+ /* add internal checksum */
+ csum_bin = as_checksum_new ();
+ as_checksum_set_kind (csum_bin, G_CHECKSUM_SHA1);
+ as_checksum_set_target (csum_bin, AS_CHECKSUM_TARGET_CONTENT);
+ as_checksum_set_value (csum_bin, checksum_bin);
+ as_checksum_set_filename (csum_bin, fw_basename);
+ as_release_add_checksum (release, csum_bin);
+ }
asb_plugin_add_app (apps, AS_APP (app));
return TRUE;
@@ -203,11 +235,12 @@ asb_plugin_merge (AsbPlugin *plugin, GList *list)
AsApp *app;
GList *l;
- /* remove the FirmwareBasename metadata */
+ /* remove the MetainfoBasename metadata */
for (l = list; l != NULL; l = l->next) {
app = AS_APP (l->data);
if (as_app_get_id_kind (app) != AS_ID_KIND_FIRMWARE)
continue;
+ as_app_remove_metadata (app, "MetainfoBasename");
as_app_remove_metadata (app, "FirmwareBasename");
}
}
diff --git a/libappstream-glib/Makefile.am b/libappstream-glib/Makefile.am
index 5d8549f..d38e7e8 100644
--- a/libappstream-glib/Makefile.am
+++ b/libappstream-glib/Makefile.am
@@ -69,6 +69,7 @@ libappstream_glib_include_HEADERS = \
appstream-glib.h \
as-app.h \
as-bundle.h \
+ as-checksum.h \
as-enums.h \
as-icon.h \
as-image.h \
@@ -92,6 +93,8 @@ libappstream_glib_la_SOURCES = \
as-bundle.c \
as-bundle-private.h \
as-cleanup.h \
+ as-checksum.c \
+ as-checksum-private.h \
as-enums.c \
as-icon.c \
as-icon-private.h \
@@ -166,6 +169,8 @@ introspection_sources = \
as-app.h \
as-bundle.c \
as-bundle.h \
+ as-checksum.c \
+ as-checksum.h \
as-enums.c \
as-enums.h \
as-icon.c \
diff --git a/libappstream-glib/appstream-glib.h b/libappstream-glib/appstream-glib.h
index abc1b1c..ed87f8c 100644
--- a/libappstream-glib/appstream-glib.h
+++ b/libappstream-glib/appstream-glib.h
@@ -26,6 +26,7 @@
#include <as-app.h>
#include <as-bundle.h>
+#include <as-checksum.h>
#include <as-enums.h>
#include <as-icon.h>
#include <as-image.h>
diff --git a/libappstream-glib/as-app.c b/libappstream-glib/as-app.c
index 50f1631..a8884e6 100644
--- a/libappstream-glib/as-app.c
+++ b/libappstream-glib/as-app.c
@@ -2144,7 +2144,10 @@ as_app_add_mimetype (AsApp *app, const gchar *mimetype, gssize mimetype_len)
static void
as_app_subsume_release (AsRelease *release, AsRelease *donor)
{
+ AsChecksum *csum;
+ AsChecksum *csum_tmp;
GPtrArray *locations;
+ GPtrArray *checksums;
const gchar *tmp;
guint i;
@@ -2165,12 +2168,15 @@ as_app_subsume_release (AsRelease *release, AsRelease *donor)
as_release_add_location (release, tmp, -1);
}
- /* copy metadata if set */
- for (i = 0; i < 4; i++) {
- tmp = as_release_get_checksum (donor, i);
- if (tmp == NULL)
+ /* copy checksums if set */
+ checksums = as_release_get_checksums (donor);
+ for (i = 0; i < checksums->len; i++) {
+ csum = g_ptr_array_index (checksums, i);
+ tmp = as_checksum_get_filename (csum);
+ csum_tmp = as_release_get_checksum_by_fn (release, tmp);
+ if (csum_tmp != NULL)
continue;
- as_release_set_checksum (release, i, tmp, -1);
+ as_release_add_checksum (release, csum);
}
}
diff --git a/libappstream-glib/as-checksum-private.h b/libappstream-glib/as-checksum-private.h
new file mode 100644
index 0000000..dd28e5f
--- /dev/null
+++ b/libappstream-glib/as-checksum-private.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014 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
+ */
+
+#if !defined (__APPSTREAM_GLIB_PRIVATE_H) && !defined (AS_COMPILATION)
+#error "Only <appstream-glib.h> can be included directly."
+#endif
+
+#ifndef __AS_CHECKSUM_PRIVATE_H
+#define __AS_CHECKSUM_PRIVATE_H
+
+#include "as-checksum.h"
+#include "as-node-private.h"
+
+G_BEGIN_DECLS
+
+GNode *as_checksum_node_insert (AsChecksum *checksum,
+ GNode *parent,
+ AsNodeContext *ctx);
+gboolean as_checksum_node_parse (AsChecksum *checksum,
+ GNode *node,
+ AsNodeContext *ctx,
+ GError **error);
+gboolean as_checksum_node_parse_dep11 (AsChecksum *checksum,
+ GNode *node,
+ AsNodeContext *ctx,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __AS_CHECKSUM_PRIVATE_H */
diff --git a/libappstream-glib/as-checksum.c b/libappstream-glib/as-checksum.c
new file mode 100644
index 0000000..7cd400a
--- /dev/null
+++ b/libappstream-glib/as-checksum.c
@@ -0,0 +1,423 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014-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
+ */
+
+/**
+ * SECTION:as-checksum
+ * @short_description: Object representing a single checksum used in a release.
+ * @include: appstream-glib.h
+ * @stability: Stable
+ *
+ * Checksums are attached to releases.
+ *
+ * See also: #AsRelease
+ */
+
+#include "config.h"
+
+#include "as-cleanup.h"
+#include "as-checksum-private.h"
+#include "as-node-private.h"
+#include "as-utils-private.h"
+#include "as-yaml.h"
+
+typedef struct _AsChecksumPrivate AsChecksumPrivate;
+struct _AsChecksumPrivate
+{
+ AsChecksumTarget target;
+ GChecksumType kind;
+ gchar *filename;
+ gchar *value;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (AsChecksum, as_checksum, G_TYPE_OBJECT)
+
+#define GET_PRIVATE(o) (as_checksum_get_instance_private (o))
+
+/**
+ * as_checksum_finalize:
+ **/
+static void
+as_checksum_finalize (GObject *object)
+{
+ AsChecksum *checksum = AS_CHECKSUM (object);
+ AsChecksumPrivate *priv = GET_PRIVATE (checksum);
+
+ g_free (priv->filename);
+ g_free (priv->value);
+
+ G_OBJECT_CLASS (as_checksum_parent_class)->finalize (object);
+}
+
+/**
+ * as_checksum_init:
+ **/
+static void
+as_checksum_init (AsChecksum *checksum)
+{
+}
+
+/**
+ * as_checksum_class_init:
+ **/
+static void
+as_checksum_class_init (AsChecksumClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = as_checksum_finalize;
+}
+
+/**
+ * as_checksum_target_from_string:
+ * @target: a source kind string
+ *
+ * Converts the text representation to an enumerated value.
+ *
+ * Return value: A #AsChecksumTarget, e.g. %AS_CHECKSUM_TARGET_CONTAINER.
+ *
+ * Since: 0.4.2
+ **/
+AsChecksumTarget
+as_checksum_target_from_string (const gchar *target)
+{
+ if (g_strcmp0 (target, "container") == 0)
+ return AS_CHECKSUM_TARGET_CONTAINER;
+ if (g_strcmp0 (target, "content") == 0)
+ return AS_CHECKSUM_TARGET_CONTENT;
+ return AS_CHECKSUM_TARGET_UNKNOWN;
+}
+
+/**
+ * as_checksum_target_to_string:
+ * @target: the #AsChecksumTarget.
+ *
+ * Converts the enumerated value to an text representation.
+ *
+ * Returns: string version of @target, or %NULL for unknown
+ *
+ * Since: 0.4.2
+ **/
+const gchar *
+as_checksum_target_to_string (AsChecksumTarget target)
+{
+ if (target == AS_CHECKSUM_TARGET_CONTAINER)
+ return "container";
+ if (target == AS_CHECKSUM_TARGET_CONTENT)
+ return "content";
+ return NULL;
+}
+
+/**
+ * as_checksum_get_filename:
+ * @checksum: a #AsChecksum instance.
+ *
+ * Gets the full qualified URL for the checksum, usually pointing at some mirror.
+ *
+ * Returns: URL
+ *
+ * Since: 0.4.2
+ **/
+const gchar *
+as_checksum_get_filename (AsChecksum *checksum)
+{
+ AsChecksumPrivate *priv = GET_PRIVATE (checksum);
+ return priv->filename;
+}
+
+/**
+ * as_checksum_get_value:
+ * @checksum: a #AsChecksum instance.
+ *
+ * Gets the suggested value the checksum, including file extension.
+ *
+ * Returns: filename
+ *
+ * Since: 0.4.2
+ **/
+const gchar *
+as_checksum_get_value (AsChecksum *checksum)
+{
+ AsChecksumPrivate *priv = GET_PRIVATE (checksum);
+ return priv->value;
+}
+
+/**
+ * as_checksum_get_kind:
+ * @checksum: a #AsChecksum instance.
+ *
+ * Gets the checksum kind.
+ *
+ * Returns: the #GChecksumType
+ *
+ * Since: 0.4.2
+ **/
+GChecksumType
+as_checksum_get_kind (AsChecksum *checksum)
+{
+ AsChecksumPrivate *priv = GET_PRIVATE (checksum);
+ return priv->kind;
+}
+
+/**
+ * as_checksum_get_target:
+ * @checksum: a #AsChecksum instance.
+ *
+ * Gets the checksum target.
+ *
+ * Returns: the #GChecksumType
+ *
+ * Since: 0.4.2
+ **/
+AsChecksumTarget
+as_checksum_get_target (AsChecksum *checksum)
+{
+ AsChecksumPrivate *priv = GET_PRIVATE (checksum);
+ return priv->target;
+}
+
+/**
+ * as_checksum_set_filename:
+ * @checksum: a #AsChecksum instance.
+ * @filename: the URL.
+ *
+ * Sets the filename used to generate the checksum.
+ *
+ * Since: 0.4.2
+ **/
+void
+as_checksum_set_filename (AsChecksum *checksum,
+ const gchar *filename)
+{
+ AsChecksumPrivate *priv = GET_PRIVATE (checksum);
+ g_free (priv->filename);
+ priv->filename = g_strdup (filename);
+}
+
+/**
+ * as_checksum_set_value:
+ * @checksum: a #AsChecksum instance.
+ * @value: the new filename value.
+ *
+ * Sets the checksum value filename.
+ *
+ * Since: 0.4.2
+ **/
+void
+as_checksum_set_value (AsChecksum *checksum, const gchar *value)
+{
+ AsChecksumPrivate *priv = GET_PRIVATE (checksum);
+ g_free (priv->value);
+ priv->value = g_strdup (value);
+}
+
+/**
+ * as_checksum_set_kind:
+ * @checksum: a #AsChecksum instance.
+ * @kind: the #GChecksumType, e.g. %G_CHECKSUM_SHA1.
+ *
+ * Sets the checksum kind.
+ *
+ * Since: 0.4.2
+ **/
+void
+as_checksum_set_kind (AsChecksum *checksum, GChecksumType kind)
+{
+ AsChecksumPrivate *priv = GET_PRIVATE (checksum);
+ priv->kind = kind;
+}
+
+/**
+ * as_checksum_set_target:
+ * @checksum: a #AsChecksum instance.
+ * @target: the #GChecksumType, e.g. %AS_CHECKSUM_TARGET_CONTAINER.
+ *
+ * Sets the checksum target.
+ *
+ * Since: 0.4.2
+ **/
+void
+as_checksum_set_target (AsChecksum *checksum, AsChecksumTarget target)
+{
+ AsChecksumPrivate *priv = GET_PRIVATE (checksum);
+ priv->target = target;
+}
+
+/**
+ * _g_checksum_type_from_string:
+ **/
+static GChecksumType
+_g_checksum_type_from_string (const gchar *checksum_type)
+{
+ if (g_ascii_strcasecmp (checksum_type, "md5") == 0)
+ return G_CHECKSUM_MD5;
+ if (g_ascii_strcasecmp (checksum_type, "sha1") == 0)
+ return G_CHECKSUM_SHA1;
+ if (g_ascii_strcasecmp (checksum_type, "sha256") == 0)
+ return G_CHECKSUM_SHA256;
+ if (g_ascii_strcasecmp (checksum_type, "sha512") == 0)
+ return G_CHECKSUM_SHA512;
+ return -1;
+}
+
+/**
+ * _g_checksum_type_to_string:
+ **/
+static const gchar *
+_g_checksum_type_to_string (GChecksumType checksum_type)
+{
+ if (checksum_type == G_CHECKSUM_MD5)
+ return "md5";
+ if (checksum_type == G_CHECKSUM_SHA1)
+ return "sha1";
+ if (checksum_type == G_CHECKSUM_SHA256)
+ return "sha256";
+ if (checksum_type == G_CHECKSUM_SHA512)
+ return "sha512";
+ return NULL;
+}
+
+/**
+ * as_checksum_node_insert: (skip)
+ * @checksum: a #AsChecksum instance.
+ * @parent: the parent #GNode to use..
+ * @ctx: the #AsNodeContext
+ *
+ * Inserts the checksum into the DOM tree.
+ *
+ * Returns: (transfer none): A populated #GNode
+ *
+ * Since: 0.4.2
+ **/
+GNode *
+as_checksum_node_insert (AsChecksum *checksum, GNode *parent, AsNodeContext *ctx)
+{
+ AsChecksumPrivate *priv = GET_PRIVATE (checksum);
+ GNode *n;
+
+ n = as_node_insert (parent, "checksum", priv->value,
+ AS_NODE_INSERT_FLAG_NONE,
+ "type", _g_checksum_type_to_string (priv->kind),
+ NULL);
+ if (priv->target != AS_CHECKSUM_TARGET_UNKNOWN) {
+ as_node_add_attribute (n, "target",
+ as_checksum_target_to_string (priv->target), -1);
+ }
+ if (priv->filename != NULL)
+ as_node_add_attribute (n, "filename", priv->filename, -1);
+ return n;
+}
+
+/**
+ * as_checksum_node_parse:
+ * @checksum: a #AsChecksum instance.
+ * @node: a #GNode.
+ * @ctx: a #AsNodeContext.
+ * @error: A #GError or %NULL.
+ *
+ * Populates the object from a DOM node.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 0.4.2
+ **/
+gboolean
+as_checksum_node_parse (AsChecksum *checksum, GNode *node,
+ AsNodeContext *ctx, GError **error)
+{
+ AsChecksumPrivate *priv = GET_PRIVATE (checksum);
+ const gchar *tmp;
+ gchar *taken;
+
+ tmp = as_node_get_attribute (node, "type");
+ if (tmp != NULL)
+ priv->kind = _g_checksum_type_from_string (tmp);
+ tmp = as_node_get_attribute (node, "target");
+ if (tmp != NULL)
+ priv->target = as_checksum_target_from_string (tmp);
+ taken = as_node_take_attribute (node, "filename");
+ if (taken != NULL) {
+ g_free (priv->filename);
+ priv->filename = taken;
+ }
+ taken = as_node_take_data (node);
+ if (taken != NULL) {
+ g_free (priv->value);
+ priv->value = taken;
+ }
+ return TRUE;
+}
+
+/**
+ * as_checksum_node_parse_dep11:
+ * @checksum: a #AsChecksum instance.
+ * @node: a #GNode.
+ * @ctx: a #AsNodeContext.
+ * @error: A #GError or %NULL.
+ *
+ * Populates the object from a DEP-11 node.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 0.4.2
+ **/
+gboolean
+as_checksum_node_parse_dep11 (AsChecksum *im, GNode *node,
+ AsNodeContext *ctx, GError **error)
+{
+ GNode *n;
+ const gchar *tmp;
+
+ for (n = node->children; n != NULL; n = n->next) {
+ tmp = as_yaml_node_get_key (n);
+ if (g_strcmp0 (tmp, "sha1") == 0) {
+ as_checksum_set_kind (im, G_CHECKSUM_SHA1);
+ as_checksum_set_value (im, as_yaml_node_get_value (n));
+ } else if (g_strcmp0 (tmp, "sha256") == 0) {
+ as_checksum_set_kind (im, G_CHECKSUM_SHA256);
+ as_checksum_set_value (im, as_yaml_node_get_value (n));
+ } else if (g_strcmp0 (tmp, "md5") == 0) {
+ as_checksum_set_kind (im, G_CHECKSUM_MD5);
+ as_checksum_set_value (im, as_yaml_node_get_value (n));
+ } else if (g_strcmp0 (tmp, "target") == 0) {
+ tmp = as_yaml_node_get_value (n);
+ as_checksum_set_target (im, as_checksum_target_from_string (tmp));
+ } else if (g_strcmp0 (tmp, "filename") == 0) {
+ as_checksum_set_filename (im, as_yaml_node_get_value (n));
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * as_checksum_new:
+ *
+ * Creates a new #AsChecksum.
+ *
+ * Returns: (transfer full): a #AsChecksum
+ *
+ * Since: 0.4.2
+ **/
+AsChecksum *
+as_checksum_new (void)
+{
+ AsChecksum *checksum;
+ checksum = g_object_new (AS_TYPE_CHECKSUM, NULL);
+ return AS_CHECKSUM (checksum);
+}
diff --git a/libappstream-glib/as-checksum.h b/libappstream-glib/as-checksum.h
new file mode 100644
index 0000000..485ae6b
--- /dev/null
+++ b/libappstream-glib/as-checksum.h
@@ -0,0 +1,101 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014-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
+ */
+
+#if !defined (__APPSTREAM_GLIB_H) && !defined (AS_COMPILATION)
+#error "Only <appstream-glib.h> can be included directly."
+#endif
+
+#ifndef __AS_CHECKSUM_H
+#define __AS_CHECKSUM_H
+
+#include <glib-object.h>
+
+#define AS_TYPE_CHECKSUM (as_checksum_get_type())
+#define AS_CHECKSUM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), AS_TYPE_CHECKSUM, AsChecksum))
+#define AS_CHECKSUM_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST((cls), AS_TYPE_CHECKSUM, AsChecksumClass))
+#define AS_IS_CHECKSUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), AS_TYPE_CHECKSUM))
+#define AS_IS_CHECKSUM_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE((cls), AS_TYPE_CHECKSUM))
+#define AS_CHECKSUM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), AS_TYPE_CHECKSUM, AsChecksumClass))
+
+G_BEGIN_DECLS
+
+typedef struct _AsChecksum AsChecksum;
+typedef struct _AsChecksumClass AsChecksumClass;
+
+struct _AsChecksum
+{
+ GObject parent;
+};
+
+struct _AsChecksumClass
+{
+ GObjectClass parent_class;
+ /*< private >*/
+ void (*_as_reserved1) (void);
+ void (*_as_reserved2) (void);
+ void (*_as_reserved3) (void);
+ void (*_as_reserved4) (void);
+ void (*_as_reserved5) (void);
+ void (*_as_reserved6) (void);
+ void (*_as_reserved7) (void);
+ void (*_as_reserved8) (void);
+};
+
+/**
+ * AsChecksumTarget:
+ * @AS_CHECKSUM_TARGET_UNKNOWN: Unknown state
+ * @AS_CHECKSUM_TARGET_CONTAINER: Container file, e.g. ".cab"
+ * @AS_CHECKSUM_TARGET_CONTENT: Extracted file, e.g. ".bin"
+ *
+ * The checksum target type.
+ **/
+typedef enum {
+ AS_CHECKSUM_TARGET_UNKNOWN, /* Since: 0.4.2 */
+ AS_CHECKSUM_TARGET_CONTAINER, /* Since: 0.4.2 */
+ AS_CHECKSUM_TARGET_CONTENT, /* Since: 0.4.2 */
+ /*< private >*/
+ AS_CHECKSUM_TARGET_LAST
+} AsChecksumTarget;
+
+GType as_checksum_get_type (void);
+AsChecksum *as_checksum_new (void);
+AsChecksumTarget as_checksum_target_from_string (const gchar *target);
+const gchar *as_checksum_target_to_string (AsChecksumTarget target);
+
+/* getters */
+const gchar *as_checksum_get_filename (AsChecksum *checksum);
+const gchar *as_checksum_get_value (AsChecksum *checksum);
+GChecksumType as_checksum_get_kind (AsChecksum *checksum);
+AsChecksumTarget as_checksum_get_target (AsChecksum *checksum);
+
+/* setters */
+void as_checksum_set_filename (AsChecksum *checksum,
+ const gchar *filename);
+void as_checksum_set_value (AsChecksum *checksum,
+ const gchar *value);
+void as_checksum_set_kind (AsChecksum *checksum,
+ GChecksumType kind);
+void as_checksum_set_target (AsChecksum *checksum,
+ AsChecksumTarget target);
+
+G_END_DECLS
+
+#endif /* __AS_CHECKSUM_H */
diff --git a/libappstream-glib/as-release.c b/libappstream-glib/as-release.c
index 43df0e1..bafd388 100644
--- a/libappstream-glib/as-release.c
+++ b/libappstream-glib/as-release.c
@@ -40,22 +40,20 @@
#include <stdlib.h>
#include "as-cleanup.h"
+#include "as-checksum-private.h"
#include "as-node-private.h"
#include "as-release-private.h"
#include "as-tag.h"
#include "as-utils-private.h"
-#define AS_RELEASE_CHECKSUM_TYPE_MAX G_CHECKSUM_SHA512
-
typedef struct _AsReleasePrivate AsReleasePrivate;
struct _AsReleasePrivate
{
gchar *version;
- gchar *filename;
GHashTable *descriptions;
guint64 timestamp;
GPtrArray *locations;
- gchar **checksums;
+ GPtrArray *checksums;
};
G_DEFINE_TYPE_WITH_PRIVATE (AsRelease, as_release, G_TYPE_OBJECT)
@@ -72,8 +70,7 @@ as_release_finalize (GObject *object)
AsReleasePrivate *priv = GET_PRIVATE (release);
g_free (priv->version);
- g_free (priv->filename);
- g_strfreev (priv->checksums);
+ g_ptr_array_unref (priv->checksums);
g_ptr_array_unref (priv->locations);
if (priv->descriptions != NULL)
g_hash_table_unref (priv->descriptions);
@@ -89,7 +86,7 @@ as_release_init (AsRelease *release)
{
AsReleasePrivate *priv = GET_PRIVATE (release);
priv->locations = g_ptr_array_new_with_free_func (g_free);
- priv->checksums = g_new0 (gchar *, AS_RELEASE_CHECKSUM_TYPE_MAX + 1);
+ priv->checksums = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
}
/**
@@ -151,23 +148,6 @@ as_release_get_version (AsRelease *release)
}
/**
- * as_release_get_filename:
- * @release: a #AsRelease instance.
- *
- * Gets the release filename.
- *
- * Returns: string, or %NULL for not set or invalid
- *
- * Since: 0.4.2
- **/
-const gchar *
-as_release_get_filename (AsRelease *release)
-{
- AsReleasePrivate *priv = GET_PRIVATE (release);
- return priv->filename;
-}
-
-/**
* as_release_get_locations:
* @release: a #AsRelease instance.
*
@@ -204,6 +184,73 @@ as_release_get_location_default (AsRelease *release)
}
/**
+ * as_release_get_checksums:
+ * @release: a #AsRelease instance.
+ *
+ * Gets the release checksums.
+ *
+ * Returns: (transfer none) (element-type AsChecksum): list of checksums
+ *
+ * Since: 0.4.2
+ **/
+GPtrArray *
+as_release_get_checksums (AsRelease *release)
+{
+ AsReleasePrivate *priv = GET_PRIVATE (release);
+ return priv->checksums;
+}
+
+/**
+ * as_release_get_checksum_by_fn:
+ * @release: a #AsRelease instance.
+ *
+ * Gets the checksum for a release.
+ *
+ * Returns: (transfer none): an #AsChecksum, or %NULL for not found
+ *
+ * Since: 0.4.2
+ **/
+AsChecksum *
+as_release_get_checksum_by_fn (AsRelease *release, const gchar *fn)
+{
+ AsChecksum *checksum;
+ AsReleasePrivate *priv = GET_PRIVATE (release);
+ guint i;
+
+ for (i = 0; i < priv->checksums->len; i++) {
+ checksum = g_ptr_array_index (priv->checksums, i);
+ if (g_strcmp0 (fn, as_checksum_get_filename (checksum)) == 0)
+ return checksum;
+ }
+ return NULL;
+}
+
+/**
+ * as_release_get_checksum_by_target:
+ * @target: a #AsChecksumTarget, e.g. %AS_CHECKSUM_TARGET_CONTAINER
+ *
+ * Gets the checksum for a release.
+ *
+ * Returns: (transfer none): an #AsChecksum, or %NULL for not found
+ *
+ * Since: 0.4.2
+ **/
+AsChecksum *
+as_release_get_checksum_by_target (AsRelease *release, AsChecksumTarget target)
+{
+ AsChecksum *checksum;
+ AsReleasePrivate *priv = GET_PRIVATE (release);
+ guint i;
+
+ for (i = 0; i < priv->checksums->len; i++) {
+ checksum = g_ptr_array_index (priv->checksums, i);
+ if (as_checksum_get_target (checksum) == target)
+ return checksum;
+ }
+ return NULL;
+}
+
+/**
* as_release_get_checksum:
* @release: a #AsRelease instance.
*
@@ -216,9 +263,16 @@ as_release_get_location_default (AsRelease *release)
const gchar *
as_release_get_checksum (AsRelease *release, GChecksumType checksum_type)
{
+ AsChecksum *checksum;
AsReleasePrivate *priv = GET_PRIVATE (release);
- g_return_val_if_fail (checksum_type <= AS_RELEASE_CHECKSUM_TYPE_MAX, NULL);
- return priv->checksums[checksum_type];
+ guint i;
+
+ for (i = 0; i < priv->checksums->len; i++) {
+ checksum = g_ptr_array_index (priv->checksums, i);
+ if (checksum_type == as_checksum_get_kind (checksum))
+ return as_checksum_get_value (checksum);
+ }
+ return NULL;
}
/**
@@ -279,26 +333,6 @@ as_release_set_version (AsRelease *release,
}
/**
- * as_release_set_filename:
- * @release: a #AsRelease instance.
- * @filename: the filename string.
- * @filename_len: the size of @filename, or -1 if %NULL-terminated.
- *
- * Sets the release filename.
- *
- * Since: 0.4.2
- **/
-void
-as_release_set_filename (AsRelease *release,
- const gchar *filename,
- gssize filename_len)
-{
- AsReleasePrivate *priv = GET_PRIVATE (release);
- g_free (priv->filename);
- priv->filename = as_strndup (filename, filename_len);
-}
-
-/**
* as_release_add_location:
* @release: a #AsRelease instance.
* @location: the location string.
@@ -323,10 +357,26 @@ as_release_add_location (AsRelease *release,
}
/**
+ * as_release_add_checksum:
+ * @release: a #AsRelease instance.
+ * @checksum: a #AsChecksum instance.
+ *
+ * Adds a release checksum.
+ *
+ * Since: 0.4.2
+ **/
+void
+as_release_add_checksum (AsRelease *release, AsChecksum *checksum)
+{
+ AsReleasePrivate *priv = GET_PRIVATE (release);
+ g_ptr_array_add (priv->checksums, g_object_ref (checksum));
+}
+
+/**
* as_release_set_checksum:
* @release: a #AsRelease instance.
* @checksum_type: a #GChecksumType, e.g. %G_CHECKSUM_SHA1
- * @checksum: the checksum string.
+ * @checksum_value: the checksum string.
* @checksum_len: the size of @checksum, or -1 if %NULL-terminated.
*
* Sets the release checksum.
@@ -336,13 +386,21 @@ as_release_add_location (AsRelease *release,
void
as_release_set_checksum (AsRelease *release,
GChecksumType checksum_type,
- const gchar *checksum,
+ const gchar *checksum_value,
gssize checksum_len)
{
+ AsChecksum *checksum;
AsReleasePrivate *priv = GET_PRIVATE (release);
- g_return_if_fail (checksum_type <= AS_RELEASE_CHECKSUM_TYPE_MAX);
- g_free (priv->checksums[checksum_type]);
- priv->checksums[checksum_type] = as_strndup (checksum, checksum_len);
+
+ /* compat */
+ if (priv->checksums->len > 0) {
+ checksum = g_ptr_array_index (priv->checksums, 0);
+ } else {
+ checksum = as_checksum_new ();
+ as_release_add_checksum (release, checksum);
+ }
+ as_checksum_set_value (checksum, checksum_value);
+ as_checksum_set_kind (checksum, checksum_type);
}
/**
@@ -393,40 +451,6 @@ as_release_set_description (AsRelease *release,
}
/**
- * _g_checksum_type_from_string:
- **/
-static GChecksumType
-_g_checksum_type_from_string (const gchar *checksum_type)
-{
- if (g_ascii_strcasecmp (checksum_type, "md5") == 0)
- return G_CHECKSUM_MD5;
- if (g_ascii_strcasecmp (checksum_type, "sha1") == 0)
- return G_CHECKSUM_SHA1;
- if (g_ascii_strcasecmp (checksum_type, "sha256") == 0)
- return G_CHECKSUM_SHA256;
- if (g_ascii_strcasecmp (checksum_type, "sha512") == 0)
- return G_CHECKSUM_SHA512;
- return -1;
-}
-
-/**
- * _g_checksum_type_to_string:
- **/
-static const gchar *
-_g_checksum_type_to_string (GChecksumType checksum_type)
-{
- if (checksum_type == G_CHECKSUM_MD5)
- return "md5";
- if (checksum_type == G_CHECKSUM_SHA1)
- return "sha1";
- if (checksum_type == G_CHECKSUM_SHA256)
- return "sha256";
- if (checksum_type == G_CHECKSUM_SHA512)
- return "sha512";
- return NULL;
-}
-
-/**
* as_release_node_insert: (skip)
* @release: a #AsRelease instance.
* @parent: the parent #GNode to use..
@@ -442,6 +466,7 @@ GNode *
as_release_node_insert (AsRelease *release, GNode *parent, AsNodeContext *ctx)
{
AsReleasePrivate *priv = GET_PRIVATE (release);
+ AsChecksum *checksum;
GNode *n;
n = as_node_insert (parent, "release", NULL,
@@ -463,18 +488,9 @@ as_release_node_insert (AsRelease *release, GNode *parent, AsNodeContext *ctx)
as_node_insert (n, "location", tmp,
AS_NODE_INSERT_FLAG_NONE, NULL);
}
- for (i = 0; i <= AS_RELEASE_CHECKSUM_TYPE_MAX; i++) {
- if (priv->checksums[i] == NULL)
- continue;
- as_node_insert (n, "checksum", priv->checksums[i],
- AS_NODE_INSERT_FLAG_NONE,
- "type", _g_checksum_type_to_string (i),
- NULL);
- }
- if (priv->filename != NULL) {
- as_node_insert (n, "filename", priv->filename,
- AS_NODE_INSERT_FLAG_NONE,
- NULL);
+ for (i = 0; i < priv->checksums->len; i++) {
+ checksum = g_ptr_array_index (priv->checksums, i);
+ as_checksum_node_insert (checksum, n, ctx);
}
}
if (priv->descriptions != NULL && as_node_context_get_version (ctx) >= 0.6) {
@@ -506,7 +522,6 @@ as_release_node_parse (AsRelease *release, GNode *node,
GNode *n;
const gchar *tmp;
gchar *taken;
- guint i;
tmp = as_node_get_attribute (node, "timestamp");
if (tmp != NULL)
@@ -525,31 +540,15 @@ as_release_node_parse (AsRelease *release, GNode *node,
g_ptr_array_add (priv->locations, as_node_take_data (n));
}
- /* get optional filename */
- for (n = node->children; n != NULL; n = n->next) {
- if (as_node_get_tag (n) != AS_TAG_FILENAME)
- continue;
- g_free (priv->filename);
- priv->filename = as_node_take_data (n);
- }
-
/* get optional checksums */
- for (i = 0; i <= AS_RELEASE_CHECKSUM_TYPE_MAX; i++) {
- g_free (priv->checksums[i]);
- priv->checksums[i] = NULL;
- }
for (n = node->children; n != NULL; n = n->next) {
- GChecksumType checksum_type;
- const gchar *type;
+ _cleanup_object_unref_ AsChecksum *csum = NULL;
if (as_node_get_tag (n) != AS_TAG_CHECKSUM)
continue;
- type = as_node_get_attribute (n, "type");
- if (type == NULL)
- continue;
- checksum_type = _g_checksum_type_from_string (type);
- if ((gint) checksum_type == -1)
- continue;
- priv->checksums[checksum_type] = as_node_take_data (n);
+ csum = as_checksum_new ();
+ if (!as_checksum_node_parse (csum, n, ctx, error))
+ return FALSE;
+ as_release_add_checksum (release, csum);
}
/* AppStream: multiple <description> tags */
diff --git a/libappstream-glib/as-release.h b/libappstream-glib/as-release.h
index c145f8c..2d7c75f 100644
--- a/libappstream-glib/as-release.h
+++ b/libappstream-glib/as-release.h
@@ -28,6 +28,8 @@
#include <glib-object.h>
+#include "as-checksum.h"
+
#define AS_TYPE_RELEASE (as_release_get_type())
#define AS_RELEASE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), AS_TYPE_RELEASE, AsRelease))
#define AS_RELEASE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST((cls), AS_TYPE_RELEASE, AsReleaseClass))
@@ -72,8 +74,11 @@ const gchar *as_release_get_description (AsRelease *release,
const gchar *locale);
GPtrArray *as_release_get_locations (AsRelease *release);
const gchar *as_release_get_location_default (AsRelease *release);
-const gchar *as_release_get_checksum (AsRelease *release,
- GChecksumType checksum_type);
+AsChecksum *as_release_get_checksum_by_fn (AsRelease *release,
+ const gchar *fn);
+AsChecksum *as_release_get_checksum_by_target (AsRelease *release,
+ AsChecksumTarget target);
+GPtrArray *as_release_get_checksums (AsRelease *release);
/* setters */
void as_release_set_version (AsRelease *release,
@@ -91,10 +96,18 @@ void as_release_set_description (AsRelease *release,
void as_release_add_location (AsRelease *release,
const gchar *location,
gssize location_len);
+void as_release_add_checksum (AsRelease *release,
+ AsChecksum *checksum);
+
+/* deprecated */
+G_DEPRECATED_FOR(as_checksum_set_value)
void as_release_set_checksum (AsRelease *release,
GChecksumType checksum_type,
- const gchar *checksum,
+ const gchar *checksum_value,
gssize checksum_len);
+G_DEPRECATED_FOR(as_checksum_get_value)
+const gchar *as_release_get_checksum (AsRelease *release,
+ GChecksumType checksum_type);
G_END_DECLS
diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c
index 2e93970..aabe9c0 100644
--- a/libappstream-glib/as-self-test.c
+++ b/libappstream-glib/as-self-test.c
@@ -27,6 +27,7 @@
#include "as-app-private.h"
#include "as-bundle-private.h"
+#include "as-checksum-private.h"
#include "as-cleanup.h"
#include "as-enums.h"
#include "as-icon-private.h"
@@ -426,6 +427,7 @@ as_test_provide_func (void)
static void
as_test_release_appstream_func (void)
{
+ AsChecksum *csum;
GError *error = NULL;
GNode *n;
GNode *root;
@@ -435,9 +437,8 @@ as_test_release_appstream_func (void)
"<release version=\"0.1.2\" timestamp=\"123\">\n"
"<location>http://foo.com/bar.zip</location>\n"
"<location>http://baz.com/bar.cab</location>\n"
- "<checksum type=\"md5\">deadbeef</checksum>\n"
- "<checksum type=\"sha1\">12345</checksum>\n"
- "<filename>firmware.cab</filename>\n"
+ "<checksum filename=\"firmware.cab\" target=\"container\" type=\"sha1\">12345</checksum>\n"
+ "<checksum filename=\"firmware.cab\" target=\"container\" type=\"md5\">deadbeef</checksum>\n"
"<description><p>This is a new release</p><ul><li>Point</li></ul></description>\n"
"<description xml:lang=\"pl\"><p>Oprogramowanie</p></description>\n"
"</release>\n";
@@ -461,15 +462,36 @@ as_test_release_appstream_func (void)
/* verify */
g_assert_cmpint (as_release_get_timestamp (release), ==, 123);
g_assert_cmpstr (as_release_get_version (release), ==, "0.1.2");
- g_assert_cmpstr (as_release_get_filename (release), ==, "firmware.cab");
g_assert_cmpstr (as_release_get_location_default (release), ==, "http://foo.com/bar.zip");
- g_assert_cmpstr (as_release_get_checksum (release, G_CHECKSUM_SHA1), ==, "12345");
- g_assert_cmpstr (as_release_get_checksum (release, G_CHECKSUM_MD5), ==, "deadbeef");
g_assert_cmpstr (as_release_get_description (release, "pl"), ==,
"<p>Oprogramowanie</p>");
g_assert_cmpstr (as_release_get_description (release, NULL), ==,
"<p>This is a new release</p><ul><li>Point</li></ul>");
+ /* checksum */
+ g_assert_cmpint (as_release_get_checksums(release)->len, ==, 2);
+ csum = as_release_get_checksum_by_fn (release, "firmware.inf");
+ g_assert (csum == NULL);
+ csum = as_release_get_checksum_by_fn (release, "firmware.cab");
+ g_assert (csum != NULL);
+ g_assert_cmpint (as_checksum_get_kind (csum), ==, G_CHECKSUM_SHA1);
+ g_assert_cmpint (as_checksum_get_target (csum), ==, AS_CHECKSUM_TARGET_CONTAINER);
+ g_assert_cmpstr (as_checksum_get_filename (csum), ==, "firmware.cab");
+ g_assert_cmpstr (as_checksum_get_value (csum), ==, "12345");
+
+ /* get by target type */
+ csum = as_release_get_checksum_by_target (release, AS_CHECKSUM_TARGET_CONTENT);
+ g_assert (csum == NULL);
+ csum = as_release_get_checksum_by_target (release, AS_CHECKSUM_TARGET_CONTAINER);
+ g_assert (csum != NULL);
+ g_assert_cmpstr (as_checksum_get_value (csum), ==, "12345");
+
+ /* deprecated */
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ g_assert_cmpstr (as_release_get_checksum (release, G_CHECKSUM_SHA1), ==, "12345");
+ g_assert_cmpstr (as_release_get_checksum (release, G_CHECKSUM_MD5), ==, "deadbeef");
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
/* back to node */
root = as_node_new ();
as_node_context_set_version (ctx, 1.0);
@@ -779,6 +801,58 @@ as_test_icon_func (void)
}
static void
+as_test_checksum_func (void)
+{
+ GError *error = NULL;
+ GNode *n;
+ GNode *root;
+ GString *xml;
+ const gchar *src = "<checksum filename=\"fn.cab\" target=\"container\" type=\"sha1\">12345</checksum>";
+ gboolean ret;
+ _cleanup_free_ AsNodeContext *ctx = NULL;
+ _cleanup_object_unref_ AsChecksum *csum = NULL;
+
+ /* helpers */
+ g_assert_cmpint (as_checksum_target_from_string ("container"), ==, AS_CHECKSUM_TARGET_CONTAINER);
+ g_assert_cmpint (as_checksum_target_from_string ("content"), ==, AS_CHECKSUM_TARGET_CONTENT);
+ g_assert_cmpint (as_checksum_target_from_string (NULL), ==, AS_CHECKSUM_TARGET_UNKNOWN);
+ g_assert_cmpstr (as_checksum_target_to_string (AS_CHECKSUM_TARGET_CONTAINER), ==, "container");
+ g_assert_cmpstr (as_checksum_target_to_string (AS_CHECKSUM_TARGET_CONTENT), ==, "content");
+ g_assert_cmpstr (as_checksum_target_to_string (AS_CHECKSUM_TARGET_UNKNOWN), ==, NULL);
+
+ csum = as_checksum_new ();
+
+ /* to object */
+ root = as_node_from_xml (src, -1, 0, &error);
+ g_assert_no_error (error);
+ g_assert (root != NULL);
+ n = as_node_find (root, "checksum");
+ g_assert (n != NULL);
+ ctx = as_node_context_new ();
+ ret = as_checksum_node_parse (csum, n, ctx, &error);
+ g_assert_no_error (error);
+ g_assert (ret);
+ as_node_unref (root);
+
+ /* verify */
+ g_assert_cmpint (as_checksum_get_kind (csum), ==, G_CHECKSUM_SHA1);
+ g_assert_cmpint (as_checksum_get_target (csum), ==, AS_CHECKSUM_TARGET_CONTAINER);
+ g_assert_cmpstr (as_checksum_get_filename (csum), ==, "fn.cab");
+ g_assert_cmpstr (as_checksum_get_value (csum), ==, "12345");
+
+ /* back to node */
+ root = as_node_new ();
+ as_node_context_set_version (ctx, 0.4);
+ n = as_checksum_node_insert (csum, root, ctx);
+ xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
+ ret = as_test_compare_lines (xml->str, src, &error);
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_string_free (xml, TRUE);
+ as_node_unref (root);
+}
+
+static void
as_test_icon_embedded_func (void)
{
GError *error = NULL;
@@ -4141,6 +4215,7 @@ main (int argc, char **argv)
/* tests go here */
g_test_add_func ("/AppStream/tag", as_test_tag_func);
g_test_add_func ("/AppStream/provide", as_test_provide_func);
+ g_test_add_func ("/AppStream/checksum", as_test_checksum_func);
g_test_add_func ("/AppStream/release", as_test_release_func);
g_test_add_func ("/AppStream/release{appdata}", as_test_release_appdata_func);
g_test_add_func ("/AppStream/release{appstream}", as_test_release_appstream_func);
diff --git a/libappstream-glib/as-tag.c b/libappstream-glib/as-tag.c
index 6d00ffe..31cf7e8 100644
--- a/libappstream-glib/as-tag.c
+++ b/libappstream-glib/as-tag.c
@@ -190,7 +190,6 @@ as_tag_to_string (AsTag tag)
"permission",
"location",
"checksum",
- "filename",
NULL };
if (tag > AS_TAG_LAST)
tag = AS_TAG_LAST;
diff --git a/libappstream-glib/as-tag.gperf b/libappstream-glib/as-tag.gperf
index 7746b90..3c31b46 100644
--- a/libappstream-glib/as-tag.gperf
+++ b/libappstream-glib/as-tag.gperf
@@ -54,4 +54,3 @@ permissions, AS_TAG_PERMISSIONS
permission, AS_TAG_PERMISSION
location, AS_TAG_LOCATION
checksum, AS_TAG_CHECKSUM
-filename, AS_TAG_FILENAME
diff --git a/libappstream-glib/as-tag.h b/libappstream-glib/as-tag.h
index 8cfc26c..ed16c5b 100644
--- a/libappstream-glib/as-tag.h
+++ b/libappstream-glib/as-tag.h
@@ -77,7 +77,6 @@
* @AS_TAG_PERMISSION: `permission`
* @AS_TAG_LOCATION: `location`
* @AS_TAG_CHECKSUM: `checksum`
- * @AS_TAG_FILENAME: `filename`
*
* The tag type.
**/
@@ -129,7 +128,6 @@ typedef enum {
AS_TAG_PERMISSION, /* Since: 0.3.5 */
AS_TAG_LOCATION, /* Since: 0.3.5 */
AS_TAG_CHECKSUM, /* Since: 0.3.5 */
- AS_TAG_FILENAME, /* Since: 0.4.2 */
/*< private >*/
AS_TAG_LAST
} AsTag;