|
Packit Service |
a3c5fa |
/*
|
|
Packit Service |
a3c5fa |
* Copyright (C) 2018 Richard Hughes <richard@hughsie.com>
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* SPDX-License-Identifier: LGPL-2.1+
|
|
Packit Service |
a3c5fa |
*/
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
#define G_LOG_DOMAIN "XbSilo"
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
#include "config.h"
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
#include <gio/gio.h>
|
|
Packit Service |
a3c5fa |
#include <string.h>
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
#include "xb-builder-fixup-private.h"
|
|
Packit Service |
a3c5fa |
#include "xb-builder-source-ctx-private.h"
|
|
Packit Service |
a3c5fa |
#include "xb-builder-source-private.h"
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
typedef struct {
|
|
Packit Service |
a3c5fa |
GObject parent_instance;
|
|
Packit Service |
a3c5fa |
GInputStream *istream;
|
|
Packit Service |
a3c5fa |
GFile *file;
|
|
Packit Service |
a3c5fa |
GPtrArray *fixups; /* of XbBuilderFixup */
|
|
Packit Service |
a3c5fa |
GPtrArray *adapters; /* of XbBuilderSourceAdapter */
|
|
Packit Service |
a3c5fa |
XbBuilderNode *info;
|
|
Packit Service |
a3c5fa |
gchar *guid;
|
|
Packit Service |
a3c5fa |
gchar *prefix;
|
|
Packit Service |
a3c5fa |
gchar *content_type;
|
|
Packit Service |
a3c5fa |
XbBuilderSourceFlags flags;
|
|
Packit Service |
a3c5fa |
} XbBuilderSourcePrivate;
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
G_DEFINE_TYPE_WITH_PRIVATE (XbBuilderSource, xb_builder_source, G_TYPE_OBJECT)
|
|
Packit Service |
a3c5fa |
#define GET_PRIVATE(o) (xb_builder_source_get_instance_private (o))
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
typedef struct {
|
|
Packit Service |
a3c5fa |
gchar *content_type;
|
|
Packit Service |
a3c5fa |
XbBuilderSourceAdapterFunc func_adapter;
|
|
Packit Service |
a3c5fa |
gpointer user_data;
|
|
Packit Service |
a3c5fa |
GDestroyNotify user_data_free;
|
|
Packit Service |
a3c5fa |
gboolean is_simple;
|
|
Packit Service |
a3c5fa |
} XbBuilderSourceAdapter;
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
static XbBuilderSourceAdapter *
|
|
Packit Service |
a3c5fa |
xb_builder_source_get_adapter_by_mime (XbBuilderSource *self,
|
|
Packit Service |
a3c5fa |
const gchar *content_type)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
for (guint i = 0; i < priv->adapters->len; i++) {
|
|
Packit Service |
a3c5fa |
XbBuilderSourceAdapter *item = g_ptr_array_index (priv->adapters, i);
|
|
Packit Service |
a3c5fa |
if (item->func_adapter == NULL)
|
|
Packit Service |
a3c5fa |
continue;
|
|
Packit Service |
a3c5fa |
if (g_strcmp0 (item->content_type, content_type) == 0)
|
|
Packit Service |
a3c5fa |
return item;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
return NULL;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/**
|
|
Packit Service |
a3c5fa |
* xb_builder_source_load_file:
|
|
Packit Service |
a3c5fa |
* @self: a #XbBuilderSource
|
|
Packit Service |
a3c5fa |
* @file: a #GFile
|
|
Packit Service |
a3c5fa |
* @flags: some #XbBuilderSourceFlags, e.g. %XB_BUILDER_SOURCE_FLAG_LITERAL_TEXT
|
|
Packit Service |
a3c5fa |
* @cancellable: a #GCancellable, or %NULL
|
|
Packit Service |
a3c5fa |
* @error: the #GError, or %NULL
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Loads an optionally compressed XML file to build a #XbSilo.
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Returns: %TRUE for success
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Since: 0.1.1
|
|
Packit Service |
a3c5fa |
**/
|
|
Packit Service |
a3c5fa |
gboolean
|
|
Packit Service |
a3c5fa |
xb_builder_source_load_file (XbBuilderSource *self,
|
|
Packit Service |
a3c5fa |
GFile *file,
|
|
Packit Service |
a3c5fa |
XbBuilderSourceFlags flags,
|
|
Packit Service |
a3c5fa |
GCancellable *cancellable,
|
|
Packit Service |
a3c5fa |
GError **error)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
const gchar *content_type = NULL;
|
|
Packit Service |
a3c5fa |
guint32 ctime_usec;
|
|
Packit Service |
a3c5fa |
guint64 ctime;
|
|
Packit Service |
a3c5fa |
g_autofree gchar *fn = NULL;
|
|
Packit Service |
a3c5fa |
g_autoptr(GFileInfo) fileinfo = NULL;
|
|
Packit Service |
a3c5fa |
g_autoptr(GString) guid = NULL;
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (XB_IS_BUILDER_SOURCE (self), FALSE);
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (G_IS_FILE (file), FALSE);
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* what kind of file is this */
|
|
Packit Service |
a3c5fa |
fileinfo = g_file_query_info (file,
|
|
Packit Service |
a3c5fa |
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
|
|
Packit Service |
a3c5fa |
G_FILE_ATTRIBUTE_TIME_CHANGED ","
|
|
Packit Service |
a3c5fa |
G_FILE_ATTRIBUTE_TIME_CHANGED_USEC,
|
|
Packit Service |
a3c5fa |
G_FILE_QUERY_INFO_NONE,
|
|
Packit Service |
a3c5fa |
cancellable,
|
|
Packit Service |
a3c5fa |
error);
|
|
Packit Service |
a3c5fa |
if (fileinfo == NULL)
|
|
Packit Service |
a3c5fa |
return FALSE;
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* add data to GUID */
|
|
Packit Service |
a3c5fa |
fn = g_file_get_path (file);
|
|
Packit Service |
a3c5fa |
guid = g_string_new (fn);
|
|
Packit Service |
a3c5fa |
ctime = g_file_info_get_attribute_uint64 (fileinfo, G_FILE_ATTRIBUTE_TIME_CHANGED);
|
|
Packit Service |
a3c5fa |
if (ctime != 0)
|
|
Packit Service |
a3c5fa |
g_string_append_printf (guid, ":ctime=%" G_GUINT64_FORMAT, ctime);
|
|
Packit Service |
a3c5fa |
ctime_usec = g_file_info_get_attribute_uint32 (fileinfo, G_FILE_ATTRIBUTE_TIME_CHANGED_USEC);
|
|
Packit Service |
a3c5fa |
if (ctime_usec != 0)
|
|
Packit Service |
a3c5fa |
g_string_append_printf (guid, ".%" G_GUINT32_FORMAT, ctime_usec);
|
|
Packit Service |
a3c5fa |
priv->guid = g_string_free (g_steal_pointer (&guid), FALSE);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* check content type of file */
|
|
Packit Service |
a3c5fa |
content_type = g_file_info_get_attribute_string (fileinfo, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
|
|
Packit Service |
a3c5fa |
if (content_type == NULL) {
|
|
Packit Service |
a3c5fa |
g_set_error_literal (error,
|
|
Packit Service |
a3c5fa |
G_IO_ERROR,
|
|
Packit Service |
a3c5fa |
G_IO_ERROR_NOT_SUPPORTED,
|
|
Packit Service |
a3c5fa |
"cannot get content type for file");
|
|
Packit Service |
a3c5fa |
return FALSE;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* success */
|
|
Packit Service |
a3c5fa |
priv->flags = flags;
|
|
Packit Service |
a3c5fa |
priv->content_type = g_strdup (content_type);
|
|
Packit Service |
a3c5fa |
priv->file = g_object_ref (file);
|
|
Packit Service |
a3c5fa |
return TRUE;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/**
|
|
Packit Service |
a3c5fa |
* xb_builder_source_set_info:
|
|
Packit Service |
a3c5fa |
* @self: a #XbBuilderSource
|
|
Packit Service |
a3c5fa |
* @info: (allow-none): a #XbBuilderNode
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Sets an optional information metadata node on the root node.
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Since: 0.1.0
|
|
Packit Service |
a3c5fa |
**/
|
|
Packit Service |
a3c5fa |
void
|
|
Packit Service |
a3c5fa |
xb_builder_source_set_info (XbBuilderSource *self, XbBuilderNode *info)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
g_return_if_fail (XB_IS_BUILDER_SOURCE (self));
|
|
Packit Service |
a3c5fa |
g_set_object (&priv->info, info);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/**
|
|
Packit Service |
a3c5fa |
* xb_builder_source_set_prefix:
|
|
Packit Service |
a3c5fa |
* @self: a #XbBuilderSource
|
|
Packit Service |
a3c5fa |
* @prefix: (allow-none): an XPath prefix, e.g. `installed`
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Sets an optional prefix on the root node. This makes any nodes added
|
|
Packit Service |
a3c5fa |
* using this source reside under a common shared parent node.
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Since: 0.1.0
|
|
Packit Service |
a3c5fa |
**/
|
|
Packit Service |
a3c5fa |
void
|
|
Packit Service |
a3c5fa |
xb_builder_source_set_prefix (XbBuilderSource *self, const gchar *prefix)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
g_return_if_fail (XB_IS_BUILDER_SOURCE (self));
|
|
Packit Service |
a3c5fa |
g_free (priv->prefix);
|
|
Packit Service |
a3c5fa |
priv->prefix = g_strdup (prefix);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/**
|
|
Packit Service |
a3c5fa |
* xb_builder_source_load_xml:
|
|
Packit Service |
a3c5fa |
* @self: a #XbBuilderSource
|
|
Packit Service |
a3c5fa |
* @xml: XML data
|
|
Packit Service |
a3c5fa |
* @flags: some #XbBuilderSourceFlags, e.g. %XB_BUILDER_SOURCE_FLAG_LITERAL_TEXT
|
|
Packit Service |
a3c5fa |
* @error: the #GError, or %NULL
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Loads XML data and begins to build a #XbSilo.
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Returns: %TRUE for success
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Since: 0.1.1
|
|
Packit Service |
a3c5fa |
**/
|
|
Packit Service |
a3c5fa |
gboolean
|
|
Packit Service |
a3c5fa |
xb_builder_source_load_xml (XbBuilderSource *self,
|
|
Packit Service |
a3c5fa |
const gchar *xml,
|
|
Packit Service |
a3c5fa |
XbBuilderSourceFlags flags,
|
|
Packit Service |
a3c5fa |
GError **error)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
g_autoptr(GBytes) blob = NULL;
|
|
Packit Service |
a3c5fa |
g_autoptr(GChecksum) csum = g_checksum_new (G_CHECKSUM_SHA1);
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (XB_IS_BUILDER_SOURCE (self), FALSE);
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (xml != NULL, FALSE);
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* add a GUID of the SHA1 hash of the entire string */
|
|
Packit Service |
a3c5fa |
g_checksum_update (csum, (const guchar *) xml, -1);
|
|
Packit Service |
a3c5fa |
priv->guid = g_strdup (g_checksum_get_string (csum));
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* create input stream */
|
|
Packit Service |
a3c5fa |
blob = g_bytes_new (xml, strlen (xml));
|
|
Packit Service |
a3c5fa |
priv->istream = g_memory_input_stream_new_from_bytes (blob);
|
|
Packit Service |
a3c5fa |
if (priv->istream == NULL)
|
|
Packit Service |
a3c5fa |
return FALSE;
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* success */
|
|
Packit Service |
a3c5fa |
priv->flags = flags;
|
|
Packit Service |
a3c5fa |
return TRUE;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/**
|
|
Packit Service |
a3c5fa |
* xb_builder_source_load_bytes:
|
|
Packit Service |
a3c5fa |
* @self: a #XbBuilderSource
|
|
Packit Service |
a3c5fa |
* @bytes: a #GBytes
|
|
Packit Service |
a3c5fa |
* @flags: some #XbBuilderSourceFlags, e.g. %XB_BUILDER_SOURCE_FLAG_LITERAL_TEXT
|
|
Packit Service |
a3c5fa |
* @error: the #GError, or %NULL
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Loads XML data and begins to build a #XbSilo.
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Returns: %TRUE for success
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Since: 0.1.2
|
|
Packit Service |
a3c5fa |
**/
|
|
Packit Service |
a3c5fa |
gboolean
|
|
Packit Service |
a3c5fa |
xb_builder_source_load_bytes (XbBuilderSource *self,
|
|
Packit Service |
a3c5fa |
GBytes *bytes,
|
|
Packit Service |
a3c5fa |
XbBuilderSourceFlags flags,
|
|
Packit Service |
a3c5fa |
GError **error)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
g_autoptr(GChecksum) csum = g_checksum_new (G_CHECKSUM_SHA1);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (XB_IS_BUILDER_SOURCE (self), FALSE);
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (bytes != NULL, FALSE);
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* add a GUID of the SHA1 hash of the entire blob */
|
|
Packit Service |
a3c5fa |
g_checksum_update (csum,
|
|
Packit Service |
a3c5fa |
(const guchar *) g_bytes_get_data (bytes, NULL),
|
|
Packit Service |
a3c5fa |
(gssize) g_bytes_get_size (bytes));
|
|
Packit Service |
a3c5fa |
priv->guid = g_strdup (g_checksum_get_string (csum));
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* create input stream */
|
|
Packit Service |
a3c5fa |
priv->istream = g_memory_input_stream_new_from_bytes (bytes);
|
|
Packit Service |
a3c5fa |
if (priv->istream == NULL)
|
|
Packit Service |
a3c5fa |
return FALSE;
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* success */
|
|
Packit Service |
a3c5fa |
priv->flags = flags;
|
|
Packit Service |
a3c5fa |
return TRUE;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/**
|
|
Packit Service |
a3c5fa |
* xb_builder_source_add_fixup:
|
|
Packit Service |
a3c5fa |
* @self: a #XbBuilderSource
|
|
Packit Service |
a3c5fa |
* @fixup: a #XbBuilderFixup
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Adds a function that will get run on every #XbBuilderNode compile creates
|
|
Packit Service |
a3c5fa |
* with this source.
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Since: 0.1.3
|
|
Packit Service |
a3c5fa |
**/
|
|
Packit Service |
a3c5fa |
void
|
|
Packit Service |
a3c5fa |
xb_builder_source_add_fixup (XbBuilderSource *self, XbBuilderFixup *fixup)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
g_return_if_fail (XB_IS_BUILDER_SOURCE (self));
|
|
Packit Service |
a3c5fa |
g_return_if_fail (XB_IS_BUILDER_FIXUP (fixup));
|
|
Packit Service |
a3c5fa |
g_ptr_array_add (priv->fixups, g_object_ref (fixup));
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/**
|
|
Packit Service |
a3c5fa |
* xb_builder_source_add_node_func:
|
|
Packit Service |
a3c5fa |
* @self: a #XbBuilderSource
|
|
Packit Service |
a3c5fa |
* @id: a text ID value, e.g. `AppStreamUpgrade`
|
|
Packit Service |
a3c5fa |
* @func: a callback
|
|
Packit Service |
a3c5fa |
* @user_data: user pointer to pass to @func, or %NULL
|
|
Packit Service |
a3c5fa |
* @user_data_free: a function which gets called to free @user_data, or %NULL
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Adds a function that will get run on every #XbBuilderNode compile creates.
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Since: 0.1.0
|
|
Packit Service |
a3c5fa |
**/
|
|
Packit Service |
a3c5fa |
void
|
|
Packit Service |
a3c5fa |
xb_builder_source_add_node_func (XbBuilderSource *self,
|
|
Packit Service |
a3c5fa |
const gchar *id,
|
|
Packit Service |
a3c5fa |
XbBuilderSourceNodeFunc func,
|
|
Packit Service |
a3c5fa |
gpointer user_data,
|
|
Packit Service |
a3c5fa |
GDestroyNotify user_data_free)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
g_autoptr(XbBuilderFixup) fixup = NULL;
|
|
Packit Service |
a3c5fa |
/* close enough... */
|
|
Packit Service |
a3c5fa |
fixup = xb_builder_fixup_new (id, (XbBuilderFixupFunc) func,
|
|
Packit Service |
a3c5fa |
user_data, user_data_free);
|
|
Packit Service |
a3c5fa |
xb_builder_source_add_fixup (self, fixup);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/**
|
|
Packit Service |
a3c5fa |
* xb_builder_source_add_converter:
|
|
Packit Service |
a3c5fa |
* @self: a #XbBuilderSource
|
|
Packit Service |
a3c5fa |
* @content_types: mimetypes, e.g. `application/x-desktop,application/gzip`
|
|
Packit Service |
a3c5fa |
* @func: a callback
|
|
Packit Service |
a3c5fa |
* @user_data: user pointer to pass to @func, or %NULL
|
|
Packit Service |
a3c5fa |
* @user_data_free: a function which gets called to free @user_data, or %NULL
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* This function is now deprecated, and does nothing.
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* See also: xb_builder_source_add_adapter()
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Since: 0.1.1
|
|
Packit Service |
a3c5fa |
**/
|
|
Packit Service |
a3c5fa |
void
|
|
Packit Service |
a3c5fa |
xb_builder_source_add_converter (XbBuilderSource *self,
|
|
Packit Service |
a3c5fa |
const gchar *content_types,
|
|
Packit Service |
a3c5fa |
XbBuilderSourceConverterFunc func,
|
|
Packit Service |
a3c5fa |
gpointer user_data,
|
|
Packit Service |
a3c5fa |
GDestroyNotify user_data_free)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
g_warning ("%s() does nothing", G_STRFUNC);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
static void
|
|
Packit Service |
a3c5fa |
xb_builder_source_init_adapter (XbBuilderSource *self,
|
|
Packit Service |
a3c5fa |
const gchar *content_types,
|
|
Packit Service |
a3c5fa |
XbBuilderSourceAdapterFunc func,
|
|
Packit Service |
a3c5fa |
gpointer user_data,
|
|
Packit Service |
a3c5fa |
GDestroyNotify user_data_free,
|
|
Packit Service |
a3c5fa |
gboolean is_simple)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
g_auto(GStrv) split = NULL;
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
g_return_if_fail (XB_IS_BUILDER_SOURCE (self));
|
|
Packit Service |
a3c5fa |
g_return_if_fail (content_types != NULL);
|
|
Packit Service |
a3c5fa |
g_return_if_fail (func != NULL);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* add each */
|
|
Packit Service |
a3c5fa |
split = g_strsplit (content_types, ",", -1);
|
|
Packit Service |
a3c5fa |
for (guint i = 0; split[i] != NULL; i++) {
|
|
Packit Service |
a3c5fa |
XbBuilderSourceAdapter *item;
|
|
Packit Service |
a3c5fa |
item = g_slice_new0 (XbBuilderSourceAdapter);
|
|
Packit Service |
a3c5fa |
item->content_type = g_strdup (split[i]);
|
|
Packit Service |
a3c5fa |
item->func_adapter = func;
|
|
Packit Service |
a3c5fa |
item->user_data = user_data;
|
|
Packit Service |
a3c5fa |
item->user_data_free = user_data_free;
|
|
Packit Service |
a3c5fa |
item->is_simple = is_simple;
|
|
Packit Service |
a3c5fa |
g_ptr_array_add (priv->adapters, item);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/**
|
|
Packit Service |
a3c5fa |
* xb_builder_source_add_adapter:
|
|
Packit Service |
a3c5fa |
* @self: a #XbBuilderSource
|
|
Packit Service |
a3c5fa |
* @content_types: mimetypes, e.g. `application/x-desktop,application/gzip`
|
|
Packit Service |
a3c5fa |
* @func: a callback, or %NULL
|
|
Packit Service |
a3c5fa |
* @user_data: user pointer to pass to @func, or %NULL
|
|
Packit Service |
a3c5fa |
* @user_data_free: a function which gets called to free @user_data, or %NULL
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Adds a function that can be used to convert streams loaded with
|
|
Packit Service |
a3c5fa |
* xb_builder_source_load_xml().
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Since: 0.1.7
|
|
Packit Service |
a3c5fa |
**/
|
|
Packit Service |
a3c5fa |
void
|
|
Packit Service |
a3c5fa |
xb_builder_source_add_adapter (XbBuilderSource *self,
|
|
Packit Service |
a3c5fa |
const gchar *content_types,
|
|
Packit Service |
a3c5fa |
XbBuilderSourceAdapterFunc func,
|
|
Packit Service |
a3c5fa |
gpointer user_data,
|
|
Packit Service |
a3c5fa |
GDestroyNotify user_data_free)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
xb_builder_source_init_adapter (self, content_types, func,
|
|
Packit Service |
a3c5fa |
user_data, user_data_free, FALSE);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/**
|
|
Packit Service |
a3c5fa |
* xb_builder_source_add_simple_adapter:
|
|
Packit Service |
a3c5fa |
* @self: a #XbBuilderSource
|
|
Packit Service |
a3c5fa |
* @content_types: mimetypes, e.g. `application/x-desktop,application/gzip`
|
|
Packit Service |
a3c5fa |
* @func: a callback, or %NULL
|
|
Packit Service |
a3c5fa |
* @user_data: user pointer to pass to @func, or %NULL
|
|
Packit Service |
a3c5fa |
* @user_data_free: a function which gets called to free @user_data, or %NULL
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Adds a function that can be used to convert streams loaded with
|
|
Packit Service |
a3c5fa |
* xb_builder_source_load_xml().
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Since: 0.1.15
|
|
Packit Service |
a3c5fa |
**/
|
|
Packit Service |
a3c5fa |
void
|
|
Packit Service |
a3c5fa |
xb_builder_source_add_simple_adapter (XbBuilderSource *self,
|
|
Packit Service |
a3c5fa |
const gchar *content_types,
|
|
Packit Service |
a3c5fa |
XbBuilderSourceAdapterFunc func,
|
|
Packit Service |
a3c5fa |
gpointer user_data,
|
|
Packit Service |
a3c5fa |
GDestroyNotify user_data_free)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
xb_builder_source_init_adapter (self, content_types, func,
|
|
Packit Service |
a3c5fa |
user_data, user_data_free, TRUE);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
gboolean
|
|
Packit Service |
a3c5fa |
xb_builder_source_fixup (XbBuilderSource *self, XbBuilderNode *bn, GError **error)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
for (guint i = 0; i < priv->fixups->len; i++) {
|
|
Packit Service |
a3c5fa |
XbBuilderFixup *fixup = g_ptr_array_index (priv->fixups, i);
|
|
Packit Service |
a3c5fa |
if (!xb_builder_fixup_node (fixup, bn, error))
|
|
Packit Service |
a3c5fa |
return FALSE;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
return TRUE;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
static gboolean
|
|
Packit Service |
a3c5fa |
xb_builder_source_info_guid_cb (XbBuilderNode *bn, gpointer data)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
GString *str = (GString *) data;
|
|
Packit Service |
a3c5fa |
if (xb_builder_node_get_text (bn) != NULL) {
|
|
Packit Service |
a3c5fa |
g_string_append_printf (str, ":%s=%s",
|
|
Packit Service |
a3c5fa |
xb_builder_node_get_element (bn),
|
|
Packit Service |
a3c5fa |
xb_builder_node_get_text (bn));
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
return FALSE;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
gchar *
|
|
Packit Service |
a3c5fa |
xb_builder_source_get_guid (XbBuilderSource *self)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
GString *str = g_string_new (priv->guid);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (XB_IS_BUILDER_SOURCE (self), NULL);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* append function IDs */
|
|
Packit Service |
a3c5fa |
for (guint i = 0; i < priv->fixups->len; i++) {
|
|
Packit Service |
a3c5fa |
XbBuilderFixup *fixup = g_ptr_array_index (priv->fixups, i);
|
|
Packit Service |
a3c5fa |
g_autofree gchar *tmp = xb_builder_fixup_get_guid (fixup);
|
|
Packit Service |
a3c5fa |
g_string_append_printf (str, ":%s", tmp);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* append any info */
|
|
Packit Service |
a3c5fa |
if (priv->info != NULL) {
|
|
Packit Service |
a3c5fa |
xb_builder_node_traverse (priv->info, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
|
|
Packit Service |
a3c5fa |
xb_builder_source_info_guid_cb, str);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* append prefix */
|
|
Packit Service |
a3c5fa |
if (priv->prefix != NULL)
|
|
Packit Service |
a3c5fa |
g_string_append_printf (str, ":prefix=%s", priv->prefix);
|
|
Packit Service |
a3c5fa |
return g_string_free (str, FALSE);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
const gchar *
|
|
Packit Service |
a3c5fa |
xb_builder_source_get_prefix (XbBuilderSource *self)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (XB_IS_BUILDER_SOURCE (self), NULL);
|
|
Packit Service |
a3c5fa |
return priv->prefix;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
XbBuilderNode *
|
|
Packit Service |
a3c5fa |
xb_builder_source_get_info (XbBuilderSource *self)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (XB_IS_BUILDER_SOURCE (self), NULL);
|
|
Packit Service |
a3c5fa |
return priv->info;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* converts foo.xml.gz to foo.xml */
|
|
Packit Service |
a3c5fa |
static void
|
|
Packit Service |
a3c5fa |
xb_builder_source_remove_last_extension (gchar *basename)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
gchar *tmp = g_strrstr (basename, ".");
|
|
Packit Service |
a3c5fa |
if (tmp != NULL)
|
|
Packit Service |
a3c5fa |
*tmp = '\0';
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
GInputStream *
|
|
Packit Service |
a3c5fa |
xb_builder_source_get_istream (XbBuilderSource *self,
|
|
Packit Service |
a3c5fa |
GCancellable *cancellable,
|
|
Packit Service |
a3c5fa |
GError **error)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
g_autofree gchar *basename = NULL;
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (XB_IS_BUILDER_SOURCE (self), NULL);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* nothing required */
|
|
Packit Service |
a3c5fa |
if (priv->istream != NULL)
|
|
Packit Service |
a3c5fa |
return g_object_ref (priv->istream);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* convert the file to a GFileInputStream */
|
|
Packit Service |
a3c5fa |
priv->istream = G_INPUT_STREAM (g_file_read (priv->file, cancellable, error));
|
|
Packit Service |
a3c5fa |
if (priv->istream == NULL)
|
|
Packit Service |
a3c5fa |
return NULL;
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* run the content type handlers until we get application/xml */
|
|
Packit Service |
a3c5fa |
basename = g_file_get_basename (priv->file);
|
|
Packit Service |
a3c5fa |
do {
|
|
Packit Service |
a3c5fa |
XbBuilderSourceAdapter *item;
|
|
Packit Service |
a3c5fa |
g_autofree gchar *content_type = NULL;
|
|
Packit Service |
a3c5fa |
g_autoptr(GInputStream) istream_tmp = NULL;
|
|
Packit Service |
a3c5fa |
g_autoptr(XbBuilderSourceCtx) ctx = xb_builder_source_ctx_new (priv->istream);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* get the content type of the stream */
|
|
Packit Service |
a3c5fa |
xb_builder_source_ctx_set_filename (ctx, basename);
|
|
Packit Service |
a3c5fa |
content_type = xb_builder_source_ctx_get_content_type (ctx,
|
|
Packit Service |
a3c5fa |
cancellable,
|
|
Packit Service |
a3c5fa |
error);
|
|
Packit Service |
a3c5fa |
if (content_type == NULL)
|
|
Packit Service |
a3c5fa |
return NULL;
|
|
Packit Service |
a3c5fa |
if (g_strcmp0 (content_type, "application/xml") == 0)
|
|
Packit Service |
a3c5fa |
break;
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/* convert the stream */
|
|
Packit Service |
a3c5fa |
item = xb_builder_source_get_adapter_by_mime (self, content_type);
|
|
Packit Service |
a3c5fa |
if (item == NULL || item->func_adapter == NULL) {
|
|
Packit Service |
a3c5fa |
g_set_error (error,
|
|
Packit Service |
a3c5fa |
G_IO_ERROR,
|
|
Packit Service |
a3c5fa |
G_IO_ERROR_NOT_SUPPORTED,
|
|
Packit Service |
a3c5fa |
"cannot process content type %s",
|
|
Packit Service |
a3c5fa |
content_type);
|
|
Packit Service |
a3c5fa |
return NULL;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
istream_tmp = item->func_adapter (self, ctx, item->user_data,
|
|
Packit Service |
a3c5fa |
cancellable, error);
|
|
Packit Service |
a3c5fa |
if (istream_tmp == NULL)
|
|
Packit Service |
a3c5fa |
return NULL;
|
|
Packit Service |
a3c5fa |
xb_builder_source_remove_last_extension (basename);
|
|
Packit Service |
a3c5fa |
g_set_object (&priv->istream, istream_tmp);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
if (item->is_simple)
|
|
Packit Service |
a3c5fa |
break;
|
|
Packit Service |
a3c5fa |
} while (TRUE);
|
|
Packit Service |
a3c5fa |
return g_object_ref (priv->istream);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
GFile *
|
|
Packit Service |
a3c5fa |
xb_builder_source_get_file (XbBuilderSource *self)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (XB_IS_BUILDER_SOURCE (self), NULL);
|
|
Packit Service |
a3c5fa |
return priv->file;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
XbBuilderSourceFlags
|
|
Packit Service |
a3c5fa |
xb_builder_source_get_flags (XbBuilderSource *self)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
g_return_val_if_fail (XB_IS_BUILDER_SOURCE (self), 0);
|
|
Packit Service |
a3c5fa |
return priv->flags;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
static GInputStream *
|
|
Packit Service |
a3c5fa |
xb_builder_source_load_gzip_cb (XbBuilderSource *self,
|
|
Packit Service |
a3c5fa |
XbBuilderSourceCtx *ctx,
|
|
Packit Service |
a3c5fa |
gpointer user_data,
|
|
Packit Service |
a3c5fa |
GCancellable *cancellable,
|
|
Packit Service |
a3c5fa |
GError **error)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
GInputStream *istream = xb_builder_source_ctx_get_stream (ctx);
|
|
Packit Service |
a3c5fa |
g_autoptr(GConverter) conv = NULL;
|
|
Packit Service |
a3c5fa |
conv = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP));
|
|
Packit Service |
a3c5fa |
return g_converter_input_stream_new (istream, conv);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
static void
|
|
Packit Service |
a3c5fa |
xb_builder_source_adapter_free (XbBuilderSourceAdapter *item)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
if (item->user_data_free != NULL)
|
|
Packit Service |
a3c5fa |
item->user_data_free (item->user_data);
|
|
Packit Service |
a3c5fa |
g_free (item->content_type);
|
|
Packit Service |
a3c5fa |
g_slice_free (XbBuilderSourceAdapter, item);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
static void
|
|
Packit Service |
a3c5fa |
xb_builder_source_finalize (GObject *obj)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSource *self = XB_BUILDER_SOURCE (obj);
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
if (priv->istream != NULL)
|
|
Packit Service |
a3c5fa |
g_object_unref (priv->istream);
|
|
Packit Service |
a3c5fa |
if (priv->info != NULL)
|
|
Packit Service |
a3c5fa |
g_object_unref (priv->info);
|
|
Packit Service |
a3c5fa |
if (priv->file != NULL)
|
|
Packit Service |
a3c5fa |
g_object_unref (priv->file);
|
|
Packit Service |
a3c5fa |
g_ptr_array_unref (priv->fixups);
|
|
Packit Service |
a3c5fa |
g_ptr_array_unref (priv->adapters);
|
|
Packit Service |
a3c5fa |
g_free (priv->guid);
|
|
Packit Service |
a3c5fa |
g_free (priv->prefix);
|
|
Packit Service |
a3c5fa |
g_free (priv->content_type);
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
G_OBJECT_CLASS (xb_builder_source_parent_class)->finalize (obj);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
static void
|
|
Packit Service |
a3c5fa |
xb_builder_source_class_init (XbBuilderSourceClass *klass)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
Packit Service |
a3c5fa |
object_class->finalize = xb_builder_source_finalize;
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
static void
|
|
Packit Service |
a3c5fa |
xb_builder_source_init (XbBuilderSource *self)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
XbBuilderSourcePrivate *priv = GET_PRIVATE (self);
|
|
Packit Service |
a3c5fa |
priv->fixups = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
|
Packit Service |
a3c5fa |
priv->adapters = g_ptr_array_new_with_free_func ((GDestroyNotify) xb_builder_source_adapter_free);
|
|
Packit Service |
a3c5fa |
xb_builder_source_add_adapter (self, "application/gzip,application/x-gzip",
|
|
Packit Service |
a3c5fa |
xb_builder_source_load_gzip_cb, NULL, NULL);
|
|
Packit Service |
a3c5fa |
}
|
|
Packit Service |
a3c5fa |
|
|
Packit Service |
a3c5fa |
/**
|
|
Packit Service |
a3c5fa |
* xb_builder_source_new:
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Creates a new builder source.
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Returns: a new #XbBuilderSource
|
|
Packit Service |
a3c5fa |
*
|
|
Packit Service |
a3c5fa |
* Since: 0.1.1
|
|
Packit Service |
a3c5fa |
**/
|
|
Packit Service |
a3c5fa |
XbBuilderSource *
|
|
Packit Service |
a3c5fa |
xb_builder_source_new (void)
|
|
Packit Service |
a3c5fa |
{
|
|
Packit Service |
a3c5fa |
return g_object_new (XB_TYPE_BUILDER_SOURCE, NULL);
|
|
Packit Service |
a3c5fa |
}
|