charset-alias-plugin.c revision 5addf4e0ac50a99af25a1b1ef3def67f6d1595de
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi MODULE_CONTEXT_REQUIRE(obj, charset_alias_user_module)
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic MODULE_CONTEXT_DEFINE_INIT(charset_alias_user_module,
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärviconst char *charset_alias_plugin_version = DOVECOT_ABI_VERSION;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic int charset_alias_to_utf8_begin(const char *charset,
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic void charset_alias_to_utf8_end(struct charset_translation *t);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic void charset_alias_to_utf8_reset(struct charset_translation *t);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic enum charset_result charset_alias_to_utf8(struct charset_translation *t,
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi const unsigned char *src,
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi/* charset_utf8_vfuncs is defined in lib-charset/charset-utf8.c */
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärviextern const struct charset_utf8_vfuncs *charset_utf8_vfuncs;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic const struct charset_utf8_vfuncs *original_charset_utf8_vfuncs;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic const struct charset_utf8_vfuncs charset_alias_utf8_vfuncs = {
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic ARRAY(struct charset_alias) charset_aliases;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic int charset_alias_user_refcount = 0;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi union mail_user_module_context module_ctx;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic const char *charset_alias_get_alias(const char *charset)
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi if (array_is_created(&charset_aliases)) {
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic int charset_alias_to_utf8_begin(const char *charset,
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi i_assert(original_charset_utf8_vfuncs != NULL);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi charset = charset_alias_get_alias(charset);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi return original_charset_utf8_vfuncs->to_utf8_begin(charset, normalizer, t_r);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic void charset_alias_to_utf8_end(struct charset_translation *t)
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi i_assert(original_charset_utf8_vfuncs != NULL);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi return original_charset_utf8_vfuncs->to_utf8_end(t);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic void charset_alias_to_utf8_reset(struct charset_translation *t)
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi i_assert(original_charset_utf8_vfuncs != NULL);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi return original_charset_utf8_vfuncs->to_utf8_reset(t);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic enum charset_result charset_alias_to_utf8(struct charset_translation *t,
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi const unsigned char *src,
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi i_assert(original_charset_utf8_vfuncs != NULL);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi return original_charset_utf8_vfuncs->to_utf8(t, src, src_size, dest);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic unsigned int charset_aliases_init(struct mail_user *user, pool_t pool, const char *str)
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi const char *key, *value, *const *keyvalues;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi i_assert(!array_is_created(&charset_aliases));
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi i_error("charset_alias: Missing '=' in charset_aliases setting");
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi key = t_strdup_until(keyvalues[i], value++);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi if (key[0] == '\0' || value[0] == '\0') {
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi i_error("charset_alias: charset or alias missing in charset_aliases setting");
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi i_debug("charset_alias: add charset-alias %s for %s", value, key);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi alias.charset = p_strdup(pool, t_str_lcase(key));
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi array_append(&charset_aliases, &alias, 1);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic void charset_alias_utf8_vfuncs_set(void)
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi original_charset_utf8_vfuncs = charset_utf8_vfuncs;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi charset_utf8_vfuncs = &charset_alias_utf8_vfuncs;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic void charset_alias_utf8_vfuncs_reset(void)
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi if (original_charset_utf8_vfuncs != NULL) {
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi charset_utf8_vfuncs = original_charset_utf8_vfuncs;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic void charset_alias_mail_user_deinit(struct mail_user *user)
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi struct charset_alias_user *cuser = CHARSET_ALIAS_USER_CONTEXT(user);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi i_assert(charset_alias_user_refcount > 0);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi if (--charset_alias_user_refcount == 0) {
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic void charset_alias_mail_user_created(struct mail_user *user)
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi struct mail_user_vfuncs *v = user->vlast;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi cuser = p_new(user->pool, struct charset_alias_user, 1);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi v->deinit = charset_alias_mail_user_deinit;
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi if (charset_alias_user_refcount++ == 0) {
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi charset_alias_pool = pool_alloconly_create("charset_alias alias list", 128);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi str = mail_user_plugin_getenv(user, "charset_aliases");
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi if (charset_aliases_init(user, charset_alias_pool, str) > 0) {
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi MODULE_CONTEXT_SET(user, charset_alias_user_module, cuser);
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvistatic struct mail_storage_hooks charset_alias_mail_storage_hooks = {
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi .mail_user_created = charset_alias_mail_user_created
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvivoid charset_alias_plugin_init(struct module *module)
acbcc2709244e470e9bd8b58917f40b2e57d9cb7Martti Rannanjärvi mail_storage_hooks_add(module, &charset_alias_mail_storage_hooks);