summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2015-03-04 12:51:54 +0000
committerRichard Hughes <richard@hughsie.com>2015-03-04 12:51:54 +0000
commitdb40ff74de159df823a55ea4142dce6fdf1560df (patch)
tree625204f7dda38b5c5c74efdd90581724d0445c39
parent177061b21dd82a6dbd7e4dc4ba8d0137c3b28ee5 (diff)
downloadappstream-glib-db40ff74de159df823a55ea4142dce6fdf1560df.tar.gz
Add support for <location> and <checksum>
This is needed for AppStream 0.9 support.
-rw-r--r--libappstream-glib/as-release.c185
-rw-r--r--libappstream-glib/as-release.h11
-rw-r--r--libappstream-glib/as-self-test.c7
-rw-r--r--libappstream-glib/as-tag.c2
-rw-r--r--libappstream-glib/as-tag.gperf2
-rw-r--r--libappstream-glib/as-tag.h4
6 files changed, 211 insertions, 0 deletions
diff --git a/libappstream-glib/as-release.c b/libappstream-glib/as-release.c
index f4f40c9..bc16468 100644
--- a/libappstream-glib/as-release.c
+++ b/libappstream-glib/as-release.c
@@ -45,12 +45,16 @@
#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;
GHashTable *descriptions;
guint64 timestamp;
+ GPtrArray *locations;
+ gchar **checksums;
};
G_DEFINE_TYPE_WITH_PRIVATE (AsRelease, as_release, G_TYPE_OBJECT)
@@ -67,6 +71,8 @@ as_release_finalize (GObject *object)
AsReleasePrivate *priv = GET_PRIVATE (release);
g_free (priv->version);
+ g_strfreev (priv->checksums);
+ g_ptr_array_unref (priv->locations);
if (priv->descriptions != NULL)
g_hash_table_unref (priv->descriptions);
@@ -79,6 +85,9 @@ as_release_finalize (GObject *object)
static void
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);
}
/**
@@ -109,6 +118,60 @@ as_release_get_version (AsRelease *release)
}
/**
+ * as_release_get_locations:
+ * @release: a #AsRelease instance.
+ *
+ * Gets the release locations, typically URLs.
+ *
+ * Returns: (transfer none) (element-type utf8): list of locations
+ *
+ * Since: 0.3.5
+ **/
+GPtrArray *
+as_release_get_locations (AsRelease *release)
+{
+ AsReleasePrivate *priv = GET_PRIVATE (release);
+ return priv->locations;
+}
+
+/**
+ * as_release_get_location_default:
+ * @release: a #AsRelease instance.
+ *
+ * Gets the default release location, typically a URL.
+ *
+ * Returns: string, or %NULL for not set or invalid
+ *
+ * Since: 0.3.5
+ **/
+const gchar *
+as_release_get_location_default (AsRelease *release)
+{
+ AsReleasePrivate *priv = GET_PRIVATE (release);
+ if (priv->locations->len == 0)
+ return NULL;
+ return g_ptr_array_index (priv->locations, 0);
+}
+
+/**
+ * as_release_get_checksum:
+ * @release: a #AsRelease instance.
+ *
+ * Gets the release checksum, typically a SHA1 hash.
+ *
+ * Returns: string, or %NULL for not set or invalid
+ *
+ * Since: 0.3.5
+ **/
+const gchar *
+as_release_get_checksum (AsRelease *release, GChecksumType checksum_type)
+{
+ AsReleasePrivate *priv = GET_PRIVATE (release);
+ g_return_val_if_fail (checksum_type <= AS_RELEASE_CHECKSUM_TYPE_MAX, NULL);
+ return priv->checksums[checksum_type];
+}
+
+/**
* as_release_get_timestamp:
* @release: a #AsRelease instance.
*
@@ -161,10 +224,53 @@ as_release_set_version (AsRelease *release,
gssize version_len)
{
AsReleasePrivate *priv = GET_PRIVATE (release);
+ g_free (priv->version);
priv->version = as_strndup (version, version_len);
}
/**
+ * as_release_add_location:
+ * @release: a #AsRelease instance.
+ * @location: the location string.
+ * @location_len: the size of @location, or -1 if %NULL-terminated.
+ *
+ * Adds a release location.
+ *
+ * Since: 0.3.5
+ **/
+void
+as_release_add_location (AsRelease *release,
+ const gchar *location,
+ gssize location_len)
+{
+ AsReleasePrivate *priv = GET_PRIVATE (release);
+ g_ptr_array_add (priv->locations, as_strndup (location, location_len));
+}
+
+/**
+ * as_release_set_checksum:
+ * @release: a #AsRelease instance.
+ * @checksum_type: a #GChecksumType, e.g. %G_CHECKSUM_SHA1
+ * @checksum: the checksum string.
+ * @checksum_len: the size of @checksum, or -1 if %NULL-terminated.
+ *
+ * Sets the release checksum.
+ *
+ * Since: 0.3.5
+ **/
+void
+as_release_set_checksum (AsRelease *release,
+ GChecksumType checksum_type,
+ const gchar *checksum,
+ gssize checksum_len)
+{
+ 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);
+}
+
+/**
* as_release_set_timestamp:
* @release: a #AsRelease instance.
* @timestamp: the timestamp value.
@@ -212,6 +318,40 @@ 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..
@@ -237,6 +377,23 @@ as_release_node_insert (AsRelease *release, GNode *parent, AsNodeContext *ctx)
"timestamp", timestamp_str,
"version", priv->version,
NULL);
+ if (as_node_context_get_version (ctx) >= 0.9) {
+ const gchar *tmp;
+ guint i;
+ for (i = 0; i < priv->locations->len; i++) {
+ tmp = g_ptr_array_index (priv->locations, i);
+ 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->descriptions != NULL && as_node_context_get_version (ctx) >= 0.6) {
as_node_insert_localized (n, "description", priv->descriptions,
AS_NODE_INSERT_FLAG_PRE_ESCAPED |
@@ -266,6 +423,7 @@ 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)
@@ -276,6 +434,33 @@ as_release_node_parse (AsRelease *release, GNode *node,
priv->version = taken;
}
+ /* get optional locations */
+ g_ptr_array_set_size (priv->locations, 0);
+ for (n = node->children; n != NULL; n = n->next) {
+ if (as_node_get_tag (n) != AS_TAG_LOCATION)
+ continue;
+ g_ptr_array_add (priv->locations, 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;
+ 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);
+ }
+
/* AppStream: multiple <description> tags */
if (as_node_context_get_source_kind (ctx) == AS_APP_SOURCE_KIND_APPSTREAM) {
for (n = node->children; n != NULL; n = n->next) {
diff --git a/libappstream-glib/as-release.h b/libappstream-glib/as-release.h
index 9e1a968..6daa1cd 100644
--- a/libappstream-glib/as-release.h
+++ b/libappstream-glib/as-release.h
@@ -67,6 +67,10 @@ const gchar *as_release_get_version (AsRelease *release);
guint64 as_release_get_timestamp (AsRelease *release);
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);
/* setters */
void as_release_set_version (AsRelease *release,
@@ -78,6 +82,13 @@ void as_release_set_description (AsRelease *release,
const gchar *locale,
const gchar *description,
gssize description_len);
+void as_release_add_location (AsRelease *release,
+ const gchar *location,
+ gssize location_len);
+void as_release_set_checksum (AsRelease *release,
+ GChecksumType checksum_type,
+ const gchar *checksum,
+ gssize checksum_len);
G_END_DECLS
diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c
index 5baea2a..b16e16f 100644
--- a/libappstream-glib/as-self-test.c
+++ b/libappstream-glib/as-self-test.c
@@ -199,6 +199,10 @@ as_test_release_appstream_func (void)
gboolean ret;
const gchar *src =
"<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"
"<description><p>This is a new release</p></description>\n"
"<description xml:lang=\"pl\"><p>Oprogramowanie</p></description>\n"
"</release>\n";
@@ -222,6 +226,9 @@ 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_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>");
diff --git a/libappstream-glib/as-tag.c b/libappstream-glib/as-tag.c
index 7f4f8f2..31cf7e8 100644
--- a/libappstream-glib/as-tag.c
+++ b/libappstream-glib/as-tag.c
@@ -188,6 +188,8 @@ as_tag_to_string (AsTag tag)
"bundle",
"permissions",
"permission",
+ "location",
+ "checksum",
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 7b4b962..3c31b46 100644
--- a/libappstream-glib/as-tag.gperf
+++ b/libappstream-glib/as-tag.gperf
@@ -52,3 +52,5 @@ veto, AS_TAG_VETO
bundle, AS_TAG_BUNDLE
permissions, AS_TAG_PERMISSIONS
permission, AS_TAG_PERMISSION
+location, AS_TAG_LOCATION
+checksum, AS_TAG_CHECKSUM
diff --git a/libappstream-glib/as-tag.h b/libappstream-glib/as-tag.h
index 77857f8..ed16c5b 100644
--- a/libappstream-glib/as-tag.h
+++ b/libappstream-glib/as-tag.h
@@ -75,6 +75,8 @@
* @AS_TAG_BUNDLE: `bundle`
* @AS_TAG_PERMISSIONS: `permissions`
* @AS_TAG_PERMISSION: `permission`
+ * @AS_TAG_LOCATION: `location`
+ * @AS_TAG_CHECKSUM: `checksum`
*
* The tag type.
**/
@@ -124,6 +126,8 @@ typedef enum {
AS_TAG_BUNDLE, /* Since: 0.3.5 */
AS_TAG_PERMISSIONS, /* Since: 0.3.5 */
AS_TAG_PERMISSION, /* Since: 0.3.5 */
+ AS_TAG_LOCATION, /* Since: 0.3.5 */
+ AS_TAG_CHECKSUM, /* Since: 0.3.5 */
/*< private >*/
AS_TAG_LAST
} AsTag;