]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
charset-alias-plugin
authorHideo Yoshizane <hideo.yoshizane@open-xchange.com>
Thu, 25 Jan 2018 00:36:22 +0000 (19:36 -0500)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 19 Feb 2018 10:12:05 +0000 (12:12 +0200)
configure.ac
src/plugins/Makefile.am
src/plugins/charset-alias/Makefile.am [new file with mode: 0644]
src/plugins/charset-alias/charset-alias-plugin.c [new file with mode: 0644]
src/plugins/charset-alias/charset-alias-plugin.h [new file with mode: 0644]

index c39e2498cdd12a9ac8724742e100cab8bc378a23..dae6db948e19892e48158a4e2d498491788c6e4e 100644 (file)
@@ -3094,6 +3094,7 @@ src/plugins/imap-zlib/Makefile
 src/plugins/mail-crypt/Makefile
 src/plugins/var-expand-crypt/Makefile
 src/plugins/apparmor/Makefile
+src/plugins/charset-alias/Makefile
 stamp.h
 dovecot-config.in])
 
index 48c9a281da8b7fac0fc397bc627252d3ab389ea1..4aa984d93fbb9e8dcdaef6d87e14a1ec7761e434 100644 (file)
@@ -52,4 +52,5 @@ SUBDIRS = \
        $(DICT_LDAP) \
        $(APPARMOR) \
        fs-compress \
