#include "common.h"
#include "commands.h"
+#include "imap-search.h"
static int fetch_and_copy(struct mail_copy_context *copy_ctx,
struct mailbox *srcbox, struct mailbox *destbox,
const char *messageset, int uidset, int *all_found)
{
- struct mail_fetch_context *fetch_ctx;
+ struct mail_search_arg *search_arg;
+ struct mail_search_context *search_ctx;
struct mail *mail;
int failed = FALSE;
- fetch_ctx = srcbox->fetch_init(srcbox, MAIL_FETCH_STREAM_HEADER |
- MAIL_FETCH_STREAM_BODY, NULL,
- messageset, uidset);
- if (fetch_ctx == NULL)
+ search_arg = imap_search_get_msgset_arg(messageset, uidset);
+ search_ctx = srcbox->search_init(srcbox, NULL, search_arg, NULL,
+ MAIL_FETCH_STREAM_HEADER |
+ MAIL_FETCH_STREAM_BODY, NULL);
+ if (search_ctx == NULL)
return FALSE;
- while ((mail = srcbox->fetch_next(fetch_ctx)) != NULL) {
+ while ((mail = srcbox->search_next(search_ctx)) != NULL) {
if (!destbox->copy(mail, copy_ctx)) {
failed = TRUE;
break;
}
}
- if (!srcbox->fetch_deinit(fetch_ctx, all_found))
+ if (!srcbox->search_deinit(search_ctx, all_found))
return FALSE;
return !failed;
str_printfa(str, " %u", uid ? mail->uid : mail->seq);
}
- ret = client->mailbox->search_deinit(ctx);
+ ret = client->mailbox->search_deinit(ctx, NULL);
if (!first || ret) {
str_append(str, "\r\n");
#include "common.h"
#include "commands.h"
+#include "imap-search.h"
static int get_modify_type(struct client *client, const char *item,
enum modify_type *modify_type, int *silent)
struct mail_full_flags flags;
enum modify_type modify_type;
struct mailbox *box;
- struct mail_fetch_context *fetch_ctx;
+ struct mail_search_arg *search_arg;
+ struct mail_search_context *search_ctx;
struct mail *mail;
const char *messageset, *item;
int silent, all_found, failed;
MAILBOX_LOCK_READ);
}
- fetch_ctx = failed ? NULL :
- box->fetch_init(box, MAIL_FETCH_FLAGS, NULL,
- messageset, client->cmd_uid);
- if (fetch_ctx == NULL)
+ search_arg = imap_search_get_msgset_arg(messageset, client->cmd_uid);
+ search_ctx = failed ? NULL :
+ box->search_init(box, NULL, search_arg, NULL,
+ MAIL_FETCH_FLAGS, NULL);
+
+ if (search_ctx == NULL)
failed = TRUE;
else {
failed = FALSE;
- while ((mail = box->fetch_next(fetch_ctx)) != NULL) {
+ while ((mail = box->search_next(search_ctx)) != NULL) {
if (!mail->update_flags(mail, &flags, modify_type)) {
failed = TRUE;
break;
}
}
- if (!box->fetch_deinit(fetch_ctx, &all_found))
+ if (!box->search_deinit(search_ctx, &all_found))
failed = TRUE;
(void)box->lock(box, MAILBOX_LOCK_UNLOCK);
#include "imap-date.h"
#include "commands.h"
#include "imap-fetch.h"
+#include "imap-search.h"
#include <unistd.h>
const char *messageset, int uidset)
{
struct mailbox *box = client->mailbox;
+ struct mail_search_arg *search_arg;
struct imap_fetch_context ctx;
struct mail *mail;
struct imap_fetch_body_data *body;
return -1;
}
- ctx.fetch_ctx = box->fetch_init(box, fetch_data, wanted_headers,
- messageset, uidset);
- if (ctx.fetch_ctx == NULL)
+ search_arg = imap_search_get_msgset_arg(messageset, uidset);
+ ctx.search_ctx = box->search_init(box, NULL, search_arg, NULL,
+ fetch_data, wanted_headers);
+ if (ctx.search_ctx == NULL)
ctx.failed = TRUE;
else {
ctx.str = str_new(default_pool, 8192);
- while ((mail = box->fetch_next(ctx.fetch_ctx)) != NULL) {
+ while ((mail = box->search_next(ctx.search_ctx)) != NULL) {
if (!fetch_mail(&ctx, mail)) {
ctx.failed = TRUE;
break;
}
str_free(ctx.str);
- if (!box->fetch_deinit(ctx.fetch_ctx, &all_found))
+ if (!box->search_deinit(ctx.search_ctx, &all_found))
ctx.failed = TRUE;
}
};
struct imap_fetch_context {
- struct mail_fetch_context *fetch_ctx;
+ struct mail_search_context *search_ctx;
enum mail_fetch_field fetch_data;
enum imap_fetch_field imap_data;
return first_sarg;
}
+struct mail_search_arg *
+imap_search_get_msgset_arg(const char *messageset, int uidset)
+{
+ struct mail_search_arg *arg;
+
+ arg = t_new(struct mail_search_arg, 1);
+ arg->type = uidset ? SEARCH_UID : SEARCH_SET;
+ arg->value.str = t_strdup(messageset);
+ return arg;
+}
struct mail_search_arg *
imap_search_args_build(pool_t pool, struct imap_arg *args, const char **error);
+struct mail_search_arg *
+imap_search_get_msgset_arg(const char *messageset, int uidset);
+
#endif
mail_sort_input(ctx, mail);
mail_sort_flush(ctx);
- ret = client->mailbox->search_deinit(ctx->search_ctx);
+ ret = client->mailbox->search_deinit(ctx->search_ctx, NULL);
if (ctx->written || ret) {
str_append(ctx->str, "\r\n");
mail_thread_finish(ctx);
o_stream_send_str(client->output, "\r\n");
- ret = client->mailbox->search_deinit(ctx->search_ctx);
+ ret = client->mailbox->search_deinit(ctx->search_ctx, NULL);
mail_thread_deinit(ctx);
return ret;
}
#include "index-messageset.h"
#include "index-mail.h"
-struct mail_fetch_context {
- struct index_mailbox *ibox;
- struct mail_index *index;
-
- struct messageset_context *msgset_ctx;
- struct index_mail mail;
-
- enum mail_lock_type old_lock;
-};
-
-struct mail_fetch_context *
-index_storage_fetch_init(struct mailbox *box,
- enum mail_fetch_field wanted_fields,
- const char *const *wanted_headers,
- const char *messageset, int uidset)
-{
- struct index_mailbox *ibox = (struct index_mailbox *) box;
- struct mail_fetch_context *ctx;
- int check_mail;
-
- ctx = i_new(struct mail_fetch_context, 1);
- ctx->old_lock = ibox->index->lock_type;
-
- check_mail = (client_workarounds &
- WORKAROUND_OE6_FETCH_NO_NEWMAIL) == 0;
- if (!index_storage_sync_and_lock(ibox, check_mail, TRUE,
- MAIL_LOCK_SHARED))
- return NULL;
-
- ctx->ibox = ibox;
- ctx->index = ibox->index;
-
- index_mail_init(ibox, &ctx->mail, wanted_fields, wanted_headers);
- ctx->msgset_ctx = index_messageset_init(ibox, messageset, uidset, TRUE);
- return ctx;
-}
-
-int index_storage_fetch_deinit(struct mail_fetch_context *ctx, int *all_found)
-{
- int ret;
-
- ret = index_messageset_deinit(ctx->msgset_ctx);
-
- if (all_found != NULL)
- *all_found = ret > 0;
-
- if (ctx->ibox->fetch_mail.pool != NULL)
- index_mail_deinit(&ctx->ibox->fetch_mail);
- if (ctx->mail.pool != NULL)
- index_mail_deinit(&ctx->mail);
-
- if (!index_storage_lock(ctx->ibox, ctx->old_lock))
- ret = -1;
-
- i_free(ctx);
- return ret >= 0;
-}
-
-struct mail *index_storage_fetch_next(struct mail_fetch_context *ctx)
-{
- const struct messageset_mail *msgset_mail;
- int ret;
-
- do {
- msgset_mail = index_messageset_next(ctx->msgset_ctx);
- if (msgset_mail == NULL) {
- ret = -1;
- break;
- }
-
- ctx->mail.mail.seq = msgset_mail->client_seq;
- ctx->mail.mail.uid = msgset_mail->rec->uid;
-
- ret = index_mail_next(&ctx->mail, msgset_mail->rec,
- msgset_mail->idx_seq, FALSE);
- } while (ret == 0);
-
- if (ret < 0) {
- /* error or last record */
- index_mail_deinit(&ctx->mail);
- return NULL;
- }
-
- return &ctx->mail.mail;
-}
-
static struct mail *
fetch_record(struct index_mailbox *ibox, struct mail_index_record *rec,
unsigned int idx_seq, enum mail_fetch_field wanted_fields)
return ctx;
}
-int index_storage_search_deinit(struct mail_search_context *ctx)
+int index_storage_search_deinit(struct mail_search_context *ctx, int *all_found)
{
- int ret;
+ int ret, msgset_ret;
ret = !ctx->failed && ctx->error == NULL;
if (ctx->msgset_ctx != NULL) {
- if (index_messageset_deinit(ctx->msgset_ctx) < 0)
+ msgset_ret = index_messageset_deinit(ctx->msgset_ctx);
+ if (msgset_ret < 0)
ret = FALSE;
+ if (all_found != NULL)
+ *all_found = msgset_ret > 0;
+ } else {
+ if (all_found != NULL)
+ *all_found = !ctx->failed;
}
if (ctx->ibox->fetch_mail.pool != NULL)
struct mailbox_status *status);
int index_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags);
-struct mail_fetch_context *
-index_storage_fetch_init(struct mailbox *box,
- enum mail_fetch_field wanted_fields,
- const char *const *wanted_headers,
- const char *messageset, int uidset);
-int index_storage_fetch_deinit(struct mail_fetch_context *ctx, int *all_found);
-struct mail *index_storage_fetch_next(struct mail_fetch_context *ctx);
-
struct mail *index_storage_fetch_uid(struct mailbox *box, unsigned int uid,
enum mail_fetch_field wanted_fields);
struct mail *index_storage_fetch_seq(struct mailbox *box, unsigned int seq,
const enum mail_sort_type *sort_program,
enum mail_fetch_field wanted_fields,
const char *const wanted_headers[]);
-int index_storage_search_deinit(struct mail_search_context *ctx);
+int index_storage_search_deinit(struct mail_search_context *ctx,
+ int *all_found);
struct mail *index_storage_search_next(struct mail_search_context *ctx);
struct mail_copy_context *index_storage_copy_init(struct mailbox *box);
index_storage_get_status,
index_storage_sync,
maildir_storage_auto_sync,
- index_storage_fetch_init,
- index_storage_fetch_deinit,
- index_storage_fetch_next,
index_storage_fetch_uid,
index_storage_fetch_seq,
index_storage_search_get_sorting,
index_storage_get_status,
index_storage_sync,
mbox_storage_auto_sync,
- index_storage_fetch_init,
- index_storage_fetch_deinit,
- index_storage_fetch_next,
index_storage_fetch_uid,
index_storage_fetch_seq,
index_storage_search_get_sorting,
void (*auto_sync)(struct mailbox *box, enum mailbox_sync_flags flags,
unsigned int min_newmail_notify_interval);
- /* Initialize new fetch request. wanted_fields isn't required, but it
- can be used for optimizations. update_flags must be set to TRUE, if
- you want to call mail->update_flags() */
- struct mail_fetch_context *
- (*fetch_init)(struct mailbox *box,
- enum mail_fetch_field wanted_fields,
- const char *const *wanted_headers,
- const char *messageset, int uidset);
- /* Deinitialize fetch request. all_found is set to TRUE if all of the
- fetched messages were found (ie. not just deleted). */
- int (*fetch_deinit)(struct mail_fetch_context *ctx, int *all_found);
- /* Fetch the next message. Returned mail object can be used until
- the next call to fetch_next() or fetch_deinit(). */
- struct mail *(*fetch_next)(struct mail_fetch_context *ctx);
-
/* Simplified fetching for a single UID or sequence. Must be called
between fetch_init() .. fetch_deinit() or
search_init() .. search_deinit() */
const enum mail_sort_type *sort_program,
enum mail_fetch_field wanted_fields,
const char *const wanted_headers[]);
- /* Deinitialize search request. */
- int (*search_deinit)(struct mail_search_context *ctx);
+ /* Deinitialize search request. all_found is set to TRUE if all of the
+ messages in search range were found. */
+ int (*search_deinit)(struct mail_search_context *ctx, int *all_found);
/* Search the next message. Returned mail object can be used until
the next call to search_next() or search_deinit(). */
struct mail *(*search_next)(struct mail_search_context *ctx);
p->box->auto_sync(p->box, flags, min_newmail_notify_interval);
}
-static struct mail_fetch_context *
-_fetch_init(struct mailbox *box, enum mail_fetch_field wanted_fields,
- const char *const *wanted_headers,
- const char *messageset, int uidset)
-{
- struct proxy_mailbox *p = (struct proxy_mailbox *) box;
-
- return p->box->fetch_init(p->box, wanted_fields, wanted_headers,
- messageset, uidset);
-}
-
static struct mail *_fetch_uid(struct mailbox *box, unsigned int uid,
enum mail_fetch_field wanted_fields)
{
pb->name = box->name;
pb->storage = box->storage;
- pb->fetch_deinit = box->fetch_deinit;
- pb->fetch_next = box->fetch_next;
pb->search_deinit = box->search_deinit;
pb->search_next = box->search_next;
pb->save_deinit = box->save_deinit;
pb->get_status = _get_status;
pb->sync = _sync;
pb->auto_sync = _auto_sync;
- pb->fetch_init = _fetch_init;
pb->fetch_uid = _fetch_uid;
pb->fetch_seq = _fetch_seq;
pb->search_get_sorting = _search_get_sorting;
#include "ostream.h"
#include "mail-storage.h"
#include "commands.h"
+#include "mail-search.h"
#include <stdlib.h>
static int init_mailbox(struct client *client)
{
- struct mail_fetch_context *ctx;
+ struct mail_search_arg search_arg;
+ struct mail_search_context *ctx;
struct mail *mail;
struct mailbox_status status;
- const char *messageset;
int i, all_found, failed;
if (!client->mailbox->get_status(client->mailbox,
if (client->messages_count == 0)
return TRUE;
+ memset(&search_arg, 0, sizeof(search_arg));
+ search_arg.type = SEARCH_ALL;
+
client->message_sizes = i_new(uoff_t, client->messages_count);
- messageset = t_strdup_printf("1:%u", client->messages_count);
for (i = 0; i < 2; i++) {
- ctx = client->mailbox->fetch_init(client->mailbox,
- MAIL_FETCH_SIZE, NULL,
- messageset, FALSE);
+ ctx = client->mailbox->search_init(client->mailbox, NULL,
+ &search_arg, NULL,
+ MAIL_FETCH_SIZE, NULL);
if (ctx == NULL) {
client_send_storage_error(client);
return FALSE;
client->total_size = 0;
failed = FALSE;
- while ((mail = client->mailbox->fetch_next(ctx)) != NULL) {
+ while ((mail = client->mailbox->search_next(ctx)) != NULL) {
uoff_t size = mail->get_size(mail);
if (size == (uoff_t)-1) {
client->message_sizes[mail->seq-1] = size;
}
- if (!client->mailbox->fetch_deinit(ctx, &all_found)) {
+ if (!client->mailbox->search_deinit(ctx, &all_found)) {
client_send_storage_error(client);
return FALSE;
}
#include "str.h"
#include "message-size.h"
#include "mail-storage.h"
+#include "mail-search.h"
#include "capability.h"
#include "commands.h"
static void fetch(struct client *client, unsigned int msgnum,
uoff_t body_lines)
{
- struct mail_fetch_context *ctx;
+ struct mail_search_arg search_arg;
+ struct mail_search_context *ctx;
struct mail *mail;
struct istream *stream;
- ctx = client->mailbox->fetch_init(client->mailbox,
- MAIL_FETCH_STREAM_HEADER |
- MAIL_FETCH_STREAM_BODY, NULL,
- dec2str(msgnum+1), FALSE);
+ memset(&search_arg, 0, sizeof(search_arg));
+ search_arg.type = SEARCH_SET;
+ search_arg.value.str = dec2str(msgnum+1);
+
+ ctx = client->mailbox->search_init(client->mailbox, NULL,
+ &search_arg, NULL,
+ MAIL_FETCH_STREAM_HEADER |
+ MAIL_FETCH_STREAM_BODY, NULL);
if (ctx == NULL) {
client_send_storage_error(client);
return;
}
- mail = client->mailbox->fetch_next(ctx);
+ mail = client->mailbox->search_next(ctx);
stream = mail == NULL ? NULL : mail->get_stream(mail, NULL, NULL);
if (stream == NULL)
client_send_line(client, "-ERR Message not found.");
client_send_line(client, ".");
}
- (void)client->mailbox->fetch_deinit(ctx, NULL);
+ (void)client->mailbox->search_deinit(ctx, NULL);
}
static int cmd_retr(struct client *client, const char *args)
static void list_uids(struct client *client, unsigned int message)
{
- struct mail_fetch_context *ctx;
+ struct mail_search_arg search_arg;
+ struct mail_search_context *ctx;
struct mail *mail;
- const char *messageset;
int found = FALSE;
if (client->messages_count == 0 && message == 0)
return;
- messageset = message == 0 ?
- t_strdup_printf("1:%u", client->messages_count) :
- t_strdup_printf("%u", message);
+ memset(&search_arg, 0, sizeof(search_arg));
+ if (message == 0)
+ search_arg.type = SEARCH_ALL;
+ else {
+ search_arg.type = SEARCH_SET;
+ search_arg.value.str = dec2str(message);
+ }
- ctx = client->mailbox->fetch_init(client->mailbox, 0, NULL,
- messageset, FALSE);
+ ctx = client->mailbox->search_init(client->mailbox, NULL,
+ &search_arg, NULL, 0, NULL);
if (ctx == NULL) {
client_send_storage_error(client);
return;
}
- while ((mail = client->mailbox->fetch_next(ctx)) != NULL) {
+ while ((mail = client->mailbox->search_next(ctx)) != NULL) {
client_send_line(client, message == 0 ?
"%u %u.%u" : "+OK %u %u.%u",
mail->seq, client->uidvalidity, mail->uid);
found = TRUE;
}
- (void)client->mailbox->fetch_deinit(ctx, NULL);
+ (void)client->mailbox->search_deinit(ctx, NULL);
if (!found && message != 0)
client_send_line(client, "-ERR Message not found.");