/*
* 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.
*
* 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 General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include "e-mail-extension-registry.h"
#include <string.h>
#include <libebackend/libebackend.h>
#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 #EMailExtension<!-//>s.
*
* #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 #EMailExtension<!-//>s that has registryed themselves
* as handlers for the @mime_type.
*
* Return value: Returns #GQueue of #EMailExtension<!-//>s 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);
}