-       var-expand-crypt
+       var-expand-crypt \
+       charset-alias   
diff --git a/src/plugins/charset-alias/Makefile.am b/src/plugins/charset-alias/Makefile.am
new file mode 100644 (file)
index 0000000..18f1bdc
--- /dev/null
@@ -0,0 +1,19 @@
+AM_CPPFLAGS = \\r
+       -I$(top_srcdir)/src/lib \\r
+       -I$(top_srcdir)/src/lib-master \\r
+       -I$(top_srcdir)/src/lib-mail \\r
+       -I$(top_srcdir)/src/lib-charset \\r
+       -I$(top_srcdir)/src/lib-index \\r
+       -I$(top_srcdir)/src/lib-storage \r
+\r
+NOPLUGIN_LDFLAGS =\r
+lib20_charset_alias_plugin_la_LDFLAGS = -module -avoid-version\r
+\r
+module_LTLIBRARIES = \\r
+       lib20_charset_alias_plugin.la\r
+\r
+lib20_charset_alias_plugin_la_SOURCES = \\r
+       charset-alias-plugin.c\r
+\r
+noinst_HEADERS = \\r
+       charset-alias-plugin.h\r
diff --git a/src/plugins/charset-alias/charset-alias-plugin.c b/src/plugins/charset-alias/charset-alias-plugin.c
new file mode 100644 (file)
index 0000000..3cf271b
--- /dev/null
@@ -0,0 +1,199 @@
+/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */\r
+\r
+#include "lib.h"\r
+#include "array.h"\r
+#include "str.h"\r
+#include "mail-user.h"\r
+#include "mail-storage-private.h"\r
+#include "mail-storage-hooks.h"\r
+#include "charset-utf8-private.h"\r
+#include "charset-alias-plugin.h"\r
+\r
+\r
+#define CHARSET_ALIAS_USER_CONTEXT(obj) \\r
+       MODULE_CONTEXT(obj, charset_alias_user_module)\r
+\r
+static MODULE_CONTEXT_DEFINE_INIT(charset_alias_user_module,\r
+                                 &mail_user_module_register);\r
+\r
+const char *charset_alias_plugin_version = DOVECOT_ABI_VERSION;\r
+\r
+static int charset_alias_to_utf8_begin(const char *charset,\r
+                                      normalizer_func_t *normalizer,\r
+                                      struct charset_translation **t_r);\r
+\r
+static void charset_alias_to_utf8_end(struct charset_translation *t);\r
+\r
+static void charset_alias_to_utf8_reset(struct charset_translation *t);\r
+\r
+static enum charset_result charset_alias_to_utf8(struct charset_translation *t,\r
+                                                const unsigned char *src,\r
+                                                size_t *src_size, buffer_t *dest);\r
+\r
+/* charset_utf8_vfuncs is defined in lib-charset/charset-utf8.c */\r
+extern const struct charset_utf8_vfuncs *charset_utf8_vfuncs;\r
+\r
+static const struct charset_utf8_vfuncs *original_charset_utf8_vfuncs;\r
+\r
+static const struct charset_utf8_vfuncs charset_alias_utf8_vfuncs = {\r
+       charset_alias_to_utf8_begin,\r
+       charset_alias_to_utf8_end,\r
+       charset_alias_to_utf8_reset,\r
+       charset_alias_to_utf8\r
+};\r
+\r
+struct charset_alias {\r
+       const char *charset;\r
+       const char *alias;\r
+};\r
+\r
+static ARRAY(struct charset_alias) charset_aliases;\r
+static pool_t charset_alias_pool;\r
+static int charset_alias_user_refcount = 0;\r
+\r
+struct charset_alias_user {\r
+       union mail_user_module_context module_ctx;\r
+};\r
+\r
+\r
+static const char *charset_alias_get_alias(const char *charset)\r
+{\r
+       const struct charset_alias* elem;\r
+       const char *key;\r
+\r
+       if (array_is_created(&charset_aliases)) {\r
+               key = t_str_lcase(charset);\r
+               array_foreach(&charset_aliases, elem) {\r
+                       if (strcmp(key, elem->charset) == 0) {\r
+                               return elem->alias;\r
+                       }\r
+               }\r
+       }\r
+       return charset;\r
+}\r
+\r
+static int charset_alias_to_utf8_begin(const char *charset,\r
+                                      normalizer_func_t *normalizer,\r
+                                      struct charset_translation **t_r)\r
+{\r
+       i_assert(original_charset_utf8_vfuncs != NULL);\r
+       charset = charset_alias_get_alias(charset);\r
+       return original_charset_utf8_vfuncs->to_utf8_begin(charset, normalizer, t_r);\r
+}\r
+static void charset_alias_to_utf8_end(struct charset_translation *t)\r
+{\r
+       i_assert(original_charset_utf8_vfuncs != NULL);\r
+       return original_charset_utf8_vfuncs->to_utf8_end(t);\r
+}\r
+\r
+static void charset_alias_to_utf8_reset(struct charset_translation *t)\r
+{\r
+       i_assert(original_charset_utf8_vfuncs != NULL);\r
+       return original_charset_utf8_vfuncs->to_utf8_reset(t);\r
+}\r
+\r
+static enum charset_result charset_alias_to_utf8(struct charset_translation *t,\r
+                                                const unsigned char *src,\r
+                                                size_t *src_size, buffer_t *dest)\r
+{\r
+       i_assert(original_charset_utf8_vfuncs != NULL);\r
+       return original_charset_utf8_vfuncs->to_utf8(t, src, src_size, dest);\r
+}\r
+\r
+static unsigned int charset_aliases_init(struct mail_user *user, pool_t pool, const char *str)\r
+{\r
+       const char *key, *value, *const *keyvalues;\r
+       struct charset_alias alias;\r
+       int i;\r
+\r
+       i_assert(!array_is_created(&charset_aliases));\r
+\r
+       p_array_init(&charset_aliases, pool, 1);\r
+       keyvalues = t_strsplit_spaces(str, " ");\r
+       for (i = 0; keyvalues[i] != '\0'; i++) {\r
+               value = strchr(keyvalues[i], '=');\r
+               if (value == NULL) {\r
+                       i_error("charset_alias: Missing '=' in charset_aliases setting");\r
+                       continue;\r
+               }\r
+               key = t_strdup_until(keyvalues[i], value++);\r
+               if (key[0] == '\0' || value[0] == '\0') {\r
+                       i_error("charset_alias: charset or alias missing in charset_aliases setting");\r
+                       continue;\r
+               }\r
+               if (strcasecmp(key, value) != 0) {\r
+                       if (user->mail_debug)\r
+                               i_debug("charset_alias: add charset-alias %s for %s", value, key);\r
+                       alias.charset = p_strdup(pool, t_str_lcase(key));\r
+                       alias.alias = p_strdup(pool, value);\r
+                       array_append(&charset_aliases, &alias, 1);\r
+               }\r
+       }\r
+       return array_count(&charset_aliases);\r
+}\r
+\r
+static void charset_alias_utf8_vfuncs_set(void)\r
+{\r
+       original_charset_utf8_vfuncs = charset_utf8_vfuncs;\r
+       charset_utf8_vfuncs = &charset_alias_utf8_vfuncs;\r
+}\r
+\r
+static void charset_alias_utf8_vfuncs_reset(void)\r
+{\r
+       if (original_charset_utf8_vfuncs != NULL) {\r
+               charset_utf8_vfuncs = original_charset_utf8_vfuncs;\r
+               original_charset_utf8_vfuncs = NULL;\r
+       }\r
+}\r
+\r
+static void charset_alias_mail_user_deinit(struct mail_user *user)\r
+{\r
+       struct charset_alias_user *cuser = CHARSET_ALIAS_USER_CONTEXT(user);\r
+\r
+       i_assert(charset_alias_user_refcount > 0);\r
+       if (--charset_alias_user_refcount == 0) {\r
+               charset_alias_utf8_vfuncs_reset();\r
+               array_free(&charset_aliases);\r
+               pool_unref(&charset_alias_pool);\r
+       }\r
+\r
+       cuser->module_ctx.super.deinit(user);\r
+}\r
+\r
+static void charset_alias_mail_user_created(struct mail_user *user)\r
+{\r
+       struct mail_user_vfuncs *v = user->vlast;\r
+       struct charset_alias_user *cuser;\r
+       const char *str;\r
+\r
+       cuser = p_new(user->pool, struct charset_alias_user, 1);\r
+       cuser->module_ctx.super = *v;\r
+       user->vlast = &cuser->module_ctx.super;\r
+       v->deinit = charset_alias_mail_user_deinit;\r
+\r
+       if (charset_alias_user_refcount++ == 0) {\r
+               charset_alias_pool = pool_alloconly_create("charset_alias alias list", 128);\r
+               str = mail_user_plugin_getenv(user, "charset_aliases");\r
+               if (str != NULL && str[0] != '\0') {\r
+                       if (charset_aliases_init(user, charset_alias_pool, str) > 0) {\r
+                               charset_alias_utf8_vfuncs_set();\r
+                       }\r
+               }\r
+       }\r
+\r
+       MODULE_CONTEXT_SET(user, charset_alias_user_module, cuser);\r
+}\r
+\r
+static struct mail_storage_hooks charset_alias_mail_storage_hooks = {\r
+       .mail_user_created = charset_alias_mail_user_created\r
+};\r
+\r
+void charset_alias_plugin_init(struct module *module)\r
+{\r
+       mail_storage_hooks_add(module, &charset_alias_mail_storage_hooks);\r
+}\r
+\r
+void charset_alias_plugin_deinit(void)\r
+{\r
+       mail_storage_hooks_remove(&charset_alias_mail_storage_hooks);\r
+}\r
diff --git a/src/plugins/charset-alias/charset-alias-plugin.h b/src/plugins/charset-alias/charset-alias-plugin.h
new file mode 100644 (file)
index 0000000..827666b
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef CHARSET_ALIAS_PLUGIN_H\r
+#define CHARSET_ALIAS_PLUGIN_H\r
+\r
+void charset_alias_plugin_init(struct module *module);\r
+void charset_alias_plugin_deinit(void);\r
+\r
+#endif\r