fts-user.c revision fac865bad1ba10e85d80b63dedfd3493a65510d4
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "lib.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "module-context.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "mail-user.h"
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi#include "fts-language.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "fts-filter.h"
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi#include "fts-tokenizer.h"
c5f932968281763df360b9c97cef60f5f80d5e3dTimo Sirainen#include "fts-user.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define FTS_USER_CONTEXT(obj) \
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen MODULE_CONTEXT(obj, fts_user_module)
d951320d498ae0800b677b754dde71574102123bTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define FTS_DEFAULT_TOKENIZERS "generic email-address"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define FTS_DEFAULT_FILTERS "normalizer-icu snowball"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstruct fts_user {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen union mail_user_module_context module_ctx;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct fts_language_list *lang_list;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct fts_tokenizer *index_tokenizer, *search_tokenizer;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct fts_user_language *data_lang;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen ARRAY_TYPE(fts_user_language) languages;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen};
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(fts_user_module,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen &mail_user_module_register);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic const char *const *str_keyvalues_to_array(const char *str)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *key, *value, *const *keyvalues;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen ARRAY_TYPE(const_string) arr;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen unsigned int i;
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (str == NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return NULL;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen t_array_init(&arr, 8);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen keyvalues = t_strsplit_spaces(str, " ");
a21f618de284dc22a480af1371d5f5cea50a39dfTimo Sirainen for (i = 0; keyvalues[i] != NULL; i++) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen value = strchr(keyvalues[i], '=');
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (value != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen key = t_strdup_until(keyvalues[i], value++);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen else {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen key = keyvalues[i];
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen value = "";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen array_append(&arr, &key, 1);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen array_append(&arr, &value, 1);
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen }
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen array_append_zero(&arr);
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen return array_idx(&arr, 0);
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic int
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenfts_user_init_languages(struct mail_user *user, struct fts_user *fuser,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char **error_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *languages, *unknown;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *lang_config[3] = {NULL, NULL, NULL};
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen languages = mail_user_plugin_getenv(user, "fts_languages");
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen if (languages == NULL) {
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen *error_r = "fts_languages setting is missing";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen lang_config[1] = mail_user_plugin_getenv(user, "fts_language_config");
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fuser->lang_list = fts_language_list_init(lang_config);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (lang_config[1] != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen lang_config[0] = "fts_language_config";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (!fts_language_list_add_names(fuser->lang_list, languages, &unknown)) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *error_r = t_strdup_printf(
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen "fts_languages: Unknown language '%s'", unknown);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (array_count(fts_language_list_get_all(fuser->lang_list)) == 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *error_r = "fts_languages setting is empty";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic int
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenfts_user_create_filters(struct mail_user *user, const struct fts_language *lang,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct fts_filter **filter_r, const char **error_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const struct fts_filter *filter_class;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct fts_filter *filter = NULL, *parent = NULL;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *filters_key, *const *filters, *filter_set_name;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *str, *error, *set_key;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen unsigned int i;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen int ret = 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* try to get the language-specific filters first */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen filters_key = t_strconcat("fts_filters_", lang->name, NULL);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen str = mail_user_plugin_getenv(user, filters_key);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (str == NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* fallback to global filters */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen filters_key = "fts_filters";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen str = mail_user_plugin_getenv(user, filters_key);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (str == NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen str = FTS_DEFAULT_FILTERS;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen filters_key = "fts_filters(built-in default)";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen filters = t_strsplit_spaces(str, " ");
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen for (i = 0; filters[i] != NULL; i++) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen filter_class = fts_filter_find(filters[i]);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (filter_class == NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *error_r = t_strdup_printf("%s: Unknown filter '%s'",
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen filters_key, filters[i]);
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen ret = -1;
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen break;
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen }
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* try the language-specific setting first */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen filter_set_name = t_str_replace(filters[i], '-', '_');
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen set_key = t_strdup_printf("fts_filters_%s_%s",
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen lang->name, filter_set_name);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen str = mail_user_plugin_getenv(user, set_key);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (str == NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen set_key = t_strdup_printf("fts_filters_%s", filter_set_name);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen str = mail_user_plugin_getenv(user, set_key);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (fts_filter_create(filter_class, parent, lang,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen str_keyvalues_to_array(str),
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen &filter, &error) < 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *error_r = t_strdup_printf("%s: %s", set_key, error);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen ret = -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen break;
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi }
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi if (parent != NULL)
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi fts_filter_unref(&parent);
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi parent = filter;
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi }
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi if (ret < 0) {
d48e40d6c77d673ad402d96571198d1cce4da225Timo Sirainen if (parent != NULL)
b78d8dbe4179aabcbf9fda41d282673558dae4d6Timo Sirainen fts_filter_unref(&parent);
b78d8dbe4179aabcbf9fda41d282673558dae4d6Timo Sirainen return -1;
b78d8dbe4179aabcbf9fda41d282673558dae4d6Timo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *filter_r = filter;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi}
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomistatic int
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomifts_user_create_tokenizer(struct mail_user *user,
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi struct fts_tokenizer **tokenizer_r, bool search,
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi const char **error_r)
a327d9301f593433c228c4cc8cca05c95b37f6fbTimo Sirainen{
8a4a0ef8264d95ffb2ba8f6f109f94ea7f3454e8Timo Sirainen const struct fts_tokenizer *tokenizer_class;
d48e40d6c77d673ad402d96571198d1cce4da225Timo Sirainen struct fts_tokenizer *tokenizer = NULL, *parent = NULL;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *tokenizers_key, *const *tokenizers, *tokenizer_set_name;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *str, *error, *set_key;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen unsigned int i;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen int ret = 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen tokenizers_key = "fts_tokenizers";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen str = mail_user_plugin_getenv(user, tokenizers_key);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (str == NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen str = FTS_DEFAULT_TOKENIZERS;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen tokenizers = t_strsplit_spaces(str, " ");
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen for (i = 0; tokenizers[i] != NULL; i++) {
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen tokenizer_class = fts_tokenizer_find(tokenizers[i]);
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen if (tokenizer_class == NULL) {
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen *error_r = t_strdup_printf("%s: Unknown tokenizer '%s'",
2c5c70e12365d7910848259f88eb237ce3a15947Timo Sirainen tokenizers_key, tokenizers[i]);
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen ret = -1;
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen break;
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen }
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen tokenizer_set_name = t_str_replace(tokenizers[i], '-', '_');
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen set_key = t_strdup_printf("fts_tokenizers_%s", tokenizer_set_name);
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen str = mail_user_plugin_getenv(user, set_key);
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen /* tell the tokenizers that we're tokenizing a search string
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen (instead of tokenizing indexed data) */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (search)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen str = t_strconcat("search=yes ", str, NULL);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (fts_tokenizer_create(tokenizer_class, parent,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen str_keyvalues_to_array(str),
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen &tokenizer, &error) < 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *error_r = t_strdup_printf("%s: %s", set_key, error);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen ret = -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen break;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (parent != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fts_tokenizer_unref(&parent);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen parent = tokenizer;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (ret < 0) {
a618726eb3eb09a3866fe93208baf923d593f4d3Timo Sirainen if (parent != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fts_tokenizer_unref(&parent);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *tokenizer_r = tokenizer;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic int fts_user_init_tokenizers(struct mail_user *user,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct fts_user *fuser,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char **error_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (fts_user_create_tokenizer(user, &fuser->index_tokenizer, FALSE,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen error_r) < 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (fts_user_create_tokenizer(user, &fuser->search_tokenizer, TRUE,
a618726eb3eb09a3866fe93208baf923d593f4d3Timo Sirainen error_r) < 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstruct fts_user_language *
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenfts_user_language_find(struct mail_user *user,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const struct fts_language *lang)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct fts_user_language *const *user_langp;
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi struct fts_user *fuser = FTS_USER_CONTEXT(user);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen array_foreach(&fuser->languages, user_langp) {
a618726eb3eb09a3866fe93208baf923d593f4d3Timo Sirainen if (strcmp((*user_langp)->lang->name, lang->name) == 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return *user_langp;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch return NULL;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch}
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Boschstruct fts_tokenizer *fts_user_get_index_tokenizer(struct mail_user *user)
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch{
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch struct fts_user *fuser = FTS_USER_CONTEXT(user);
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch return fuser->index_tokenizer;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch}
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Boschstruct fts_tokenizer *fts_user_get_search_tokenizer(struct mail_user *user)
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch{
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch struct fts_user *fuser = FTS_USER_CONTEXT(user);
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch return fuser->search_tokenizer;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch}
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Boschstatic int fts_user_language_create(struct mail_user *user,
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch struct fts_user *fuser,
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch const struct fts_language *lang,
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch const char **error_r)
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch{
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch struct fts_filter *filter;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch struct fts_user_language *user_lang;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch if (fts_user_create_filters(user, lang, &filter, error_r) < 0)
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch return -1;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
4388ddff22681fc4385c963532b20c3560606667Stephan Bosch user_lang = p_new(user->pool, struct fts_user_language, 1);
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch user_lang->lang = lang;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch user_lang->filter = filter;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch array_append(&fuser->languages, &user_lang, 1);
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch return 0;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch}
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Boschstatic int fts_user_languages_fill_all(struct mail_user *user,
6793538c389d3e725456e3eabb697e2743233646Stephan Bosch struct fts_user *fuser,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char **error_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek const struct fts_language *const *langp;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen array_foreach(fts_language_list_get_all(fuser->lang_list), langp) {
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen if (fts_user_language_create(user, fuser, *langp, error_r) < 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstruct fts_language_list *fts_user_get_language_list(struct mail_user *user)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct fts_user *fuser = FTS_USER_CONTEXT(user);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return fuser->lang_list;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
4487c66123ca4830f8afbf4efcd7a260848d0e05Timo Sirainenconst ARRAY_TYPE(fts_user_language) *
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenfts_user_get_all_languages(struct mail_user *user)
4487c66123ca4830f8afbf4efcd7a260848d0e05Timo Sirainen{
4487c66123ca4830f8afbf4efcd7a260848d0e05Timo Sirainen struct fts_user *fuser = FTS_USER_CONTEXT(user);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return &fuser->languages;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
2c5c70e12365d7910848259f88eb237ce3a15947Timo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstruct fts_user_language *fts_user_get_data_lang(struct mail_user *user)
cb3ab2fd5668700a89b274a43595cfbfa1616e4bTimo Sirainen{
cb3ab2fd5668700a89b274a43595cfbfa1616e4bTimo Sirainen struct fts_user *fuser = FTS_USER_CONTEXT(user);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct fts_user_language *lang;
6793538c389d3e725456e3eabb697e2743233646Stephan Bosch const char *error;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (fuser->data_lang != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return fuser->data_lang;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen lang = p_new(user->pool, struct fts_user_language, 1);
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen lang->lang = &fts_language_data;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (fts_filter_create(fts_filter_lowercase, NULL, lang->lang, NULL,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen &lang->filter, &error) < 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_unreached();
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_assert(lang->filter != NULL);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fuser->data_lang = lang;
a2d962e729a1c162145b86b3b6a666ef0a139e52Timo Sirainen return fuser->data_lang;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch}
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipekstatic void fts_user_free(struct fts_user *fuser)
9a84b90d894a741ae6e090de104d31382a41d0aaJosef 'Jeff' Sipek{
9a84b90d894a741ae6e090de104d31382a41d0aaJosef 'Jeff' Sipek struct fts_user_language *const *user_langp;
9a84b90d894a741ae6e090de104d31382a41d0aaJosef 'Jeff' Sipek
9a84b90d894a741ae6e090de104d31382a41d0aaJosef 'Jeff' Sipek if (fuser->lang_list != NULL)
33a80622828063f5be6f743855d5273fabe8ae58Timo Sirainen fts_language_list_deinit(&fuser->lang_list);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen array_foreach(&fuser->languages, user_langp) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if ((*user_langp)->filter != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fts_filter_unref(&(*user_langp)->filter);
a618726eb3eb09a3866fe93208baf923d593f4d3Timo Sirainen }
a618726eb3eb09a3866fe93208baf923d593f4d3Timo Sirainen if (fuser->data_lang != NULL && fuser->data_lang->filter != NULL)
a618726eb3eb09a3866fe93208baf923d593f4d3Timo Sirainen fts_filter_unref(&fuser->data_lang->filter);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (fuser->index_tokenizer != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fts_tokenizer_unref(&fuser->index_tokenizer);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (fuser->search_tokenizer != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fts_tokenizer_unref(&fuser->search_tokenizer);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenint fts_mail_user_init(struct mail_user *user, const char **error_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
a238c6fede2022e5a4af707107ffb8f047b7753fTimo Sirainen struct fts_user *fuser;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fuser = p_new(user->pool, struct fts_user, 1);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen p_array_init(&fuser->languages, user->pool, 4);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (fts_user_init_languages(user, fuser, error_r) < 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fts_user_free(fuser);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (fts_user_languages_fill_all(user, fuser, error_r) < 0 ||
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fts_user_init_tokenizers(user, fuser, error_r) < 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fts_user_free(fuser);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen MODULE_CONTEXT_SET(user, fts_user_module, fuser);
48325adac125d7ff275ec69b05b7a92be9637630Timo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenvoid fts_mail_user_deinit(struct mail_user *user)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct fts_user *fuser = FTS_USER_CONTEXT(user);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (fuser != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fts_user_free(fuser);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen