static void fts_backend_solr_update_set_mailbox(struct fts_backend_update_context *_ctx, struct mailbox *box) { struct solr_fts_backend_update_context *ctx = (struct solr_fts_backend_update_context *)_ctx; struct mailbox_status status; struct mail_namespace *ns; if (ctx->prev_uid != 0) { fts_index_set_last_uid(ctx->cur_box, ctx->prev_uid); ctx->prev_uid = 0; } ctx->cur_box = box; ctx->uid_validity = 0; i_free_and_null(ctx->id_box_name); if (box != NULL) { ctx->id_box_name = i_strdup(fts_box_get_root(box, &ns)); mailbox_get_open_status(box, STATUS_UIDVALIDITY, &status); ctx->uid_validity = status.uidvalidity; } }
int fts_indexer_init(struct fts_backend *backend, struct mailbox *box, struct fts_indexer_context **ctx_r) { struct fts_indexer_context *ctx; struct mailbox_status status; uint32_t last_uid, seq1, seq2; const char *path, *cmd, *value, *error; int fd; if (fts_backend_get_last_uid(backend, box, &last_uid) < 0) return -1; mailbox_get_open_status(box, STATUS_UIDNEXT, &status); if (status.uidnext == last_uid+1) { /* everything is already indexed */ return 0; } mailbox_get_seq_range(box, last_uid+1, (uint32_t)-1, &seq1, &seq2); if (seq1 == 0) { /* no new messages (last messages in mailbox were expunged) */ return 0; } cmd = t_strdup_printf("PREPEND\t1\t%s\t%s\t0\t%s\n", str_tabescape(box->storage->user->username), str_tabescape(box->vname), str_tabescape(box->storage->user->session_id)); fd = fts_indexer_cmd(box->storage->user, cmd, &path); if (fd == -1) return -1; /* connect to indexer and request immediate indexing of the mailbox */ ctx = i_new(struct fts_indexer_context, 1); ctx->box = box; ctx->path = i_strdup(path); ctx->fd = fd; ctx->input = i_stream_create_fd(fd, 128, FALSE); ctx->search_start_time = ioloop_timeval; value = mail_user_plugin_getenv(box->storage->user, "fts_index_timeout"); if (value != NULL) { if (settings_get_time(value, &ctx->timeout_secs, &error) < 0) i_error("Invalid fts_index_timeout setting: %s", error); } *ctx_r = ctx; return 1; }
static int fts_backend_solr_get_last_uid_fallback(struct solr_fts_backend *backend, struct mailbox *box, uint32_t *last_uid_r) { struct mail_namespace *ns; struct mailbox_status status; struct solr_result **results; const struct seq_range *uidvals; const char *box_name; unsigned int count; string_t *str; pool_t pool; int ret = 0; str = t_str_new(256); str_append(str, "fl=uid&rows=1&sort=uid+desc&q="); box_name = fts_box_get_root(box, &ns); mailbox_get_open_status(box, STATUS_UIDVALIDITY, &status); str_printfa(str, "uidv:%u+AND+box:", status.uidvalidity); solr_quote_http(str, box_name); solr_add_ns_query_http(str, backend, ns); str_append(str, "+AND+user:"******"solr last uid lookup", 1024); if (solr_connection_select(backend->solr_conn, str_c(str), pool, &results) < 0) ret = -1; else if (results[0] == NULL) { /* no UIDs */ *last_uid_r = 0; } else { uidvals = array_get(&results[0]->uids, &count); i_assert(count > 0); if (count == 1 && uidvals[0].seq1 == uidvals[0].seq2) { *last_uid_r = uidvals[0].seq1; } else { i_error("fts_solr: Last UID lookup returned multiple rows"); ret = -1; } } pool_unref(&pool); return ret; }
int imap_msgpart_url_open_mailbox(struct imap_msgpart_url *mpurl, struct mailbox **box_r, enum mail_error *error_code_r, const char **error_r) { struct mailbox_status box_status; enum mailbox_flags flags = MAILBOX_FLAG_READONLY; struct mail_namespace *ns; struct mailbox *box; if (mpurl->box != NULL) { *box_r = mpurl->box; *error_code_r = MAIL_ERROR_NONE; return 1; } /* find mailbox namespace */ ns = mail_namespace_find(mpurl->user->namespaces, mpurl->mailbox); /* open mailbox */ if (mpurl->selected_box != NULL && mailbox_equals(mpurl->selected_box, ns, mpurl->mailbox)) box = mpurl->selected_box; else box = mailbox_alloc(ns->list, mpurl->mailbox, flags); if (mailbox_open(box) < 0) { *error_r = mail_storage_get_last_error(mailbox_get_storage(box), error_code_r); if (box != mpurl->selected_box) mailbox_free(&box); return *error_code_r == MAIL_ERROR_TEMP ? -1 : 0; } /* verify UIDVALIDITY */ mailbox_get_open_status(box, STATUS_UIDVALIDITY, &box_status); if (mpurl->uidvalidity > 0 && box_status.uidvalidity != mpurl->uidvalidity) { *error_r = "Invalid UIDVALIDITY"; *error_code_r = MAIL_ERROR_EXPUNGED; if (box != mpurl->selected_box) mailbox_free(&box); return 0; } mpurl->box = box; *box_r = box; return 1; }
void client_send_mailbox_flags(struct client *client, bool selecting) { struct mailbox_status status; unsigned int count = array_count(client->keywords.names); const char *const *keywords; string_t *str; if (!selecting && count == client->keywords.announce_count) { /* no changes to keywords and we're not selecting a mailbox */ return; } client->keywords.announce_count = count; mailbox_get_open_status(client->mailbox, STATUS_PERMANENT_FLAGS, &status); keywords = count == 0 ? NULL : array_idx(client->keywords.names, 0); str = t_str_new(128); str_append(str, "* FLAGS ("); imap_write_flags(str, MAIL_FLAGS_NONRECENT, keywords); str_append_c(str, ')'); client_send_line(client, str_c(str)); if (!status.permanent_keywords) keywords = NULL; str_truncate(str, 0); str_append(str, "* OK [PERMANENTFLAGS ("); imap_write_flags(str, status.permanent_flags, keywords); if (status.allow_new_keywords) { if (status.permanent_flags != 0 || keywords != NULL) str_append_c(str, ' '); str_append(str, "\\*"); } str_append(str, ")] "); if (mailbox_is_readonly(client->mailbox)) str_append(str, "Read-only mailbox."); else str_append(str, "Flags permitted."); client_send_line(client, str_c(str)); }
static int imap_map_read(struct mailbox *box) { struct pop3_migration_mailbox *mbox = POP3_MIGRATION_CONTEXT(box); struct mailbox_status status; struct mailbox_transaction_context *t; struct mail_search_args *search_args; struct mail_search_context *ctx; struct mail *mail; struct imap_msg_map *map; uoff_t psize; int ret = 0; mailbox_get_open_status(box, STATUS_MESSAGES, &status); i_assert(!array_is_created(&mbox->imap_msg_map)); p_array_init(&mbox->imap_msg_map, box->pool, status.messages); t = mailbox_transaction_begin(box, 0); search_args = mail_search_build_init(); mail_search_build_add_all(search_args); ctx = mailbox_search_init(t, search_args, NULL, MAIL_FETCH_PHYSICAL_SIZE, NULL); mail_search_args_unref(&search_args); while (mailbox_search_next(ctx, &mail)) { if (mail_get_physical_size(mail, &psize) < 0) { i_error("pop3_migration: Failed to get psize for imap uid %u: %s", mail->uid, mailbox_get_last_error(box, NULL)); ret = -1; break; } map = array_append_space(&mbox->imap_msg_map); map->uid = mail->uid; map->psize = psize; } if (mailbox_search_deinit(&ctx) < 0) ret = -1; (void)mailbox_transaction_commit(&t); return ret; }
static int get_metadata_virtual_size(struct mailbox *box, struct mailbox_metadata *metadata_r) { struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box); struct index_vsize_header vsize_hdr; struct mailbox_status status; const void *data; size_t size; int ret; mailbox_get_open_status(box, STATUS_MESSAGES | STATUS_UIDNEXT, &status); mail_index_get_header_ext(box->view, ibox->vsize_hdr_ext_id, &data, &size); if (size == sizeof(vsize_hdr)) memcpy(&vsize_hdr, data, sizeof(vsize_hdr)); else { if (size != 0) { mail_storage_set_critical(box->storage, "vsize-hdr has invalid size: %"PRIuSIZE_T, size); } memset(&vsize_hdr, 0, sizeof(vsize_hdr)); } if (vsize_hdr.highest_uid + 1 == status.uidnext && vsize_hdr.message_count == status.messages) { /* up to date */ metadata_r->virtual_size = vsize_hdr.vsize; return 0; } if (vsize_hdr.highest_uid >= status.uidnext) { mail_storage_set_critical(box->storage, "vsize-hdr has invalid highest-uid (%u >= %u)", vsize_hdr.highest_uid, status.uidnext); memset(&vsize_hdr, 0, sizeof(vsize_hdr)); } ret = virtual_size_add_new(box, &vsize_hdr); metadata_r->virtual_size = vsize_hdr.vsize; return ret; }
int imap_msgpart_url_parse(struct mail_user *user, struct mailbox *selected_box, const char *urlstr, struct imap_msgpart_url **mpurl_r, const char **error_r) { struct mailbox_status box_status; struct imap_url base_url, *url; const char *error; /* build base url */ memset(&base_url, 0, sizeof(base_url)); if (selected_box != NULL) { mailbox_get_open_status(selected_box, STATUS_UIDVALIDITY, &box_status); base_url.mailbox = mailbox_get_vname(selected_box); base_url.uidvalidity = box_status.uidvalidity; } /* parse url */ if (imap_url_parse(urlstr, &base_url, IMAP_URL_PARSE_REQUIRE_RELATIVE, &url, &error) < 0) { *error_r = t_strconcat("Invalid IMAP URL: ", error, NULL); return 0; } if (url->mailbox == NULL) { *error_r = "Mailbox-relative IMAP URL, but no mailbox selected"; return 0; } if (url->uid == 0 || url->search_program != NULL) { *error_r = "Invalid messagepart IMAP URL"; return 0; } if (imap_msgpart_url_create(user, url, mpurl_r, error_r) < 0) return -1; (*mpurl_r)->selected_box = selected_box; return 1; }
static int index_mailbox(struct master_connection *conn, struct mail_user *user, const char *mailbox, unsigned int max_recent_msgs, const char *what) { struct mail_namespace *ns; struct mailbox *box; struct mailbox_status status; const char *path, *errstr; enum mail_error error; enum mailbox_sync_flags sync_flags = MAILBOX_SYNC_FLAG_FULL_READ; int ret; ns = mail_namespace_find(user->namespaces, mailbox); box = mailbox_alloc(ns->list, mailbox, 0); mailbox_set_reason(box, "indexing"); ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX, &path); if (ret < 0) { i_error("Getting path to mailbox %s failed: %s", mailbox, mailbox_get_last_internal_error(box, NULL)); mailbox_free(&box); return -1; } if (ret == 0) { i_info("Indexes disabled for mailbox %s, skipping", mailbox); mailbox_free(&box); return 0; } ret = 0; if (max_recent_msgs != 0) { /* index only if there aren't too many recent messages. don't bother syncing the mailbox, that alone can take a while with large maildirs. */ if (mailbox_open(box) < 0) { i_error("Opening mailbox %s failed: %s", mailbox, mailbox_get_last_internal_error(box, NULL)); ret = -1; } else { mailbox_get_open_status(box, STATUS_RECENT, &status); } if (ret < 0 || status.recent > max_recent_msgs) { mailbox_free(&box); return ret; } } if (strchr(what, 'o') != NULL) sync_flags |= MAILBOX_SYNC_FLAG_OPTIMIZE; if (mailbox_sync(box, sync_flags) < 0) { errstr = mailbox_get_last_internal_error(box, &error); if (error != MAIL_ERROR_NOTFOUND) { i_error("Syncing mailbox %s failed: %s", mailbox, errstr); } else if (user->mail_debug) { i_debug("Syncing mailbox %s failed: %s", mailbox, errstr); } ret = -1; } else if (strchr(what, 'i') != NULL) { if (index_mailbox_precache(conn, box) < 0) ret = -1; } mailbox_free(&box); return ret; }