From 067bbc6bdef832c5488ab200cf1b815b54480074 Mon Sep 17 00:00:00 2001 From: Crispin Flowerday Date: Fri, 23 Sep 2005 18:56:47 +0000 Subject: Add support for extension description files in the keyfile format, using 2005-09-23 Crispin Flowerday * data/Makefile.am: * data/epiphany.m4: * src/ephy-extensions-manager.c: (free_extension_info), (ephy_extensions_manager_load_xml_string), (ephy_extensions_manager_load_ini_string), (path_to_identifier), (ephy_extensions_manager_load_file), (load_extension), (load_file_from_monitor), (dir_changed_cb), (ephy_extensions_manager_load_dir): Add support for extension description files in the keyfile format, using the extension .ephy-extension. Also included is a m4 macro to help do the translation of these files. --- src/ephy-extensions-manager.c | 260 +++++++++++++++++++++++++++++++++++------- 1 file changed, 218 insertions(+), 42 deletions(-) (limited to 'src/ephy-extensions-manager.c') diff --git a/src/ephy-extensions-manager.c b/src/ephy-extensions-manager.c index c2e3227df..8f01e4f2b 100644 --- a/src/ephy-extensions-manager.c +++ b/src/ephy-extensions-manager.c @@ -2,6 +2,7 @@ * Copyright (C) 2003 Marco Pesenti Gritti * Copyright (C) 2003, 2004 Christian Persch * Copyright (C) 2004 Adam Hooper + * Copyright (C) 2005 Crispin Flowerday * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -84,12 +85,12 @@ typedef struct { EphyExtensionInfo info; guint version; - gboolean load_deferred; + gboolean load_deferred; /* NOT USED? */ gboolean load_failed; - xmlChar *gettext_domain; - xmlChar *locale_directory; - xmlChar *loader_type; + char *gettext_domain; /* NOT USED? */ + char *locale_directory; /* NOT USED? */ + char *loader_type; GData *loader_attributes; EphyLoader *loader; /* NULL if never loaded */ @@ -268,14 +269,14 @@ free_extension_info (ExtensionInfo *info) EphyExtensionInfo *einfo = (EphyExtensionInfo *) info; g_free (einfo->identifier); - xmlFree ((xmlChar *) einfo->name); - xmlFree ((xmlChar *) einfo->description); - g_list_foreach (einfo->authors, (GFunc) xmlFree, NULL); + g_free (einfo->name); + g_free (einfo->description); + g_list_foreach (einfo->authors, (GFunc) g_free, NULL); g_list_free (einfo->authors); - xmlFree ((xmlChar *) einfo->url); - xmlFree ((xmlChar *) info->gettext_domain); - xmlFree ((xmlChar *) info->locale_directory); - xmlFree ((xmlChar *) info->loader_type); + g_free (einfo->url); + g_free (info->gettext_domain); + g_free (info->locale_directory); + g_free (info->loader_type); g_datalist_clear (&info->loader_attributes); if (info->extension != NULL) @@ -363,9 +364,9 @@ typedef enum } ParserState; static void -ephy_extensions_manager_load_string (EphyExtensionsManager *manager, - const char *identifier, - /* const */ char *xml) +ephy_extensions_manager_load_xml_string (EphyExtensionsManager *manager, + const char *identifier, + /* const */ char *xml) { xmlDocPtr doc; xmlTextReaderPtr reader; @@ -377,7 +378,7 @@ ephy_extensions_manager_load_string (EphyExtensionsManager *manager, LocalisedString description = { NULL, G_MAXUINT }; LocalisedString name = { NULL, G_MAXUINT }; - LOG ("Loading description file for '%s'", identifier); + LOG ("Loading XML description file for '%s'", identifier); if (g_list_find_custom (manager->priv->data, identifier, (GCompareFunc) find_extension_info) != NULL) @@ -495,21 +496,29 @@ ephy_extensions_manager_load_string (EphyExtensionsManager *manager, type == XML_READER_TYPE_ELEMENT && xmlStrEqual (tag, (const xmlChar *) "loader")) { + xmlChar * attr; + state = STATE_LOADER; + + attr = xmlTextReaderGetAttribute + (reader, (const xmlChar *) "type"); - info->loader_type = xmlTextReaderGetAttribute (reader, (const xmlChar *) "type"); + info->loader_type = g_strdup ((char*)attr); + + xmlFree (attr); } else if (state == STATE_LOADER_ATTRIBUTE && type == XML_READER_TYPE_TEXT && attr_quark != 0) { - xmlChar *value; + const xmlChar *value; - value = xmlTextReaderValue (reader); + value = xmlTextReaderConstValue (reader); g_datalist_id_set_data_full (&info->loader_attributes, - attr_quark, value, - (GDestroyNotify) xmlFree); + attr_quark, + g_strdup ((char*)value), + (GDestroyNotify) g_free); attr_quark = 0; } else if (state == STATE_LOADER_ATTRIBUTE && @@ -521,8 +530,12 @@ ephy_extensions_manager_load_string (EphyExtensionsManager *manager, else if (state == STATE_AUTHOR && type == XML_READER_TYPE_TEXT) { + const xmlChar *attr; + + attr = xmlTextReaderConstValue (reader); + einfo->authors = g_list_prepend - (einfo->authors, xmlTextReaderValue (reader)); + (einfo->authors, g_strdup ((char*)attr)); } else if (state == STATE_DESCRIPTION && type == XML_READER_TYPE_TEXT) @@ -532,7 +545,11 @@ ephy_extensions_manager_load_string (EphyExtensionsManager *manager, else if (state == STATE_GETTEXT_DOMAIN && type == XML_READER_TYPE_TEXT) { - info->gettext_domain = xmlTextReaderValue (reader); + const xmlChar *attr; + + attr = xmlTextReaderConstValue (reader); + + info->gettext_domain = g_strdup ((char*)attr); } else if (state == STATE_LOAD_DEFERRED && type == XML_READER_TYPE_TEXT) @@ -540,13 +557,18 @@ ephy_extensions_manager_load_string (EphyExtensionsManager *manager, const xmlChar *value; value = xmlTextReaderConstValue (reader); + info->load_deferred = (value != NULL && xmlStrEqual (value, (const xmlChar *) "true")); } else if (state == STATE_LOCALE_DIRECTORY && type == XML_READER_TYPE_TEXT) { - info->locale_directory = xmlTextReaderValue (reader); + const xmlChar *attr; + + attr = xmlTextReaderConstValue (reader); + + info->locale_directory = g_strdup ((char*)attr); } else if (state == STATE_NAME && type == XML_READER_TYPE_TEXT) @@ -561,7 +583,11 @@ ephy_extensions_manager_load_string (EphyExtensionsManager *manager, else if (state == STATE_URL && type == XML_READER_TYPE_TEXT) { - einfo->url = (char *)xmlTextReaderValue (reader); + const xmlChar *attr; + + attr = xmlTextReaderConstValue (reader); + + einfo->url = g_strdup ((char*)attr); } else if (state == STATE_AUTHOR && type == XML_READER_TYPE_END_ELEMENT && @@ -651,6 +677,9 @@ ephy_extensions_manager_load_string (EphyExtensionsManager *manager, einfo->description = (char *)description.string; einfo->name = (char *)name.string; + /* Reverse authors list */ + einfo->authors = g_list_reverse (einfo->authors); + /* sanity check */ if (ret < 0 || state != STATE_STOP || einfo->name == NULL || einfo->description == NULL || @@ -665,13 +694,138 @@ ephy_extensions_manager_load_string (EphyExtensionsManager *manager, g_signal_emit (manager, signals[ADDED], 0, info); } +static void +ephy_extensions_manager_load_ini_string (EphyExtensionsManager *manager, + const char * identifier, + const char * contents) +{ + ExtensionInfo *info; + EphyExtensionInfo *einfo; + gchar ** list; + int i; + GKeyFile *key_file; + GError *err = NULL; + + LOG ("Loading INI description file for '%s'", identifier); + + if (g_list_find_custom (manager->priv->data, identifier, + (GCompareFunc) find_extension_info) != NULL) + { + g_warning ("Extension description for '%s' already read!", + identifier); + return; + } + + key_file = g_key_file_new (); + if (g_key_file_load_from_data (key_file, contents, strlen (contents), + G_KEY_FILE_NONE, &err) == FALSE) + { + g_warning ("Could load key file for '%s': '%s'", + identifier, err->message); + g_error_free (err); + g_key_file_free (key_file); + return; + } + + if (g_key_file_has_group (key_file, "Epiphany Extension") == FALSE || + g_key_file_has_group (key_file, "Loader") == FALSE) + { + g_warning ("Invalid extension description file for '%s'; " + "missing 'Epiphany Extension' or 'Loader' group", + identifier); + + g_key_file_free (key_file); + return; + } + + info = g_new0 (ExtensionInfo, 1); + einfo = (EphyExtensionInfo *) info; + einfo->identifier = g_strdup (identifier); + g_datalist_init (&info->loader_attributes); + + einfo->name = g_key_file_get_locale_string (key_file, + "Epiphany Extension", + "Name", + NULL, NULL); + + einfo->description = g_key_file_get_locale_string (key_file, + "Epiphany Extension", + "Description", + NULL, NULL); + + einfo->url = g_key_file_get_locale_string (key_file, + "Epiphany Extension", + "URL", + NULL, NULL); + + list = g_key_file_get_string_list (key_file, + "Epiphany Extension", + "Authors", NULL, NULL); + for (i = 0 ; list[i]; i++ ) + { + einfo->authors = g_list_prepend (einfo->authors, + g_strstrip (g_strdup (list[i]))); + } + einfo->authors = g_list_reverse (einfo->authors); + g_strfreev (list); + + info->version = g_key_file_get_integer (key_file, + "Epiphany Extension", + "Version", NULL); + + /* Load the loader flags */ + list = g_key_file_get_keys (key_file, "Loader", NULL, NULL); + for (i = 0 ; list[i]; i++ ) + { + + char * value; + GQuark attr_quark = 0; + + value = g_key_file_get_string (key_file, "Loader", + list[i], NULL); + + if (strcmp (list[i], "Type") == 0) + { + info->loader_type = value; + continue; + } + + attr_quark = g_quark_from_string (list[i]); + + g_datalist_id_set_data_full (&info->loader_attributes, + attr_quark, value, + (GDestroyNotify) g_free); + } + g_strfreev (list); + + g_key_file_free (key_file); + + /* sanity check */ + if (einfo->name == NULL || einfo->description == NULL || + info->loader_type == NULL || info->loader_type[0] == '\0') + { + free_extension_info (info); + return; + } + + manager->priv->data = g_list_prepend (manager->priv->data, info); + + g_signal_emit (manager, signals[ADDED], 0, info); +} + static char * path_to_identifier (const char *path) { char *identifier, *dot; identifier = g_path_get_basename (path); - dot = strstr (identifier, ".xml"); + dot = strstr (identifier, ".ephy-extension"); + + if (!dot) + { + dot = strstr (identifier, ".xml"); + } + g_return_val_if_fail (dot != NULL, NULL); *dot = '\0'; @@ -684,10 +838,10 @@ ephy_extensions_manager_load_file (EphyExtensionsManager *manager, const char *path) { char *identifier; - char *xml; + char *contents; GError *err = NULL; - g_file_get_contents (path, &xml, NULL, &err); + g_file_get_contents (path, &contents, NULL, &err); if (err != NULL) { @@ -700,12 +854,22 @@ ephy_extensions_manager_load_file (EphyExtensionsManager *manager, identifier = path_to_identifier (path); g_return_if_fail (identifier != NULL); - ephy_extensions_manager_load_string (manager, identifier, xml); + if (g_str_has_suffix (path, ".ephy-extension")) + { + ephy_extensions_manager_load_ini_string (manager, identifier, + contents); + } + else if (g_str_has_suffix (path, ".xml")) + { + ephy_extensions_manager_load_xml_string (manager, identifier, + contents); + } g_free (identifier); - g_free (xml); + g_free (contents); } + static int find_loader (const LoaderInfo *info, const char *type) @@ -838,7 +1002,8 @@ load_extension (EphyExtensionsManager *manager, if (info->load_failed) return; /* get a loader */ - loader = get_loader_for_type (manager, (const char *)info->loader_type); + loader = get_loader_for_type (manager, + info->loader_type); if (loader == NULL) { g_message ("No loader found for extension '%s' of type '%s'\n", @@ -1035,7 +1200,7 @@ load_file_from_monitor (EphyExtensionsManager *manager, /* When a file is installed, it sometimes gets CREATED empty and then * gets its contents filled later (for a CHANGED signal). Theoretically * I suppose we could get a CHANGED signal when the file is half-full, - * but I doubt that'll happen much (the xml files are <1000 bytes). We + * but I doubt that'll happen much (the files are <1000 bytes). We * don't want warnings all over the place, so we return from this * function if the file is empty. (We're assuming that if a file is * empty it'll be filled soon and this function will be called again.) @@ -1043,11 +1208,11 @@ load_file_from_monitor (EphyExtensionsManager *manager, * Oh, and we return if the extension is already loaded, too. */ char *identifier; - char *xml; + char *contents; gsize len; GError *err = NULL; - g_file_get_contents (path, &xml, &len, &err); + g_file_get_contents (path, &contents, &len, &err); if (err != NULL) { @@ -1058,7 +1223,7 @@ load_file_from_monitor (EphyExtensionsManager *manager, } if (len == 0) { - g_free (xml); + g_free (contents); return; } @@ -1069,14 +1234,23 @@ load_file_from_monitor (EphyExtensionsManager *manager, (GCompareFunc) find_extension_info) != NULL) { g_free (identifier); - g_free (xml); + g_free (contents); return; } - ephy_extensions_manager_load_string (manager, identifier, xml); - + if (g_str_has_suffix (path, ".ephy-extension")) + { + ephy_extensions_manager_load_ini_string (manager, + identifier, contents); + } + else if (g_str_has_suffix (path, ".xml")) + { + ephy_extensions_manager_load_xml_string (manager, + identifier, contents); + } + g_free (identifier); - g_free (xml); + g_free (contents); sync_loaded_extensions (manager); } @@ -1091,10 +1265,11 @@ dir_changed_cb (GnomeVFSMonitorHandle *handle, char *path; /* - * We only deal with XML files: Add them to the manager when created, - * remove them when deleted. + * We only deal with XML and INI files: + * Add them to the manager when created, remove them when deleted. */ - if (g_str_has_suffix (info_uri, ".xml") == FALSE) return; + if (g_str_has_suffix (info_uri, ".ephy-extension") == FALSE && + g_str_has_suffix (info_uri, ".xml") == FALSE) return; path = gnome_vfs_get_local_path_from_uri (info_uri); @@ -1136,7 +1311,8 @@ ephy_extensions_manager_load_dir (EphyExtensionsManager *manager, } while ((e = readdir (d)) != NULL) { - if (g_str_has_suffix (e->d_name, ".xml")) + if (g_str_has_suffix (e->d_name, ".ephy-extension") || + g_str_has_suffix (e->d_name, ".xml")) { file_path = g_build_filename (path, e->d_name, NULL); ephy_extensions_manager_load_file (manager, file_path); -- cgit v1.2.3