bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen#include "lib.h"
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen#include "str.h"
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen#include "imap-util.h"
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen#include "mail-namespace.h"
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen#include "mail-search.h"
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen#include "mailbox-list-iter.h"
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen#include "fts-tokenizer.h"
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen#include "fts-filter.h"
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen#include "fts-language.h"
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen#include "fts-storage.h"
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen#include "fts-search-args.h"
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen#include "fts-user.h"
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen#include "doveadm-print.h"
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen#include "doveadm-mail.h"
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen#include "doveadm-mailbox-list-iter.h"
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen#include "doveadm-fts.h"
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainenconst char *doveadm_fts_plugin_version = DOVECOT_ABI_VERSION;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainenstruct fts_tokenize_cmd_context {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen struct doveadm_mail_cmd_context ctx;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen const char *language;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen const char *tokens;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen};
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainenstatic int
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainencmd_search_box(struct doveadm_mail_cmd_context *ctx,
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen const struct mailbox_info *info)
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen{
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen struct mailbox *box;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen struct fts_backend *backend;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen struct fts_result result;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen int ret = 0;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen backend = fts_list_backend(info->ns->list);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen if (backend == NULL) {
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen i_error("fts not enabled for %s", info->vname);
7c38d250253a668152475879a179438c07dc690dTimo Sirainen ctx->exit_code = EX_CONFIG;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen return -1;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen }
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&result);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen i_array_init(&result.definite_uids, 16);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen i_array_init(&result.maybe_uids, 16);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen i_array_init(&result.scores, 16);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen box = mailbox_alloc(info->ns->list, info->vname, 0);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen if (fts_backend_lookup(backend, box, ctx->search_args->args,
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen FTS_LOOKUP_FLAG_AND_ARGS, &result) < 0) {
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen i_error("fts lookup failed");
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen doveadm_mail_failed_error(ctx, MAIL_ERROR_TEMP);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen ret = -1;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen } else {
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen printf("%s: ", info->vname);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen if (array_count(&result.definite_uids) == 0)
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen printf("no results\n");
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen else T_BEGIN {
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen string_t *str = t_str_new(128);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen imap_write_seq_range(str, &result.definite_uids);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen printf("%s\n", str_c(str));
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen } T_END;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen if (array_count(&result.maybe_uids) > 0) T_BEGIN {
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen string_t *str = t_str_new(128);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen imap_write_seq_range(str, &result.maybe_uids);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen printf(" - maybe: %s\n", str_c(str));
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen } T_END;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen fts_backend_lookup_done(backend);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen }
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen mailbox_free(&box);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen array_free(&result.definite_uids);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen array_free(&result.maybe_uids);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen array_free(&result.scores);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen return ret;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen}
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainenstatic int
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainencmd_fts_lookup_run(struct doveadm_mail_cmd_context *ctx,
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen struct mail_user *user)
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen{
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen const enum mailbox_list_iter_flags iter_flags =
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen MAILBOX_LIST_ITER_NO_AUTO_BOXES |
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen struct doveadm_mailbox_list_iter *iter;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen const struct mailbox_info *info;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen int ret = 0;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen iter = doveadm_mailbox_list_iter_init(ctx, user, ctx->search_args,
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen iter_flags);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) T_BEGIN {
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen if (cmd_search_box(ctx, info) < 0)
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen ret = -1;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen } T_END;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen if (doveadm_mailbox_list_iter_deinit(&iter) < 0)
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen ret = -1;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen return ret;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen}
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainenstatic void
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainencmd_fts_lookup_init(struct doveadm_mail_cmd_context *ctx,
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen const char *const args[])
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen{
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen if (args[0] == NULL)
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen doveadm_mail_help_name("fts lookup");
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen ctx->search_args = doveadm_mail_build_search_args(args);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen}
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainenstatic struct doveadm_mail_cmd_context *
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainencmd_fts_lookup_alloc(void)
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen{
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen struct doveadm_mail_cmd_context *ctx;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen ctx->v.run = cmd_fts_lookup_run;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen ctx->v.init = cmd_fts_lookup_init;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen return ctx;
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen}
2e3e24888f9ce3da3116ee1d6a60f42394b6026cTimo Sirainen
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainenstatic int
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainencmd_fts_expand_run(struct doveadm_mail_cmd_context *ctx,
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen struct mail_user *user)
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen{
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen struct mail_namespace *ns = mail_namespace_find_inbox(user->namespaces);
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen struct mailbox *box;
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen struct fts_backend *backend;
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen string_t *str = t_str_new(128);
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen backend = fts_list_backend(ns->list);
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen if (backend == NULL) {
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen i_error("fts not enabled for INBOX");
7c38d250253a668152475879a179438c07dc690dTimo Sirainen ctx->exit_code = EX_CONFIG;
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen return -1;
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen }
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen box = mailbox_alloc(ns->list, "INBOX", 0);
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen mail_search_args_init(ctx->search_args, box, FALSE, NULL);
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen if (fts_search_args_expand(backend, ctx->search_args) < 0)
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen i_fatal("Couldn't expand search args");
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen mail_search_args_to_cmdline(str, ctx->search_args->args);
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen printf("%s\n", str_c(str));
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen mailbox_free(&box);
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen return 0;
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen}
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainenstatic void
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainencmd_fts_expand_init(struct doveadm_mail_cmd_context *ctx,
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen const char *const args[])
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen{
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen if (args[0] == NULL)
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen doveadm_mail_help_name("fts expand");
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen ctx->search_args = doveadm_mail_build_search_args(args);
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen}
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainenstatic struct doveadm_mail_cmd_context *
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainencmd_fts_expand_alloc(void)
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen{
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen struct doveadm_mail_cmd_context *ctx;
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen ctx->v.run = cmd_fts_expand_run;
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen ctx->v.init = cmd_fts_expand_init;
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen return ctx;
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen}
be1126eef34743095ddbee3fecbafe0574d54eacTimo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainenstatic int
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainencmd_fts_tokenize_run(struct doveadm_mail_cmd_context *_ctx,
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen struct mail_user *user)
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen{
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen struct fts_tokenize_cmd_context *ctx =
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen (struct fts_tokenize_cmd_context *)_ctx;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen struct mail_namespace *ns = mail_namespace_find_inbox(user->namespaces);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen struct fts_backend *backend;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen struct fts_user_language *user_lang;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen const struct fts_language *lang = NULL;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen int ret, ret2;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen bool final = FALSE;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen backend = fts_list_backend(ns->list);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (backend == NULL) {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen i_error("fts not enabled for INBOX");
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen _ctx->exit_code = EX_CONFIG;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen return -1;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen }
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (ctx->language == NULL) {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen struct fts_language_list *lang_list =
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen fts_user_get_language_list(user);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen enum fts_language_result result;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen result = fts_language_detect(lang_list,
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen (const unsigned char *)ctx->tokens, strlen(ctx->tokens),
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen &lang);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (lang == NULL)
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen lang = fts_language_list_get_first(lang_list);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen switch (result) {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen case FTS_LANGUAGE_RESULT_SHORT:
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen i_warning("Text too short, can't detect its language - assuming %s", lang->name);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen break;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen case FTS_LANGUAGE_RESULT_UNKNOWN:
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen i_warning("Can't detect its language - assuming %s", lang->name);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen break;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen case FTS_LANGUAGE_RESULT_OK:
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen break;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen case FTS_LANGUAGE_RESULT_ERROR:
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen i_error("Language detection library initialization failed");
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen _ctx->exit_code = EX_CONFIG;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen return -1;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen default:
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen i_unreached();
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen }
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen } else {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen lang = fts_language_find(ctx->language);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (lang == NULL) {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen i_error("Unknown language: %s", ctx->language);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen _ctx->exit_code = EX_USAGE;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen return -1;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen }
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen }
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen user_lang = fts_user_language_find(user, lang);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (user_lang == NULL) {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen i_error("Language not enabled for user: %s", ctx->language);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen _ctx->exit_code = EX_USAGE;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen return -1;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen }
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen fts_tokenizer_reset(user_lang->index_tokenizer);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen for (;;) {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen const char *token, *error;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (!final) {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen ret = fts_tokenizer_next(user_lang->index_tokenizer,
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen (const unsigned char *)ctx->tokens, strlen(ctx->tokens),
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen &token, &error);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen } else {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen ret = fts_tokenizer_final(user_lang->index_tokenizer,
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen &token, &error);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen }
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (ret < 0)
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen break;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (ret > 0 && user_lang->filter != NULL) {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen ret2 = fts_filter_filter(user_lang->filter, &token, &error);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (ret2 > 0)
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen doveadm_print(token);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen else if (ret2 < 0)
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen i_error("Couldn't create indexable tokens: %s", error);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen }
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (ret == 0) {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (final)
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen break;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen final = TRUE;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen }
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen }
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen return 0;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen}
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainenstatic void
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainencmd_fts_tokenize_init(struct doveadm_mail_cmd_context *_ctx,
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen const char *const args[])
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen{
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen struct fts_tokenize_cmd_context *ctx =
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen (struct fts_tokenize_cmd_context *)_ctx;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen if (args[0] == NULL)
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen doveadm_mail_help_name("fts tokenize");
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen ctx->tokens = p_strdup(_ctx->pool, t_strarray_join(args, " "));
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen doveadm_print_header("token", "token", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen}
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainenstatic bool
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainencmd_fts_tokenize_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen{
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen struct fts_tokenize_cmd_context *ctx =
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen (struct fts_tokenize_cmd_context *)_ctx;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen switch (c) {
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen case 'l':
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen ctx->language = p_strdup(_ctx->pool, optarg);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen break;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen default:
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen return FALSE;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen }
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen return TRUE;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen}
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainenstatic struct doveadm_mail_cmd_context *
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainencmd_fts_tokenize_alloc(void)
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen{
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen struct fts_tokenize_cmd_context *ctx;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct fts_tokenize_cmd_context);
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen ctx->ctx.v.run = cmd_fts_tokenize_run;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen ctx->ctx.v.init = cmd_fts_tokenize_init;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen ctx->ctx.v.parse_arg = cmd_fts_tokenize_parse_arg;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen ctx->ctx.getopt_args = "l";
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen return &ctx->ctx;
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen}
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainenstatic int
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainenfts_namespace_find(struct mail_user *user, const char *ns_prefix,
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen struct mail_namespace **ns_r)
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen{
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen struct mail_namespace *ns;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen if (ns_prefix == NULL)
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen ns = mail_namespace_find_inbox(user->namespaces);
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen else {
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen ns = mail_namespace_find_prefix(user->namespaces, ns_prefix);
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen if (ns == NULL) {
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen i_error("Namespace prefix not found: %s", ns_prefix);
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen return -1;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen }
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen }
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen if (fts_list_backend(ns->list) == NULL) {
0226f0f9198bf7d5897e8473e58aa72ae1a72e39Timo Sirainen i_error("fts not enabled for user's namespace %s",
0226f0f9198bf7d5897e8473e58aa72ae1a72e39Timo Sirainen ns_prefix != NULL ? ns_prefix : "INBOX");
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen return -1;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen }
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen *ns_r = ns;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen return 0;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen}
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainenstatic int
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainencmd_fts_optimize_run(struct doveadm_mail_cmd_context *ctx,
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen struct mail_user *user)
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen{
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen const char *ns_prefix = ctx->args[0];
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen struct mail_namespace *ns;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen struct fts_backend *backend;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (fts_namespace_find(user, ns_prefix, &ns) < 0) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_mail_failed_error(ctx, MAIL_ERROR_NOTFOUND);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return -1;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen backend = fts_list_backend(ns->list);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (fts_backend_optimize(backend) < 0) {
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen i_error("fts optimize failed");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_mail_failed_error(ctx, MAIL_ERROR_TEMP);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return -1;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return 0;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen}
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainenstatic void
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainencmd_fts_optimize_init(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen const char *const args[])
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen{
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen if (str_array_length(args) > 1)
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen doveadm_mail_help_name("fts optimize");
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen}
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainenstatic struct doveadm_mail_cmd_context *
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainencmd_fts_optimize_alloc(void)
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen{
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen struct doveadm_mail_cmd_context *ctx;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen ctx->v.run = cmd_fts_optimize_run;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen ctx->v.init = cmd_fts_optimize_init;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen return ctx;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen}
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainenstatic int
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainencmd_fts_rescan_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user)
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen{
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen const char *ns_prefix = ctx->args[0];
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen struct mail_namespace *ns;
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen struct fts_backend *backend;
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (fts_namespace_find(user, ns_prefix, &ns) < 0) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_mail_failed_error(ctx, MAIL_ERROR_NOTFOUND);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return -1;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen backend = fts_list_backend(ns->list);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (fts_backend_rescan(backend) < 0) {
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen i_error("fts rescan failed");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_mail_failed_error(ctx, MAIL_ERROR_TEMP);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return -1;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return 0;
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen}
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainenstatic void
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainencmd_fts_rescan_init(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen const char *const args[])
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen{
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen if (str_array_length(args) > 1)
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen doveadm_mail_help_name("fts rescan");
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen}
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainenstatic struct doveadm_mail_cmd_context *
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainencmd_fts_rescan_alloc(void)
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen{
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen struct doveadm_mail_cmd_context *ctx;
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen ctx->v.run = cmd_fts_rescan_run;
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen ctx->v.init = cmd_fts_rescan_init;
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen return ctx;
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen}
3dfa8c707590b8a37a99095dc617d0b4eac3cf87Timo Sirainen
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomistatic struct doveadm_cmd_ver2 fts_commands[] = {
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi{
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .name = "fts lookup",
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .mail_cmd = cmd_fts_lookup_alloc,
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<search query>",
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAMS_START
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_MAIL_COMMON
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAMS_END
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi},
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi{
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .name = "fts expand",
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .mail_cmd = cmd_fts_expand_alloc,
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<search query>",
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAMS_START
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_MAIL_COMMON
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAMS_END
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi},
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen{
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen .name = "fts tokenize",
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen .mail_cmd = cmd_fts_tokenize_alloc,
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<text>",
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo SirainenDOVEADM_CMD_PARAMS_START
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo SirainenDOVEADM_CMD_MAIL_COMMON
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo SirainenDOVEADM_CMD_PARAM('l', "language", CMD_PARAM_STR, 0)
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo SirainenDOVEADM_CMD_PARAM('\0', "text", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo SirainenDOVEADM_CMD_PARAMS_END
78d33b52c5b738bd9f20fe5ffcd05dd754284ba6Timo Sirainen},
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi{
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .name = "fts optimize",
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .mail_cmd = cmd_fts_optimize_alloc,
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "[<namespace>]",
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAMS_START
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_MAIL_COMMON
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAM('\0', "namespace", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAMS_END
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi},
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi{
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .name = "fts rescan",
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .mail_cmd = cmd_fts_rescan_alloc,
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "[<namespace>]",
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAMS_START
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_MAIL_COMMON
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAM('\0', "namespace", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki TuomiDOVEADM_CMD_PARAMS_END
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi},
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen};
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainenvoid doveadm_fts_plugin_init(struct module *module ATTR_UNUSED)
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen{
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen unsigned int i;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen for (i = 0; i < N_ELEMENTS(fts_commands); i++)
e47f08b87b409b42acf353c3156c21e1ccc35ac4Aki Tuomi doveadm_cmd_register_ver2(&fts_commands[i]);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen doveadm_dump_fts_expunge_log_init();
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen}
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainenvoid doveadm_fts_plugin_deinit(void)
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen{
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen}