From c31ddb6fe751077d29026ac7bc05333a9a02994a Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Sat, 12 Jul 2014 10:27:11 +0200 Subject: [PATCH] Add gres:// type links support for libxml2 --- src/astrognome.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/src/astrognome.c b/src/astrognome.c index 658f3a4..ba4797d 100644 --- a/src/astrognome.c +++ b/src/astrognome.c @@ -20,6 +20,7 @@ GtkBuilder *builder; GtkFileFilter *filter_all = NULL; GtkFileFilter *filter_chart = NULL; +GHashTable *xinclude_positions; const char *moonStateName[] = { "New Moon", @@ -47,6 +48,100 @@ init_filters(void) g_object_ref_sink(filter_chart); } +static int +xml_match_gresource(const char *uri) +{ + if ((uri != NULL) && (!strncmp("gres://", uri, 7))) { + g_debug("Matched gres:// type link."); + + return 1; + } else { + return 0; + } +} + +static void * +xml_open_gresource(const gchar *uri) +{ + gchar *path; + GBytes *res_location; + gsize *position; + + if ((uri == NULL) || (strncmp("gres://", uri, 7))) { + return NULL; + } + + path = g_strdup_printf("/eu/polonkai/gergely/Astrognome/%s", uri + 7); + g_debug("Opening gresource %s", path); + + res_location = g_resources_lookup_data( + path, + G_RESOURCE_LOOKUP_FLAGS_NONE, + NULL + ); + g_free(path); + + if ((position = g_hash_table_lookup(xinclude_positions, res_location)) == NULL) { + g_hash_table_insert(xinclude_positions, res_location, g_new0(gsize, 1)); + } else { + g_warning("Reopening gres:// link?"); + *position = 0; + } + + return res_location; +} + +static int +xml_close_gresource(void *context) +{ + if (context == NULL) { + return -1; + } + + g_debug("Closing gres:// link"); + + g_hash_table_remove(xinclude_positions, context); + g_bytes_unref((GBytes *)context); + + return 0; +} + +static int +xml_read_gresource(void *context, char *buffer, int len) +{ + const gchar *data; + gsize max_length; + GBytes *data_holder = (GBytes *)context; + gsize *position; + + if ((context == NULL) || (buffer == NULL) || (len < 0)) { + return -1; + } + + data = g_bytes_get_data(data_holder, &max_length); + position = g_hash_table_lookup(xinclude_positions, data_holder); + + if (position == NULL) { + g_warning("Trying to read non-opened gres:// link!"); + + return -1; + } + + if (*position >= max_length) { + return 0; + } + + if (len > max_length - *position) { + len = max_length - *position; + } + + memcpy(buffer, data + *position, len); + g_debug("Read %d bytes", len); + *position += len; + + return len; +} + int main(int argc, char *argv[]) { @@ -89,10 +184,22 @@ main(int argc, char *argv[]) LIBXML_TEST_VERSION; xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; + xmlRegisterInputCallbacks( + xml_match_gresource, + xml_open_gresource, + xml_read_gresource, + xml_close_gresource + ); xsltInit(); xsltSetXIncludeDefault(1); exsltRegisterAll(); gswe_init(); + xinclude_positions = g_hash_table_new_full( + g_bytes_hash, + g_bytes_equal, + (GDestroyNotify)g_bytes_unref, + (GDestroyNotify)g_free + ); memset(&options, 0, sizeof(AstrognomeOptions)); @@ -135,6 +242,7 @@ main(int argc, char *argv[]) status = g_application_run(G_APPLICATION(app), argc, argv); + g_hash_table_destroy(xinclude_positions); g_object_unref(app); return status;