bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen#include "lib.h"
5b6470e0e2ef4012430cdeca7d9b89c1278a0ed4Timo Sirainen#include "crc32.h"
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen#include "mail-storage-hooks.h"
64f30df0bee5218c9a69915e796d9d1376cfbf29Timo Sirainen#include "lucene-wrapper.h"
4ba3717a04823875c2a1d60ff9dc8177ae033d12Timo Sirainen#include "fts-user.h"
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen#include "fts-lucene-plugin.h"
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainenconst char *fts_lucene_plugin_version = DOVECOT_ABI_VERSION;
f6c1297c26b355c4aec2a08978f51ec3efecb351Timo Sirainen
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainenstruct fts_lucene_user_module fts_lucene_user_module =
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen MODULE_CONTEXT_INIT(&mail_user_module_register);
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainenstatic int
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainenfts_lucene_plugin_init_settings(struct mail_user *user,
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen struct fts_lucene_settings *set,
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen const char *str)
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen{
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen const char *const *tmp;
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen for (tmp = t_strsplit_spaces(str, " "); *tmp != NULL; tmp++) {
c37098f8ce6d512ba41f09564d04ed25720f0a77Timo Sirainen if (strncmp(*tmp, "default_language=", 17) == 0) {
c37098f8ce6d512ba41f09564d04ed25720f0a77Timo Sirainen set->default_language =
c37098f8ce6d512ba41f09564d04ed25720f0a77Timo Sirainen p_strdup(user->pool, *tmp + 17);
c37098f8ce6d512ba41f09564d04ed25720f0a77Timo Sirainen } else if (strncmp(*tmp, "textcat_conf=", 13) == 0) {
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen set->textcat_conf = p_strdup(user->pool, *tmp + 13);
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen } else if (strncmp(*tmp, "textcat_dir=", 12) == 0) {
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen set->textcat_dir = p_strdup(user->pool, *tmp + 12);
2e5d624013c30633e8ded148d338ce46c321a995Timo Sirainen } else if (strncmp(*tmp, "whitespace_chars=", 17) == 0) {
2e5d624013c30633e8ded148d338ce46c321a995Timo Sirainen set->whitespace_chars = p_strdup(user->pool, *tmp + 17);
88b9f9eb91da632d3e941fe4276f8ace03205b25Timo Sirainen } else if (strcmp(*tmp, "normalize") == 0) {
88b9f9eb91da632d3e941fe4276f8ace03205b25Timo Sirainen set->normalize = TRUE;
f26ef7a3a562dc42a1e9a4dde546bd30df3241e8Timo Sirainen } else if (strcmp(*tmp, "no_snowball") == 0) {
f26ef7a3a562dc42a1e9a4dde546bd30df3241e8Timo Sirainen set->no_snowball = TRUE;
57b523eeb99ed5d7f5002907a409cdef54353ce5Timo Sirainen } else if (strcmp(*tmp, "mime_parts") == 0) {
57b523eeb99ed5d7f5002907a409cdef54353ce5Timo Sirainen set->mime_parts = TRUE;
4f4daf7df84f450c7342de569bf25195e93d6bc7Timo Sirainen } else if (strcmp(*tmp, "use_libfts") == 0) {
4f4daf7df84f450c7342de569bf25195e93d6bc7Timo Sirainen set->use_libfts = TRUE;
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen } else {
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen i_error("fts_lucene: Invalid setting: %s", *tmp);
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen return -1;
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen }
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen }
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen if (set->textcat_conf != NULL && set->textcat_dir == NULL) {
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen i_error("fts_lucene: textcat_conf set, but textcat_dir unset");
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen return -1;
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen }
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen if (set->textcat_conf == NULL && set->textcat_dir != NULL) {
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen i_error("fts_lucene: textcat_dir set, but textcat_conf unset");
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen return -1;
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen }
2e5d624013c30633e8ded148d338ce46c321a995Timo Sirainen if (set->whitespace_chars == NULL)
2e5d624013c30633e8ded148d338ce46c321a995Timo Sirainen set->whitespace_chars = "";
db9ad8c821c01a18a520c2a07b2d6dc501b4017aTimo Sirainen#ifndef HAVE_FTS_STEMMER
c37098f8ce6d512ba41f09564d04ed25720f0a77Timo Sirainen if (set->default_language != NULL) {
c37098f8ce6d512ba41f09564d04ed25720f0a77Timo Sirainen i_error("fts_lucene: default_language set, "
c37098f8ce6d512ba41f09564d04ed25720f0a77Timo Sirainen "but Dovecot built without stemmer support");
c37098f8ce6d512ba41f09564d04ed25720f0a77Timo Sirainen return -1;
c37098f8ce6d512ba41f09564d04ed25720f0a77Timo Sirainen }
57a712a4998e4bb0073080232225380cd2cea625Timo Sirainen#else
57a712a4998e4bb0073080232225380cd2cea625Timo Sirainen if (set->default_language == NULL)
57a712a4998e4bb0073080232225380cd2cea625Timo Sirainen set->default_language = "english";
c37098f8ce6d512ba41f09564d04ed25720f0a77Timo Sirainen#endif
db9ad8c821c01a18a520c2a07b2d6dc501b4017aTimo Sirainen#ifndef HAVE_FTS_TEXTCAT
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen if (set->textcat_conf != NULL) {
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen i_error("fts_lucene: textcat_dir set, "
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen "but Dovecot built without textcat support");
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen return -1;
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen }
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen#endif
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen return 0;
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen}
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen
5b6470e0e2ef4012430cdeca7d9b89c1278a0ed4Timo Sirainenuint32_t fts_lucene_settings_checksum(const struct fts_lucene_settings *set)
5b6470e0e2ef4012430cdeca7d9b89c1278a0ed4Timo Sirainen{
2e5d624013c30633e8ded148d338ce46c321a995Timo Sirainen uint32_t crc;
2e5d624013c30633e8ded148d338ce46c321a995Timo Sirainen
4f4daf7df84f450c7342de569bf25195e93d6bc7Timo Sirainen if (set->use_libfts)
4f4daf7df84f450c7342de569bf25195e93d6bc7Timo Sirainen return crc32_str("l");
4f4daf7df84f450c7342de569bf25195e93d6bc7Timo Sirainen
bfcca12a441275b7f4cd510b95669b163263b2e7Timo Sirainen /* checksum is always different when compiling with/without stemmer */
bfcca12a441275b7f4cd510b95669b163263b2e7Timo Sirainen crc = set->default_language == NULL ? 0 :
bfcca12a441275b7f4cd510b95669b163263b2e7Timo Sirainen crc32_str(set->default_language);
2e5d624013c30633e8ded148d338ce46c321a995Timo Sirainen crc = crc32_str_more(crc, set->whitespace_chars);
88b9f9eb91da632d3e941fe4276f8ace03205b25Timo Sirainen if (set->normalize)
88b9f9eb91da632d3e941fe4276f8ace03205b25Timo Sirainen crc = crc32_str_more(crc, "n");
f26ef7a3a562dc42a1e9a4dde546bd30df3241e8Timo Sirainen if (set->no_snowball)
f26ef7a3a562dc42a1e9a4dde546bd30df3241e8Timo Sirainen crc = crc32_str_more(crc, "s");
57b523eeb99ed5d7f5002907a409cdef54353ce5Timo Sirainen /* don't include mime_parts here, since changing it doesn't
57b523eeb99ed5d7f5002907a409cdef54353ce5Timo Sirainen necessarily need the index to be rebuilt */
2e5d624013c30633e8ded148d338ce46c321a995Timo Sirainen return crc;
5b6470e0e2ef4012430cdeca7d9b89c1278a0ed4Timo Sirainen}
5b6470e0e2ef4012430cdeca7d9b89c1278a0ed4Timo Sirainen
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainenstatic void fts_lucene_mail_user_deinit(struct mail_user *user)
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen{
a220c655b1a3d923713afe8b83641c1050b44dbaAki Tuomi struct fts_lucene_user *fuser = FTS_LUCENE_USER_CONTEXT_REQUIRE(user);
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen
6634e45500e81cfa36932203ee69c81745efd3e6Timo Sirainen if (fuser->set.use_libfts)
6634e45500e81cfa36932203ee69c81745efd3e6Timo Sirainen fts_mail_user_deinit(user);
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen fuser->module_ctx.super.deinit(user);
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen}
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen
5b6470e0e2ef4012430cdeca7d9b89c1278a0ed4Timo Sirainenstatic void fts_lucene_mail_user_created(struct mail_user *user)
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen{
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen struct mail_user_vfuncs *v = user->vlast;
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen struct fts_lucene_user *fuser;
4ba3717a04823875c2a1d60ff9dc8177ae033d12Timo Sirainen const char *env, *error;
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen fuser = p_new(user->pool, struct fts_lucene_user, 1);
5b6470e0e2ef4012430cdeca7d9b89c1278a0ed4Timo Sirainen env = mail_user_plugin_getenv(user, "fts_lucene");
5b6470e0e2ef4012430cdeca7d9b89c1278a0ed4Timo Sirainen if (env == NULL)
5b6470e0e2ef4012430cdeca7d9b89c1278a0ed4Timo Sirainen env = "";
5b6470e0e2ef4012430cdeca7d9b89c1278a0ed4Timo Sirainen
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen if (fts_lucene_plugin_init_settings(user, &fuser->set, env) < 0) {
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen /* invalid settings, disabling */
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen return;
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen }
4ba3717a04823875c2a1d60ff9dc8177ae033d12Timo Sirainen if (fuser->set.use_libfts) {
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen if (fts_mail_user_init(user, &error) < 0) {
4ba3717a04823875c2a1d60ff9dc8177ae033d12Timo Sirainen i_error("fts_lucene: %s", error);
4ba3717a04823875c2a1d60ff9dc8177ae033d12Timo Sirainen return;
4ba3717a04823875c2a1d60ff9dc8177ae033d12Timo Sirainen }
4ba3717a04823875c2a1d60ff9dc8177ae033d12Timo Sirainen }
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen fuser->module_ctx.super = *v;
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen user->vlast = &fuser->module_ctx.super;
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen v->deinit = fts_lucene_mail_user_deinit;
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen MODULE_CONTEXT_SET(user, fts_lucene_user_module, fuser);
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen}
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainenstatic struct mail_storage_hooks fts_lucene_mail_storage_hooks = {
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen .mail_user_created = fts_lucene_mail_user_created
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen};
6380f2bc729a03b328793e8ad6ba7587620fa184Timo Sirainen
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainenvoid fts_lucene_plugin_init(struct module *module ATTR_UNUSED)
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen{
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen fts_backend_register(&fts_backend_lucene);
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen mail_storage_hooks_add(module, &fts_lucene_mail_storage_hooks);
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen}
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainenvoid fts_lucene_plugin_deinit(void)
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen{
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen fts_backend_unregister(fts_backend_lucene.name);
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen mail_storage_hooks_remove(&fts_lucene_mail_storage_hooks);
64f30df0bee5218c9a69915e796d9d1376cfbf29Timo Sirainen lucene_shutdown();
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen}
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainenconst char *fts_lucene_plugin_dependencies[] = { "fts", NULL };