[gcab] Add GCabCabinet:signature and gcab_cabinet_get_signature()
- From: Marc-Andre Lureau <malureau src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcab] Add GCabCabinet:signature and gcab_cabinet_get_signature()
- Date: Thu, 14 Feb 2013 00:48:45 +0000 (UTC)
commit a046cf5b65f60bd181e7381845267ff3a8b36fb2
Author: Marc-Andrà Lureau <marcandre lureau gmail com>
Date: Thu Feb 14 01:45:54 2013 +0100
Add GCabCabinet:signature and gcab_cabinet_get_signature()
docs/reference/gcab-sections.txt | 1 +
libgcab.syms | 4 ++
libgcab/gcab-cabinet.c | 81 +++++++++++++++++++++++++++++++++++++-
libgcab/gcab-cabinet.h | 3 +
libgcab/gcab-priv.h | 10 +++++
5 files changed, 98 insertions(+), 1 deletions(-)
---
diff --git a/docs/reference/gcab-sections.txt b/docs/reference/gcab-sections.txt
index aa91791..73c8159 100644
--- a/docs/reference/gcab-sections.txt
+++ b/docs/reference/gcab-sections.txt
@@ -9,6 +9,7 @@ gcab_cabinet_get_folders
gcab_cabinet_add_folder
gcab_cabinet_write
gcab_cabinet_write_simple
+gcab_cabinet_get_signature
GCAB_ERROR
GCabError
<SUBSECTION Standard>
diff --git a/libgcab.syms b/libgcab.syms
index 7db0aee..079e893 100644
--- a/libgcab.syms
+++ b/libgcab.syms
@@ -30,3 +30,7 @@ LIBGCAB1_0.2 {
gcab_file_get_extract_name;
gcab_file_set_extract_name;
} LIBGCAB1_0.0;
+
+LIBGCAB1_0.5 {
+ gcab_cabinet_get_signature;
+} LIBGCAB1_0.2;
diff --git a/libgcab/gcab-cabinet.c b/libgcab/gcab-cabinet.c
index ec50a93..9aadc79 100644
--- a/libgcab/gcab-cabinet.c
+++ b/libgcab/gcab-cabinet.c
@@ -25,12 +25,15 @@ struct _GCabCabinet
GPtrArray *folders;
GByteArray *reserved;
cheader_t cheader;
+ GByteArray *signature;
+ GInputStream *stream;
};
enum {
PROP_0,
- PROP_RESERVED
+ PROP_RESERVED,
+ PROP_SIGNATURE,
};
G_DEFINE_TYPE (GCabCabinet, gcab_cabinet, G_TYPE_OBJECT);
@@ -55,6 +58,9 @@ gcab_cabinet_finalize (GObject *object)
g_ptr_array_unref (self->folders);
if (self->reserved)
g_byte_array_unref (self->reserved);
+ if (self->signature)
+ g_byte_array_unref (self->signature);
+ g_clear_object (&self->stream);
G_OBJECT_CLASS (gcab_cabinet_parent_class)->finalize (object);
}
@@ -71,6 +77,11 @@ gcab_cabinet_set_property (GObject *object, guint prop_id, const GValue *value,
g_byte_array_unref (self->reserved);
self->reserved = g_value_dup_boxed (value);
break;
+ case PROP_SIGNATURE:
+ if (self->signature)
+ g_byte_array_unref (self->signature);
+ self->signature = g_value_dup_boxed (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -87,6 +98,9 @@ gcab_cabinet_get_property (GObject *object, guint prop_id, GValue *value, GParam
case PROP_RESERVED:
g_value_set_boxed (value, self->reserved);
break;
+ case PROP_SIGNATURE:
+ g_value_set_boxed (value, gcab_cabinet_get_signature (self, NULL, NULL));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -109,6 +123,11 @@ gcab_cabinet_class_init (GCabCabinetClass *klass)
g_param_spec_boxed ("reserved", "Reserved", "Reserved",
G_TYPE_BYTE_ARRAY,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_SIGNATURE,
+ g_param_spec_boxed ("signature", "Signature", "Signature",
+ G_TYPE_BYTE_ARRAY,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
/**
@@ -356,6 +375,9 @@ gcab_cabinet_load (GCabCabinet *self,
g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (!error || *error == NULL, FALSE);
g_return_val_if_fail (self->folders->len == 0, FALSE);
+ g_return_val_if_fail (self->stream == NULL, FALSE);
+
+ self->stream = g_object_ref (stream);
gboolean success = FALSE;
cheader_t cheader;
@@ -480,3 +502,60 @@ gcab_cabinet_extract_simple (GCabCabinet *cabinet,
{
return gcab_cabinet_extract (cabinet, path, file_callback, NULL, user_data, cancellable, error);
}
+
+/**
+ * gcab_cabinet_get_signature:
+ * @cabinet: a #GCabCabinet
+ * @cancellable: (allow-none): optional #GCancellable object,
+ * %NULL to ignore
+ * @error: (allow-none): #GError to set on error, or %NULL
+ *
+ * Lookup the cabinet authenticode signature if any.
+ *
+ * Returns: the array containing the PKCS#7 signed data or %NULL if
+ * none found or error.
+ **/
+const GByteArray *
+gcab_cabinet_get_signature (GCabCabinet *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ const guint8 magic[] = { 0x00, 0x00, 0x10, 0x00 };
+ guint8 *reserved;
+ guint32 offset;
+ guint32 size;
+
+ g_return_val_if_fail (GCAB_IS_CABINET (self), NULL);
+ g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (!error || *error == NULL, NULL);
+
+ if (self->signature)
+ return self->signature;
+
+ if (!G_IS_SEEKABLE (self->stream))
+ return NULL;
+
+ if (!self->reserved || self->reserved->len != 20)
+ return NULL;
+
+ reserved = self->reserved->data;
+ if (memcmp (reserved, magic, sizeof (magic)) != 0)
+ return NULL;
+
+ offset = GCAB_READ_UINT32_LE (reserved + 4);
+ size = GCAB_READ_UINT32_LE (reserved + 8);
+ if (g_getenv ("GCAB_DEBUG"))
+ g_debug ("signature offset: %u size: %u", offset, size);
+
+ self->signature = g_byte_array_sized_new (size);
+ g_byte_array_set_size (self->signature, size);
+
+ if (!g_seekable_seek (G_SEEKABLE (self->stream), offset, G_SEEK_SET, cancellable, error))
+ return NULL;
+
+ if (g_input_stream_read (self->stream, self->signature->data, self->signature->len,
+ cancellable, error) != self->signature->len)
+ return NULL;
+
+ return self->signature;
+}
diff --git a/libgcab/gcab-cabinet.h b/libgcab/gcab-cabinet.h
index 9922b2d..1b1c45f 100644
--- a/libgcab/gcab-cabinet.h
+++ b/libgcab/gcab-cabinet.h
@@ -105,6 +105,9 @@ gboolean gcab_cabinet_extract_simple(GCabCabinet *cabinet,
gpointer user_data,
GCancellable *cancellable,
GError **error);
+const GByteArray * gcab_cabinet_get_signature (GCabCabinet *cabinet,
+ GCancellable *cancellable,
+ GError **error);
G_END_DECLS
diff --git a/libgcab/gcab-priv.h b/libgcab/gcab-priv.h
index 2d4d932..c5be95f 100644
--- a/libgcab/gcab-priv.h
+++ b/libgcab/gcab-priv.h
@@ -10,6 +10,16 @@
#include "gcab-cabinet.h"
#include "gcab-enums.h"
+/* Copied from GStream, FIXME that should be in GLib imho */
+#define _GCAB_GET(__data, __idx, __size, __shift) \
+ (((guint##__size) (((const guint8 *) (__data))[__idx])) << (__shift))
+
+#define GCAB_READ_UINT32_LE(data) (_GCAB_GET (data, 3, 32, 24) | \
+ _GCAB_GET (data, 2, 32, 16) | \
+ _GCAB_GET (data, 1, 32, 8) | \
+ _GCAB_GET (data, 0, 32, 0))
+
+
struct _GCabFile
{
GObject parent_instance;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]