imap-fetch.c revision baf1148108b7d9739626b47cc57298c36929586a
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2002-2004 Timo Sirainen */
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "common.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "buffer.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "istream.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "ostream.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "str.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "message-send.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "message-size.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "imap-date.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "commands.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "imap-fetch.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "imap-util.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch#include <stdlib.h>
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschconst struct imap_fetch_handler default_handlers[7];
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic buffer_t *fetch_handlers = NULL;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic int imap_fetch_handler_cmp(const void *p1, const void *p2)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const struct imap_fetch_handler *h1 = p1, *h2 = p2;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return strcmp(h1->name, h2->name);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschvoid imap_fetch_handlers_register(const struct imap_fetch_handler *handlers,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch size_t count)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch void *data;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch size_t size;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch if (fetch_handlers == NULL) {
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch fetch_handlers = buffer_create_dynamic(default_pool,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch 128, (size_t)-1);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch buffer_append(fetch_handlers, handlers, sizeof(*handlers) * count);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch data = buffer_get_modifyable_data(fetch_handlers, &size);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch qsort(data, size / sizeof(*handlers), sizeof(*handlers),
10962368c30afde135743fd9796122e88a708e87Stephan Bosch imap_fetch_handler_cmp);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic int imap_fetch_handler_bsearch(const void *name_p, const void *handler_p)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const char *name = name_p;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch const struct imap_fetch_handler *h = handler_p;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch int i;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch for (i = 0; h->name[i] != '\0'; i++) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (h->name[i] != name[i]) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (name[i] < 'A' || name[i] >= 'Z')
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return name[i] - h->name[i];
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return name[i] < 'A' || name[i] >= 'Z' ? 0 : -1;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschint imap_fetch_init_handler(struct imap_fetch_context *ctx, const char *arg)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const struct imap_fetch_handler *handler;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch handler = bsearch(arg, fetch_handlers->data,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch fetch_handlers->used /
10962368c30afde135743fd9796122e88a708e87Stephan Bosch sizeof(struct imap_fetch_handler),
10962368c30afde135743fd9796122e88a708e87Stephan Bosch sizeof(struct imap_fetch_handler),
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch imap_fetch_handler_bsearch);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (handler == NULL) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch client_send_command_error(ctx->client,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch t_strconcat("Unknown command ", arg, NULL));
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return FALSE;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return handler->init(ctx, arg);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstruct imap_fetch_context *imap_fetch_init(struct client *client)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct imap_fetch_context *ctx;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (fetch_handlers == NULL) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch imap_fetch_handlers_register(default_handlers,
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch sizeof(default_handlers) /
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch sizeof(default_handlers[0]));
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx = p_new(client->cmd_pool, struct imap_fetch_context, 1);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->client = client;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->box = client->mailbox;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->cur_str = str_new(default_pool, 8192);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->seen_flag.flags = MAIL_SEEN;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->all_headers_buf =
10962368c30afde135743fd9796122e88a708e87Stephan Bosch buffer_create_dynamic(client->cmd_pool, 128, (size_t)-1);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->handlers =
10962368c30afde135743fd9796122e88a708e87Stephan Bosch buffer_create_dynamic(client->cmd_pool, 128, (size_t)-1);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return ctx;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch}
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschvoid imap_fetch_add_handler(struct imap_fetch_context *ctx,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch imap_fetch_handler_t *handler, void *context)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const struct imap_fetch_context_handler *handlers;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch struct imap_fetch_context_handler h;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch size_t i, size;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (context == NULL) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* don't allow duplicate handlers */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch handlers = buffer_get_data(ctx->handlers, &size);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch size /= sizeof(*handlers);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch for (i = 0; i < size; i++) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (handlers[i].handler == handler &&
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch handlers[i].context == NULL)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch memset(&h, 0, sizeof(h));
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch h.handler = handler;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch h.context = context;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch buffer_append(ctx->handlers, &h, sizeof(h));
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschvoid imap_fetch_begin(struct imap_fetch_context *ctx,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch struct mail_search_arg *search_arg)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const void *null = NULL;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const void *data;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (ctx->flags_update_seen) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (mailbox_is_readonly(ctx->box))
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->flags_update_seen = FALSE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch else if (!ctx->flags_have_handler) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->flags_show_only_seen_changes = TRUE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch (void)imap_fetch_init_handler(ctx, "FLAGS");
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (buffer_get_used_size(ctx->all_headers_buf) != 0 &&
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ((ctx->fetch_data & (MAIL_FETCH_STREAM_HEADER |
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch MAIL_FETCH_STREAM_BODY)) == 0)) {
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch buffer_append(ctx->all_headers_buf, &null, sizeof(null));
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch data = buffer_get_data(ctx->all_headers_buf, NULL);
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch ctx->all_headers_ctx =
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch mailbox_header_lookup_init(ctx->box, data);
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch }
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch ctx->trans = mailbox_transaction_begin(ctx->box, TRUE);
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch ctx->select_counter = ctx->client->select_counter;
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch ctx->search_ctx =
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch mailbox_search_init(ctx->trans, NULL, search_arg, NULL,
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch ctx->fetch_data, ctx->all_headers_ctx);
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch}
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Boschint imap_fetch(struct imap_fetch_context *ctx)
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch{
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch const struct imap_fetch_context_handler *handlers;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch size_t size;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch int ret;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch if (ctx->cont_handler != NULL) {
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch if ((ret = ctx->cont_handler(ctx)) <= 0) {
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch if (ret < 0)
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch ctx->failed = TRUE;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return ret;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmody ctx->cont_handler = NULL;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->cur_offset = 0;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->cur_handler++;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch handlers = buffer_get_data(ctx->handlers, &size);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch size /= sizeof(*handlers);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch for (;;) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (o_stream_get_buffer_used_size(ctx->client->output) >=
10962368c30afde135743fd9796122e88a708e87Stephan Bosch CLIENT_OUTPUT_OPTIMAL_SIZE) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ret = o_stream_flush(ctx->client->output);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (ret <= 0)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return ret;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (ctx->cur_mail == NULL) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (ctx->cur_input != NULL) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch i_stream_unref(ctx->cur_input);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->cur_input = NULL;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->cur_mail = mailbox_search_next(ctx->search_ctx);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (ctx->cur_mail == NULL)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch break;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch str_printfa(ctx->cur_str, "* %u FETCH (",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->cur_mail->seq);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (o_stream_send(ctx->client->output,
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen str_data(ctx->cur_str),
10962368c30afde135743fd9796122e88a708e87Stephan Bosch str_len(ctx->cur_str)) < 0) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->failed = TRUE;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return -1;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch str_truncate(ctx->cur_str, 0);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch str_append_c(ctx->cur_str, ' ');
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->first = TRUE;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch for (; ctx->cur_handler < size; ctx->cur_handler++) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch t_push();
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ret = handlers[ctx->cur_handler].
10962368c30afde135743fd9796122e88a708e87Stephan Bosch handler(ctx, ctx->cur_mail,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch handlers[ctx->cur_handler].context);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch t_pop();
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen if (ret <= 0) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (ret < 0)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->failed = TRUE;
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmody else
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen i_assert(ctx->cont_handler != NULL);
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmody return ret;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->cont_handler = NULL;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->cur_offset = 0;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (str_len(ctx->cur_str) > 1) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (o_stream_send(ctx->client->output,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch str_data(ctx->cur_str) + ctx->first,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch str_len(ctx->cur_str) - 1 -
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->first) < 0) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->failed = TRUE;
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen return -1;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch str_truncate(ctx->cur_str, 0);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->failed = TRUE;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->cur_mail = NULL;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->cur_handler = 0;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return 1;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschint imap_fetch_deinit(struct imap_fetch_context *ctx)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch str_free(ctx->cur_str);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (ctx->cur_input != NULL) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch i_stream_unref(ctx->cur_input);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->cur_input = NULL;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (ctx->search_ctx != NULL) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (mailbox_search_deinit(ctx->search_ctx) < 0)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch ctx->failed = TRUE;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch }
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (ctx->all_headers_ctx != NULL)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch mailbox_header_lookup_deinit(ctx->all_headers_ctx);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (ctx->trans != NULL) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (ctx->failed)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch mailbox_transaction_rollback(ctx->trans);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch else {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (mailbox_transaction_commit(ctx->trans) < 0)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->failed = TRUE;
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch return ctx->failed ? -1 : 0;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic int fetch_body(struct imap_fetch_context *ctx, struct mail *mail,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch void *context __attr_unused__)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const char *body;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch body = mail->get_special(mail, MAIL_FETCH_IMAP_BODY);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (body == NULL)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (ctx->first)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->first = FALSE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch else {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (o_stream_send(ctx->client->output, " ", 1) < 0)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return -1;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (o_stream_send(ctx->client->output, "BODY (", 6) < 0 ||
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch o_stream_send_str(ctx->client->output, body) < 0 ||
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch o_stream_send(ctx->client->output, ")", 1) < 0)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return 1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic int fetch_body_init(struct imap_fetch_context *ctx, const char *arg)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (arg[4] == '\0') {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->fetch_data |= MAIL_FETCH_IMAP_BODY;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch imap_fetch_add_handler(ctx, fetch_body, NULL);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return TRUE;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return fetch_body_section_init(ctx, arg);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic int fetch_bodystructure(struct imap_fetch_context *ctx,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct mail *mail, void *context __attr_unused__)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *bodystructure;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch bodystructure = mail->get_special(mail, MAIL_FETCH_IMAP_BODYSTRUCTURE);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (bodystructure == NULL)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (ctx->first)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->first = FALSE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch else {
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch if (o_stream_send(ctx->client->output, " ", 1) < 0)
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (o_stream_send(ctx->client->output, "BODYSTRUCTURE (", 15) < 0 ||
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmody o_stream_send_str(ctx->client->output, bodystructure) < 0 ||
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch o_stream_send(ctx->client->output, ")", 1) < 0)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return 1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic int fetch_bodystructure_init(struct imap_fetch_context *ctx,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const char *arg __attr_unused__)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->fetch_data |= MAIL_FETCH_IMAP_BODYSTRUCTURE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch imap_fetch_add_handler(ctx, fetch_bodystructure, NULL);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return TRUE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic int fetch_envelope(struct imap_fetch_context *ctx, struct mail *mail,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch void *context __attr_unused__)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const char *envelope;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch envelope = mail->get_special(mail, MAIL_FETCH_IMAP_ENVELOPE);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (envelope == NULL)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (ctx->first)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->first = FALSE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch else {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (o_stream_send(ctx->client->output, " ", 1) < 0)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (o_stream_send(ctx->client->output, "ENVELOPE (", 10) < 0 ||
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch o_stream_send_str(ctx->client->output, envelope) < 0 ||
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch o_stream_send(ctx->client->output, ")", 1) < 0)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return 1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic int fetch_envelope_init(struct imap_fetch_context *ctx,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const char *arg __attr_unused__)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->fetch_data |= MAIL_FETCH_IMAP_ENVELOPE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch imap_fetch_add_handler(ctx, fetch_envelope, NULL);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return TRUE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic int fetch_flags(struct imap_fetch_context *ctx, struct mail *mail,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch void *context __attr_unused__)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const struct mail_full_flags *flags;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch struct mail_full_flags full_flags;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch flags = mail->get_flags(mail);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (flags == NULL)
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch return -1;
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch if (ctx->flags_update_seen && (flags->flags & MAIL_SEEN) == 0) {
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch /* Add \Seen flag */
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch full_flags = *flags;
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch full_flags.flags |= MAIL_SEEN;
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch flags = &full_flags;
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch if (mail->update_flags(mail, &ctx->seen_flag, MODIFY_ADD) < 0)
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch return -1;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch } else if (ctx->flags_show_only_seen_changes) {
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch return 1;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch }
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch str_append(ctx->cur_str, "FLAGS (");
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch imap_write_flags(ctx->cur_str, flags);
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch str_append(ctx->cur_str, ") ");
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return 1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic int fetch_flags_init(struct imap_fetch_context *ctx,
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmody const char *arg __attr_unused__)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ctx->flags_have_handler = TRUE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->fetch_data |= MAIL_FETCH_FLAGS;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch imap_fetch_add_handler(ctx, fetch_flags, NULL);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return TRUE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic int fetch_internaldate(struct imap_fetch_context *ctx, struct mail *mail,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch void *context __attr_unused__)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch time_t time;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch time = mail->get_received_date(mail);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (time == (time_t)-1)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch str_printfa(ctx->cur_str, "INTERNALDATE \"%s\" ",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch imap_to_datetime(time));
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return 1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic int fetch_internaldate_init(struct imap_fetch_context *ctx,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const char *arg __attr_unused__)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ctx->fetch_data |= MAIL_FETCH_RECEIVED_DATE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch imap_fetch_add_handler(ctx, fetch_internaldate, NULL);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return TRUE;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic int fetch_uid(struct imap_fetch_context *ctx, struct mail *mail,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch void *context __attr_unused__)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch str_printfa(ctx->cur_str, "UID %u ", mail->uid);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return 1;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic int fetch_uid_init(struct imap_fetch_context *ctx __attr_unused__,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *arg __attr_unused__)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch imap_fetch_add_handler(ctx, fetch_uid, NULL);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return TRUE;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmodyconst struct imap_fetch_handler default_handlers[7] = {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch { "BODY", fetch_body_init },
10962368c30afde135743fd9796122e88a708e87Stephan Bosch { "BODYSTRUCTURE", fetch_bodystructure_init },
10962368c30afde135743fd9796122e88a708e87Stephan Bosch { "ENVELOPE", fetch_envelope_init },
10962368c30afde135743fd9796122e88a708e87Stephan Bosch { "FLAGS", fetch_flags_init },
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmody { "INTERNALDATE", fetch_internaldate_init },
10962368c30afde135743fd9796122e88a708e87Stephan Bosch { "RFC822", fetch_rfc822_init },
10962368c30afde135743fd9796122e88a708e87Stephan Bosch { "UID", fetch_uid_init }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch};
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch