/* * Copyright (C) 2018 Richard Hughes * * SPDX-License-Identifier: LGPL-2.1+ */ #define G_LOG_DOMAIN "XbSilo" #include "config.h" #include #include "xb-builder-source-ctx-private.h" typedef struct { GObject parent_instance; GInputStream *istream; gchar *filename; gchar *content_type; } XbBuilderSourceCtxPrivate; G_DEFINE_TYPE_WITH_PRIVATE (XbBuilderSourceCtx, xb_builder_source_ctx, G_TYPE_OBJECT) #define GET_PRIVATE(o) (xb_builder_source_ctx_get_instance_private (o)) /** * xb_builder_source_ctx_get_stream: * @self: a #XbBuilderSourceCtx * * Returns the input stream currently being processed. * * Returns: (transfer none): a #GInputStream * * Since: 0.1.7 **/ GInputStream * xb_builder_source_ctx_get_stream (XbBuilderSourceCtx *self) { XbBuilderSourceCtxPrivate *priv = GET_PRIVATE (self); g_return_val_if_fail (XB_IS_BUILDER_SOURCE_CTX (self), NULL); return priv->istream; } /** * xb_builder_source_ctx_get_bytes: * @self: a #XbBuilderSourceCtx * @cancellable: a #GCancellable, or %NULL * @error: the #GError, or %NULL * * Returns the data currently being processed. * * Returns: (transfer none): a #GInputStream * * Since: 0.1.7 **/ GBytes * xb_builder_source_ctx_get_bytes (XbBuilderSourceCtx *self, GCancellable *cancellable, GError **error) { XbBuilderSourceCtxPrivate *priv = GET_PRIVATE (self); g_return_val_if_fail (XB_IS_BUILDER_SOURCE_CTX (self), NULL); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); return g_input_stream_read_bytes (priv->istream, 128 * 1024 * 1024, /* 128Mb */ cancellable, error); } /** * xb_builder_source_ctx_get_filename: * @self: a #XbBuilderSourceCtx * * Returns the basename of the file currently being processed. * * Returns: a filename, or %NULL if unset * * Since: 0.1.7 **/ const gchar * xb_builder_source_ctx_get_filename (XbBuilderSourceCtx *self) { XbBuilderSourceCtxPrivate *priv = GET_PRIVATE (self); g_return_val_if_fail (XB_IS_BUILDER_SOURCE_CTX (self), NULL); return priv->filename; } /** * xb_builder_source_ctx_get_content_type: * @self: a #XbBuilderSourceCtx * * Returns the content type of the input stream currently being * processed. * * Returns: (transfer full): a content type (e.g. `application/x-desktop`), or %NULL * * Since: 0.1.7 **/ gchar * xb_builder_source_ctx_get_content_type (XbBuilderSourceCtx *self, GCancellable *cancellable, GError **error) { XbBuilderSourceCtxPrivate *priv = GET_PRIVATE (self); g_autofree gchar *content_type = NULL; g_return_val_if_fail (XB_IS_BUILDER_SOURCE_CTX (self), NULL); if (G_IS_SEEKABLE (priv->istream)) { gsize bufsz = 0; guchar buf[4096] = { 0x00 }; if (!g_input_stream_read_all (priv->istream, buf, sizeof(buf), &bufsz, cancellable, error)) return NULL; if (!g_seekable_seek (G_SEEKABLE (priv->istream), 0, G_SEEK_SET, cancellable, error)) return NULL; if (bufsz > 0) content_type = g_content_type_guess (priv->filename, buf, bufsz, NULL); } /* either unseekable, or empty */ if (content_type == NULL) content_type = g_content_type_guess (priv->filename, NULL, 0, NULL); #ifdef _WIN32 /* map Windows "mime-type" to a content type */ if (g_strcmp0 (content_type, ".gz") == 0) return g_strdup ("application/gzip"); if (g_strcmp0 (content_type, ".txt") == 0 || g_strcmp0 (content_type, ".xml") == 0) return g_strdup ("application/xml"); if (g_strcmp0 (content_type, ".desktop") == 0) return g_strdup ("application/x-desktop"); #endif return g_steal_pointer (&content_type); } /* private */ void xb_builder_source_ctx_set_filename (XbBuilderSourceCtx *self, const gchar *filename) { XbBuilderSourceCtxPrivate *priv = GET_PRIVATE (self); g_return_if_fail (XB_IS_BUILDER_SOURCE_CTX (self)); g_return_if_fail (filename != NULL); g_free (priv->filename); priv->filename = g_strdup (filename); } static void xb_builder_source_ctx_init (XbBuilderSourceCtx *self) { } static void xb_builder_source_ctx_finalize (GObject *obj) { XbBuilderSourceCtx *self = XB_BUILDER_SOURCE_CTX (obj); XbBuilderSourceCtxPrivate *priv = GET_PRIVATE (self); g_free (priv->filename); g_object_unref (priv->istream); G_OBJECT_CLASS (xb_builder_source_ctx_parent_class)->finalize (obj); } static void xb_builder_source_ctx_class_init (XbBuilderSourceCtxClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = xb_builder_source_ctx_finalize; } /** * xb_builder_source_ctx_new: * @element: An element name, e.g. "component" * * Creates a new builder source_ctx. * * Returns: (transfer full): a new #XbBuilderSourceCtx * * Since: 0.1.7 **/ XbBuilderSourceCtx * xb_builder_source_ctx_new (GInputStream *istream) { XbBuilderSourceCtx *self = g_object_new (XB_TYPE_BUILDER_SOURCE_CTX, NULL); XbBuilderSourceCtxPrivate *priv = GET_PRIVATE (self); priv->istream = g_object_ref (istream); return self; }