imap-fetch.c revision d21f14c01d5546f4bf1b2cbb28ac1f00c24d952a
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen/* Copyright (C) 2002-2004 Timo Sirainen */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenconst struct imap_fetch_handler default_handlers[7];
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int imap_fetch_handler_cmp(const void *p1, const void *p2)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen const struct imap_fetch_handler *h1 = p1, *h2 = p2;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenvoid imap_fetch_handlers_register(const struct imap_fetch_handler *handlers,
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen fetch_handlers = buffer_create_dynamic(default_pool, 128);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen buffer_append(fetch_handlers, handlers, sizeof(*handlers) * count);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen data = buffer_get_modifyable_data(fetch_handlers, &size);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen qsort(data, size / sizeof(*handlers), sizeof(*handlers),
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int imap_fetch_handler_bsearch(const void *name_p, const void *handler_p)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen const struct imap_fetch_handler *h = handler_p;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return name[i] < 'A' || name[i] >= 'Z' ? 0 : -1;
4c07b08af30e1065f7022980b60474f229d8cadfTimo Sirainenint imap_fetch_init_handler(struct imap_fetch_context *ctx, const char *name,
e60a349c641bb2f4723e4a395a25f55531682d2bTimo Sirainenstruct imap_fetch_context *imap_fetch_init(struct client_command_context *cmd)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen imap_fetch_handlers_register(default_handlers,
e60a349c641bb2f4723e4a395a25f55531682d2bTimo Sirainen ctx = p_new(cmd->pool, struct imap_fetch_context, 1);
e60a349c641bb2f4723e4a395a25f55531682d2bTimo Sirainen ctx->all_headers_buf = buffer_create_dynamic(cmd->pool, 128);
e60a349c641bb2f4723e4a395a25f55531682d2bTimo Sirainen ctx->handlers = buffer_create_dynamic(cmd->pool, 128);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenvoid imap_fetch_add_handler(struct imap_fetch_context *ctx,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen const struct imap_fetch_context_handler *handlers;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* don't allow duplicate handlers */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen handlers = buffer_get_data(ctx->handlers, &size);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen for (i = 0; i < size; i++) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen memset(&h, 0, sizeof(h));
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenvoid imap_fetch_begin(struct imap_fetch_context *ctx,
4c07b08af30e1065f7022980b60474f229d8cadfTimo Sirainen (void)imap_fetch_init_handler(ctx, "FLAGS", NULL);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (buffer_get_used_size(ctx->all_headers_buf) != 0 &&
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ((ctx->fetch_data & (MAIL_FETCH_STREAM_HEADER |
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen buffer_append(ctx->all_headers_buf, &null, sizeof(null));
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen data = buffer_get_data(ctx->all_headers_buf, NULL);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ctx->trans = mailbox_transaction_begin(ctx->box, TRUE);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ctx->select_counter = ctx->client->select_counter;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen mailbox_search_init(ctx->trans, NULL, search_arg, NULL,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen const struct imap_fetch_context_handler *handlers;
d21f14c01d5546f4bf1b2cbb28ac1f00c24d952aTimo Sirainen /* not an error, just lost it. */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen handlers = buffer_get_data(ctx->handlers, &size);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (o_stream_get_buffer_used_size(ctx->client->output) >=
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ctx->cur_mail = mailbox_search_next(ctx->search_ctx);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen for (; ctx->cur_handler < size; ctx->cur_handler++) {
d21f14c01d5546f4bf1b2cbb28ac1f00c24d952aTimo Sirainen /* not an error, just lost it. */
2ae7cffa50608be0e1261e0a993333a8bdc0550dTimo Sirainen if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenint imap_fetch_deinit(struct imap_fetch_context *ctx)
2ba4e9bedb0fa778dfbccec5370018b4d0040d9cTimo Sirainen if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (mailbox_search_deinit(ctx->search_ctx) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen mailbox_header_lookup_deinit(ctx->all_headers_ctx);
b2c1349cf07410aefab0f5b17153af9e5cfcf48fTimo Sirainen if (mailbox_transaction_commit(ctx->trans, 0) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int fetch_body(struct imap_fetch_context *ctx, struct mail *mail,
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen body = mail->get_special(mail, MAIL_FETCH_IMAP_BODY);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (o_stream_send(ctx->client->output, " ", 1) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (o_stream_send(ctx->client->output, "BODY (", 6) < 0 ||
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen o_stream_send_str(ctx->client->output, body) < 0 ||
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen o_stream_send(ctx->client->output, ")", 1) < 0)
4c07b08af30e1065f7022980b60474f229d8cadfTimo Sirainenstatic int fetch_body_init(struct imap_fetch_context *ctx, const char *name,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen imap_fetch_add_handler(ctx, fetch_body, NULL);
4c07b08af30e1065f7022980b60474f229d8cadfTimo Sirainen return fetch_body_section_init(ctx, name, args);
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainenstatic int fetch_bodystructure(struct imap_fetch_context *ctx,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen struct mail *mail, void *context __attr_unused__)
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen bodystructure = mail->get_special(mail, MAIL_FETCH_IMAP_BODYSTRUCTURE);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (o_stream_send(ctx->client->output, " ", 1) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (o_stream_send(ctx->client->output, "BODYSTRUCTURE (", 15) < 0 ||
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen o_stream_send_str(ctx->client->output, bodystructure) < 0 ||
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen o_stream_send(ctx->client->output, ")", 1) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int fetch_bodystructure_init(struct imap_fetch_context *ctx,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ctx->fetch_data |= MAIL_FETCH_IMAP_BODYSTRUCTURE;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen imap_fetch_add_handler(ctx, fetch_bodystructure, NULL);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int fetch_envelope(struct imap_fetch_context *ctx, struct mail *mail,
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen envelope = mail->get_special(mail, MAIL_FETCH_IMAP_ENVELOPE);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (o_stream_send(ctx->client->output, " ", 1) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (o_stream_send(ctx->client->output, "ENVELOPE (", 10) < 0 ||
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen o_stream_send_str(ctx->client->output, envelope) < 0 ||
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen o_stream_send(ctx->client->output, ")", 1) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int fetch_envelope_init(struct imap_fetch_context *ctx,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen imap_fetch_add_handler(ctx, fetch_envelope, NULL);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int fetch_flags(struct imap_fetch_context *ctx, struct mail *mail,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const char *const *keywords;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (ctx->flags_update_seen && (flags & MAIL_SEEN) == 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* Add \Seen flag */
9a97b508a9bd66b1d75b108b57e0a5693eb3a086Timo Sirainen if (mail->update_flags(mail, MODIFY_ADD, MAIL_SEEN) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen } else if (ctx->flags_show_only_seen_changes) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen imap_write_flags(ctx->cur_str, flags, keywords);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int fetch_flags_init(struct imap_fetch_context *ctx,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen imap_fetch_add_handler(ctx, fetch_flags, NULL);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int fetch_internaldate(struct imap_fetch_context *ctx, struct mail *mail,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen str_printfa(ctx->cur_str, "INTERNALDATE \"%s\" ",
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int fetch_internaldate_init(struct imap_fetch_context *ctx,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen imap_fetch_add_handler(ctx, fetch_internaldate, NULL);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int fetch_uid(struct imap_fetch_context *ctx, struct mail *mail,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen str_printfa(ctx->cur_str, "UID %u ", mail->uid);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int fetch_uid_init(struct imap_fetch_context *ctx __attr_unused__,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenconst struct imap_fetch_handler default_handlers[7] = {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen { "BODYSTRUCTURE", fetch_bodystructure_init },