Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
de3e700
commit a12a2fa
Showing
5 changed files
with
228 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,4 +52,5 @@ SUBDIRS = \ | |
$(DICT_LDAP) \ | ||
$(APPARMOR) \ | ||
fs-compress \ | ||
var-expand-crypt | ||
var-expand-crypt \ | ||
charset-alias |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
AM_CPPFLAGS = \ | ||
-I$(top_srcdir)/src/lib \ | ||
-I$(top_srcdir)/src/lib-master \ | ||
-I$(top_srcdir)/src/lib-mail \ | ||
-I$(top_srcdir)/src/lib-charset \ | ||
-I$(top_srcdir)/src/lib-index \ | ||
-I$(top_srcdir)/src/lib-storage | ||
|
||
NOPLUGIN_LDFLAGS = | ||
lib20_charset_alias_plugin_la_LDFLAGS = -module -avoid-version | ||
|
||
module_LTLIBRARIES = \ | ||
lib20_charset_alias_plugin.la | ||
|
||
lib20_charset_alias_plugin_la_SOURCES = \ | ||
charset-alias-plugin.c | ||
|
||
noinst_HEADERS = \ | ||
charset-alias-plugin.h |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */ | ||
|
||
#include "lib.h" | ||
#include "array.h" | ||
#include "str.h" | ||
#include "mail-user.h" | ||
#include "mail-storage-private.h" | ||
#include "mail-storage-hooks.h" | ||
#include "charset-utf8-private.h" | ||
#include "charset-alias-plugin.h" | ||
|
||
|
||
#define CHARSET_ALIAS_USER_CONTEXT(obj) \ | ||
MODULE_CONTEXT(obj, charset_alias_user_module) | ||
|
||
static MODULE_CONTEXT_DEFINE_INIT(charset_alias_user_module, | ||
&mail_user_module_register); | ||
|
||
const char *charset_alias_plugin_version = DOVECOT_ABI_VERSION; | ||
|
||
static int charset_alias_to_utf8_begin(const char *charset, | ||
normalizer_func_t *normalizer, | ||
struct charset_translation **t_r); | ||
|
||
static void charset_alias_to_utf8_end(struct charset_translation *t); | ||
|
||
static void charset_alias_to_utf8_reset(struct charset_translation *t); | ||
|
||
static enum charset_result charset_alias_to_utf8(struct charset_translation *t, | ||
const unsigned char *src, | ||
size_t *src_size, buffer_t *dest); | ||
|
||
/* charset_utf8_vfuncs is defined in lib-charset/charset-utf8.c */ | ||
extern const struct charset_utf8_vfuncs *charset_utf8_vfuncs; | ||
|
||
static const struct charset_utf8_vfuncs *original_charset_utf8_vfuncs; | ||
|
||
static const struct charset_utf8_vfuncs charset_alias_utf8_vfuncs = { | ||
charset_alias_to_utf8_begin, | ||
charset_alias_to_utf8_end, | ||
charset_alias_to_utf8_reset, | ||
charset_alias_to_utf8 | ||
}; | ||
|
||
struct charset_alias { | ||
const char *charset; | ||
const char *alias; | ||
}; | ||
|
||
static ARRAY(struct charset_alias) charset_aliases; | ||
static pool_t charset_alias_pool; | ||
static int charset_alias_user_refcount = 0; | ||
|
||
struct charset_alias_user { | ||
union mail_user_module_context module_ctx; | ||
}; | ||
|
||
|
||
static const char *charset_alias_get_alias(const char *charset) | ||
{ | ||
const struct charset_alias* elem; | ||
const char *key; | ||
|
||
if (array_is_created(&charset_aliases)) { | ||
key = t_str_lcase(charset); | ||
array_foreach(&charset_aliases, elem) { | ||
if (strcmp(key, elem->charset) == 0) { | ||
return elem->alias; | ||
} | ||
} | ||
} | ||
return charset; | ||
} | ||
|
||
static int charset_alias_to_utf8_begin(const char *charset, | ||
normalizer_func_t *normalizer, | ||
struct charset_translation **t_r) | ||
{ | ||
i_assert(original_charset_utf8_vfuncs != NULL); | ||
charset = charset_alias_get_alias(charset); | ||
return original_charset_utf8_vfuncs->to_utf8_begin(charset, normalizer, t_r); | ||
} | ||
static void charset_alias_to_utf8_end(struct charset_translation *t) | ||
{ | ||
i_assert(original_charset_utf8_vfuncs != NULL); | ||
return original_charset_utf8_vfuncs->to_utf8_end(t); | ||
} | ||
|
||
static void charset_alias_to_utf8_reset(struct charset_translation *t) | ||
{ | ||
i_assert(original_charset_utf8_vfuncs != NULL); | ||
return original_charset_utf8_vfuncs->to_utf8_reset(t); | ||
} | ||
|
||
static enum charset_result charset_alias_to_utf8(struct charset_translation *t, | ||
const unsigned char *src, | ||
size_t *src_size, buffer_t *dest) | ||
{ | ||
i_assert(original_charset_utf8_vfuncs != NULL); | ||
return original_charset_utf8_vfuncs->to_utf8(t, src, src_size, dest); | ||
} | ||
|
||
static unsigned int charset_aliases_init(struct mail_user *user, pool_t pool, const char *str) | ||
{ | ||
const char *key, *value, *const *keyvalues; | ||
struct charset_alias alias; | ||
int i; | ||
|
||
i_assert(!array_is_created(&charset_aliases)); | ||
|
||
p_array_init(&charset_aliases, pool, 1); | ||
keyvalues = t_strsplit_spaces(str, " "); | ||
for (i = 0; keyvalues[i] != '\0'; i++) { | ||
value = strchr(keyvalues[i], '='); | ||
if (value == NULL) { | ||
i_error("charset_alias: Missing '=' in charset_aliases setting"); | ||
continue; | ||
} | ||
key = t_strdup_until(keyvalues[i], value++); | ||
if (key[0] == '\0' || value[0] == '\0') { | ||
i_error("charset_alias: charset or alias missing in charset_aliases setting"); | ||
continue; | ||
} | ||
if (strcasecmp(key, value) != 0) { | ||
if (user->mail_debug) | ||
i_debug("charset_alias: add charset-alias %s for %s", value, key); | ||
alias.charset = p_strdup(pool, t_str_lcase(key)); | ||
alias.alias = p_strdup(pool, value); | ||
array_append(&charset_aliases, &alias, 1); | ||
} | ||
} | ||
return array_count(&charset_aliases); | ||
} | ||
|
||
static void charset_alias_utf8_vfuncs_set(void) | ||
{ | ||
original_charset_utf8_vfuncs = charset_utf8_vfuncs; | ||
charset_utf8_vfuncs = &charset_alias_utf8_vfuncs; | ||
} | ||
|
||
static void charset_alias_utf8_vfuncs_reset(void) | ||
{ | ||
if (original_charset_utf8_vfuncs != NULL) { | ||
charset_utf8_vfuncs = original_charset_utf8_vfuncs; | ||
original_charset_utf8_vfuncs = NULL; | ||
} | ||
} | ||
|
||
static void charset_alias_mail_user_deinit(struct mail_user *user) | ||
{ | ||
struct charset_alias_user *cuser = CHARSET_ALIAS_USER_CONTEXT(user); | ||
|
||
i_assert(charset_alias_user_refcount > 0); | ||
if (--charset_alias_user_refcount == 0) { | ||
charset_alias_utf8_vfuncs_reset(); | ||
array_free(&charset_aliases); | ||
pool_unref(&charset_alias_pool); | ||
} | ||
|
||
cuser->module_ctx.super.deinit(user); | ||
} | ||
|
||
static void charset_alias_mail_user_created(struct mail_user *user) | ||
{ | ||
struct mail_user_vfuncs *v = user->vlast; | ||
struct charset_alias_user *cuser; | ||
const char *str; | ||
|
||
cuser = p_new(user->pool, struct charset_alias_user, 1); | ||
cuser->module_ctx.super = *v; | ||
user->vlast = &cuser->module_ctx.super; | ||
v->deinit = charset_alias_mail_user_deinit; | ||
|
||
if (charset_alias_user_refcount++ == 0) { | ||
charset_alias_pool = pool_alloconly_create("charset_alias alias list", 128); | ||
str = mail_user_plugin_getenv(user, "charset_aliases"); | ||
if (str != NULL && str[0] != '\0') { | ||
if (charset_aliases_init(user, charset_alias_pool, str) > 0) { | ||
charset_alias_utf8_vfuncs_set(); | ||
} | ||
} | ||
} | ||
|
||
MODULE_CONTEXT_SET(user, charset_alias_user_module, cuser); | ||
} | ||
|
||
static struct mail_storage_hooks charset_alias_mail_storage_hooks = { | ||
.mail_user_created = charset_alias_mail_user_created | ||
}; | ||
|
||
void charset_alias_plugin_init(struct module *module) | ||
{ | ||
mail_storage_hooks_add(module, &charset_alias_mail_storage_hooks); | ||
} | ||
|
||
void charset_alias_plugin_deinit(void) | ||
{ | ||
mail_storage_hooks_remove(&charset_alias_mail_storage_hooks); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#ifndef CHARSET_ALIAS_PLUGIN_H | ||
#define CHARSET_ALIAS_PLUGIN_H | ||
|
||
void charset_alias_plugin_init(struct module *module); | ||
void charset_alias_plugin_deinit(void); | ||
|
||
#endif |