bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenstatic ARRAY(const struct fts_backend *) backends;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenvoid fts_backend_register(const struct fts_backend *backend)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen for (i = 0; i < count; i++) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen i_panic("fts_backend_unregister(%s): unknown backend", name);
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainenstatic const struct fts_backend *
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainenfts_backend_class_lookup(const char *backend_name)
c63544d7d2580c680b07f9569e87e9cebee383d5Timo Sirainen for (i = 0; i < count; i++) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_init(const char *backend_name, struct mail_namespace *ns,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char **error_r, struct fts_backend **backend_r)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenvoid fts_backend_deinit(struct fts_backend **_backend)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_get_last_uid(struct fts_backend *backend, struct mailbox *box,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* virtual mailboxes themselves don't have any indexes,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen so catch this call here */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return backend->v.get_last_uid(backend, box, last_uid_r);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_backend_is_updating(struct fts_backend *backend)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenfts_backend_update_init(struct fts_backend *backend)
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen if ((backend->flags & FTS_BACKEND_FLAG_NORMALIZE_INPUT) != 0)
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen ctx->normalizer = backend->ns->user->default_normalizer;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void fts_backend_set_cur_mailbox(struct fts_backend_update_context *ctx)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->backend->v.update_set_mailbox(ctx, ctx->cur_box);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_update_deinit(struct fts_backend_update_context **_ctx)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_backend_update_context *ctx = *_ctx;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid fts_backend_update_set_mailbox(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ctx->backend_box != NULL && box != ctx->backend_box) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* make sure we don't reference the backend box anymore */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->backend->v.update_set_mailbox(ctx, NULL);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid fts_backend_update_expunge(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_backend_update_set_build_key(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!ctx->backend->v.update_set_build_key(ctx, key))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid fts_backend_update_unset_build_key(struct fts_backend_update_context *ctx)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_update_build_more(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return ctx->backend->v.update_build_more(ctx, data, size);
de11cf486e0d0448537b1b5d546496ab85e7cda8Timo Sirainenint fts_backend_refresh(struct fts_backend *backend)
263d455e9198e8aa45c7a99601ad6a5a9dcdd915Timo Sirainenint fts_backend_reset_last_uids(struct fts_backend *backend)
263d455e9198e8aa45c7a99601ad6a5a9dcdd915Timo Sirainen iter = mailbox_list_iter_init(backend->ns->list, "*",
263d455e9198e8aa45c7a99601ad6a5a9dcdd915Timo Sirainen while ((info = mailbox_list_iter_next(iter)) != NULL) {
263d455e9198e8aa45c7a99601ad6a5a9dcdd915Timo Sirainen (MAILBOX_NONEXISTENT | MAILBOX_NOSELECT)) != 0)
263d455e9198e8aa45c7a99601ad6a5a9dcdd915Timo Sirainen box = mailbox_alloc(info->ns->list, info->vname, 0);
a569c6df4ffe05acc242e269d926449e50702d59Timo Sirainenint fts_backend_rescan(struct fts_backend *backend)
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen box = mailbox_alloc(backend->ns->list, "", 0);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen virtual_storage = box->virtual_vfuncs != NULL;
263d455e9198e8aa45c7a99601ad6a5a9dcdd915Timo Sirainen /* just reset the last-uids for a virtual storage. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_optimize(struct fts_backend *backend)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenfts_merge_maybies(ARRAY_TYPE(seq_range) *dest_maybe,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* add/leave to dest_maybe if at least one list has maybe,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen and no lists have none */
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen /* create unwanted sequences list from both sources */
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen new_range.seq1 = 0; new_range.seq2 = (uint32_t)-1;
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen seq_range_array_remove_seq_range(&src_unwanted, src_maybe);
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen seq_range_array_remove_seq_range(&src_unwanted, src_definite);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* drop unwanted uids */
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen seq_range_array_remove_seq_range(dest_maybe, &src_unwanted);
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen /* add uids that are in dest_definite and src_maybe lists */
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen for (i = 0; i < count; i++) {
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen for (seq = range[i].seq1; seq <= range[i].seq2; seq++) {
809923ba26218971792182ae8894936f9ac99364Timo Sirainenvoid fts_filter_uids(ARRAY_TYPE(seq_range) *definite_dest,
809923ba26218971792182ae8894936f9ac99364Timo Sirainen /* keep only what exists in both lists. the rest is in
809923ba26218971792182ae8894936f9ac99364Timo Sirainen maybies or not wanted */
809923ba26218971792182ae8894936f9ac99364Timo Sirainen seq_range_array_intersect(definite_dest, definite_filter);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_backend_default_can_lookup(struct fts_backend *backend,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_backend_can_lookup(struct fts_backend *backend,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic int fts_score_map_sort(const struct fts_score_map *m1,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_lookup(struct fts_backend *backend, struct mailbox *box,
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen if (backend->v.lookup(backend, box, args, flags, result) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!result->scores_sorted && array_is_created(&result->scores)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_sort(&result->scores, fts_score_map_sort);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_lookup_multi(struct fts_backend *backend,
2022c259052c6cbb595cc90d36c0d4bdbf5254b6Timo Sirainen unsigned int i;
f3bed8816ef2842845b8bf1714a9458dd47460d0Timo Sirainen if (backend->v.lookup_multi(backend, boxes, args,
2022c259052c6cbb595cc90d36c0d4bdbf5254b6Timo Sirainen result->box_results = p_new(result->pool, struct fts_result, i+1);
db0fb9eb7da6059fa1af1e5429c898c81bdc2aa9Timo Sirainen struct fts_result *box_result = &result->box_results[i];
db0fb9eb7da6059fa1af1e5429c898c81bdc2aa9Timo Sirainen p_array_init(&box_result->definite_uids, result->pool, 32);
db0fb9eb7da6059fa1af1e5429c898c81bdc2aa9Timo Sirainen p_array_init(&box_result->maybe_uids, result->pool, 32);
db0fb9eb7da6059fa1af1e5429c898c81bdc2aa9Timo Sirainen p_array_init(&box_result->scores, result->pool, 32);
2022c259052c6cbb595cc90d36c0d4bdbf5254b6Timo Sirainen if (backend->v.lookup(backend, boxes[i], args,
b7fdf4fe23801de680e0be5aca0596a3c9ea3f8fTimo Sirainenvoid fts_backend_lookup_done(struct fts_backend *backend)
54d437dea655b338e45a8917880f3d3a2a7b698dTimo Sirainenstatic uint32_t fts_index_get_ext_id(struct mailbox *box)
54d437dea655b338e45a8917880f3d3a2a7b698dTimo Sirainen return mail_index_ext_register(box->index, "fts",
54d437dea655b338e45a8917880f3d3a2a7b698dTimo Sirainenbool fts_index_get_header(struct mailbox *box, struct fts_index_header *hdr_r)
54d437dea655b338e45a8917880f3d3a2a7b698dTimo Sirainen mail_index_get_header_ext(view, fts_index_get_ext_id(box),
54d437dea655b338e45a8917880f3d3a2a7b698dTimo Sirainen trans = mail_index_transaction_begin(box->view, 0);
54d437dea655b338e45a8917880f3d3a2a7b698dTimo Sirainen mail_index_update_header_ext(trans, ext_id, 0, hdr, sizeof(*hdr));
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_index_set_last_uid(struct mailbox *box, uint32_t last_uid)
54d437dea655b338e45a8917880f3d3a2a7b698dTimo Sirainenint fts_index_have_compatible_settings(struct mailbox_list *list,
96da164ade36c54e94083de1a545216ebc2afa31Timo Sirainen struct mail_namespace *ns = mailbox_list_get_namespace(list);
96da164ade36c54e94083de1a545216ebc2afa31Timo Sirainen if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0)
96da164ade36c54e94083de1a545216ebc2afa31Timo Sirainen if (len > 0 && ns->prefix[len-1] == mail_namespace_get_sep(ns))
54d437dea655b338e45a8917880f3d3a2a7b698dTimo Sirainen if (mailbox_sync(box, (enum mailbox_sync_flags)0) < 0) {
b8673ed3de3d1931ea5319c7557b72235cfe31feTimo Sirainen i_error("fts: Failed to sync mailbox %s: %s", vname,
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_last_internal_error(box, NULL));
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_header_want_indexed(const char *hdr_name)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unsigned int i;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (i = 0; i < N_ELEMENTS(indexed_headers); i++) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (strcasecmp(hdr_name, indexed_headers[i]) == 0)
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainenbool fts_header_has_language(const char *hdr_name)
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainen /* FIXME: should email address headers be detected as different
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainen languages? That mainly contains people's names.. */
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainen /*if (message_header_is_address(hdr_name))
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainen return TRUE;*/
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainen /* Subject definitely contains language-specific data that can be
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainen detected. Comment and Keywords headers also could contain, although
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainen just about nobody uses those headers.
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainen For now we assume that other headers contain non-language specific
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainen data that we don't want to filter in special ways. For example
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainen it is good to be able to search for Message-IDs. */
4ac43ad128cb9b22f1c936659a1ff62e5b6c8bc3Timo Sirainen return strcasecmp(hdr_name, "Subject") == 0 ||
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_mailbox_get_guid(struct mailbox *box, const char **guid_r)