/* * e-mail-extension-registry.c * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with the program; if not, see * */ #include "e-mail-extension-registry.h" #include #include #include "e-mail-formatter-extension.h" #include "e-mail-parser-extension.h" #define E_MAIL_EXTENSION_REGISTRY_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_MAIL_EXTENSION_REGISTRY, EMailExtensionRegistryPrivate)) struct _EMailExtensionRegistryPrivate { GHashTable *table; }; G_DEFINE_ABSTRACT_TYPE ( EMailExtensionRegistry, e_mail_extension_registry, G_TYPE_OBJECT) /** * EMailExtensionRegistry: * * The #EMailExtensionRegistry is an abstract class representing a registry * for #EMailExtensions. * * #EMailParser and #EMailFormatter both have internally a registry object * based on the #EMailExtensionRegistry. * * One extension can registry itself for more mime-types. */ static void destroy_queue (GQueue *queue) { g_queue_free_full (queue, g_object_unref); } static void mail_extension_registry_add_extension (EMailExtensionRegistry *registry, const gchar **mime_types, GType extension_type, GCompareDataFunc compare_func) { GObject *extension; gint ii; if (mime_types == NULL) { g_critical ( "%s does not define any MIME types", g_type_name (extension_type)); return; } extension = g_object_new (extension_type, NULL); for (ii = 0; mime_types[ii] != NULL; ii++) { GQueue *queue; queue = g_hash_table_lookup ( registry->priv->table, mime_types[ii]); if (queue == NULL) { queue = g_queue_new (); g_hash_table_insert ( registry->priv->table, (gpointer) mime_types[ii], queue); } g_queue_insert_sorted ( queue, g_object_ref (extension), compare_func, NULL); if (camel_debug ("emformat:registry")) { printf ( "Added extension '%s' for type '%s'\n", g_type_name (extension_type), mime_types[ii]); } } g_object_unref (extension); } static void mail_extension_registry_finalize (GObject *object) { EMailExtensionRegistryPrivate *priv; priv = E_MAIL_EXTENSION_REGISTRY_GET_PRIVATE (object); g_hash_table_destroy (priv->table); /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (e_mail_extension_registry_parent_class)-> finalize (object); } void e_mail_extension_registry_class_init (EMailExtensionRegistryClass *class) { GObjectClass *object_class; g_type_class_add_private ( class, sizeof (EMailExtensionRegistryPrivate)); object_class = G_OBJECT_CLASS (class); object_class->finalize = mail_extension_registry_finalize; } void e_mail_extension_registry_init (EMailExtensionRegistry *registry) { registry->priv = E_MAIL_EXTENSION_REGISTRY_GET_PRIVATE (registry); registry->priv->table = g_hash_table_new_full ( (GHashFunc) g_str_hash, (GEqualFunc) g_str_equal, (GDestroyNotify) NULL, (GDestroyNotify) destroy_queue); } /** * e_mail_extension_registry_get_for_mime_type: * @registry: An #EMailExtensionRegistry * @mime_type: A string with mime-type to look up * * Tries to lookup list of #EMailExtensions that has registryed themselves * as handlers for the @mime_type. * * Return value: Returns #GQueue of #EMailExtensions or %NULL when there * are no extension registryed for given @mime_type. */ GQueue * e_mail_extension_registry_get_for_mime_type (EMailExtensionRegistry *registry, const gchar *mime_type) { g_return_val_if_fail (E_IS_MAIL_EXTENSION_REGISTRY (registry), NULL); g_return_val_if_fail (mime_type && *mime_type, NULL); return g_hash_table_lookup (registry->priv->table, mime_type); } /** * e_mail_extension_registry_get_fallback: * @registry: An #EMailExtensionRegistry * @mime_type: A string with mime-type whose fallback to look up * * Tries to lookup fallback parsers for given mime type. For instance, for * multipart/alternative, it will try to lookup multipart/ * parser. * * Return Value: Returns #QGueue of #EMailExtension>s or %NULL when there * are no extensions registryed for the fallback type. */ GQueue * e_mail_extension_registry_get_fallback (EMailExtensionRegistry *registry, const gchar *mime_type) { gchar *s, *type; gsize len; GQueue *parsers; g_return_val_if_fail (E_IS_MAIL_EXTENSION_REGISTRY (registry), NULL); g_return_val_if_fail (mime_type && *mime_type, NULL); s = strchr (mime_type, '/'); if (!s) return NULL; len = s - mime_type; s = g_alloca (len); strncpy (s, mime_type, len); type = g_ascii_strdown (s, len); s = g_strdup_printf ("%s/*", type); parsers = g_hash_table_lookup (registry->priv->table, s); g_free (type); g_free (s); return parsers; } /******************************************************************************/ G_DEFINE_TYPE_WITH_CODE ( EMailParserExtensionRegistry, e_mail_parser_extension_registry, E_TYPE_MAIL_EXTENSION_REGISTRY, G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL)) static void e_mail_parser_extension_registry_class_init (EMailParserExtensionRegistryClass *class) { } static void e_mail_parser_extension_registry_init (EMailParserExtensionRegistry *registry) { } static gint mail_parser_extension_registry_compare (gconstpointer extension1, gconstpointer extension2, gpointer user_data) { EMailParserExtensionClass *class1; EMailParserExtensionClass *class2; class1 = E_MAIL_PARSER_EXTENSION_GET_CLASS (extension1); class2 = E_MAIL_PARSER_EXTENSION_GET_CLASS (extension2); if (class1->priority == class2->priority) return 0; return (class1->priority < class2->priority) ? -1 : 1; } void e_mail_parser_extension_registry_load (EMailParserExtensionRegistry *registry) { GType *children; GType base_extension_type; guint ii, n_children; g_return_if_fail (E_IS_MAIL_PARSER_EXTENSION_REGISTRY (registry)); base_extension_type = E_TYPE_MAIL_PARSER_EXTENSION; children = g_type_children (base_extension_type, &n_children); for (ii = 0; ii < n_children; ii++) { EMailParserExtensionClass *class; if (G_TYPE_IS_ABSTRACT (children[ii])) continue; class = g_type_class_ref (children[ii]); mail_extension_registry_add_extension ( E_MAIL_EXTENSION_REGISTRY (registry), class->mime_types, children[ii], mail_parser_extension_registry_compare); g_type_class_unref (class); } g_free (children); } /******************************************************************************/ G_DEFINE_TYPE_WITH_CODE ( EMailFormatterExtensionRegistry, e_mail_formatter_extension_registry, E_TYPE_MAIL_EXTENSION_REGISTRY, G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL)) static void e_mail_formatter_extension_registry_class_init (EMailFormatterExtensionRegistryClass *class) { } static void e_mail_formatter_extension_registry_init (EMailFormatterExtensionRegistry *registry) { } static gint mail_formatter_extension_registry_compare (gconstpointer extension1, gconstpointer extension2, gpointer user_data) { EMailFormatterExtensionClass *class1; EMailFormatterExtensionClass *class2; class1 = E_MAIL_FORMATTER_EXTENSION_GET_CLASS (extension1); class2 = E_MAIL_FORMATTER_EXTENSION_GET_CLASS (extension2); if (class1->priority == class2->priority) return 0; return (class1->priority < class2->priority) ? -1 : 1; } void e_mail_formatter_extension_registry_load (EMailFormatterExtensionRegistry *registry, GType base_extension_type) { GType *children; guint ii, n_children; g_return_if_fail (E_IS_MAIL_FORMATTER_EXTENSION_REGISTRY (registry)); children = g_type_children (base_extension_type, &n_children); for (ii = 0; ii < n_children; ii++) { EMailFormatterExtensionClass *class; if (G_TYPE_IS_ABSTRACT (children[ii])) continue; class = g_type_class_ref (children[ii]); mail_extension_registry_add_extension ( E_MAIL_EXTENSION_REGISTRY (registry), class->mime_types, children[ii], mail_formatter_extension_registry_compare); g_type_class_unref (class); } g_free (children); }